41package com.jogamp.opengl.awt;
44import java.awt.EventQueue;
45import java.awt.FontMetrics;
46import java.awt.Graphics;
47import java.awt.Graphics2D;
48import java.awt.GraphicsConfiguration;
49import java.awt.GraphicsEnvironment;
50import java.awt.Rectangle;
51import java.awt.event.HierarchyEvent;
52import java.awt.event.HierarchyListener;
53import java.awt.geom.NoninvertibleTransformException;
54import java.awt.geom.Rectangle2D;
55import java.awt.image.BufferedImage;
56import java.awt.image.DataBufferInt;
57import java.beans.Beans;
58import java.nio.IntBuffer;
61import com.jogamp.nativewindow.AbstractGraphicsDevice;
62import com.jogamp.nativewindow.NativeSurface;
63import com.jogamp.nativewindow.ScalableSurface;
64import com.jogamp.nativewindow.SurfaceUpdatedListener;
65import com.jogamp.nativewindow.WindowClosingProtocol;
66import com.jogamp.nativewindow.util.PixelFormat;
67import com.jogamp.opengl.GL;
68import com.jogamp.opengl.GL2;
69import com.jogamp.opengl.GL2ES3;
70import com.jogamp.opengl.GL2GL3;
71import com.jogamp.opengl.GLAnimatorControl;
72import com.jogamp.opengl.GLAutoDrawable;
73import com.jogamp.opengl.GLCapabilities;
74import com.jogamp.opengl.GLCapabilitiesChooser;
75import com.jogamp.opengl.GLCapabilitiesImmutable;
76import com.jogamp.opengl.GLContext;
77import com.jogamp.opengl.GLDrawable;
78import com.jogamp.opengl.GLDrawableFactory;
79import com.jogamp.opengl.GLEventListener;
80import com.jogamp.opengl.GLException;
81import com.jogamp.opengl.GLFBODrawable;
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;
87import javax.swing.JPanel;
89import jogamp.nativewindow.SurfaceScaleUtils;
90import jogamp.nativewindow.WrappedSurface;
91import jogamp.nativewindow.jawt.JAWTUtil;
92import jogamp.opengl.Debug;
93import jogamp.opengl.GLContextImpl;
94import jogamp.opengl.GLDrawableFactoryImpl;
95import jogamp.opengl.GLDrawableHelper;
96import jogamp.opengl.GLDrawableImpl;
97import jogamp.opengl.awt.AWTTilePainter;
98import jogamp.opengl.awt.Java2D;
99import jogamp.opengl.util.glsl.GLSLTextureRaster;
101import com.jogamp.common.util.InterruptSource;
102import com.jogamp.common.util.PropertyAccess;
103import com.jogamp.common.util.awt.AWTEDTExecutor;
104import com.jogamp.common.util.locks.LockFactory;
105import com.jogamp.common.util.locks.RecursiveLock;
106import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
107import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
108import com.jogamp.opengl.FBObject;
109import com.jogamp.opengl.GLRendererQuirks;
110import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
111import com.jogamp.opengl.util.GLPixelBuffer.SingletonGLPixelBufferProvider;
112import com.jogamp.opengl.util.GLDrawableUtil;
113import com.jogamp.opengl.util.GLPixelStorageModes;
114import com.jogamp.opengl.util.TileRenderer;
115import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
116import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
117import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
118import com.jogamp.opengl.util.texture.TextureState;
188@SuppressWarnings(
"serial")
190 private static final boolean DEBUG;
191 private static final boolean DEBUG_FRAMES;
192 private static final boolean DEBUG_VIEWPORT;
193 private static final boolean USE_GLSL_VERTICAL_FLIP;
194 private static final boolean SKIP_VERTICAL_FLIP_DEFAULT;
197 private static final boolean java2dOGLEnabledByProp;
200 private static final boolean useJava2DGLPipeline;
203 private static boolean java2DGLPipelineOK;
206 Debug.initSingleton();
207 DEBUG = Debug.debug(
"GLJPanel");
208 DEBUG_FRAMES = PropertyAccess.isPropertyDefined(
"jogl.debug.GLJPanel.Frames",
true);
209 DEBUG_VIEWPORT = PropertyAccess.isPropertyDefined(
"jogl.debug.GLJPanel.Viewport",
true);
210 USE_GLSL_VERTICAL_FLIP = !PropertyAccess.isPropertyDefined(
"jogl.gljpanel.noglsl",
true);
211 SKIP_VERTICAL_FLIP_DEFAULT = PropertyAccess.isPropertyDefined(
"jogl.gljpanel.noverticalflip",
true);
212 boolean enabled = PropertyAccess.getBooleanProperty(
"sun.java2d.opengl",
false);
213 java2dOGLEnabledByProp = enabled && !PropertyAccess.isPropertyDefined(
"jogl.gljpanel.noogl",
true);
216 if( java2dOGLEnabledByProp ) {
220 if (Java2D.isOGLPipelineResourceCompatible() && Java2D.isFBOEnabled()) {
221 if(
null != Java2D.getShareContext(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()) ) {
226 useJava2DGLPipeline = enabled;
227 java2DGLPipelineOK = enabled;
229 System.err.println(
"GLJPanel: DEBUG_VIEWPORT "+DEBUG_VIEWPORT);
230 System.err.println(
"GLJPanel: USE_GLSL_VERTICAL_FLIP "+USE_GLSL_VERTICAL_FLIP);
231 System.err.println(
"GLJPanel: SKIP_VERTICAL_FLIP_DEFAULT "+SKIP_VERTICAL_FLIP_DEFAULT);
232 System.err.println(
"GLJPanel: java2dOGLEnabledByProp "+java2dOGLEnabledByProp);
233 System.err.println(
"GLJPanel: useJava2DGLPipeline "+useJava2DGLPipeline);
234 System.err.println(
"GLJPanel: java2DGLPipelineOK "+java2DGLPipelineOK);
240 if(
null == singleAWTGLPixelBufferProvider ) {
243 return singleAWTGLPixelBufferProvider;
246 private final RecursiveLock lock = LockFactory.createRecursiveLock();
248 private final GLDrawableHelper helper;
249 private boolean autoSwapBufferMode;
251 private volatile boolean isInitialized;
259 private volatile GLDrawableFactoryImpl factory;
261 private int additionalCtxCreationFlags = 0;
264 private boolean handleReshape =
false;
265 private boolean sendReshape =
true;
270 private int reshapeWidth = 0;
272 private int reshapeHeight = 0;
275 private int panelWidth = 0;
277 private int panelHeight = 0;
281 private int viewportX = 0;
282 private int viewportY = 0;
284 private int requestedTextureUnit = 0;
287 private volatile Backend backend;
288 private boolean useGLSLVertFlip = USE_GLSL_VERTICAL_FLIP;
289 private boolean skipGLOrientationVerticalFlip = SKIP_VERTICAL_FLIP_DEFAULT;
292 private final Updater updater =
new Updater();
294 private boolean oglPipelineUsable() {
295 return null == customPixelBufferProvider && useJava2DGLPipeline && java2DGLPipelineOK;
298 private volatile boolean isShowing =
false;
299 private final HierarchyListener hierarchyListener =
new HierarchyListener() {
301 public void hierarchyChanged(
final HierarchyEvent e) {
302 isShowing =
GLJPanel.this.isShowing();
335 this(userCapsRequest,
null);
358 if (userCapsRequest !=
null) {
364 reqOffscreenCaps = caps;
366 this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.
getGLProfile() );
367 this.chooser = chooser;
369 helper =
new GLDrawableHelper();
370 autoSwapBufferMode = helper.getAutoSwapBufferMode();
372 this.setFocusable(
true);
373 this.addHierarchyListener(hierarchyListener);
374 this.isShowing = isShowing();
377 handleReshape =
false;
407 new InterruptSource.Thread(
null,
null, getThreadName()+
"-GLJPanel_Init") {
410 if( !isInitialized ) {
411 initializeBackendImpl();
416 if( !isInitialized ) {
417 return initializeBackendImpl();
426 helper.setSharedContext(this.getContext(), sharedContext);
431 helper.setSharedAutoDrawable(
this, sharedAutoDrawable);
442 if(
null == custom ) {
443 throw new IllegalArgumentException(
"Null PixelBufferProvider");
445 if(
null != backend ) {
446 throw new IllegalStateException(
"Backend already realized.");
448 customPixelBufferProvider = custom;
464 if( isShowing || ( printActive && isVisible() ) ) {
465 if (EventQueue.isDispatchThread()) {
467 paintImmediatelyAction.run();
472 EventQueue.invokeAndWait(paintImmediatelyAction);
473 }
catch (
final Exception e) {
482 System.err.println(getThreadName()+
": GLJPanel.dispose() - start");
486 if (backend !=
null && backend.getContext() !=
null) {
487 final boolean animatorPaused;
490 animatorPaused = animator.
pause();
492 animatorPaused =
false;
495 if(backend.getContext().isCreated()) {
498 if(
null != backend) {
501 isInitialized =
false;
507 if( animatorPaused ) {
513 handleReshape =
false;
523 System.err.println(getThreadName()+
": GLJPanel.dispose() - stop");
543 if (Beans.isDesignTime()) {
545 g.setColor(Color.BLACK);
546 g.fillRect(0, 0, getWidth(), getHeight());
547 final FontMetrics fm = g.getFontMetrics();
548 String name = getName();
550 name = getClass().getName();
551 final int idx = name.lastIndexOf(
'.');
553 name = name.substring(idx + 1);
556 final Rectangle2D bounds = fm.getStringBounds(name, g);
557 g.setColor(Color.WHITE);
559 (
int) ((getWidth() - bounds.getWidth()) / 2),
560 (
int) ((getHeight() + bounds.getHeight()) / 2));
564 final RecursiveLock _lock = lock;
567 if( !isInitialized ) {
568 initializeBackendImpl();
571 if (!isInitialized || printActive) {
580 updatePixelScale(backend);
581 if ( handleReshape ) {
582 handleReshape =
false;
583 sendReshape = handleReshape();
587 updater.setGraphics(g);
588 backend.doPaintComponent(g);
596 private final void updateWrappedSurfaceScale(
final GLDrawable d) {
598 if( s instanceof WrappedSurface ) {
599 ((WrappedSurface)s).setSurfaceScale(hasPixelScale);
623 private final boolean updatePixelScale(
final Backend b) {
624 final float[] min = { 1, 1 };
625 final float[] max = { hasPixelScale[0], hasPixelScale[1] };
626 if( JAWTUtil.getPixelScale(getGraphicsConfiguration(), min, max) ) {
628 System.err.printf(
"GLJPanel.updatePixelScale %.2f %.2f -> %.2f %.2f\n", hasPixelScale[0], hasPixelScale[1], max[0], max[1]);
630 System.arraycopy(max, 0, hasPixelScale, 0, 2);
631 reshapeImpl(getWidth(), getHeight());
632 updateWrappedSurfaceScale(b.getDrawable());
654 System.arraycopy(hasPixelScale, 0, result, 0, 2);
679 System.arraycopy(hasPixelScale, 0, result, 0, 2);
692 System.err.println(getThreadName()+
": GLJPanel.addNotify() - 0");
699 final float[] min = { 1, 1 };
700 final float[] max = { hasPixelScale[0], hasPixelScale[1] };
701 if( JAWTUtil.getPixelScale(getGraphicsConfiguration(), min, max) ) {
703 System.err.printf(
"GLJPanel.addNotify: pixelScale %.2f %.2f -> %.2f %.2f\n", hasPixelScale[0], hasPixelScale[1], max[0], max[1]);
705 System.arraycopy(max, 0, hasPixelScale, 0, 2);
708 reshapeImpl(getWidth(), getHeight());
711 System.err.println(getThreadName()+
": GLJPanel.addNotify() - X");
729 super.removeNotify();
739 @SuppressWarnings(
"deprecation")
741 public void reshape(
final int x,
final int y,
final int width,
final int height) {
742 super.reshape(x, y, width, height);
743 reshapeImpl(width, height);
746 private void reshapeImpl(
final int width,
final int height) {
747 final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]);
748 final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]);
749 if( !printActive && ( handleReshape || scaledWidth != panelWidth || scaledHeight != panelHeight ) ) {
750 reshapeWidth = scaledWidth;
751 reshapeHeight = scaledHeight;
752 handleReshape =
true;
755 System.err.println(getThreadName()+
": GLJPanel.reshape.0 "+this.getName()+
" resize ["+(printActive?
"printing":
"paint")+
756 "] [ this "+getWidth()+
"x"+getHeight()+
", pixelScale "+getPixelScaleStr()+
757 ", panel "+panelWidth+
"x"+panelHeight +
758 "] -> "+(handleReshape?
"":
"[skipped] ") + width+
"x"+height+
" * "+getPixelScaleStr()+
759 " -> "+scaledWidth+
"x"+scaledHeight+
", reshapeSize "+reshapeWidth+
"x"+reshapeHeight);
763 private volatile boolean printActive =
false;
764 private GLAnimatorControl printAnimator =
null;
765 private GLAutoDrawable printGLAD =
null;
766 private AWTTilePainter printAWTTiles =
null;
769 public void setupPrint(
final double scaleMatX,
final double scaleMatY,
final int numSamples,
final int tileWidth,
final int tileHeight) {
772 System.err.printf(getThreadName()+
": GLJPanel.setupPrint: scale %f / %f, samples %d, tileSz %d x %d%n", scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight);
774 final int componentCount = isOpaque() ? 3 : 4;
776 printAWTTiles =
new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
777 AWTEDTExecutor.singleton.invoke(getTreeLock(),
true ,
true , setupPrintOnEDT);
779 private final Runnable setupPrintOnEDT =
new Runnable() {
782 final RecursiveLock _lock = lock;
785 if( !isInitialized ) {
786 initializeBackendImpl();
788 if (!isInitialized) {
790 System.err.println(getThreadName()+
": Info: GLJPanel setupPrint - skipped GL render, drawable not valid yet");
797 System.err.println(getThreadName()+
": Info: GLJPanel setupPrint - skipped GL render, panel not visible");
803 handleReshape =
false;
804 printAnimator = helper.getAnimator();
805 if(
null != printAnimator ) {
806 printAnimator.remove(GLJPanel.this);
809 printGLAD = GLJPanel.this;
810 final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
811 final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
812 GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
813 final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
814 final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
815 printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
817 final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
818 newGLADCaps.setDoubleBuffered(
false);
819 newGLADCaps.setOnscreen(
false);
820 if( printNumSamples != newGLADCaps.getNumSamples() ) {
821 newGLADCaps.setSampleBuffers(0 < printNumSamples);
822 newGLADCaps.setNumSamples(printNumSamples);
824 final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
826 final boolean reqNewGLAD = ( reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
829 System.err.println(
"AWT print.setup: reqNewGLAD "+reqNewGLAD+
"[ samples "+reqNewGLADSamples+
", size "+reqNewGLADSize+
", safe "+reqNewGLADSafe+
"], "+
830 ", drawableSize "+printDrawable.getSurfaceWidth()+
"x"+printDrawable.getSurfaceHeight()+
831 ", customTileSize "+printAWTTiles.customTileWidth+
"x"+printAWTTiles.customTileHeight+
832 ", scaleMat "+printAWTTiles.scaleMatX+
" x "+printAWTTiles.scaleMatY+
833 ", numSamples "+printAWTTiles.customNumSamples+
" -> "+printNumSamples+
", printAnimator "+printAnimator);
836 final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
837 GLOffscreenAutoDrawable offGLAD =
null;
839 offGLAD = factory.createOffscreenAutoDrawable(
null, newGLADCaps,
null,
840 printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
841 printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
842 }
catch (
final GLException gle) {
844 System.err.println(
"Caught: "+gle.getMessage());
845 gle.printStackTrace();
848 if(
null != offGLAD ) {
850 GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
851 printDrawable = printGLAD.getDelegatedDrawable();
854 printAWTTiles.setGLOrientation( !GLJPanel.this.skipGLOrientationVerticalFlip && printGLAD.isGLOriented(), printGLAD.isGLOriented() );
855 printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
856 printAWTTiles.renderer.attachAutoDrawable(printGLAD);
858 System.err.println(
"AWT print.setup "+printAWTTiles);
859 System.err.println(
"AWT print.setup AA "+printNumSamples+
", "+newGLADCaps);
860 System.err.println(
"AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+
"x"+printGLAD.getSurfaceHeight()+
", "+printGLAD);
861 System.err.println(
"AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+
"x"+printDrawable.getSurfaceHeight()+
", "+printDrawable);
872 throw new IllegalStateException(
"setupPrint() not called");
875 handleReshape =
false;
876 AWTEDTExecutor.singleton.invoke(getTreeLock(),
true ,
true , releasePrintOnEDT);
879 private final Runnable releasePrintOnEDT =
new Runnable() {
882 final RecursiveLock _lock = lock;
886 System.err.println(getThreadName()+
": GLJPanel.releasePrintOnEDT.0 "+printAWTTiles);
888 printAWTTiles.dispose();
890 if( printGLAD != GLJPanel.this ) {
895 if(
null != printAnimator ) {
896 printAnimator.add(GLJPanel.this);
897 printAnimator =
null;
901 final int awtWidth = GLJPanel.this.getWidth();
902 final int awtHeight= GLJPanel.this.getHeight();
903 final int scaledAWTWidth = SurfaceScaleUtils.scale(awtWidth, hasPixelScale[0]);
904 final int scaledAWTHeight= SurfaceScaleUtils.scale(awtHeight, hasPixelScale[1]);
905 final GLDrawable drawable = GLJPanel.this.getDelegatedDrawable();
906 if( scaledAWTWidth != panelWidth || scaledAWTHeight != panelHeight ||
907 drawable.getSurfaceWidth() != panelWidth || drawable.getSurfaceHeight() != panelHeight ) {
910 System.err.println(getThreadName()+
": GLJPanel.releasePrintOnEDT.0: resize [printing] panel " +panelWidth+
"x"+panelHeight +
" @ scale "+getPixelScaleStr()+
911 ", draw "+drawable.getSurfaceWidth()+
"x"+drawable.getSurfaceHeight()+
912 " -> " + awtWidth+
"x"+awtHeight+
" * "+getPixelScaleStr()+
" -> "+scaledAWTWidth+
"x"+scaledAWTHeight);
914 reshapeWidth = scaledAWTWidth;
915 reshapeHeight = scaledAWTHeight;
916 sendReshape = handleReshape();
929 public void print(
final Graphics graphics) {
931 throw new IllegalStateException(
"setupPrint() not called");
933 if(DEBUG && !EventQueue.isDispatchThread()) {
934 System.err.println(getThreadName()+
": Warning: GLCanvas print - not called from AWT-EDT");
938 handleReshape =
false;
940 final Graphics2D g2d = (Graphics2D)graphics;
942 printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
943 final TileRenderer tileRenderer = printAWTTiles.renderer;
945 System.err.println(
"AWT print.0: "+tileRenderer);
947 if( !tileRenderer.
eot() ) {
953 backend.doPlainPaint();
955 }
while ( !tileRenderer.
eot() );
957 System.err.println(
"AWT print.1: "+printAWTTiles);
960 tileRenderer.
reset();
961 printAWTTiles.resetGraphics2D();
964 }
catch (
final NoninvertibleTransformException nte) {
965 System.err.println(
"Caught: Inversion failed of: "+g2d.getTransform());
966 nte.printStackTrace();
969 System.err.println(
"AWT print.X: "+printAWTTiles);
975 System.err.println(
"AWT printComponent.X: "+printAWTTiles);
982 if (backend !=
null) {
983 backend.setOpaque(opaque);
985 super.setOpaque(opaque);
990 helper.addGLEventListener(listener);
995 helper.addGLEventListener(index, listener);
1000 return helper.getGLEventListenerCount();
1005 return helper.getGLEventListener(index);
1010 return helper.areAllGLEventListenerInitialized();
1015 return helper.getGLEventListenerInitState(listener);
1020 helper.setGLEventListenerInitState(listener, initialized);
1025 final DisposeGLEventListenerAction r =
new DisposeGLEventListenerAction(listener,
remove);
1026 if (EventQueue.isDispatchThread()) {
1032 EventQueue.invokeAndWait(r);
1033 }
catch (
final Exception e) {
1042 return helper.removeGLEventListener(listener);
1047 helper.setAnimator(animatorControl);
1052 return helper.getAnimator();
1057 return helper.setExclusiveContextThread(t, getContext());
1062 return helper.getExclusiveContextThread();
1066 public boolean invoke(
final boolean wait,
final GLRunnable glRunnable)
throws IllegalStateException {
1067 return helper.invoke(
this, wait, glRunnable);
1071 public boolean invoke(
final boolean wait,
final List<GLRunnable> glRunnables)
throws IllegalStateException {
1072 return helper.invoke(
this, wait, glRunnables);
1077 helper.flushGLRunnables();
1082 final RecursiveLock _lock = lock;
1085 final Backend b = backend;
1089 return b.createContext(shareWith);
1101 return isInitialized;
1106 final RecursiveLock _lock = lock;
1109 final Backend b = backend;
1113 final GLContext oldCtx = b.getContext();
1114 GLDrawableHelper.switchContext(b.getDrawable(), oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
1115 b.setContext(newCtx);
1125 final Backend b = backend;
1129 return b.getDrawable();
1134 final Backend b = backend;
1138 return b.getContext();
1143 if (Beans.isDesignTime()) {
1147 return (context ==
null) ? null : context.
getGL();
1153 if (context !=
null) {
1162 this.autoSwapBufferMode = enable;
1163 boolean backendHandlesSwapBuffer =
false;
1164 if( isInitialized ) {
1165 final Backend b = backend;
1167 backendHandlesSwapBuffer= b.handlesSwapBuffer();
1170 if( !backendHandlesSwapBuffer ) {
1171 helper.setAutoSwapBufferMode(enable);
1177 return autoSwapBufferMode;
1182 if( isInitialized ) {
1183 final Backend b = backend;
1192 additionalCtxCreationFlags = flags;
1197 return additionalCtxCreationFlags;
1213 return oglPipelineUsable();
1237 final Backend b = backend;
1241 return b.getDrawable().isGLOriented();
1276 final Backend b = backend;
1280 return b.getChosenGLCapabilities();
1285 return reqOffscreenCaps;
1301 if(
null == caps ) {
1302 throw new IllegalArgumentException(
"null caps");
1308 dispose(
new Runnable() {
1313 reqOffscreenCaps = caps;
1314 initializeBackendImpl();
1327 final Backend b = backend;
1331 return b.getDrawable().getNativeSurface();
1336 final Backend b = backend;
1340 return b.getDrawable().getNativeSurface().getSurfaceHandle();
1358 final Backend b = backend;
1362 return b.getTextureUnit();
1379 requestedTextureUnit = v;
1386 private final Object initSync =
new Object();
1387 private boolean initializeBackendImpl() {
1388 synchronized(initSync) {
1389 if( !isInitialized ) {
1390 if( handleReshape ) {
1392 System.err.println(getThreadName()+
": GLJPanel.initializeBackendImpl.1: ["+(printActive?
"printing":
"paint")+
"] "+
1393 panelWidth+
"x"+panelHeight+
" @ scale "+getPixelScaleStr() +
" -> " +
1394 reshapeWidth+
"x"+reshapeHeight+
" @ scale "+getPixelScaleStr());
1396 panelWidth = reshapeWidth;
1397 panelHeight = reshapeHeight;
1398 handleReshape =
false;
1401 System.err.println(getThreadName()+
": GLJPanel.initializeBackendImpl.0: ["+(printActive?
"printing":
"paint")+
"] "+
1402 panelWidth+
"x"+panelHeight+
" @ scale "+getPixelScaleStr());
1406 if ( 0 >= panelWidth || 0 >= panelHeight ) {
1410 if (
null == backend ) {
1411 if ( oglPipelineUsable() ) {
1412 backend =
new J2DOGLBackend();
1414 backend =
new OffscreenBackend(customPixelBufferProvider);
1416 isInitialized =
false;
1419 if (!isInitialized) {
1420 this.factory = GLDrawableFactoryImpl.getFactoryImpl( reqOffscreenCaps.
getGLProfile() );
1421 backend.initialize();
1423 return isInitialized;
1430 private final String getPixelScaleStr() {
return "["+hasPixelScale[0]+
", "+hasPixelScale[1]+
"]"; }
1442 private boolean handleReshape() {
1444 System.err.println(getThreadName()+
": GLJPanel.handleReshape: "+
1445 panelWidth+
"x"+panelHeight+
" @ scale "+getPixelScaleStr() +
" -> " +
1446 reshapeWidth+
"x"+reshapeHeight+
" @ scale "+getPixelScaleStr());
1448 panelWidth = reshapeWidth;
1449 panelHeight = reshapeHeight;
1451 return backend.handleReshape();
1456 class Updater
implements GLEventListener {
1459 public void setGraphics(
final Graphics g) {
1464 public void init(
final GLAutoDrawable drawable) {
1465 if (!backend.preGL(g)) {
1468 helper.init(GLJPanel.this, !sendReshape);
1469 backend.postGL(g,
false);
1473 public void dispose(
final GLAutoDrawable drawable) {
1474 helper.disposeAllGLEventListener(GLJPanel.this,
false);
1478 public void display(
final GLAutoDrawable drawable) {
1479 if (!backend.preGL(g)) {
1484 System.err.println(getThreadName()+
": GLJPanel.display: reshape(" + viewportX +
"," + viewportY +
" " + panelWidth +
"x" + panelHeight +
" @ scale "+getPixelScaleStr()+
")");
1486 helper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight);
1487 sendReshape =
false;
1490 helper.display(GLJPanel.this);
1491 backend.postGL(g,
true);
1494 public void plainPaint(
final GLAutoDrawable drawable) {
1495 helper.display(GLJPanel.this);
1499 public void reshape(
final GLAutoDrawable drawable,
final int x,
final int y,
final int width,
final int height) {
1506 final GLDrawable d = (
null != backend ) ? backend.getDrawable() :
null;
1507 return "AWT-GLJPanel[ drawableType "+ ( (
null != d ) ? d.getClass().getName() :
"null" ) +
1508 ", chosenCaps " + getChosenGLCapabilities() +
1512 private final Runnable disposeAction =
new Runnable() {
1515 final RecursiveLock _lock = lock;
1518 if (
null != backend ) {
1519 final GLContext _context = backend.getContext();
1520 final boolean backendDestroy = !backend.isUsingOwnLifecycle();
1523 if(
null != _context && _context.
isCreated() ) {
1525 helper.disposeGL(
GLJPanel.this, _context, !backendDestroy);
1527 exceptionOnDisposeGL = gle;
1530 Throwable exceptionBackendDestroy =
null;
1531 if ( backendDestroy ) {
1534 }
catch(
final Throwable re ) {
1535 exceptionBackendDestroy = re;
1538 isInitialized =
false;
1542 if(
null != exceptionOnDisposeGL ) {
1543 throw exceptionOnDisposeGL;
1545 if(
null != exceptionBackendDestroy ) {
1555 private final Runnable updaterInitAction =
new Runnable() {
1558 updater.init(GLJPanel.this);
1562 private final Runnable updaterDisplayAction =
new Runnable() {
1565 updater.display(GLJPanel.this);
1569 private final Runnable updaterPlainDisplayAction =
new Runnable() {
1572 updater.plainPaint(GLJPanel.this);
1576 private final Runnable paintImmediatelyAction =
new Runnable() {
1579 paintImmediately(0, 0, getWidth(), getHeight());
1583 private class DisposeGLEventListenerAction
implements Runnable {
1584 GLEventListener listener;
1585 private final boolean remove;
1586 private DisposeGLEventListenerAction(
final GLEventListener listener,
final boolean remove) {
1587 this.listener = listener;
1588 this.remove =
remove;
1593 final Backend b = backend;
1595 listener = helper.disposeGLEventListener(GLJPanel.this, b.getDrawable(), b.getContext(), listener,
remove);
1600 private int getGLInteger(
final GL gl,
final int which) {
1601 final int[] tmp =
new int[1];
1602 gl.glGetIntegerv(which, tmp, 0);
1606 protected static String
getThreadName() {
return Thread.currentThread().getName(); }
1617 static interface Backend {
1619 public boolean isUsingOwnLifecycle();
1622 public void initialize();
1625 public void destroy();
1628 public void setOpaque(
boolean opaque);
1646 public int getTextureUnit();
1659 public boolean handleReshape();
1665 public boolean preGL(Graphics g);
1673 public boolean handlesSwapBuffer();
1678 public void swapBuffers();
1685 public void postGL(Graphics g,
boolean isDisplay);
1688 public void doPaintComponent(Graphics g);
1691 public void doPlainPaint();
1697 class OffscreenBackend
implements Backend {
1698 private final AWTGLPixelBufferProvider pixelBufferProvider;
1699 private final boolean useSingletonBuffer;
1700 private AWTGLPixelBuffer pixelBuffer;
1701 private BufferedImage alignedImage;
1705 protected IntBuffer readBackIntsForCPUVFlip;
1708 private volatile GLDrawable offscreenDrawable;
1709 private boolean offscreenIsFBO;
1711 private GLSLTextureRaster glslTextureRaster;
1713 private volatile GLContextImpl offscreenContext;
1714 private boolean flipVertical;
1715 private int frameCount = 0;
1718 private final GLPixelStorageModes psm =
new GLPixelStorageModes();
1720 OffscreenBackend(
final AWTGLPixelBufferProvider custom) {
1721 if(
null == custom) {
1722 pixelBufferProvider = getSingleAWTGLPixelBufferProvider();
1724 pixelBufferProvider = custom;
1726 if( pixelBufferProvider instanceof SingletonGLPixelBufferProvider ) {
1727 useSingletonBuffer =
true;
1729 useSingletonBuffer =
false;
1734 public final boolean isUsingOwnLifecycle() {
return false; }
1737 public final void initialize() {
1739 System.err.println(getThreadName()+
": OffscreenBackend: initialize() - frameCount "+frameCount);
1741 GLException glException =
null;
1743 final GLContext[] shareWith = {
null };
1744 if( helper.isSharedGLContextPending(shareWith) ) {
1747 offscreenDrawable = factory.createOffscreenDrawable(
1751 panelWidth, panelHeight);
1752 updateWrappedSurfaceScale(offscreenDrawable);
1754 if( DEBUG_FRAMES ) {
1757 public final void surfaceUpdated(
final Object updater,
final NativeSurface ns,
final long when) {
1758 System.err.println(getThreadName()+
": OffscreenBackend.swapBuffers - frameCount "+frameCount);
1765 flipVertical = !GLJPanel.this.skipGLOrientationVerticalFlip && offscreenDrawable.
isGLOriented();
1767 final boolean useGLSLFlip_pre = flipVertical && offscreenIsFBO && reqOffscreenCaps.
getGLProfile().
isGL2ES2() && useGLSLVertFlip;
1768 if( offscreenIsFBO && !useGLSLFlip_pre ) {
1770 ((GLFBODrawable)offscreenDrawable).setFBOMode(0);
1773 offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]);
1774 offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
1775 if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
1776 isInitialized =
true;
1777 helper.setAutoSwapBufferMode(
false);
1779 final GL gl = offscreenContext.getGL();
1785 final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
1786 final boolean glslCompliant = !offscreenContext.hasRendererQuirk(GLRendererQuirks.GLSLNonCompliant);
1787 final boolean useGLSLFlip = useGLSLFlip_pre && gl.isGL2ES2() && glslCompliant;
1789 System.err.println(getThreadName()+
": OffscreenBackend.initialize: useGLSLFlip "+useGLSLFlip+
1790 " [flip "+flipVertical+
", isFBO "+offscreenIsFBO+
", isGL2ES2 "+gl.isGL2ES2()+
1791 ", glslVertFlip "+useGLSLVertFlip+
"/"+USE_GLSL_VERTICAL_FLIP+
", glslNonCompliant "+!glslCompliant+
1792 ", isGL2ES2 " + gl.isGL2ES2()+
"\n "+offscreenDrawable+
"]");
1795 final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
1796 fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
1798 fboFlipped =
new FBObject();
1799 fboFlipped.
init(gl, panelWidth, panelHeight, 0);
1802 gl.glClear(GL.GL_COLOR_BUFFER_BIT);
1803 glslTextureRaster =
new GLSLTextureRaster(fboDrawable.getTextureUnit(),
true);
1804 glslTextureRaster.init(gl.getGL2ES2());
1805 glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
1806 }
catch (
final Exception ex) {
1807 ex.printStackTrace();
1808 if(
null != glslTextureRaster) {
1809 glslTextureRaster.dispose(gl.getGL2ES2());
1810 glslTextureRaster =
null;
1812 if(
null != fboFlipped) {
1819 glslTextureRaster =
null;
1821 offscreenContext.release();
1823 isInitialized =
false;
1825 }
catch(
final GLException gle ) {
1828 if( !isInitialized ) {
1829 if(
null != offscreenContext) {
1831 offscreenContext =
null;
1833 if(
null != offscreenDrawable) {
1834 offscreenDrawable.setRealized(
false);
1835 offscreenDrawable =
null;
1838 if(
null != glException ) {
1839 throw new GLException(
"Caught GLException: "+glException.getMessage(), glException);
1845 public final void destroy() {
1847 System.err.println(getThreadName()+
": OffscreenBackend: destroy() - offscreenContext: "+(
null!=offscreenContext)+
" - offscreenDrawable: "+(
null!=offscreenDrawable)+
" - frameCount "+frameCount);
1849 if (
null != offscreenContext && offscreenContext.isCreated() ) {
1850 if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
1852 final GL gl = offscreenContext.getGL();
1853 if(
null != glslTextureRaster) {
1854 glslTextureRaster.dispose(gl.getGL2ES2());
1856 if(
null != fboFlipped) {
1860 offscreenContext.destroy();
1864 offscreenContext =
null;
1865 glslTextureRaster =
null;
1867 offscreenContext =
null;
1869 if (offscreenDrawable !=
null) {
1870 final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
1871 offscreenDrawable.setRealized(
false);
1872 offscreenDrawable =
null;
1873 if(
null != adevice) {
1877 offscreenIsFBO =
false;
1879 if(
null != readBackIntsForCPUVFlip ) {
1880 readBackIntsForCPUVFlip.clear();
1881 readBackIntsForCPUVFlip =
null;
1883 if(
null != pixelBuffer ) {
1884 if( !useSingletonBuffer ) {
1885 pixelBuffer.dispose();
1889 alignedImage =
null;
1893 public final void setOpaque(
final boolean opaque) {
1894 if ( opaque != isOpaque() && !useSingletonBuffer ) {
1895 pixelBuffer.dispose();
1897 alignedImage =
null;
1902 public final boolean preGL(
final Graphics g) {
1908 public final boolean handlesSwapBuffer() {
1913 public final void swapBuffers() {
1914 final GLDrawable d = offscreenDrawable;
1921 public final void postGL(
final Graphics g,
final boolean isDisplay) {
1923 if( DEBUG_FRAMES ) {
1924 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: - frameCount "+frameCount);
1927 final GL gl = offscreenContext.getGL();
1933 final TextureState usrTexState, fboTexState;
1934 final int fboTexUnit;
1936 if( offscreenIsFBO ) {
1937 fboTexUnit = GL.GL_TEXTURE0 + ((GLFBODrawable)offscreenDrawable).getTextureUnit();
1938 usrTexState =
new TextureState(gl, GL.GL_TEXTURE_2D);
1939 if( fboTexUnit != usrTexState.getUnit() ) {
1943 gl.glActiveTexture(fboTexUnit);
1944 fboTexState =
new TextureState(gl, fboTexUnit, GL.GL_TEXTURE_2D);
1946 fboTexState = usrTexState;
1955 if( autoSwapBufferMode ) {
1958 offscreenDrawable.swapBuffers();
1961 final int componentCount;
1962 final int alignment;
1973 final PixelFormat awtPixelFormat = pixelBufferProvider.getAWTPixelFormat(gl.getGLProfile(), componentCount);
1974 final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount,
true);
1976 if( useSingletonBuffer ) {
1977 pixelBuffer = (AWTGLPixelBuffer) ((SingletonGLPixelBufferProvider)pixelBufferProvider).getSingleBuffer(awtPixelFormat.comp, pixelAttribs,
true);
1979 if(
null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, panelWidth, panelHeight, 0) ) {
1980 pixelBuffer.dispose();
1982 alignedImage =
null;
1984 final boolean DEBUG_INIT;
1985 if (
null == pixelBuffer ) {
1986 if (0 >= panelWidth || 0 >= panelHeight ) {
1989 pixelBuffer = pixelBufferProvider.allocate(gl, awtPixelFormat.comp, pixelAttribs,
true, panelWidth, panelHeight, 1, 0);
1991 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" pixelBufferProvider isSingletonBufferProvider "+useSingletonBuffer+
", 0x"+Integer.toHexString(pixelBufferProvider.hashCode())+
", "+pixelBufferProvider.getClass().getSimpleName());
1992 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" pixelBuffer 0x"+Integer.toHexString(pixelBuffer.hashCode())+
", "+pixelBuffer+
", alignment "+alignment);
1993 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" flippedVertical "+flipVertical+
", glslTextureRaster "+(
null!=glslTextureRaster)+
", isGL2ES3 "+gl.isGL2ES3());
1994 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" panelSize "+panelWidth+
"x"+panelHeight+
" @ scale "+getPixelScaleStr());
1995 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" pixelAttribs "+pixelAttribs);
1996 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" awtPixelFormat "+awtPixelFormat);
2004 if( offscreenDrawable.getSurfaceWidth() != panelWidth || offscreenDrawable.getSurfaceHeight() != panelHeight ) {
2005 throw new InternalError(
"OffscreenDrawable panelSize mismatch (reshape missed): panelSize "+panelWidth+
"x"+panelHeight+
" != drawable "+offscreenDrawable.getSurfaceWidth()+
"x"+offscreenDrawable.getSurfaceHeight()+
", on thread "+getThreadName());
2007 if(
null == alignedImage ||
2008 panelWidth != alignedImage.getWidth() || panelHeight != alignedImage.getHeight() ||
2009 !pixelBuffer.isDataBufferSource(alignedImage) ) {
2010 alignedImage = pixelBuffer.getAlignedImage(panelWidth, panelHeight);
2012 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+
" new alignedImage "+alignedImage.getWidth()+
"x"+alignedImage.getHeight()+
" @ scale "+getPixelScaleStr()+
", "+alignedImage+
", pixelBuffer "+pixelBuffer.width+
"x"+pixelBuffer.height+
", "+pixelBuffer);
2015 final IntBuffer readBackInts;
2017 if( !flipVertical ||
null != glslTextureRaster ) {
2018 readBackInts = (IntBuffer) pixelBuffer.buffer;
2020 if(
null == readBackIntsForCPUVFlip || pixelBuffer.width * pixelBuffer.height > readBackIntsForCPUVFlip.remaining() ) {
2021 readBackIntsForCPUVFlip = IntBuffer.allocate(pixelBuffer.width * pixelBuffer.height);
2023 readBackInts = readBackIntsForCPUVFlip;
2027 if( DEBUG_FRAMES ) {
2028 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.readPixels: - frameCount "+frameCount);
2032 psm.setPackAlignment(gl, alignment);
2033 if( gl.isGL2ES3() ) {
2034 final GL2ES3 gl2es3 = gl.getGL2ES3();
2035 psm.setPackRowLength(gl2es3, panelWidth);
2036 gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
2038 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.0: fboDrawable "+offscreenDrawable);
2039 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.0: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl2es3.getDefaultReadBuffer()));
2040 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.0: def-readBuffer 0x"+Integer.toHexString(gl2es3.getDefaultReadBuffer()));
2041 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.0: def-readFBO 0x"+Integer.toHexString(gl2es3.getDefaultReadFramebuffer()));
2042 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.0: bound-readFBO 0x"+Integer.toHexString(gl2es3.getBoundFramebuffer(GL.GL_READ_FRAMEBUFFER)));
2046 if(
null != glslTextureRaster) {
2047 final boolean viewportChange;
2048 final int[] usrViewport =
new int[] { 0, 0, 0, 0 };
2049 gl.glGetIntegerv(GL.GL_VIEWPORT, usrViewport, 0);
2050 viewportChange = 0 != usrViewport[0] || 0 != usrViewport[1] ||
2051 panelWidth != usrViewport[2] || panelHeight != usrViewport[3];
2052 if( DEBUG_VIEWPORT ) {
2053 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL: "+GLJPanel.this.getName()+
" Viewport: change "+viewportChange+
2054 ", "+usrViewport[0]+
"/"+usrViewport[1]+
" "+usrViewport[2]+
"x"+usrViewport[3]+
2055 " -> 0/0 "+panelWidth+
"x"+panelHeight);
2057 if( viewportChange ) {
2058 gl.glViewport(0, 0, panelWidth, panelHeight);
2062 final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
2063 final FBObject.TextureAttachment fboTex = fboDrawable.getColorbuffer(GL.GL_FRONT).getTextureAttachment();
2065 fboFlipped.
bind(gl);
2068 gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
2071 glslTextureRaster.display(gl.getGL2ES2());
2073 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: fboDrawable "+fboDrawable);
2074 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: read from fbo-rb "+fboFlipped.
getReadFramebuffer()+
", fbo "+fboFlipped);
2075 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
2076 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: def-readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
2077 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: def-readFBO 0x"+Integer.toHexString(gl.getDefaultReadFramebuffer()));
2078 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: bound-readFBO 0x"+Integer.toHexString(gl.getBoundFramebuffer(GL.GL_READ_FRAMEBUFFER)));
2079 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.1: "+GLJPanel.this.getName()+
" pixelAttribs "+pixelAttribs);
2081 gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
2085 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.2: fboDrawable "+fboDrawable);
2086 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.2: read from fbo-rb "+fboFlipped.
getReadFramebuffer()+
", fbo "+fboFlipped);
2087 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.2: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
2088 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.2: def-readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
2089 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.2: def-readFBO 0x"+Integer.toHexString(gl.getDefaultReadFramebuffer()));
2090 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.postGL.0.2: bound-readFBO 0x"+Integer.toHexString(gl.getBoundFramebuffer(GL.GL_READ_FRAMEBUFFER)));
2092 if( viewportChange ) {
2093 gl.glViewport(usrViewport[0], usrViewport[1], usrViewport[2], usrViewport[3]);
2096 gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
2098 if ( flipVertical ) {
2103 final BufferedImage image = alignedImage;
2104 final int[] src = readBackInts.array();
2105 final int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
2106 final int incr = panelWidth;
2108 int destPos = (panelHeight - 1) * panelWidth;
2109 for (; destPos >= 0; srcPos += incr, destPos -= incr) {
2110 System.arraycopy(src, srcPos, dest, destPos, incr);
2114 if( 0 != fboTexUnit ) {
2115 fboTexState.restore(gl);
2116 if( fboTexUnit != usrTexState.getUnit() ) {
2117 usrTexState.restore(gl);
2130 public final int getTextureUnit() {
2131 if(
null != glslTextureRaster &&
null != offscreenDrawable) {
2132 return ((GLFBODrawable)offscreenDrawable).getTextureUnit();
2138 public final void doPaintComponent(
final Graphics g) {
2139 helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
2141 if (
null != alignedImage ) {
2142 if( DEBUG_FRAMES ) {
2143 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount);
2146 g.drawImage(alignedImage, 0, 0,
2147 SurfaceScaleUtils.scaleInv(alignedImage.getWidth(), hasPixelScale[0]),
2148 SurfaceScaleUtils.scaleInv(alignedImage.getHeight(), hasPixelScale[1]),
null);
2154 public final void doPlainPaint() {
2155 helper.invokeGL(offscreenDrawable, offscreenContext, updaterPlainDisplayAction, updaterInitAction);
2159 public final boolean handleReshape() {
2160 GLDrawableImpl _drawable = (GLDrawableImpl)offscreenDrawable;
2162 final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight);
2163 if(_drawable != _drawableNew) {
2165 _drawable = _drawableNew;
2166 offscreenDrawable = _drawableNew;
2167 updateWrappedSurfaceScale(offscreenDrawable);
2171 System.err.println(getThreadName()+
": GLJPanel.OffscreenBackend.handleReshape: " +panelWidth+
"x"+panelHeight +
" @ scale "+getPixelScaleStr() +
" -> " + _drawable.getSurfaceWidth()+
"x"+_drawable.getSurfaceHeight());
2173 panelWidth = _drawable.getSurfaceWidth();
2174 panelHeight = _drawable.getSurfaceHeight();
2176 if(
null != glslTextureRaster ) {
2177 if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
2179 final GL gl = offscreenContext.getGL();
2180 fboFlipped.
reset(gl, panelWidth, panelHeight, 0);
2181 glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, panelWidth, panelHeight);
2183 offscreenContext.release();
2187 return _drawable.isRealized();
2191 public final GLContext createContext(
final GLContext shareWith) {
2192 return (
null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) :
null;
2196 public final void setContext(
final GLContext ctx) {
2197 offscreenContext=(GLContextImpl)ctx;
2201 public final GLContext getContext() {
2202 return offscreenContext;
2206 public final GLDrawable getDrawable() {
2207 return offscreenDrawable;
2211 public final GLCapabilitiesImmutable getChosenGLCapabilities() {
2212 if (offscreenDrawable ==
null) {
2215 return offscreenDrawable.getChosenGLCapabilities();
2219 public final GLProfile getGLProfile() {
2220 if (offscreenDrawable ==
null) {
2223 return offscreenDrawable.getGLProfile();
2227 class J2DOGLBackend
implements Backend {
2231 private Object j2dSurface;
2235 private GLContext j2dContext;
2238 private GLDrawable joglDrawable;
2240 private GLContext joglContext;
2243 private final int[] drawBuffer =
new int[1];
2244 private final int[] readBuffer =
new int[1];
2247 private final int[] frameBuffer =
new int[1];
2253 private boolean checkedForFBObjectWorkarounds;
2254 private boolean fbObjectWorkarounds;
2255 private int[] frameBufferDepthBuffer;
2256 private int[] frameBufferTexture;
2257 private boolean createNewDepthBuffer;
2268 private boolean checkedGLVendor;
2269 private boolean vendorIsATI;
2274 private GraphicsConfiguration workaroundConfig;
2277 public final boolean isUsingOwnLifecycle() {
return true; }
2280 public final void initialize() {
2282 System.err.println(getThreadName()+
": J2DOGL: initialize()");
2285 isInitialized =
true;
2289 public final void destroy() {
2290 Java2D.invokeWithOGLContextCurrent(
null,
new Runnable() {
2294 System.err.println(getThreadName()+
": J2DOGL: destroy() - joglContext: "+(
null!=joglContext)+
" - joglDrawable: "+(
null!=joglDrawable));
2296 if (joglContext !=
null) {
2297 joglContext.destroy();
2300 joglDrawable =
null;
2301 if (j2dContext !=
null) {
2302 j2dContext.destroy();
2310 public final void setOpaque(
final boolean opaque) {
2315 public final GLContext createContext(
final GLContext shareWith) {
2316 if(
null != shareWith) {
2317 throw new GLException(
"J2DOGLBackend cannot create context w/ additional shared context, since it already needs to share the context w/ J2D.");
2319 return (
null != joglDrawable &&
null != j2dContext) ? joglDrawable.createContext(j2dContext) :
null;
2323 public final void setContext(
final GLContext ctx) {
2328 public final GLContext getContext() {
2333 public final GLDrawable getDrawable() {
2334 return joglDrawable;
2338 public final int getTextureUnit() {
return -1; }
2341 public final GLCapabilitiesImmutable getChosenGLCapabilities() {
2343 return new GLCapabilities(
null);
2347 public final GLProfile getGLProfile() {
2349 return GLProfile.getDefault(GLProfile.getDefaultDevice());
2353 public final boolean handleReshape() {
2359 public final boolean preGL(
final Graphics g) {
2360 final GL2 gl = joglContext.getGL().getGL2();
2362 gl.glEnable(GL.GL_SCISSOR_TEST);
2363 final Rectangle r = Java2D.getOGLScissorBox(g);
2367 System.err.println(getThreadName()+
": Java2D.getOGLScissorBox() returned null");
2372 System.err.println(getThreadName()+
": GLJPanel: gl.glScissor(" + r.x +
", " + r.y +
", " + r.width +
", " + r.height +
")");
2375 gl.glScissor(r.x, r.y, r.width, r.height);
2376 final Rectangle oglViewport = Java2D.getOGLViewport(g, panelWidth, panelHeight);
2380 if ((viewportX != oglViewport.x) ||
2381 (viewportY != oglViewport.y)) {
2384 System.err.println(getThreadName()+
": Sending reshape because viewport changed");
2385 System.err.println(
" viewportX (" + viewportX +
") ?= oglViewport.x (" + oglViewport.x +
")");
2386 System.err.println(
" viewportY (" + viewportY +
") ?= oglViewport.y (" + oglViewport.y +
")");
2389 viewportX = oglViewport.x;
2390 viewportY = oglViewport.y;
2396 if (Java2D.isFBOEnabled() &&
2397 Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
2401 final int fboTextureTarget = Java2D.getOGLTextureType(g);
2403 if (!checkedForFBObjectWorkarounds) {
2404 checkedForFBObjectWorkarounds =
true;
2405 gl.glBindTexture(fboTextureTarget, 0);
2406 gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBuffer[0]);
2407 final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
2408 if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
2410 fbObjectWorkarounds =
true;
2411 createNewDepthBuffer =
true;
2413 System.err.println(getThreadName()+
": GLJPanel: ERR GL_FRAMEBUFFER_BINDING: Discovered Invalid J2D FBO("+frameBuffer[0]+
"): "+FBObject.getStatusString(status) +
2414 ", frame_buffer_object workarounds to be necessary");
2418 frameBufferTexture =
null;
2420 System.err.println(getThreadName()+
": GLJPanel: OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
2425 if (fbObjectWorkarounds && createNewDepthBuffer) {
2426 if (frameBufferDepthBuffer ==
null)
2427 frameBufferDepthBuffer =
new int[1];
2431 if (frameBufferDepthBuffer[0] != 0) {
2432 gl.glDeleteRenderbuffers(1, frameBufferDepthBuffer, 0);
2433 frameBufferDepthBuffer[0] = 0;
2436 gl.glBindTexture(fboTextureTarget, frameBufferTexture[0]);
2437 final int[] width =
new int[1];
2438 final int[] height =
new int[1];
2439 gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2ES3.GL_TEXTURE_WIDTH, width, 0);
2440 gl.glGetTexLevelParameteriv(fboTextureTarget, 0, GL2ES3.GL_TEXTURE_HEIGHT, height, 0);
2442 gl.glGenRenderbuffers(1, frameBufferDepthBuffer, 0);
2444 System.err.println(getThreadName()+
": GLJPanel: Generated frameBufferDepthBuffer " + frameBufferDepthBuffer[0] +
2445 " with width " + width[0] +
", height " + height[0]);
2448 gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, frameBufferDepthBuffer[0]);
2450 gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, width[0], height[0]);
2452 gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0);
2453 createNewDepthBuffer =
false;
2456 gl.glBindTexture(fboTextureTarget, 0);
2457 gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBuffer[0]);
2459 if (fbObjectWorkarounds) {
2461 gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
2462 GL.GL_COLOR_ATTACHMENT0,
2464 frameBufferTexture[0],
2467 System.err.println(getThreadName()+
": GLJPanel: frameBufferDepthBuffer: " + frameBufferDepthBuffer[0]);
2469 gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
2470 GL.GL_DEPTH_ATTACHMENT,
2472 frameBufferDepthBuffer[0]);
2476 final int status = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
2477 if (status != GL.GL_FRAMEBUFFER_COMPLETE) {
2478 throw new GLException(
"Error: framebuffer was incomplete: status = 0x" +
2479 Integer.toHexString(status));
2484 System.err.println(getThreadName()+
": GLJPanel: Setting up drawBuffer " + drawBuffer[0] +
2485 " and readBuffer " + readBuffer[0]);
2488 gl.glDrawBuffer(drawBuffer[0]);
2489 gl.glReadBuffer(readBuffer[0]);
2496 public final boolean handlesSwapBuffer() {
2501 public final void swapBuffers() {
2502 final GLDrawable d = joglDrawable;
2509 public final void postGL(
final Graphics g,
final boolean isDisplay) {
2513 final GL gl = joglContext.getGL();
2516 if (Java2D.isFBOEnabled() &&
2517 Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
2521 gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
2526 public final void doPaintComponent(
final Graphics g) {
2544 if (Java2D.isFBOEnabled()) {
2545 if (workaroundConfig ==
null) {
2546 workaroundConfig = GraphicsEnvironment.
2547 getLocalGraphicsEnvironment().
2548 getDefaultScreenDevice().
2549 getDefaultConfiguration();
2551 Java2D.invokeWithOGLSharedContextCurrent(workaroundConfig,
new Runnable() { @Override
2552 public void run() {}});
2555 Java2D.invokeWithOGLContextCurrent(g,
new Runnable() {
2559 System.err.println(getThreadName()+
": GLJPanel.invokeWithOGLContextCurrent");
2563 if (j2dContext ==
null) {
2564 j2dContext = factory.createExternalGLContext();
2566 System.err.println(getThreadName()+
": GLJPanel.Created External Context: "+j2dContext);
2576 j2dContext.makeCurrent();
2577 final GL gl = j2dContext.getGL();
2578 if ((getGLInteger(gl, GL.GL_RED_BITS) < reqOffscreenCaps.
getRedBits()) ||
2579 (getGLInteger(gl, GL.GL_GREEN_BITS) < reqOffscreenCaps.
getGreenBits()) ||
2580 (getGLInteger(gl, GL.GL_BLUE_BITS) < reqOffscreenCaps.
getBlueBits()) ||
2582 (getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) < reqOffscreenCaps.
getAccumRedBits()) ||
2583 (getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) < reqOffscreenCaps.
getAccumGreenBits()) ||
2584 (getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) < reqOffscreenCaps.
getAccumBlueBits()) ||
2585 (getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) < reqOffscreenCaps.
getAccumAlphaBits()) ||
2587 (getGLInteger(gl, GL.GL_STENCIL_BITS) < reqOffscreenCaps.
getStencilBits())) {
2589 System.err.println(getThreadName()+
": GLJPanel: Falling back to pbuffer-based support because Java2D context insufficient");
2590 System.err.println(
" Available Required");
2591 System.err.println(
"GL_RED_BITS " + getGLInteger(gl, GL.GL_RED_BITS) +
" " + reqOffscreenCaps.
getRedBits());
2592 System.err.println(
"GL_GREEN_BITS " + getGLInteger(gl, GL.GL_GREEN_BITS) +
" " + reqOffscreenCaps.
getGreenBits());
2593 System.err.println(
"GL_BLUE_BITS " + getGLInteger(gl, GL.GL_BLUE_BITS) +
" " + reqOffscreenCaps.
getBlueBits());
2594 System.err.println(
"GL_ALPHA_BITS " + getGLInteger(gl, GL.GL_ALPHA_BITS) +
" " + reqOffscreenCaps.
getAlphaBits());
2595 System.err.println(
"GL_ACCUM_RED_BITS " + getGLInteger(gl, GL2.GL_ACCUM_RED_BITS) +
" " + reqOffscreenCaps.
getAccumRedBits());
2596 System.err.println(
"GL_ACCUM_GREEN_BITS " + getGLInteger(gl, GL2.GL_ACCUM_GREEN_BITS) +
" " + reqOffscreenCaps.
getAccumGreenBits());
2597 System.err.println(
"GL_ACCUM_BLUE_BITS " + getGLInteger(gl, GL2.GL_ACCUM_BLUE_BITS) +
" " + reqOffscreenCaps.
getAccumBlueBits());
2598 System.err.println(
"GL_ACCUM_ALPHA_BITS " + getGLInteger(gl, GL2.GL_ACCUM_ALPHA_BITS) +
" " + reqOffscreenCaps.
getAccumAlphaBits());
2599 System.err.println(
"GL_DEPTH_BITS " + getGLInteger(gl, GL.GL_DEPTH_BITS) +
" " + reqOffscreenCaps.
getDepthBits());
2600 System.err.println(
"GL_STENCIL_BITS " + getGLInteger(gl, GL.GL_STENCIL_BITS) +
" " + reqOffscreenCaps.
getStencilBits());
2602 isInitialized =
false;
2604 java2DGLPipelineOK =
false;
2605 handleReshape =
true;
2606 j2dContext.destroy();
2611 j2dContext.makeCurrent();
2614 captureJ2DState(j2dContext.getGL(), g);
2615 final Object curSurface = Java2D.getOGLSurfaceIdentifier(g);
2616 if (curSurface !=
null) {
2617 if (j2dSurface != curSurface) {
2618 if (joglContext !=
null) {
2619 joglContext.destroy();
2621 joglDrawable =
null;
2624 System.err.println(getThreadName()+
": Sending reshape because surface changed");
2625 System.err.println(
"New surface = " + curSurface);
2628 j2dSurface = curSurface;
2630 System.err.print(getThreadName()+
": Surface type: ");
2631 final int surfaceType = Java2D.getOGLSurfaceType(g);
2632 if (surfaceType == Java2D.UNDEFINED) {
2633 System.err.println(
"UNDEFINED");
2634 }
else if (surfaceType == Java2D.WINDOW) {
2635 System.err.println(
"WINDOW");
2636 }
else if (surfaceType == Java2D.PBUFFER) {
2637 System.err.println(
"PBUFFER");
2638 }
else if (surfaceType == Java2D.TEXTURE) {
2639 System.err.println(
"TEXTURE");
2640 }
else if (surfaceType == Java2D.FLIP_BACKBUFFER) {
2641 System.err.println(
"FLIP_BACKBUFFER");
2642 }
else if (surfaceType == Java2D.FBOBJECT) {
2643 System.err.println(
"FBOBJECT");
2645 System.err.println(
"(Unknown surface type " + surfaceType +
")");
2649 if (joglContext ==
null) {
2650 final AbstractGraphicsDevice device = j2dContext.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
2651 if (factory.canCreateExternalGLDrawable(device)) {
2652 joglDrawable = factory.createExternalGLDrawable();
2653 joglContext = joglDrawable.createContext(j2dContext);
2655 System.err.println(
"-- Created External Drawable: "+joglDrawable);
2656 System.err.println(
"-- Created Context: "+joglContext);
2659 if (Java2D.isFBOEnabled() &&
2660 Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT &&
2661 fbObjectWorkarounds) {
2662 createNewDepthBuffer =
true;
2665 helper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction);
2668 j2dContext.release();
2675 public final void doPlainPaint() {
2676 helper.invokeGL(joglDrawable, joglContext, updaterPlainDisplayAction, updaterInitAction);
2679 private final void captureJ2DState(
final GL gl,
final Graphics g) {
2680 gl.glGetIntegerv(GL2GL3.GL_DRAW_BUFFER, drawBuffer, 0);
2681 gl.glGetIntegerv(GL2ES3.GL_READ_BUFFER, readBuffer, 0);
2682 if (Java2D.isFBOEnabled() &&
2683 Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT) {
2684 gl.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, frameBuffer, 0);
2685 if(!gl.glIsFramebuffer(frameBuffer[0])) {
2686 checkedForFBObjectWorkarounds=
true;
2687 fbObjectWorkarounds =
true;
2688 createNewDepthBuffer =
true;
2690 System.err.println(getThreadName()+
": GLJPanel: Fetched ERR GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]+
" - NOT A FBO"+
2691 ", frame_buffer_object workarounds to be necessary");
2694 System.err.println(getThreadName()+
": GLJPanel: Fetched OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]);
2697 if(fbObjectWorkarounds || !checkedForFBObjectWorkarounds) {
2699 if (frameBufferTexture ==
null)
2700 frameBufferTexture =
new int[1];
2704 gl.glGetFramebufferAttachmentParameteriv(GL.GL_FRAMEBUFFER,
2705 GL.GL_COLOR_ATTACHMENT0,
2706 GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2707 frameBufferTexture, 0);
2709 System.err.println(getThreadName()+
": GLJPanel: FBO COLOR_ATTACHMENT0: " + frameBufferTexture[0]);
2713 if (!checkedGLVendor) {
2714 checkedGLVendor =
true;
2715 final String vendor = gl.glGetString(GL.GL_VENDOR);
2717 if ((vendor !=
null) &&
2718 vendor.startsWith(
"ATI")) {
2729 gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
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.
Core utility class simplifying usage of framebuffer objects (FBO) with all GLProfiles.
final void bind(final GL gl)
Bind this FBO, i.e.
final int getReadFramebuffer()
Returns the framebuffer name to read from.
final void destroy(final GL gl)
final ColorAttachment attachColorbuffer(final GL gl, final int attachmentPoint, final boolean alpha)
Attaches a newly created and initialized Colorbuffer, i.e.
final void unbind(final GL gl)
Unbind this FBO, i.e.
final boolean reset(final GL gl, int newWidth, int newHeight, int newSamples)
Resets this FBO's instance.
void init(final GL gl, final int newWidth, final int newHeight, final int newSamples)
Initializes this FBO's instance.
Specifies a set of OpenGL capabilities.
void setDoubleBuffered(final boolean enable)
Enables or disables double buffering.
Abstraction for an OpenGL rendering context.
final boolean isCreated()
Indicates whether the underlying native OpenGL context has been created.
abstract GL setGL(GL gl)
Sets the GL pipeline object for this GLContext.
abstract GL getGL()
Returns the GL pipeline object for this GLContext.
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.
final boolean isGL2ES2()
Indicates whether this profile is capable of GL2ES2.
static GLProfile getDefault(final AbstractGraphicsDevice device)
Returns a default GLProfile object, reflecting the best for the running platform.
static AbstractGraphicsDevice getDefaultDevice()
This API provides access to the threading model for the implementation of the classes in this package...
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 lightweight Swing component which provides OpenGL rendering support.
final GLCapabilitiesImmutable getRequestedGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the user requested OpenGL capabilities (pixel fo...
final float[] getCurrentSurfaceScale(final float[] result)
Returns the current pixel scale of the associated NativeSurface.
GLJPanel(final GLCapabilitiesImmutable userCapsRequest, final GLCapabilitiesChooser chooser)
Creates a new GLJPanel component.
GLEventListener removeGLEventListener(final GLEventListener listener)
Removes the given listener from this drawable queue.
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...
void removeNotify()
Overridden to track when this component is removed from a container.
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.Returns the underlying NativeSurface...
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
GLContext createContext(final GLContext shareWith)
Creates a new context for drawing to this drawable that will optionally share buffer objects,...
GLAnimatorControl getAnimator()
void destroy()
Just an alias for removeNotify.
void setRealized(final boolean realized)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
final RecursiveLock getUpstreamLock()
Returns the recursive lock object of the upstream widget to synchronize multithreaded access on top o...
void dispose(final Runnable post)
long getHandle()
Returns the GL drawable handle, guaranteed to be valid after realization and while it's surface is be...
float[] getMinimumSurfaceScale(final float[] result)
Returns the minimum pixel scale of the associated NativeSurface.the passed storage containing the min...
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
final GLProfile getGLProfile()
Fetches the GLProfile for this drawable.
final GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
void printComponent(final Graphics g)
void addGLEventListener(final int index, final GLEventListener listener)
Adds the given listener at the given index of this drawable queue.
final boolean getUseGLSLVerticalFlip()
See setUseGLSLVerticalFlip(boolean).
AWTGLPixelBufferProvider getCustomPixelBufferProvider()
GL setGL(final GL gl)
Sets the GL pipeline object this GLAutoDrawable uses.
void setContextCreationFlags(final int flags)
final boolean initializeBackend(final boolean offthread)
Attempts to initialize the backend, if not initialized yet.
int getContextCreationFlags()
WindowClosingMode getDefaultCloseOperation()
boolean getAutoSwapBufferMode()
Indicates whether automatic buffer swapping is enabled for this drawable.
final void setSkipGLOrientationVerticalFlip(final boolean v)
Skip isGLOriented() based vertical flip, which usually is required by the offscreen backend,...
final Thread getExclusiveContextThread()
final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable)
Specifies an GLAutoDrawable, which OpenGL context shall be shared by this GLAutoDrawable's GLContext.
final Object getUpstreamWidget()
Method may return the upstream UI toolkit object holding this GLAutoDrawable instance,...
boolean areAllGLEventListenerInitialized()
Returns true if all added GLEventListener are initialized, otherwise false.
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
final void setSharedContext(final GLContext sharedContext)
Specifies an OpenGL context, which shall be shared by this GLAutoDrawable's GLContext.
void paintComponent(final Graphics g)
Overridden to cause OpenGL rendering to be performed during repaint cycles.
boolean invoke(final boolean wait, final List< GLRunnable > glRunnables)
Extends invoke(boolean, GLRunnable) functionality allowing to inject a list of GLRunnables.
GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx)
Associate the new context, newtCtx, to this auto-drawable.
int getGLEventListenerCount()
Returns the number of GLEventListener of this drawable queue.
void addNotify()
Overridden to track when this component is added to a container.
void setPixelBufferProvider(final AWTGLPixelBufferProvider custom)
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.
final boolean getSkipGLOrientationVerticalFlip()
See setSkipGLOrientationVerticalFlip(boolean).
final void setRequestedGLCapabilities(final GLCapabilitiesImmutable caps)
Set a new requested GLCapabilitiesImmutable for this GLJPanel allowing reconfiguration.
void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight)
Shall be called before PrinterJob#print().
final void setTextureUnit(final int v)
Allows user to request a texture unit to be used, must be called before the first initialization,...
final GLDrawableFactory getFactory()
Return the GLDrawableFactory being used to create this instance.
GLEventListener getGLEventListener(final int index)
Returns the GLEventListener at the given index of this drawable queue.
float[] getMaximumSurfaceScale(final float[] result)
Returns the maximum pixel scale of the associated NativeSurface.The maximum pixel scale maybe used to...
void swapBuffers()
Swaps the front and back buffers of this drawable.
boolean isGLOriented()
Returns true if the drawable is rendered in OpenGL's coordinate system, origin at bottom left....
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
final void setUseGLSLVerticalFlip(final boolean v)
Toggle using GLSL texture renderer for the isGLOriented() based vertical flip, which usually is requi...
final boolean setSurfaceScale(final float[] pixelScale)
Request a pixel scale in x- and y-direction for the associated NativeSurface, where size_in_pixel_uni...
void releasePrint()
Shall be called after PrinterJob#print().
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 flushGLRunnables()
Flushes all enqueued GLRunnable of this GLAutoDrawable including notifying waiting executor.
boolean shouldPreserveColorBufferIfTranslucent()
For a translucent GLJPanel (one for which setOpaque(false) has been called), indicates whether the ap...
final int getTextureUnit()
Returns the used texture unit, i.e.
final Thread setExclusiveContextThread(final Thread t)
Dedicates this instance's GLContext to the given thread.
final boolean isThreadGLCapable()
Indicates whether the current thread is capable of performing OpenGL-related work.
void setAutoSwapBufferMode(final boolean enable)
Enables or disables automatic buffer swapping for this drawable.
GLContext getContext()
Returns the context associated with this drawable.
GLJPanel(final GLCapabilitiesImmutable userCapsRequest)
Creates a new GLJPanel component with the requested set of OpenGL capabilities, using the default Ope...
boolean getGLEventListenerInitState(final GLEventListener listener)
Retrieves whether the given listener is initialized or not.
final float[] getRequestedSurfaceScale(final float[] result)
Returns the requested pixel scale of the associated NativeSurface.If canSetSurfaceScale() returns fal...
void setOpaque(final boolean opaque)
final boolean canSetSurfaceScale()
Returns true if setSurfaceScale(float[]) is supported, otherwise false.For pure downstream scalable s...
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.
GLJPanel()
Creates a new GLJPanel component with a default set of OpenGL capabilities and using the default Open...
WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
void print(final Graphics graphics)
void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized)
Sets the given listener's initialized state.
void setAnimator(final GLAnimatorControl animatorControl)
Registers the usage of an animator, an com.jogamp.opengl.GLAnimatorControl implementation.
static String getThreadName()
void addGLEventListener(final GLEventListener listener)
Adds the given listener to the end of this drawable queue.
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...
Provider for AWTGLPixelBuffer instances.
Provider for singleton AWTGLPixelBuffer instances.
Window closing mode if triggered by toolkit close operation.
int getAlphaBits()
Returns the number of bits for the color buffer's alpha component.
int getBlueBits()
Returns the number of bits for the color buffer's blue component.
int getRedBits()
Returns the number of bits for the color buffer's red component.
int getGreenBits()
Returns the number of bits for the color buffer's green component.
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
void addSurfaceUpdatedListener(SurfaceUpdatedListener l)
Appends the given SurfaceUpdatedListener to the end of the list.
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.
boolean pause()
Pauses this animator.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
Provides a mechanism by which applications can customize the window type selection for a given GLCapa...
Specifies an immutable set of OpenGL capabilities.
int getAccumGreenBits()
Returns the number of bits for the accumulation buffer's green component.
int getDepthBits()
Returns the number of depth buffer bits.
GLProfile getGLProfile()
Returns the GL profile you desire or used by the drawable.
int getAccumRedBits()
Returns the number of bits for the accumulation buffer's red component.
int getAccumAlphaBits()
Returns the number of bits for the accumulation buffer's alpha component.
int getAccumBlueBits()
Returns the number of bits for the accumulation buffer's blue component.
boolean isFBO()
Returns whether FBO offscreen mode is requested, available or chosen.
int getStencilBits()
Returns the number of stencil buffer bits.
An abstraction for an OpenGL rendering target.
GLCapabilitiesImmutable getRequestedGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the user requested OpenGL capabilities (pixel fo...
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.
void setRealized(boolean realized)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
void swapBuffers()
Swaps the front and back buffers of this drawable.
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.