aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/javax')
-rw-r--r--src/jogl/classes/javax/media/opengl/GLArrayData.java57
-rw-r--r--src/jogl/classes/javax/media/opengl/GLBase.java15
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java26
-rw-r--r--src/jogl/classes/javax/media/opengl/GLFBODrawable.java22
-rw-r--r--src/jogl/classes/javax/media/opengl/GLUniformData.java20
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java8
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java681
7 files changed, 395 insertions, 434 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLArrayData.java b/src/jogl/classes/javax/media/opengl/GLArrayData.java
index 5d17f6874..8e1383031 100644
--- a/src/jogl/classes/javax/media/opengl/GLArrayData.java
+++ b/src/jogl/classes/javax/media/opengl/GLArrayData.java
@@ -30,6 +30,8 @@ package javax.media.opengl;
import java.nio.Buffer;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+
/**
*
* The total number of bytes hold by the referenced buffer is:
@@ -38,6 +40,19 @@ import java.nio.Buffer;
*/
public interface GLArrayData {
/**
+ * Implementation and type dependent object association.
+ * <p>
+ * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState}
+ * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's
+ * data persistence, location and state change.<br/>
+ * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}.
+ * </p>
+ * @param obj implementation and type dependent association
+ * @param enable pass true to enable the association and false to disable it.
+ */
+ public void associate(Object obj, boolean enable);
+
+ /**
* Returns true if this data set is intended for a GLSL vertex shader attribute,
* otherwise false, ie intended for fixed function vertex pointer
*/
@@ -47,10 +62,10 @@ public interface GLArrayData {
* The index of the predefined array index, see list below,
* or -1 in case of a shader attribute array.
*
- * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY
- * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY
- * @see javax.media.opengl.GL2#GL_COLOR_ARRAY
- * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY
+ * @see GLPointerFunc#GL_VERTEX_ARRAY
+ * @see GLPointerFunc#GL_NORMAL_ARRAY
+ * @see GLPointerFunc#GL_COLOR_ARRAY
+ * @see GLPointerFunc#GL_TEXTURE_COORD_ARRAY
*/
public int getIndex();
@@ -61,6 +76,11 @@ public interface GLArrayData {
/**
* Set a new name for this array.
+ * <p>
+ * This clears the location, i.e. sets it to -1.
+ * </p>
+ * @see #setLocation(int)
+ * @see #setLocation(GL2ES2, int)
*/
public void setName(String newName);
@@ -72,14 +92,37 @@ public interface GLArrayData {
public int getLocation();
/**
- * Sets the determined location of the shader attribute
- * This is usually done within ShaderState.
+ * Sets the given location of the shader attribute
*
+ * @return the given location
* @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData)
*/
- public void setLocation(int v);
+ public int setLocation(int v);
/**
+ * Retrieves the location of the shader attribute from the linked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return &ge;0 denotes a valid attribute location as found and used in the given shader program.
+ * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
+ */
+ public int setLocation(GL2ES2 gl, int program);
+
+ /**
+ * Binds the location of the shader attribute to the given location for the unlinked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return the given location
+ */
+ public int setLocation(GL2ES2 gl, int program, int location);
+
+ /**
* Determines whether the data is server side (VBO) and enabled,
* or a client side array (false).
*/
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index 9bcee819a..82bb06b9c 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -432,6 +432,19 @@ public interface GLBase {
* </p>
*/
public int getDefaultReadFramebuffer();
-
+
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ */
+ public int getDefaultReadBuffer();
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index de10a2815..235003c38 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -970,6 +970,32 @@ public abstract class GLContext {
*/
public abstract int getDefaultReadFramebuffer();
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ */
+ public abstract int getDefaultReadBuffer();
+
+ /** On some platforms the mismatch between OpenGL's coordinate
+ system (origin at bottom left) and the window system's
+ coordinate system (origin at top left) necessitates a vertical
+ flip of pixels read from offscreen contexts.
+ <p>
+ Default impl. is <code>true</code>.
+ </p>
+ */
+ public abstract boolean isGLOrientationFlippedVertical();
+
+ /** Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
+ public abstract int getDefaultPixelDataType();
+
/**
* @return The extension implementing the GLDebugOutput feature,
* either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>.
diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
index 079d9af5c..4d6c7c20e 100644
--- a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
@@ -101,7 +101,8 @@ public interface GLFBODrawable extends GLDrawable {
void setTextureUnit(int unit);
/**
- * Set a new sample size
+ * Set the number of sample buffers if using MSAA
+ *
* @param gl GL context object bound to this drawable, will be made current during operation.
* A prev. current context will be make current after operation.
* @param newSamples new sample size
@@ -113,6 +114,25 @@ public interface GLFBODrawable extends GLDrawable {
* @return the number of sample buffers if using MSAA, otherwise 0
*/
int getNumSamples();
+
+ /**
+ * Sets the number of buffers (FBO) being used if using {@link GLCapabilities#getDoubleBuffered() double buffering}.
+ * <p>
+ * If {@link GLCapabilities#getDoubleBuffered() double buffering} is not chosen, this is a NOP.
+ * </p>
+ * <p>
+ * Must be called before {@link #isInitialized() initialization}, otherwise an exception is thrown.
+ * </p>
+ * @return the new number of buffers (FBO) used, maybe different than the requested <code>bufferCount</code> (see above)
+ * @throws GLException if already initialized, see {@link #isInitialized()}.
+ */
+ int setNumBuffers(int bufferCount) throws GLException;
+
+ /**
+ * @return the number of buffers (FBO) being used. 1 if not using {@link GLCapabilities#getDoubleBuffered() double buffering},
+ * otherwise &ge; 2, depending on {@link #setNumBuffers(int)}.
+ */
+ int getNumBuffers();
/**
* @return the used {@link DoubleBufferMode}
diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java
index 18a422670..60d0c58bf 100644
--- a/src/jogl/classes/javax/media/opengl/GLUniformData.java
+++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java
@@ -147,10 +147,26 @@ public class GLUniformData {
public int getLocation() { return location; }
/**
- * Sets the determined location of the shader uniform.
+ * Sets the given location of the shader uniform.
+ * @return the given location
*/
- public GLUniformData setLocation(int location) { this.location=location; return this; }
+ public int setLocation(int location) { this.location=location; return location; }
+ /**
+ * Retrieves the location of the shader uniform from the linked shader program.
+ * <p>
+ * No validation is performed within the implementation.
+ * </p>
+ * @param gl
+ * @param program
+ * @return &ge;0 denotes a valid uniform location as found and used in the given shader program.
+ * &lt;0 denotes an invalid location, i.e. not found or used in the given shader program.
+ */
+ public int setLocation(GL2ES2 gl, int program) {
+ location = gl.glGetUniformLocation(program, name);
+ return location;
+ }
+
public Object getObject() {
return data;
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index a40cdcf88..efdc69ed8 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -915,7 +915,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// Catch dispose GLExceptions by GLEventListener, just 'print' them
// so we can continue with the destruction.
try {
- helper.disposeGL(GLCanvas.this, context);
+ helper.disposeGL(GLCanvas.this, context, true);
} catch (GLException gle) {
gle.printStackTrace();
}
@@ -1024,7 +1024,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
final RecursiveLock _lock = lock;
_lock.lock();
try {
- helper.invokeGL(drawable, context, displayAction, initAction);
+ if( null != drawable && drawable.isRealized() ) {
+ helper.invokeGL(drawable, context, displayAction, initAction);
+ }
} finally {
_lock.unlock();
}
@@ -1037,7 +1039,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
final RecursiveLock _lock = lock;
_lock.lock();
try {
- if(null != drawable) {
+ if( null != drawable && drawable.isRealized() ) {
drawable.swapBuffers();
}
} finally {
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index dcfc1f0dd..23dedaa66 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -49,10 +49,8 @@ import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.beans.Beans;
-import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
@@ -73,7 +71,7 @@ import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
+import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.Threading;
@@ -86,10 +84,11 @@ import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.awt.Java2D;
import jogamp.opengl.awt.Java2DGLContext;
+import jogamp.opengl.util.glsl.GLSLTextureRaster;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.opengl.FBObject;
-import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.GLPixelStorageModes;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
// context whenever the displayChanged() function is called on their
@@ -122,14 +121,17 @@ import com.jogamp.opengl.util.GLBuffers;
* </P>
*/
-@SuppressWarnings({ "serial", "deprecation" })
+@SuppressWarnings("serial")
public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol {
private static final boolean DEBUG = Debug.debug("GLJPanel");
private GLDrawableHelper helper = new GLDrawableHelper();
private volatile boolean isInitialized;
+ //
// Data used for either pbuffers or pixmap-based offscreen surfaces
+ //
+ /** Single buffered offscreen caps */
private GLCapabilitiesImmutable offscreenCaps;
private GLProfile glProfile;
private GLDrawableFactoryImpl factory;
@@ -150,16 +152,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Used by all backends either directly or indirectly to hook up callbacks
private Updater updater = new Updater();
- // Turns off the pbuffer-based backend (used by default, unless the
- // Java 2D / OpenGL pipeline is in use)
- private static boolean hardwareAccelerationDisabled =
- Debug.isPropertyDefined("jogl.gljpanel.nohw", true);
-
- // Turns off the fallback to software-based rendering from
- // pbuffer-based rendering
- private static boolean softwareRenderingDisabled =
- Debug.isPropertyDefined("jogl.gljpanel.nosw", true);
-
// Indicates whether the Java 2D OpenGL pipeline is enabled
private boolean oglPipelineEnabled =
Java2D.isOGLPipelineActive() &&
@@ -354,7 +346,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// re-creating it -- tricky to do properly while the context is
// current
if (handleReshape) {
- handleReshape();
+ handleReshape = false;
+ sendReshape = handleReshape();
}
updater.setGraphics(g);
@@ -395,8 +388,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
called on all registered {@link GLEventListener}s. Subclasses
which override this method must call super.reshape() in
their reshape() method in order to function properly. <P>
-
- <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+ *
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("deprecation")
@Override
public void reshape(int x, int y, int width, int height) {
super.reshape(x, y, width, height);
@@ -618,12 +613,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public NativeSurface getNativeSurface() {
- throw new GLException("FIXME");
+ if(null != backend) {
+ return backend.getDrawable().getNativeSurface();
+ }
+ return null;
}
@Override
public long getHandle() {
- throw new GLException("FIXME");
+ if(null != backend) {
+ return backend.getDrawable().getNativeSurface().getSurfaceHandle();
+ }
+ return 0;
}
@Override
@@ -636,13 +637,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
//
private void createAndInitializeBackend() {
- if (panelWidth == 0 ||
- panelHeight == 0) {
+ if ( 0 >= panelWidth || 0 >= panelHeight ) {
// See whether we have a non-zero size yet and can go ahead with
// initialization
- if (reshapeWidth == 0 ||
- reshapeHeight == 0) {
- return;
+ if (0 >= reshapeWidth || 0 >= reshapeHeight ) {
+ return;
}
// Pull down reshapeWidth and reshapeHeight into panelWidth and
@@ -652,29 +651,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
panelHeight = reshapeHeight;
}
- do {
- if (backend == null) {
+ if ( null == backend ) {
if (oglPipelineEnabled) {
- backend = new J2DOGLBackend();
+ backend = new J2DOGLBackend();
} else {
- if (!hardwareAccelerationDisabled &&
- factory.canCreateGLPbuffer(null)) {
- backend = new PbufferBackend();
- } else {
- if (softwareRenderingDisabled) {
- throw new GLException("Fallback to software rendering disabled by user");
- }
- backend = new SoftwareBackend();
- }
+ backend = new OffscreenBackend();
}
- }
+ isInitialized = false;
+ }
- if (!isInitialized) {
+ if (!isInitialized) {
backend.initialize();
- }
- // The backend might set itself to null, indicating it punted to
- // a different implementation -- try again
- } while (backend == null);
+ }
awtWindowClosingProtocol.addClosingListenerOneShot();
}
@@ -689,7 +677,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return awtWindowClosingProtocol.setDefaultCloseOperation(op);
}
- private void handleReshape() {
+ private boolean handleReshape() {
panelWidth = reshapeWidth;
panelHeight = reshapeHeight;
@@ -698,9 +686,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
panelWidth + "," + panelHeight + ")");
}
- sendReshape = true;
- backend.handleReshape();
- handleReshape = false;
+ return backend.handleReshape();
}
// This is used as the GLEventListener for the pbuffer-based backend
@@ -762,16 +748,17 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
public void run() {
if ( null != backend ) {
final GLContext _context = backend.getContext();
+ final boolean backendDestroy = !backend.isUsingOwnLifecycle();
if( null != _context && _context.isCreated() ) {
// Catch dispose GLExceptions by GLEventListener, just 'print' them
// so we can continue with the destruction.
try {
- helper.disposeGL(GLJPanel.this, _context);
+ helper.disposeGL(GLJPanel.this, _context, !backendDestroy);
} catch (GLException gle) {
gle.printStackTrace();
}
}
- if ( !backend.isUsingOwnThreadManagment() ) {
+ if ( backendDestroy ) {
backend.destroy();
backend = null;
isInitialized = false;
@@ -815,15 +802,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
};
- private int getNextPowerOf2(int number) {
- // Workaround for problems where 0 width or height are transiently
- // seen during layout
- if (number == 0) {
- return 2;
- }
- return GLBuffers.getNextPowerOf2(number);
- }
-
private int getGLInteger(GL gl, int which) {
int[] tmp = new int[1];
gl.glGetIntegerv(which, tmp, 0);
@@ -843,7 +821,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// / JOGL bridge
static interface Backend {
// Create, Destroy, ..
- public boolean isUsingOwnThreadManagment();
+ public boolean isUsingOwnLifecycle();
// Called each time the backend needs to initialize itself
public void initialize();
@@ -876,7 +854,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Called to handle a reshape event. When this is called, the
// OpenGL context associated with the backend is not current, to
// make it easier to destroy and re-create pbuffers if necessary.
- public void handleReshape();
+ public boolean handleReshape();
// Called before the OpenGL work is done in init() and display().
// If false is returned, this render is aborted.
@@ -894,12 +872,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Base class used by both the software (pixmap) and pbuffer
// backends, both of which rely on reading back the OpenGL frame
// buffer and drawing it with a BufferedImage
- abstract class AbstractReadbackBackend implements Backend {
+ class OffscreenBackend implements Backend {
// This image is exactly the correct size to render into the panel
protected BufferedImage offscreenImage;
// One of these is used to store the read back pixels before storing
// in the BufferedImage
- protected ByteBuffer readBackBytes;
protected IntBuffer readBackInts;
protected int readBackWidthInPixels;
protected int readBackHeightInPixels;
@@ -907,12 +884,118 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private int glFormat;
private int glType;
+ // Implementation using software rendering
+ private GLDrawableImpl offscreenDrawable;
+ private FBObject fboFlipped;
+ private GLSLTextureRaster glslTextureRaster;
+ private final int fboTextureUnit = 0;
+
+ private GLContextImpl offscreenContext;
+ private boolean flippedVertical;
+
// For saving/restoring of OpenGL state during ReadPixels
- private int[] swapbytes = new int[1];
- private int[] rowlength = new int[1];
- private int[] skiprows = new int[1];
- private int[] skippixels = new int[1];
- private int[] alignment = new int[1];
+ private final GLPixelStorageModes psm = new GLPixelStorageModes();
+
+ @Override
+ public boolean isUsingOwnLifecycle() { return false; }
+
+ @Override
+ public void initialize() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": OffscreenBackend: initialize()");
+ }
+ try {
+ offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable(
+ null /* default platform device */,
+ offscreenCaps,
+ chooser,
+ panelWidth, panelHeight);
+ offscreenDrawable.setRealized(true);
+ offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
+ offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ isInitialized = true;
+ final GL gl = offscreenContext.getGL();
+ flippedVertical = offscreenContext.isGLOrientationFlippedVertical();
+ final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
+ if( chosenCaps.isFBO() && flippedVertical && gl.isGL2ES2() ) {
+ helper.setAutoSwapBufferMode(false);
+ final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
+ try {
+ fboFlipped = new FBObject();
+ fboFlipped.reset(gl, fboDrawable.getWidth(), fboDrawable.getHeight(), 0, false);
+ fboFlipped.attachTexture2D(gl, 0, chosenCaps.getAlphaBits()>0);
+ // fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ glslTextureRaster = new GLSLTextureRaster(fboTextureUnit, true);
+ glslTextureRaster.init(gl.getGL2ES2());
+ glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, fboDrawable.getWidth(), fboDrawable.getHeight());
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ if(null != glslTextureRaster) {
+ glslTextureRaster.dispose(gl.getGL2ES2());
+ glslTextureRaster = null;
+ }
+ if(null != fboFlipped) {
+ fboFlipped.destroy(gl);
+ fboFlipped = null;
+ }
+ }
+ } else {
+ fboFlipped = null;
+ glslTextureRaster = null;
+ }
+ offscreenContext.release();
+ } else {
+ isInitialized = false;
+ }
+ } finally {
+ if( !isInitialized ) {
+ if(null != offscreenContext) {
+ offscreenContext.destroy();
+ offscreenContext = null;
+ }
+ if(null != offscreenDrawable) {
+ offscreenDrawable.setRealized(false);
+ offscreenDrawable = null;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
+ }
+ if ( null != offscreenContext && offscreenContext.isCreated() ) {
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ try {
+ final GL gl = offscreenContext.getGL();
+ if(null != glslTextureRaster) {
+ glslTextureRaster.dispose(gl.getGL2ES2());
+ }
+ if(null != fboFlipped) {
+ fboFlipped.destroy(gl);
+ }
+ } finally {
+ offscreenContext.destroy();
+ }
+ }
+ }
+ offscreenContext = null;
+ glslTextureRaster = null;
+ fboFlipped = null;
+ offscreenContext = null;
+
+ if (offscreenDrawable != null) {
+ final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ offscreenDrawable.setRealized(false);
+ offscreenDrawable = null;
+ if(null != adevice) {
+ adevice.close();
+ }
+ }
+ }
@Override
public void setOpaque(boolean opaque) {
@@ -935,128 +1018,85 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
if (isDisplay) {
// Must now copy pixels from offscreen context into surface
if (offscreenImage == null) {
- if (panelWidth > 0 && panelHeight > 0) {
- // It looks like NVidia's drivers (at least the ones on my
- // notebook) are buggy and don't allow a sub-rectangle to be
- // read from a pbuffer...this doesn't really matter because
- // it's the Graphics.drawImage() calls that are the
- // bottleneck
-
- int awtFormat = 0;
-
- // Should be more flexible in these BufferedImage formats;
- // perhaps see what the preferred image types are on the
- // given platform
- if (isOpaque()) {
- awtFormat = BufferedImage.TYPE_INT_RGB;
- } else {
- awtFormat = BufferedImage.TYPE_INT_ARGB;
- }
-
- offscreenImage = new BufferedImage(panelWidth,
- panelHeight,
- awtFormat);
- switch (awtFormat) {
- case BufferedImage.TYPE_3BYTE_BGR:
- glFormat = GL2.GL_BGR;
- glType = GL.GL_UNSIGNED_BYTE;
- readBackBytes = ByteBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels * 3);
- break;
-
- case BufferedImage.TYPE_INT_RGB:
- case BufferedImage.TYPE_INT_ARGB:
- glFormat = GL.GL_BGRA;
- glType = getGLPixelType();
+ if (0 >= panelWidth || 0 >= panelHeight ) {
+ return;
+ }
+ final boolean withAlpha = !isOpaque();
+
+ glFormat = GL.GL_BGRA;
+ glType = GL.GL_UNSIGNED_BYTE; // offscreenContext.getDefaultPixelDataType();
+
+ if(!flippedVertical || null != glslTextureRaster) {
+ offscreenImage = new BufferedImage(panelWidth, panelHeight, withAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ final int[] readBackIntBuffer = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
+ readBackInts = IntBuffer.wrap(readBackIntBuffer);
+ } else {
+ offscreenImage = new BufferedImage(panelWidth, panelHeight, withAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels);
- break;
-
- default:
- // FIXME: Support more off-screen image types (current
- // offscreen context implementations don't use others, and
- // some of the OpenGL formats aren't supported in the 1.1
- // headers, which we're currently using)
- throw new GLException("Unsupported offscreen image type " + awtFormat);
- }
+ }
+ if(DEBUG) {
+ System.err.println(getThreadName()+": OffscreenBackend postGL offscreenImage-init: flippedVertical "+flippedVertical+", glslTextureRaster "+(null!=glslTextureRaster));
}
}
- if (offscreenImage != null) {
- GL2 gl = getGL().getGL2();
- // Save current modes
- gl.glGetIntegerv(GL2.GL_PACK_SWAP_BYTES, swapbytes, 0);
- gl.glGetIntegerv(GL2.GL_PACK_ROW_LENGTH, rowlength, 0);
- gl.glGetIntegerv(GL2.GL_PACK_SKIP_ROWS, skiprows, 0);
- gl.glGetIntegerv(GL2.GL_PACK_SKIP_PIXELS, skippixels, 0);
- gl.glGetIntegerv(GL2.GL_PACK_ALIGNMENT, alignment, 0);
-
- gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, GL.GL_FALSE);
- gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, readBackWidthInPixels);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0);
- gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1);
-
- // Actually read the pixels.
- gl.glReadBuffer(GL2.GL_FRONT);
- if (readBackBytes != null) {
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes);
- } else if (readBackInts != null) {
+ final GL gl = offscreenContext.getGL();
+
+ // Save current modes
+ psm.setAlignment(gl, 1, 1);
+ if(gl.isGL2GL3()) {
+ final GL2GL3 gl2gl3 = gl.getGL2GL3();
+ gl2gl3.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, readBackWidthInPixels);
+ gl2gl3.glReadBuffer(gl2gl3.getDefaultReadBuffer());
+ }
+
+ if(null != glslTextureRaster) { // implies flippedVertical
+ // perform vert-flipping via OpenGL/FBO
+ final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
+ final FBObject.TextureAttachment fboTex = fboDrawable.getTextureBuffer(GL.GL_FRONT);
+
+ fboDrawable.swapBuffers();
+ fboFlipped.bind(gl);
+
+ // gl.glActiveTexture(fboDrawable.getTextureUnit()); // implicit!
+ gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
+ // gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
+ glslTextureRaster.display(gl.getGL2ES2());
gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts);
- }
- // Restore saved modes.
- gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, swapbytes[0]);
- gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, rowlength[0]);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, skiprows[0]);
- gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, skippixels[0]);
- gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, alignment[0]);
-
- if (readBackBytes != null || readBackInts != null) {
- // Copy temporary data into raster of BufferedImage for faster
- // blitting Note that we could avoid this copy in the cases
- // where !offscreenContext.offscreenImageNeedsVerticalFlip(),
- // but that's the software rendering path which is very slow
- // anyway
- Object src = null;
- Object dest = null;
- int srcIncr = 0;
- int destIncr = 0;
-
- if (readBackBytes != null) {
- src = readBackBytes.array();
- dest = ((DataBufferByte) offscreenImage.getRaster().getDataBuffer()).getData();
- srcIncr = readBackWidthInPixels * 3;
- destIncr = offscreenImage.getWidth() * 3;
- } else {
- src = readBackInts.array();
- dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
- srcIncr = readBackWidthInPixels;
- destIncr = offscreenImage.getWidth();
+ fboFlipped.unbind(gl);
+ } else {
+ gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts);
+
+ if ( flippedVertical ) {
+ // Copy temporary data into raster of BufferedImage for faster
+ // blitting Note that we could avoid this copy in the cases
+ // where !offscreenContext.offscreenImageNeedsVerticalFlip(),
+ // but that's the software rendering path which is very slow
+ // anyway
+ final Object src = readBackInts.array();
+ final Object dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
+ final int srcIncr = readBackWidthInPixels;
+ final int destIncr = offscreenImage.getWidth();
+ int srcPos = 0;
+ int destPos = (offscreenImage.getHeight() - 1) * destIncr;
+ for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) {
+ System.arraycopy(src, srcPos, dest, destPos, destIncr);
+ }
}
+ }
- if (flipVertically()) {
- int srcPos = 0;
- int destPos = (offscreenImage.getHeight() - 1) * destIncr;
- for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) {
- System.arraycopy(src, srcPos, dest, destPos, destIncr);
- }
- } else {
- int srcPos = 0;
- int destEnd = destIncr * offscreenImage.getHeight();
- for (int destPos = 0; destPos < destEnd; srcPos += srcIncr, destPos += destIncr) {
- System.arraycopy(src, srcPos, dest, destPos, destIncr);
- }
- }
+ // Restore saved modes.
+ psm.restore(gl);
- // Note: image will be drawn back in paintComponent() for
- // correctness on all platforms
- }
- }
+ // Note: image will be drawn back in paintComponent() for
+ // correctness on all platforms
}
}
@Override
public void doPaintComponent(Graphics g) {
- doPaintComponentImpl();
+ helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
+
if (offscreenImage != null) {
// Draw resulting image in one shot
g.drawImage(offscreenImage, 0, 0,
@@ -1066,57 +1106,52 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
}
- protected abstract void doPaintComponentImpl();
- protected abstract int getGLPixelType();
- protected abstract boolean flipVertically();
- }
-
- class SoftwareBackend extends AbstractReadbackBackend {
- // Implementation using software rendering
- private GLDrawableImpl offscreenDrawable;
- private GLContextImpl offscreenContext;
-
- @Override
- public boolean isUsingOwnThreadManagment() { return false; }
-
@Override
- public void initialize() {
- if(DEBUG) {
- System.err.println(getThreadName()+": SoftwareBackend: initialize()");
- }
- // Fall-through path: create an offscreen context instead
- offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable(
- null /* default platform device */,
- offscreenCaps,
- chooser,
- Math.max(1, panelWidth),
- Math.max(1, panelHeight));
- offscreenDrawable.setRealized(true);
- offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
- offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
-
- isInitialized = true;
- }
+ public boolean handleReshape() {
+ /** FIXME: Shall we utilize such resize optimization (snippet kept alive from removed pbuffer backend) ?
+ // Use factor larger than 2 during shrinks for some hysteresis
+ float shrinkFactor = 2.5f;
+ if ( (panelWidth > readBackWidthInPixels) || (panelHeight > readBackHeightInPixels) ||
+ (panelWidth < (readBackWidthInPixels / shrinkFactor)) || (panelHeight < (readBackHeightInPixels / shrinkFactor))) {
+ if (DEBUG) {
+ System.err.println(getThreadName()+": Resizing offscreen from (" + readBackWidthInPixels + ", " + readBackHeightInPixels + ") " +
+ " to fit (" + panelWidth + ", " + panelHeight + ")");
+ }
+ } */
+
+ GLDrawableImpl _drawable = offscreenDrawable;
+ {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ _drawable = _drawableNew;
+ offscreenDrawable = _drawableNew;
+ }
+ }
+ panelWidth = _drawable.getWidth();
+ panelHeight = _drawable.getHeight();
+ readBackWidthInPixels = panelWidth;
+ readBackHeightInPixels = panelHeight;
+
+ if( null != glslTextureRaster ) {
+ if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+ try {
+ final GL gl = offscreenContext.getGL();
+ fboFlipped.reset(gl, _drawable.getWidth(), _drawable.getHeight(), 0, false);
+ glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, _drawable.getWidth(), _drawable.getHeight());
+ } finally {
+ offscreenContext.release();
+ }
+ }
+ }
- @Override
- public void destroy() {
- if(DEBUG) {
- System.err.println(getThreadName()+": SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
- }
- if (offscreenContext != null) {
- offscreenContext.destroy();
- offscreenContext = null;
- }
- if (offscreenDrawable != null) {
- final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
- offscreenDrawable.setRealized(false);
- offscreenDrawable = null;
- if(null != adevice) {
- adevice.close();
+ if (offscreenImage != null) {
+ offscreenImage.flush();
+ offscreenImage = null;
}
- }
+ return _drawable.isRealized();
}
-
+
@Override
public GLContext createContext(GLContext shareWith) {
return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null;
@@ -1152,201 +1187,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
return offscreenDrawable.getGLProfile();
}
-
- @Override
- public void handleReshape() {
- destroy();
- initialize();
- readBackWidthInPixels = Math.max(1, panelWidth);
- readBackHeightInPixels = Math.max(1, panelHeight);
-
- if (offscreenImage != null) {
- offscreenImage.flush();
- offscreenImage = null;
- }
- }
-
- @Override
- protected void doPaintComponentImpl() {
- helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
- }
-
- @Override
- protected int getGLPixelType() {
- return offscreenContext.getOffscreenContextPixelDataType();
- }
-
- @Override
- protected boolean flipVertically() {
- return offscreenContext.offscreenImageNeedsVerticalFlip();
- }
- }
-
- class PbufferBackend extends AbstractReadbackBackend {
- private GLPbuffer pbuffer;
- private int pbufferWidth = 256;
- private int pbufferHeight = 256;
-
- @Override
- public boolean isUsingOwnThreadManagment() { return false; }
-
- @Override
- public void initialize() {
- if (pbuffer != null) {
- throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)");
- }
- if(DEBUG) {
- System.err.println(getThreadName()+": PbufferBackend: initialize()");
- }
- try {
- pbuffer = factory.createGLPbuffer(null /* default platform device */,
- offscreenCaps,
- null,
- pbufferWidth,
- pbufferHeight,
- shareWith);
- pbuffer.setContextCreationFlags(additionalCtxCreationFlags);
- pbuffer.addGLEventListener(updater);
- isInitialized = true;
- } catch (GLException e) {
- if (DEBUG) {
- e.printStackTrace();
- System.err.println(getThreadName()+": GLJPanel: Falling back on software rendering because of problems creating pbuffer");
- }
- hardwareAccelerationDisabled = true;
- backend = null;
- isInitialized = false;
- createAndInitializeBackend();
- }
- }
-
- @Override
- public void destroy() {
- if(DEBUG) {
- System.err.println(getThreadName()+": PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer));
- }
- if (pbuffer != null) {
- pbuffer.destroy();
- pbuffer = null;
- }
- }
-
- @Override
- public GLContext createContext(GLContext shareWith) {
- return (null != pbuffer) ? pbuffer.createContext(shareWith) : null;
- }
-
- @Override
- public void setContext(GLContext ctx) {
- if (pbuffer == null || Beans.isDesignTime()) {
- return;
- }
- pbuffer.setContext(ctx);
- }
-
- @Override
- public GLContext getContext() {
- // Workaround for crashes in NetBeans GUI builder
- if (null == pbuffer || Beans.isDesignTime()) {
- return null;
- }
- return pbuffer.getContext();
- }
-
- @Override
- public GLDrawable getDrawable() {
- return pbuffer;
- }
-
- @Override
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- if (pbuffer == null) {
- return null;
- }
- return pbuffer.getChosenGLCapabilities();
- }
-
- @Override
- public GLProfile getGLProfile() {
- if (pbuffer == null) {
- return null;
- }
- return pbuffer.getGLProfile();
- }
-
- @Override
- public void handleReshape() {
- // Use factor larger than 2 during shrinks for some hysteresis
- float shrinkFactor = 2.5f;
- if ((panelWidth > pbufferWidth) || (panelHeight > pbufferHeight) ||
- (panelWidth < (pbufferWidth / shrinkFactor)) || (panelHeight < (pbufferHeight / shrinkFactor))) {
- if (DEBUG) {
- System.err.println(getThreadName()+": Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " +
- " to fit (" + panelWidth + ", " + panelHeight + ")");
- }
- // Must destroy and recreate pbuffer to fit
- if (pbuffer != null) {
- // Watch for errors during pbuffer destruction (due to
- // buggy / bad OpenGL drivers, in particular SiS) and fall
- // back to software rendering
- try {
- pbuffer.destroy();
- } catch (GLException e) {
- hardwareAccelerationDisabled = true;
- backend = null;
- isInitialized = false;
- // Just disabled hardware acceleration during this resize operation; do a fixup
- readBackWidthInPixels = Math.max(1, panelWidth);
- readBackHeightInPixels = Math.max(1, panelHeight);
- if (DEBUG) {
- System.err.println(getThreadName()+": Warning: falling back to software rendering due to bugs in OpenGL drivers");
- e.printStackTrace();
- }
- createAndInitializeBackend();
- return;
- }
- }
- pbuffer = null;
- isInitialized = false;
- pbufferWidth = getNextPowerOf2(panelWidth);
- pbufferHeight = getNextPowerOf2(panelHeight);
- if (DEBUG && !hardwareAccelerationDisabled) {
- System.err.println(getThreadName()+": New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")");
- }
- initialize();
- }
-
- // It looks like NVidia's drivers (at least the ones on my
- // notebook) are buggy and don't allow a rectangle of less than
- // the pbuffer's width to be read...this doesn't really matter
- // because it's the Graphics.drawImage() calls that are the
- // bottleneck. Should probably make the size of the offscreen
- // image be the exact size of the pbuffer to save some work on
- // resize operations...
- readBackWidthInPixels = pbufferWidth;
- readBackHeightInPixels = panelHeight;
-
- if (offscreenImage != null) {
- offscreenImage.flush();
- offscreenImage = null;
- }
- }
-
- @Override
- protected void doPaintComponentImpl() {
- pbuffer.display();
- }
-
- @Override
- protected int getGLPixelType() {
- // This seems to be a good choice on all platforms
- return GL2.GL_UNSIGNED_INT_8_8_8_8_REV;
- }
-
- @Override
- protected boolean flipVertically() {
- return true;
- }
}
class J2DOGLBackend implements Backend {
@@ -1399,7 +1239,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private GraphicsConfiguration workaroundConfig;
@Override
- public boolean isUsingOwnThreadManagment() { return true; }
+ public boolean isUsingOwnLifecycle() { return true; }
@Override
public void initialize() {
@@ -1472,8 +1312,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void handleReshape() {
+ public boolean handleReshape() {
// Empty in this implementation
+ return true;
}
@Override
@@ -1618,7 +1459,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Cause OpenGL pipeline to flush its results because
// otherwise it's possible we will buffer up multiple frames'
// rendering results, resulting in apparent mouse lag
- GL gl = getGL();
+ GL gl = joglContext.getGL();
gl.glFinish();
if (Java2D.isFBOEnabled() &&