diff --git a/core/.classpath b/core/.classpath index 4ecc4a578..05a436d3e 100644 --- a/core/.classpath +++ b/core/.classpath @@ -2,7 +2,7 @@ - - + + diff --git a/core/library/export.txt b/core/library/export.txt index 437cdc697..308d1a35a 100644 --- a/core/library/export.txt +++ b/core/library/export.txt @@ -1,7 +1,10 @@ +# If you want to support more platforms, visit jogamp.org to get the +# natives libraries for the platform in question (i.e. Solaris). + name = OpenGL -application.macosx=core.jar,lwjgl.jar,lwjgl_util.jar -application.windows32=core.jar,lwjgl.jar,lwjgl_util.jar -application.windows64=core.jar,lwjgl.jar,lwjgl_util.jar -application.linux32=core.jar,lwjgl.jar,lwjgl_util.jar -application.linux64=core.jar,lwjgl.jar,lwjgl_util.jar +application.macosx=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-macosx-universal.jar,gluegen-rt-natives-macosx-universal.jar +application.windows32=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-windows-i586.jar,gluegen-rt-natives-windows-i586.jar +application.windows64=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-windows-amd64.jar,gluegen-rt-natives-windows-amd64.jar +application.linux32=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-linux-i586.jar,gluegen-rt-natives-linux-i586.jar +application.linux64=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-linux-amd64.jar,gluegen-rt-natives-linux-amd64.jar diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 61a77cc5f..53358b52b 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -668,7 +668,7 @@ public class PGraphicsOpenGL extends PGraphics { @Override public PSurface createSurface() { // ignore - return new PSurfaceLWJGL(this); + return new PSurfaceJOGL(this); // return new PSurfaceNEWT(this); } @@ -1772,7 +1772,7 @@ public class PGraphicsOpenGL extends PGraphics { // Factory method protected PGL createPGL(PGraphicsOpenGL pg) { - return new PLWJGL(pg); + return new PJOGL(pg); } diff --git a/core/src/processing/opengl/PJOGL.java b/core/src/processing/opengl/PJOGL.java new file mode 100644 index 000000000..c562f6a7c --- /dev/null +++ b/core/src/processing/opengl/PJOGL.java @@ -0,0 +1,2653 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +package processing.opengl; + +import java.awt.Canvas; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.PathIterator; +import java.io.IOException; +import java.net.URL; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +//import java.util.concurrent.CountDownLatch; + + + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2; +import com.jogamp.opengl.GL2ES1; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GL2ES3; +import com.jogamp.opengl.GL2GL3; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLContext; +import com.jogamp.opengl.GLDrawable; +//import javax.media.opengl.GLEventListener; +//import javax.media.opengl.GLFBODrawable; +import com.jogamp.opengl.GLProfile; +//import javax.media.opengl.awt.GLCanvas; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.glu.GLU; +import com.jogamp.opengl.glu.GLUtessellator; +import com.jogamp.opengl.glu.GLUtessellatorCallbackAdapter; + +import processing.core.PApplet; +import processing.core.PGraphics; +import processing.opengl.PGL; +import processing.opengl.PGraphicsOpenGL; + +//import com.jogamp.newt.awt.NewtCanvasAWT; +//import com.jogamp.newt.opengl.GLWindow; +//import com.jogamp.opengl.FBObject; + + +public class PJOGL extends PGL { + // OpenGL profile to use (2, 3 or 4) + public static int PROFILE = 2; + + // Enables/disables Retina support on OSX + public static boolean RETINA = false; + + // The two windowing toolkits available to use in JOGL: + public static final int AWT = 0; // http://jogamp.org/wiki/index.php/Using_JOGL_in_AWT_SWT_and_Swing + public static final int NEWT = 1; // http://jogamp.org/jogl/doc/NEWT-Overview.html + + // ........................................................ + + // Public members to access the underlying GL objects and context + + /** Basic GL functionality, common to all profiles */ + public GL gl; + + /** GLU interface **/ + public GLU glu; + + /** The rendering context (holds rendering state info) */ + public GLContext context; + + /** The canvas where OpenGL rendering takes place */ + public Canvas canvas; + + /** Selected GL profile */ + public static GLProfile profile; + + // ........................................................ + + // Additional parameters + + /** Time that the Processing's animation thread will wait for JOGL's rendering + * thread to be done with a single frame. + */ + protected static int DRAW_TIMEOUT_MILLIS = 500; + + // ........................................................ + + // OS-specific configuration + + /* + protected static int WINDOW_TOOLKIT; + protected static int EVENTS_TOOLKIT; + protected static boolean USE_JOGL_FBOLAYER; + static { + if (PApplet.platform == PConstants.WINDOWS) { + // Using AWT on Windows because NEWT displays a black background while + // initializing, and the cursor functions don't work. GLWindow has some + // functions for basic cursor handling (hide/show): + // GLWindow.setPointerVisible(false); + // but apparently nothing to set the cursor icon: + // https://jogamp.org/bugzilla/show_bug.cgi?id=409 + WINDOW_TOOLKIT = AWT; + EVENTS_TOOLKIT = AWT; + USE_FBOLAYER_BY_DEFAULT = false; + USE_JOGL_FBOLAYER = false; + } else if (PApplet.platform == PConstants.MACOSX) { + // Note: The JOGL FBO layer (in 2.0.2) seems incompatible with NEWT. + WINDOW_TOOLKIT = AWT; + EVENTS_TOOLKIT = AWT; + USE_FBOLAYER_BY_DEFAULT = true; + USE_JOGL_FBOLAYER = true; + } else if (PApplet.platform == PConstants.LINUX) { + WINDOW_TOOLKIT = AWT; + EVENTS_TOOLKIT = AWT; + USE_FBOLAYER_BY_DEFAULT = false; + USE_JOGL_FBOLAYER = false; + } else if (PApplet.platform == PConstants.OTHER) { + WINDOW_TOOLKIT = NEWT; // NEWT works on the Raspberry pi? + EVENTS_TOOLKIT = NEWT; + USE_FBOLAYER_BY_DEFAULT = false; + USE_JOGL_FBOLAYER = false; + } + } +*/ + +// protected static boolean USE_FBOLAYER_BY_DEFAULT = false; +// protected static boolean USE_JOGL_FBOLAYER = false; + + // ........................................................ + + // Protected JOGL-specific objects needed to access the GL profiles + + /** The capabilities of the OpenGL rendering surface */ + protected GLCapabilitiesImmutable capabilities; + + /** The rendering surface */ + protected GLDrawable drawable; + + /** GLES2 functionality (shaders, etc) */ + protected GL2ES2 gl2; + + /** GL3 interface */ + protected GL2GL3 gl3; + + /** GL2 desktop functionality (blit framebuffer, map buffer range, + * multisampled renderbuffers) */ + protected GL2 gl2x; + + /** The AWT-OpenGL canvas */ +// protected GLCanvas canvasAWT; + + /** The NEWT window */ +// protected GLWindow windowNEWT; + + /** The NEWT-OpenGL canvas */ +// protected NewtCanvasAWT canvasNEWT; + + /** The listener that fires the frame rendering in Processing */ +// protected PGLListener listener; + + /** This countdown latch is used to maintain the synchronization between + * Processing's drawing thread and JOGL's rendering thread */ +// protected CountDownLatch drawLatch = new CountDownLatch(0); + + /** Flag used to do request final display() call to make sure that the + * buffers are properly swapped. + */ +// protected boolean prevCanDraw = false; + + /** Stores exceptions that ocurred during drawing */ + protected Exception drawException; + + // ........................................................ + + // JOGL's FBO-layer + + /** Back (== draw, current frame) buffer */ +// protected FBObject backFBO; + /** Sink buffer, used in the multisampled case */ +// protected FBObject sinkFBO; + /** Front (== read, previous frame) buffer */ +// protected FBObject frontFBO; +// protected FBObject.TextureAttachment backTexAttach; +// protected FBObject.TextureAttachment frontTexAttach; + +// protected boolean changedFrontTex = false; +// protected boolean changedBackTex = false; + + // ........................................................ + + // Retina support + + int pixel_scale = 1; + + // ........................................................ + + // Utility arrays to copy projection/modelview matrices to GL + + protected float[] projMatrix; + protected float[] mvMatrix; + + // ........................................................ + + // Static initialization for some parameters that need to be different for + // JOGL + + static { + MIN_DIRECT_BUFFER_SIZE = 2; + INDEX_TYPE = GL.GL_UNSIGNED_SHORT; + } + + + /////////////////////////////////////////////////////////////// + + // Initialization, finalization + + + public PJOGL(PGraphicsOpenGL pg) { + super(pg); + glu = new GLU(); + } + + + /* + @Override + public Canvas getCanvas() { + return canvas; + } +*/ + + + protected void setFps(float fps) { + if (!setFps || targetFps != fps) { + if (60 < fps) { + // Disables v-sync + gl.setSwapInterval(0); + } else if (30 < fps) { + gl.setSwapInterval(1); + } else { + gl.setSwapInterval(2); + } + targetFps = currentFps = fps; + setFps = true; + } + } + + + /* + @Override + protected void initSurface(int antialias) { + + if (profile == null) { + if (PROFILE == 2) { + try { + profile = GLProfile.getGL2ES1(); + } catch (GLException ex) { + profile = GLProfile.getMaxFixedFunc(true); + } + } else if (PROFILE == 3) { + try { + profile = GLProfile.getGL2GL3(); + } catch (GLException ex) { + profile = GLProfile.getMaxProgrammable(true); + } + if (!profile.isGL3()) { + PGraphics.showWarning("Requested profile GL3 but is not available, got: " + profile); + } + } else if (PROFILE == 4) { + try { + profile = GLProfile.getGL4ES3(); + } catch (GLException ex) { + profile = GLProfile.getMaxProgrammable(true); + } + if (!profile.isGL4()) { + PGraphics.showWarning("Requested profile GL4 but is not available, got: " + profile); + } + } else throw new RuntimeException(UNSUPPORTED_GLPROF_ERROR); + + if (2 < PROFILE) { + texVertShaderSource = convertVertexSource(texVertShaderSource, 120, 150); + tex2DFragShaderSource = convertFragmentSource(tex2DFragShaderSource, 120, 150); + texRectFragShaderSource = convertFragmentSource(texRectFragShaderSource, 120, 150); + } + } + + if (canvasAWT != null || canvasNEWT != null) { + // Restarting... + if (canvasAWT != null) { + canvasAWT.removeGLEventListener(listener); + pg.parent.removeListeners(canvasAWT); + pg.parent.remove(canvasAWT); + } else if (canvasNEWT != null) { + windowNEWT.removeGLEventListener(listener); + pg.parent.remove(canvasNEWT); + } + sinkFBO = backFBO = frontFBO = null; + } + + // Setting up the desired capabilities; + GLCapabilities caps = new GLCapabilities(profile); + caps.setAlphaBits(REQUESTED_ALPHA_BITS); + caps.setDepthBits(REQUESTED_DEPTH_BITS); + caps.setStencilBits(REQUESTED_STENCIL_BITS); + + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + if (USE_FBOLAYER_BY_DEFAULT) { + if (USE_JOGL_FBOLAYER) { + caps.setPBuffer(false); + caps.setFBO(true); + if (1 < antialias) { + caps.setSampleBuffers(true); + caps.setNumSamples(antialias); + } else { + caps.setSampleBuffers(false); + } + fboLayerRequested = false; + } else { + caps.setPBuffer(false); + caps.setFBO(false); + caps.setSampleBuffers(false); + fboLayerRequested = 1 < antialias; + } + } else { + if (1 < antialias) { + caps.setSampleBuffers(true); + caps.setNumSamples(antialias); + } else { + caps.setSampleBuffers(false); + } + fboLayerRequested = false; + } + caps.setDepthBits(REQUESTED_DEPTH_BITS); + caps.setStencilBits(REQUESTED_STENCIL_BITS); + caps.setAlphaBits(REQUESTED_ALPHA_BITS); + reqNumSamples = qualityToSamples(antialias); + + if (WINDOW_TOOLKIT == AWT) { + canvasAWT = new GLCanvas(caps); + + if (RETINA) { + canvasAWT.setSurfaceScale(new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, + ScalableSurface.AUTOMAX_PIXELSCALE }); + retf = 2; + } else { + canvasAWT.setSurfaceScale(new int[] { ScalableSurface.IDENTITY_PIXELSCALE, + ScalableSurface.IDENTITY_PIXELSCALE }); + } + + canvasAWT.setBounds(0, 0, pg.width, pg.height); + canvasAWT.setBackground(new Color(pg.backgroundColor, true)); + canvasAWT.setFocusable(true); + + pg.parent.setLayout(new BorderLayout()); + pg.parent.add(canvasAWT, BorderLayout.CENTER); + canvasAWT.requestFocusInWindow(); + + + + canvas = canvasAWT; + canvasNEWT = null; + } else if (WINDOW_TOOLKIT == NEWT) { + windowNEWT = GLWindow.create(caps); + canvasNEWT = new NewtCanvasAWT(windowNEWT); + canvasNEWT.setBounds(0, 0, pg.width, pg.height); + canvasNEWT.setBackground(new Color(pg.backgroundColor, true)); + canvasNEWT.setFocusable(true); + + pg.parent.setLayout(new BorderLayout()); + pg.parent.add(canvasNEWT, BorderLayout.CENTER); + canvasNEWT.requestFocusInWindow(); + + int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + windowNEWT.setSurfaceScale(reqSurfacePixelScale); + + canvas = canvasNEWT; + canvasAWT = null; + } + + pg.parent.defaultSize = false; + registerListeners(); + + + fboLayerCreated = false; + fboLayerInUse = false; + firstFrame = true; + setFps = false; + } + */ + +/* + @Override + protected void reinitSurface() { + sinkFBO = backFBO = frontFBO = null; + fboLayerCreated = false; + fboLayerInUse = false; + firstFrame = true; + pg.parent.defaultSize = false; + } +*/ + +// @Override +// protected void registerListeners() { +// if (WINDOW_TOOLKIT == AWT) { +// pg.parent.addListeners(canvasAWT); +// +// listener = new PGLListener(); +// canvasAWT.addGLEventListener(listener); +// } else if (WINDOW_TOOLKIT == NEWT) { +// if (EVENTS_TOOLKIT == NEWT) { +// NEWTMouseListener mouseListener = new NEWTMouseListener(); +// windowNEWT.addMouseListener(mouseListener); +// NEWTKeyListener keyListener = new NEWTKeyListener(); +// windowNEWT.addKeyListener(keyListener); +// NEWTWindowListener winListener = new NEWTWindowListener(); +// windowNEWT.addWindowListener(winListener); +// } else if (EVENTS_TOOLKIT == AWT) { +// pg.parent.addListeners(canvasNEWT); +// } +// +// listener = new PGLListener(); +// windowNEWT.addGLEventListener(listener); +// } +// +// if (canvas != null) { +// canvas.setFocusTraversalKeysEnabled(false); +// } +// } + + +// @Override +// protected void deleteSurface() { +// super.deleteSurface(); +// +// if (canvasAWT != null) { +// canvasAWT.removeGLEventListener(listener); +// pg.parent.removeListeners(canvasAWT); +// } else if (canvasNEWT != null) { +// windowNEWT.removeGLEventListener(listener); +// } +// } + +/* + @Override + protected int getReadFramebuffer() { + if (fboLayerInUse) { + return glColorFbo.get(0); + } else if (capabilities.isFBO()) { + return context.getDefaultReadFramebuffer(); + } else { + return 0; + } + } + + + @Override + protected int getDrawFramebuffer() { + if (fboLayerInUse) { + if (1 < numSamples) { + return glMultiFbo.get(0); + } else { + return glColorFbo.get(0); + } + } else if (capabilities.isFBO()) { + return context.getDefaultDrawFramebuffer(); + } else { + return 0; + } + } + + + @Override + protected int getDefaultDrawBuffer() { + if (fboLayerInUse) { + return COLOR_ATTACHMENT0; + } else if (capabilities.isFBO()) { + return GL.GL_COLOR_ATTACHMENT0; + } else if (capabilities.getDoubleBuffered()) { + return GL.GL_BACK; + } else { + return GL.GL_FRONT; + } + } + + + @Override + protected int getDefaultReadBuffer() { + if (fboLayerInUse) { + return COLOR_ATTACHMENT0; + } else if (capabilities.isFBO()) { + return GL.GL_COLOR_ATTACHMENT0; + } else if (capabilities.getDoubleBuffered()) { + return GL.GL_BACK; + } else { + return GL.GL_FRONT; + } + } + + + @Override + protected boolean isFBOBacked() { + return super.isFBOBacked() || capabilities.isFBO(); + } + + + @Override + protected int getDepthBits() { + return capabilities.getDepthBits(); + } + + + @Override + protected int getStencilBits() { + return capabilities.getStencilBits(); + } + + + @Override + protected Texture wrapBackTexture(Texture texture) { + if (texture == null || changedBackTex) { + if (USE_JOGL_FBOLAYER) { + texture = new Texture(pg); + texture.init(pg.width, pg.height, + backTexAttach.getName(), TEXTURE_2D, RGBA, + backTexAttach.getWidth(), backTexAttach.getHeight(), + backTexAttach.minFilter, backTexAttach.magFilter, + backTexAttach.wrapS, backTexAttach.wrapT); + texture.invertedY(true); + texture.colorBuffer(true); + pg.setCache(pg, texture); + } else { + texture = super.wrapBackTexture(null); + } + } else { + if (USE_JOGL_FBOLAYER) { + texture.glName = backTexAttach.getName(); + } else { + texture = super.wrapBackTexture(texture); + } + } + return texture; + } + + + @Override + protected Texture wrapFrontTexture(Texture texture) { + if (texture == null || changedFrontTex) { + if (USE_JOGL_FBOLAYER) { + texture = new Texture(pg); + texture.init(pg.width, pg.height, + backTexAttach.getName(), TEXTURE_2D, RGBA, + frontTexAttach.getWidth(), frontTexAttach.getHeight(), + frontTexAttach.minFilter, frontTexAttach.magFilter, + frontTexAttach.wrapS, frontTexAttach.wrapT); + texture.invertedY(true); + texture.colorBuffer(true); + } else { + texture = super.wrapFrontTexture(null); + } + } else { + if (USE_JOGL_FBOLAYER) { + texture.glName = frontTexAttach.getName(); + } else { + texture = super.wrapFrontTexture(texture); + } + } + return texture; + } + + + @Override + protected void bindFrontTexture() { + if (USE_JOGL_FBOLAYER) { + usingFrontTex = true; + if (!texturingIsEnabled(TEXTURE_2D)) { + enableTexturing(TEXTURE_2D); + } + bindTexture(TEXTURE_2D, frontTexAttach.getName()); + } else super.bindFrontTexture(); + } + + + @Override + protected void unbindFrontTexture() { + if (USE_JOGL_FBOLAYER) { + if (textureIsBound(TEXTURE_2D, frontTexAttach.getName())) { + // We don't want to unbind another texture + // that might be bound instead of this one. + if (!texturingIsEnabled(TEXTURE_2D)) { + enableTexturing(TEXTURE_2D); + bindTexture(TEXTURE_2D, 0); + disableTexturing(TEXTURE_2D); + } else { + bindTexture(TEXTURE_2D, 0); + } + } + } else super.unbindFrontTexture(); + } + + + @Override + protected void syncBackTexture() { + if (USE_JOGL_FBOLAYER) { + if (usingFrontTex) needSepFrontTex = true; + if (1 < numSamples && backFBO != null) { + backFBO.syncSamplingSink(gl); + backFBO.bind(gl); + } + } else super.syncBackTexture(); + } + + + @Override + protected void beginDraw(boolean clear0) { + if (!setFps) setFps(targetFps); + if (USE_JOGL_FBOLAYER) return; + super.beginDraw(clear0); + } + + + @Override + protected void endDraw(boolean clear0) { + if (isFBOBacked()) { + if (USE_JOGL_FBOLAYER) { + if (!clear0 && isFBOBacked() && !isMultisampled() && + frontFBO != null && backFBO != null) { + // Draw the back texture into the front texture, which will be used as + // back texture in the next frame. Otherwise flickering will occur if + // the sketch uses "incremental drawing" (background() not called). + frontFBO.bind(gl); + gl.glDisable(GL.GL_BLEND); + drawTexture(TEXTURE_2D, backTexAttach.getName(), + backTexAttach.getWidth(), backTexAttach.getHeight(), + pg.width, pg.height, + 0, 0, pg.width, pg.height, 0, 0, pg.width, pg.height); + backFBO.bind(gl); + } + } else { + super.endDraw(clear0); + } + } + } +*/ + + @Override + protected void getGL(PGL pgl) { + PJOGL pjogl = (PJOGL)pgl; + + this.drawable = pjogl.drawable; + this.context = pjogl.context; + this.glContext = pjogl.glContext; + setThread(pjogl.glThread); + + this.gl = pjogl.gl; + this.gl2 = pjogl.gl2; + this.gl2x = pjogl.gl2x; + this.gl3 = pjogl.gl3; + } + + + protected void getGL(GLAutoDrawable glDrawable) { + context = glDrawable.getContext(); + glContext = context.hashCode(); + setThread(Thread.currentThread()); + + gl = context.getGL(); + gl2 = gl.getGL2ES2(); + try { + gl2x = gl.getGL2(); + } catch (com.jogamp.opengl.GLException e) { + gl2x = null; + } + try { + gl3 = gl.getGL2GL3(); + } catch (com.jogamp.opengl.GLException e) { + gl3 = null; + } + } + + + + /* + @Override + protected boolean canDraw() { + return true; +// return pg.initialized; +// && pg.parent.isDisplayable(); + } + + + @Override + protected void requestFocus() { } + + + @Override + protected void requestDraw() { + + drawException = null; + boolean canDraw = pg.parent.canDraw(); + if (pg.initialized && (canDraw || prevCanDraw)) { + drawLatch = new CountDownLatch(1); + if (WINDOW_TOOLKIT == AWT) { + canvasAWT.display(); + } else if (WINDOW_TOOLKIT == NEWT) { + windowNEWT.display(); + } + try { + drawLatch.await(DRAW_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (canDraw) prevCanDraw = true; + else prevCanDraw = false; + } + + // Throw wherever exception happened during drawing outside the GL thread + // to it is properly picked up by the PDE. + if (drawException != null) { + if (drawException instanceof RuntimeException) { + throw (RuntimeException)drawException; + } else { + throw new RuntimeException(drawException); + } + } + } + + + @Override + protected void swapBuffers() { + if (WINDOW_TOOLKIT == AWT) { + canvasAWT.swapBuffers(); + } else if (WINDOW_TOOLKIT == NEWT) { + windowNEWT.swapBuffers(); + } + } + */ + + + @Override + protected void beginGL() { + if (gl2x != null) { + if (projMatrix == null) { + projMatrix = new float[16]; + } + gl2x.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + projMatrix[ 0] = pg.projection.m00; + projMatrix[ 1] = pg.projection.m10; + projMatrix[ 2] = pg.projection.m20; + projMatrix[ 3] = pg.projection.m30; + projMatrix[ 4] = pg.projection.m01; + projMatrix[ 5] = pg.projection.m11; + projMatrix[ 6] = pg.projection.m21; + projMatrix[ 7] = pg.projection.m31; + projMatrix[ 8] = pg.projection.m02; + projMatrix[ 9] = pg.projection.m12; + projMatrix[10] = pg.projection.m22; + projMatrix[11] = pg.projection.m32; + projMatrix[12] = pg.projection.m03; + projMatrix[13] = pg.projection.m13; + projMatrix[14] = pg.projection.m23; + projMatrix[15] = pg.projection.m33; + gl2x.glLoadMatrixf(projMatrix, 0); + + if (mvMatrix == null) { + mvMatrix = new float[16]; + } + gl2x.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + mvMatrix[ 0] = pg.modelview.m00; + mvMatrix[ 1] = pg.modelview.m10; + mvMatrix[ 2] = pg.modelview.m20; + mvMatrix[ 3] = pg.modelview.m30; + mvMatrix[ 4] = pg.modelview.m01; + mvMatrix[ 5] = pg.modelview.m11; + mvMatrix[ 6] = pg.modelview.m21; + mvMatrix[ 7] = pg.modelview.m31; + mvMatrix[ 8] = pg.modelview.m02; + mvMatrix[ 9] = pg.modelview.m12; + mvMatrix[10] = pg.modelview.m22; + mvMatrix[11] = pg.modelview.m32; + mvMatrix[12] = pg.modelview.m03; + mvMatrix[13] = pg.modelview.m13; + mvMatrix[14] = pg.modelview.m23; + mvMatrix[15] = pg.modelview.m33; + gl2x.glLoadMatrixf(mvMatrix, 0); + } + } + + + @Override + protected boolean hasFBOs() { + if (context.hasBasicFBOSupport()) return true; + else return super.hasFBOs(); + } + + + @Override + protected boolean hasShaders() { + if (context.hasGLSL()) return true; + else return super.hasShaders(); + } + + + /////////////////////////////////////////////////////////// + + // JOGL event listeners + +/* + protected void getBuffers(GLWindow glWindow) { + if (false) { +// if (capabilities.isFBO()) { +// if (USE_JOGL_FBOLAYER && capabilities.isFBO()) { + // The onscreen drawing surface is backed by an FBO layer. + GLFBODrawable fboDrawable = null; + fboDrawable = (GLFBODrawable)glWindow.getDelegatedDrawable(); + + if (fboDrawable != null) { + backFBO = fboDrawable.getFBObject(GL.GL_BACK); + if (1 < numSamples) { + if (needSepFrontTex) { + // When using multisampled FBO, the back buffer is the MSAA + // surface so it cannot be read from. The sink buffer contains + // the readable 2D texture. + // In this case, we create an auxiliary "front" buffer that it is + // swapped with the sink buffer at the beginning of each frame. + // In this way, we always have a readable copy of the previous + // frame in the front texture, while the back is synchronized + // with the contents of the MSAA back buffer when requested. + if (frontFBO == null) { + // init + frontFBO = new FBObject(); + frontFBO.reset(gl, pg.width, pg.height, numSamples); + frontFBO.attachTexture2D(gl, 0, true); + sinkFBO = backFBO.getSamplingSinkFBO(); + changedFrontTex = changedBackTex = true; + } else { + // swap + FBObject temp = sinkFBO; + sinkFBO = frontFBO; + frontFBO = temp; + backFBO.setSamplingSink(sinkFBO); + changedFrontTex = changedBackTex = false; + } + backTexAttach = (FBObject.TextureAttachment) sinkFBO. + getColorbuffer(0); + frontTexAttach = (FBObject.TextureAttachment)frontFBO. + getColorbuffer(0); + } else { + changedFrontTex = changedBackTex = sinkFBO == null; + + // Default setting (to save resources): the front and back + // textures are the same. + sinkFBO = backFBO.getSamplingSinkFBO(); + backTexAttach = (FBObject.TextureAttachment) sinkFBO. + getColorbuffer(0); + frontTexAttach = backTexAttach; + } + } else { + // w/out multisampling, rendering is done on the back buffer. + frontFBO = fboDrawable.getFBObject(GL.GL_FRONT); + backTexAttach = (FBObject.TextureAttachment) backFBO.getColorbuffer(0); + frontTexAttach = (FBObject.TextureAttachment) frontFBO.getColorbuffer(0); + } + } + + } + } +*/ + + protected void init(GLAutoDrawable glDrawable) { + firstFrame = true; + capabilities = glDrawable.getChosenGLCapabilities(); + if (!hasFBOs()) { + throw new RuntimeException(MISSING_FBO_ERROR); + } + if (!hasShaders()) { + throw new RuntimeException(MISSING_GLSL_ERROR); + } +// if (USE_JOGL_FBOLAYER && capabilities.isFBO()) { +// int maxs = maxSamples(); +// numSamples = PApplet.min(capabilities.getNumSamples(), maxs); +// } + } + + /* + protected class PGLListener implements GLEventListener { + public PGLListener() {} + + @Override + public void display(GLAutoDrawable glDrawable) { + + getGL(glDrawable); + + if (USE_JOGL_FBOLAYER && capabilities.isFBO()) { + // The onscreen drawing surface is backed by an FBO layer. + GLFBODrawable fboDrawable = null; + + if (WINDOW_TOOLKIT == AWT) { + GLCanvas glCanvas = (GLCanvas)glDrawable; + fboDrawable = (GLFBODrawable)glCanvas.getDelegatedDrawable(); + } else { + GLWindow glWindow = (GLWindow)glDrawable; + fboDrawable = (GLFBODrawable)glWindow.getDelegatedDrawable(); + } + + if (fboDrawable != null) { + backFBO = fboDrawable.getFBObject(GL.GL_BACK); + if (1 < numSamples) { + if (needSepFrontTex) { + // When using multisampled FBO, the back buffer is the MSAA + // surface so it cannot be read from. The sink buffer contains + // the readable 2D texture. + // In this case, we create an auxiliary "front" buffer that it is + // swapped with the sink buffer at the beginning of each frame. + // In this way, we always have a readable copy of the previous + // frame in the front texture, while the back is synchronized + // with the contents of the MSAA back buffer when requested. + if (frontFBO == null) { + // init + frontFBO = new FBObject(); + frontFBO.reset(gl, pg.width, pg.height, numSamples); + frontFBO.attachTexture2D(gl, 0, true); + sinkFBO = backFBO.getSamplingSinkFBO(); + changedFrontTex = changedBackTex = true; + } else { + // swap + FBObject temp = sinkFBO; + sinkFBO = frontFBO; + frontFBO = temp; + backFBO.setSamplingSink(sinkFBO); + changedFrontTex = changedBackTex = false; + } + backTexAttach = (FBObject.TextureAttachment) sinkFBO. + getColorbuffer(0); + frontTexAttach = (FBObject.TextureAttachment)frontFBO. + getColorbuffer(0); + } else { + changedFrontTex = changedBackTex = sinkFBO == null; + + // Default setting (to save resources): the front and back + // textures are the same. + sinkFBO = backFBO.getSamplingSinkFBO(); + backTexAttach = (FBObject.TextureAttachment) sinkFBO. + getColorbuffer(0); + frontTexAttach = backTexAttach; + } + } else { + // w/out multisampling, rendering is done on the back buffer. + frontFBO = fboDrawable.getFBObject(GL.GL_FRONT); + backTexAttach = (FBObject.TextureAttachment) backFBO.getColorbuffer(0); + frontTexAttach = (FBObject.TextureAttachment) frontFBO.getColorbuffer(0); + } + } + } + + try { + pg.parent.handleDraw(); + } catch (Exception ex) { + drawException = ex; + } + drawLatch.countDown(); + } + + @Override + public void dispose(GLAutoDrawable adrawable) { + } + + @Override + public void init(GLAutoDrawable glDrawable) { + getGL(glDrawable); + + capabilities = glDrawable.getChosenGLCapabilities(); + if (!hasFBOs()) { + throw new RuntimeException(MISSING_FBO_ERROR); + } + if (!hasShaders()) { + throw new RuntimeException(MISSING_GLSL_ERROR); + } + if (USE_JOGL_FBOLAYER && capabilities.isFBO()) { + int maxs = maxSamples(); + numSamples = PApplet.min(capabilities.getNumSamples(), maxs); + } + } + + @Override + public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) { + //getGL(glDrawable); + } + +// private void getGL(GLAutoDrawable glDrawable) { +// drawable = glDrawable; +// context = glDrawable.getContext(); +// glContext = context.hashCode(); +// glThread = Thread.currentThread(); +// +// gl = context.getGL(); +// gl2 = gl.getGL2ES2(); +// try { +// gl2x = gl.getGL2(); +// } catch (javax.media.opengl.GLException e) { +// gl2x = null; +// } +// try { +// gl3 = gl.getGL2GL3(); +// } catch (javax.media.opengl.GLException e) { +// gl3 = null; +// } +// } + } + */ + + /* + protected void nativeMouseEvent(com.jogamp.newt.event.MouseEvent nativeEvent, + int peAction) { + int modifiers = nativeEvent.getModifiers(); + int peModifiers = modifiers & + (InputEvent.SHIFT_MASK | + InputEvent.CTRL_MASK | + InputEvent.META_MASK | + InputEvent.ALT_MASK); + + int peButton = 0; + if ((modifiers & InputEvent.BUTTON1_MASK) != 0) { + peButton = PConstants.LEFT; + } else if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { + peButton = PConstants.CENTER; + } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { + peButton = PConstants.RIGHT; + } + + if (PApplet.platform == PConstants.MACOSX) { + //if (nativeEvent.isPopupTrigger()) { + if ((modifiers & InputEvent.CTRL_MASK) != 0) { + peButton = PConstants.RIGHT; + } + } + + int peCount = 0; + if (peAction == MouseEvent.WHEEL) { + peCount = nativeEvent.isShiftDown() ? (int)nativeEvent.getRotation()[0] : + (int)nativeEvent.getRotation()[1]; + } else { + peCount = nativeEvent.getClickCount(); + } + + MouseEvent me = new MouseEvent(nativeEvent, nativeEvent.getWhen(), + peAction, peModifiers, + nativeEvent.getX(), nativeEvent.getY(), + peButton, + peCount); + + pg.parent.postEvent(me); + } + + protected void nativeKeyEvent(com.jogamp.newt.event.KeyEvent nativeEvent, + int peAction) { + int peModifiers = nativeEvent.getModifiers() & + (InputEvent.SHIFT_MASK | + InputEvent.CTRL_MASK | + InputEvent.META_MASK | + InputEvent.ALT_MASK); + + char keyChar; + if (nativeEvent.getKeyChar() == 0) { + keyChar = PConstants.CODED; + } else { + keyChar = nativeEvent.getKeyChar(); + } + + KeyEvent ke = new KeyEvent(nativeEvent, nativeEvent.getWhen(), + peAction, peModifiers, + keyChar, + nativeEvent.getKeyCode()); + + pg.parent.postEvent(ke); + } + + protected class NEWTWindowListener implements com.jogamp.newt.event.WindowListener { + public NEWTWindowListener() { + super(); + } + @Override + public void windowGainedFocus(com.jogamp.newt.event.WindowEvent arg0) { + pg.parent.focusGained(null); + } + + @Override + public void windowLostFocus(com.jogamp.newt.event.WindowEvent arg0) { + pg.parent.focusLost(null); + } + + @Override + public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent arg0) { + } + + @Override + public void windowDestroyed(com.jogamp.newt.event.WindowEvent arg0) { + } + + @Override + public void windowMoved(com.jogamp.newt.event.WindowEvent arg0) { + } + + @Override + public void windowRepaint(com.jogamp.newt.event.WindowUpdateEvent arg0) { + } + + @Override + public void windowResized(com.jogamp.newt.event.WindowEvent arg0) { } + } + + // NEWT mouse listener + protected class NEWTMouseListener extends com.jogamp.newt.event.MouseAdapter { + public NEWTMouseListener() { + super(); + } + @Override + public void mousePressed(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.PRESS); + } + @Override + public void mouseReleased(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.RELEASE); + } + @Override + public void mouseClicked(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.CLICK); + } + @Override + public void mouseDragged(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.DRAG); + } + @Override + public void mouseMoved(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.MOVE); + } + @Override + public void mouseWheelMoved(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.WHEEL); + } + @Override + public void mouseEntered(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.ENTER); + } + @Override + public void mouseExited(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.EXIT); + } + } + + // NEWT key listener + protected class NEWTKeyListener extends com.jogamp.newt.event.KeyAdapter { + public NEWTKeyListener() { + super(); + } + @Override + public void keyPressed(com.jogamp.newt.event.KeyEvent e) { + nativeKeyEvent(e, KeyEvent.PRESS); + } + @Override + public void keyReleased(com.jogamp.newt.event.KeyEvent e) { + nativeKeyEvent(e, KeyEvent.RELEASE); + } + public void keyTyped(com.jogamp.newt.event.KeyEvent e) { + nativeKeyEvent(e, KeyEvent.TYPE); + } + } +*/ + + /////////////////////////////////////////////////////////// + + // Utility functions + + + @Override + protected void enableTexturing(int target) { + if (PROFILE == 2) enable(target); + if (target == TEXTURE_2D) { + texturingTargets[0] = true; + } else if (target == TEXTURE_RECTANGLE) { + texturingTargets[1] = true; + } + } + + + @Override + protected void disableTexturing(int target) { + if (PROFILE == 2) disable(target); + if (target == TEXTURE_2D) { + texturingTargets[0] = false; + } else if (target == TEXTURE_RECTANGLE) { + texturingTargets[1] = false; + } + } + + + + @Override + protected int getFontAscent(Object font) { + return pg.getFontMetrics((Font) font).getAscent(); + } + + + @Override + protected int getFontDescent(Object font) { + return pg.getFontMetrics((Font) font).getDescent(); + } + + + @Override + protected int getTextWidth(Object font, char[] buffer, int start, int stop) { + // maybe should use one of the newer/fancier functions for this? + int length = stop - start; + FontMetrics metrics = pg.getFontMetrics((Font) font); + return metrics.charsWidth(buffer, start, length); + } + + + @Override + protected Object getDerivedFont(Object font, float size) { + return ((Font) font).deriveFont(size); + } + + + @Override + protected String[] loadVertexShader(String filename, int version) { + if (2 < PROFILE && version < 150) { + String[] fragSrc0 = pg.parent.loadStrings(filename); + return convertFragmentSource(fragSrc0, version, 150); + } else { + return pg.parent.loadStrings(filename); + } + } + + + @Override + protected String[] loadFragmentShader(String filename, int version) { + if (2 < PROFILE && version < 150) { + String[] vertSrc0 = pg.parent.loadStrings(filename); + return convertVertexSource(vertSrc0, version, 150); + } else { + return pg.parent.loadStrings(filename); + } + } + + + @Override + protected String[] loadFragmentShader(URL url, int version) { + try { + if (2 < PROFILE && version < 150) { + String[] fragSrc0 = PApplet.loadStrings(url.openStream()); + return convertFragmentSource(fragSrc0, version, 150); + } else { + return PApplet.loadStrings(url.openStream()); + } + } catch (IOException e) { + PGraphics.showException("Cannot load fragment shader " + url.getFile()); + } + return null; + } + + + @Override + protected String[] loadVertexShader(URL url, int version) { + try { + if (2 < PROFILE && version < 150) { + String[] vertSrc0 = PApplet.loadStrings(url.openStream()); + return convertVertexSource(vertSrc0, version, 150); + } else { + return PApplet.loadStrings(url.openStream()); + } + } catch (IOException e) { + PGraphics.showException("Cannot load vertex shader " + url.getFile()); + } + return null; + } + + + /////////////////////////////////////////////////////////// + + // Tessellator + + + @Override + protected Tessellator createTessellator(TessellatorCallback callback) { + return new Tessellator(callback); + } + + + protected static class Tessellator implements PGL.Tessellator { + protected GLUtessellator tess; + protected TessellatorCallback callback; + protected GLUCallback gluCallback; + + public Tessellator(TessellatorCallback callback) { + this.callback = callback; + tess = GLU.gluNewTess(); + gluCallback = new GLUCallback(); + + GLU.gluTessCallback(tess, GLU.GLU_TESS_BEGIN, gluCallback); + GLU.gluTessCallback(tess, GLU.GLU_TESS_END, gluCallback); + GLU.gluTessCallback(tess, GLU.GLU_TESS_VERTEX, gluCallback); + GLU.gluTessCallback(tess, GLU.GLU_TESS_COMBINE, gluCallback); + GLU.gluTessCallback(tess, GLU.GLU_TESS_ERROR, gluCallback); + } + + @Override + public void beginPolygon() { + GLU.gluTessBeginPolygon(tess, null); + } + + @Override + public void endPolygon() { + GLU.gluTessEndPolygon(tess); + } + + @Override + public void setWindingRule(int rule) { + GLU.gluTessProperty(tess, GLU.GLU_TESS_WINDING_RULE, rule); + } + + @Override + public void beginContour() { + GLU.gluTessBeginContour(tess); + } + + @Override + public void endContour() { + GLU.gluTessEndContour(tess); + } + + @Override + public void addVertex(double[] v) { + GLU.gluTessVertex(tess, v, 0, v); + } + + protected class GLUCallback extends GLUtessellatorCallbackAdapter { + @Override + public void begin(int type) { + callback.begin(type); + } + + @Override + public void end() { + callback.end(); + } + + @Override + public void vertex(Object data) { + callback.vertex(data); + } + + @Override + public void combine(double[] coords, Object[] data, + float[] weight, Object[] outData) { + callback.combine(coords, data, weight, outData); + } + + @Override + public void error(int errnum) { + callback.error(errnum); + } + } + } + + + @Override + protected String tessError(int err) { + return glu.gluErrorString(err); + } + + + /////////////////////////////////////////////////////////// + + // Font outline + + + static { + SHAPE_TEXT_SUPPORTED = true; + SEG_MOVETO = PathIterator.SEG_MOVETO; + SEG_LINETO = PathIterator.SEG_LINETO; + SEG_QUADTO = PathIterator.SEG_QUADTO; + SEG_CUBICTO = PathIterator.SEG_CUBICTO; + SEG_CLOSE = PathIterator.SEG_CLOSE; + } + + + @Override + protected FontOutline createFontOutline(char ch, Object font) { + return new FontOutline(ch, (Font) font); + } + + + protected class FontOutline implements PGL.FontOutline { + PathIterator iter; + + public FontOutline(char ch, Font font) { + char textArray[] = new char[] { ch }; + FontRenderContext frc = pg.getFontRenderContext(font); + GlyphVector gv = font.createGlyphVector(frc, textArray); + Shape shp = gv.getOutline(); + iter = shp.getPathIterator(null); + } + + public boolean isDone() { + return iter.isDone(); + } + + public int currentSegment(float coords[]) { + return iter.currentSegment(coords); + } + + public void next() { + iter.next(); + } + } + + + /////////////////////////////////////////////////////////// + + // Constants + + static { + FALSE = GL.GL_FALSE; + TRUE = GL.GL_TRUE; + + INT = GL2ES2.GL_INT; + BYTE = GL.GL_BYTE; + SHORT = GL.GL_SHORT; + FLOAT = GL.GL_FLOAT; + BOOL = GL2ES2.GL_BOOL; + UNSIGNED_INT = GL.GL_UNSIGNED_INT; + UNSIGNED_BYTE = GL.GL_UNSIGNED_BYTE; + UNSIGNED_SHORT = GL.GL_UNSIGNED_SHORT; + + RGB = GL.GL_RGB; + RGBA = GL.GL_RGBA; + ALPHA = GL.GL_ALPHA; + LUMINANCE = GL.GL_LUMINANCE; + LUMINANCE_ALPHA = GL.GL_LUMINANCE_ALPHA; + + UNSIGNED_SHORT_5_6_5 = GL.GL_UNSIGNED_SHORT_5_6_5; + UNSIGNED_SHORT_4_4_4_4 = GL.GL_UNSIGNED_SHORT_4_4_4_4; + UNSIGNED_SHORT_5_5_5_1 = GL.GL_UNSIGNED_SHORT_5_5_5_1; + + RGBA4 = GL.GL_RGBA4; + RGB5_A1 = GL.GL_RGB5_A1; + RGB565 = GL.GL_RGB565; + RGB8 = GL.GL_RGB8; + RGBA8 = GL.GL_RGBA8; + ALPHA8 = GL.GL_ALPHA8; + + READ_ONLY = GL2GL3.GL_READ_ONLY; + WRITE_ONLY = GL.GL_WRITE_ONLY; + READ_WRITE = GL2GL3.GL_READ_WRITE; + + TESS_WINDING_NONZERO = GLU.GLU_TESS_WINDING_NONZERO; + TESS_WINDING_ODD = GLU.GLU_TESS_WINDING_ODD; + + GENERATE_MIPMAP_HINT = GL.GL_GENERATE_MIPMAP_HINT; + FASTEST = GL.GL_FASTEST; + NICEST = GL.GL_NICEST; + DONT_CARE = GL.GL_DONT_CARE; + + VENDOR = GL.GL_VENDOR; + RENDERER = GL.GL_RENDERER; + VERSION = GL.GL_VERSION; + EXTENSIONS = GL.GL_EXTENSIONS; + SHADING_LANGUAGE_VERSION = GL2ES2.GL_SHADING_LANGUAGE_VERSION; + + MAX_SAMPLES = GL2ES3.GL_MAX_SAMPLES; + SAMPLES = GL.GL_SAMPLES; + + ALIASED_LINE_WIDTH_RANGE = GL.GL_ALIASED_LINE_WIDTH_RANGE; + ALIASED_POINT_SIZE_RANGE = GL.GL_ALIASED_POINT_SIZE_RANGE; + + DEPTH_BITS = GL.GL_DEPTH_BITS; + STENCIL_BITS = GL.GL_STENCIL_BITS; + + CCW = GL.GL_CCW; + CW = GL.GL_CW; + + VIEWPORT = GL.GL_VIEWPORT; + + ARRAY_BUFFER = GL.GL_ARRAY_BUFFER; + ELEMENT_ARRAY_BUFFER = GL.GL_ELEMENT_ARRAY_BUFFER; + + MAX_VERTEX_ATTRIBS = GL2ES2.GL_MAX_VERTEX_ATTRIBS; + + STATIC_DRAW = GL.GL_STATIC_DRAW; + DYNAMIC_DRAW = GL.GL_DYNAMIC_DRAW; + STREAM_DRAW = GL2ES2.GL_STREAM_DRAW; + + BUFFER_SIZE = GL.GL_BUFFER_SIZE; + BUFFER_USAGE = GL.GL_BUFFER_USAGE; + + POINTS = GL.GL_POINTS; + LINE_STRIP = GL.GL_LINE_STRIP; + LINE_LOOP = GL.GL_LINE_LOOP; + LINES = GL.GL_LINES; + TRIANGLE_FAN = GL.GL_TRIANGLE_FAN; + TRIANGLE_STRIP = GL.GL_TRIANGLE_STRIP; + TRIANGLES = GL.GL_TRIANGLES; + + CULL_FACE = GL.GL_CULL_FACE; + FRONT = GL.GL_FRONT; + BACK = GL.GL_BACK; + FRONT_AND_BACK = GL.GL_FRONT_AND_BACK; + + POLYGON_OFFSET_FILL = GL.GL_POLYGON_OFFSET_FILL; + + UNPACK_ALIGNMENT = GL.GL_UNPACK_ALIGNMENT; + PACK_ALIGNMENT = GL.GL_PACK_ALIGNMENT; + + TEXTURE_2D = GL.GL_TEXTURE_2D; + TEXTURE_RECTANGLE = GL2GL3.GL_TEXTURE_RECTANGLE; + + TEXTURE_BINDING_2D = GL.GL_TEXTURE_BINDING_2D; + TEXTURE_BINDING_RECTANGLE = GL2GL3.GL_TEXTURE_BINDING_RECTANGLE; + + MAX_TEXTURE_SIZE = GL.GL_MAX_TEXTURE_SIZE; + TEXTURE_MAX_ANISOTROPY = GL.GL_TEXTURE_MAX_ANISOTROPY_EXT; + MAX_TEXTURE_MAX_ANISOTROPY = GL.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT; + + MAX_VERTEX_TEXTURE_IMAGE_UNITS = GL2ES2.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS; + MAX_TEXTURE_IMAGE_UNITS = GL2ES2.GL_MAX_TEXTURE_IMAGE_UNITS; + MAX_COMBINED_TEXTURE_IMAGE_UNITS = GL2ES2.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS; + + NUM_COMPRESSED_TEXTURE_FORMATS = GL.GL_NUM_COMPRESSED_TEXTURE_FORMATS; + COMPRESSED_TEXTURE_FORMATS = GL.GL_COMPRESSED_TEXTURE_FORMATS; + + NEAREST = GL.GL_NEAREST; + LINEAR = GL.GL_LINEAR; + LINEAR_MIPMAP_NEAREST = GL.GL_LINEAR_MIPMAP_NEAREST; + LINEAR_MIPMAP_LINEAR = GL.GL_LINEAR_MIPMAP_LINEAR; + + CLAMP_TO_EDGE = GL.GL_CLAMP_TO_EDGE; + REPEAT = GL.GL_REPEAT; + + TEXTURE0 = GL.GL_TEXTURE0; + TEXTURE1 = GL.GL_TEXTURE1; + TEXTURE2 = GL.GL_TEXTURE2; + TEXTURE3 = GL.GL_TEXTURE3; + TEXTURE_MIN_FILTER = GL.GL_TEXTURE_MIN_FILTER; + TEXTURE_MAG_FILTER = GL.GL_TEXTURE_MAG_FILTER; + TEXTURE_WRAP_S = GL.GL_TEXTURE_WRAP_S; + TEXTURE_WRAP_T = GL.GL_TEXTURE_WRAP_T; + TEXTURE_WRAP_R = GL2ES2.GL_TEXTURE_WRAP_R; + + TEXTURE_CUBE_MAP = GL.GL_TEXTURE_CUBE_MAP; + TEXTURE_CUBE_MAP_POSITIVE_X = GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X; + TEXTURE_CUBE_MAP_POSITIVE_Y = GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y; + TEXTURE_CUBE_MAP_POSITIVE_Z = GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z; + TEXTURE_CUBE_MAP_NEGATIVE_X = GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X; + TEXTURE_CUBE_MAP_NEGATIVE_Y = GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; + TEXTURE_CUBE_MAP_NEGATIVE_Z = GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; + + VERTEX_SHADER = GL2ES2.GL_VERTEX_SHADER; + FRAGMENT_SHADER = GL2ES2.GL_FRAGMENT_SHADER; + INFO_LOG_LENGTH = GL2ES2.GL_INFO_LOG_LENGTH; + SHADER_SOURCE_LENGTH = GL2ES2.GL_SHADER_SOURCE_LENGTH; + COMPILE_STATUS = GL2ES2.GL_COMPILE_STATUS; + LINK_STATUS = GL2ES2.GL_LINK_STATUS; + VALIDATE_STATUS = GL2ES2.GL_VALIDATE_STATUS; + SHADER_TYPE = GL2ES2.GL_SHADER_TYPE; + DELETE_STATUS = GL2ES2.GL_DELETE_STATUS; + + FLOAT_VEC2 = GL2ES2.GL_FLOAT_VEC2; + FLOAT_VEC3 = GL2ES2.GL_FLOAT_VEC3; + FLOAT_VEC4 = GL2ES2.GL_FLOAT_VEC4; + FLOAT_MAT2 = GL2ES2.GL_FLOAT_MAT2; + FLOAT_MAT3 = GL2ES2.GL_FLOAT_MAT3; + FLOAT_MAT4 = GL2ES2.GL_FLOAT_MAT4; + INT_VEC2 = GL2ES2.GL_INT_VEC2; + INT_VEC3 = GL2ES2.GL_INT_VEC3; + INT_VEC4 = GL2ES2.GL_INT_VEC4; + BOOL_VEC2 = GL2ES2.GL_BOOL_VEC2; + BOOL_VEC3 = GL2ES2.GL_BOOL_VEC3; + BOOL_VEC4 = GL2ES2.GL_BOOL_VEC4; + SAMPLER_2D = GL2ES2.GL_SAMPLER_2D; + SAMPLER_CUBE = GL2ES2.GL_SAMPLER_CUBE; + + LOW_FLOAT = GL2ES2.GL_LOW_FLOAT; + MEDIUM_FLOAT = GL2ES2.GL_MEDIUM_FLOAT; + HIGH_FLOAT = GL2ES2.GL_HIGH_FLOAT; + LOW_INT = GL2ES2.GL_LOW_INT; + MEDIUM_INT = GL2ES2.GL_MEDIUM_INT; + HIGH_INT = GL2ES2.GL_HIGH_INT; + + CURRENT_VERTEX_ATTRIB = GL2ES2.GL_CURRENT_VERTEX_ATTRIB; + + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING; + VERTEX_ATTRIB_ARRAY_ENABLED = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_ENABLED; + VERTEX_ATTRIB_ARRAY_SIZE = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_SIZE; + VERTEX_ATTRIB_ARRAY_STRIDE = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_STRIDE; + VERTEX_ATTRIB_ARRAY_TYPE = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_TYPE; + VERTEX_ATTRIB_ARRAY_NORMALIZED = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_NORMALIZED; + VERTEX_ATTRIB_ARRAY_POINTER = GL2ES2.GL_VERTEX_ATTRIB_ARRAY_POINTER; + + BLEND = GL.GL_BLEND; + ONE = GL.GL_ONE; + ZERO = GL.GL_ZERO; + SRC_ALPHA = GL.GL_SRC_ALPHA; + DST_ALPHA = GL.GL_DST_ALPHA; + ONE_MINUS_SRC_ALPHA = GL.GL_ONE_MINUS_SRC_ALPHA; + ONE_MINUS_DST_COLOR = GL.GL_ONE_MINUS_DST_COLOR; + ONE_MINUS_SRC_COLOR = GL.GL_ONE_MINUS_SRC_COLOR; + DST_COLOR = GL.GL_DST_COLOR; + SRC_COLOR = GL.GL_SRC_COLOR; + + SAMPLE_ALPHA_TO_COVERAGE = GL.GL_SAMPLE_ALPHA_TO_COVERAGE; + SAMPLE_COVERAGE = GL.GL_SAMPLE_COVERAGE; + + KEEP = GL.GL_KEEP; + REPLACE = GL.GL_REPLACE; + INCR = GL.GL_INCR; + DECR = GL.GL_DECR; + INVERT = GL.GL_INVERT; + INCR_WRAP = GL.GL_INCR_WRAP; + DECR_WRAP = GL.GL_DECR_WRAP; + NEVER = GL.GL_NEVER; + ALWAYS = GL.GL_ALWAYS; + + EQUAL = GL.GL_EQUAL; + LESS = GL.GL_LESS; + LEQUAL = GL.GL_LEQUAL; + GREATER = GL.GL_GREATER; + GEQUAL = GL.GL_GEQUAL; + NOTEQUAL = GL.GL_NOTEQUAL; + + FUNC_ADD = GL.GL_FUNC_ADD; + FUNC_MIN = GL2ES3.GL_MIN; + FUNC_MAX = GL2ES3.GL_MAX; + FUNC_REVERSE_SUBTRACT = GL.GL_FUNC_REVERSE_SUBTRACT; + FUNC_SUBTRACT = GL.GL_FUNC_SUBTRACT; + + DITHER = GL.GL_DITHER; + + CONSTANT_COLOR = GL2ES2.GL_CONSTANT_COLOR; + CONSTANT_ALPHA = GL2ES2.GL_CONSTANT_ALPHA; + ONE_MINUS_CONSTANT_COLOR = GL2ES2.GL_ONE_MINUS_CONSTANT_COLOR; + ONE_MINUS_CONSTANT_ALPHA = GL2ES2.GL_ONE_MINUS_CONSTANT_ALPHA; + SRC_ALPHA_SATURATE = GL.GL_SRC_ALPHA_SATURATE; + + SCISSOR_TEST = GL.GL_SCISSOR_TEST; + STENCIL_TEST = GL.GL_STENCIL_TEST; + DEPTH_TEST = GL.GL_DEPTH_TEST; + DEPTH_WRITEMASK = GL.GL_DEPTH_WRITEMASK; + ALPHA_TEST = GL2ES1.GL_ALPHA_TEST; + + COLOR_BUFFER_BIT = GL.GL_COLOR_BUFFER_BIT; + DEPTH_BUFFER_BIT = GL.GL_DEPTH_BUFFER_BIT; + STENCIL_BUFFER_BIT = GL.GL_STENCIL_BUFFER_BIT; + + FRAMEBUFFER = GL.GL_FRAMEBUFFER; + COLOR_ATTACHMENT0 = GL.GL_COLOR_ATTACHMENT0; + COLOR_ATTACHMENT1 = GL2ES2.GL_COLOR_ATTACHMENT1; + COLOR_ATTACHMENT2 = GL2ES2.GL_COLOR_ATTACHMENT2; + COLOR_ATTACHMENT3 = GL2ES2.GL_COLOR_ATTACHMENT3; + RENDERBUFFER = GL.GL_RENDERBUFFER; + DEPTH_ATTACHMENT = GL.GL_DEPTH_ATTACHMENT; + STENCIL_ATTACHMENT = GL.GL_STENCIL_ATTACHMENT; + READ_FRAMEBUFFER = GL2ES3.GL_READ_FRAMEBUFFER; + DRAW_FRAMEBUFFER = GL2ES3.GL_DRAW_FRAMEBUFFER; + + RGBA8 = GL.GL_RGBA8; + DEPTH24_STENCIL8 = GL.GL_DEPTH24_STENCIL8; + + DEPTH_COMPONENT = GL2ES2.GL_DEPTH_COMPONENT; + DEPTH_COMPONENT16 = GL.GL_DEPTH_COMPONENT16; + DEPTH_COMPONENT24 = GL.GL_DEPTH_COMPONENT24; + DEPTH_COMPONENT32 = GL.GL_DEPTH_COMPONENT32; + + STENCIL_INDEX = GL2ES2.GL_STENCIL_INDEX; + STENCIL_INDEX1 = GL.GL_STENCIL_INDEX1; + STENCIL_INDEX4 = GL.GL_STENCIL_INDEX4; + STENCIL_INDEX8 = GL.GL_STENCIL_INDEX8; + + DEPTH_STENCIL = GL.GL_DEPTH_STENCIL; + + FRAMEBUFFER_COMPLETE = GL.GL_FRAMEBUFFER_COMPLETE; + FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; + FRAMEBUFFER_INCOMPLETE_DIMENSIONS = GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + FRAMEBUFFER_INCOMPLETE_FORMATS = GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS; + FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER; + FRAMEBUFFER_INCOMPLETE_READ_BUFFER = GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER; + FRAMEBUFFER_UNSUPPORTED = GL.GL_FRAMEBUFFER_UNSUPPORTED; + + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE; + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME; + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = GL.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL; + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = GL.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE; + + RENDERBUFFER_WIDTH = GL.GL_RENDERBUFFER_WIDTH; + RENDERBUFFER_HEIGHT = GL.GL_RENDERBUFFER_HEIGHT; + RENDERBUFFER_RED_SIZE = GL.GL_RENDERBUFFER_RED_SIZE; + RENDERBUFFER_GREEN_SIZE = GL.GL_RENDERBUFFER_GREEN_SIZE; + RENDERBUFFER_BLUE_SIZE = GL.GL_RENDERBUFFER_BLUE_SIZE; + RENDERBUFFER_ALPHA_SIZE = GL.GL_RENDERBUFFER_ALPHA_SIZE; + RENDERBUFFER_DEPTH_SIZE = GL.GL_RENDERBUFFER_DEPTH_SIZE; + RENDERBUFFER_STENCIL_SIZE = GL.GL_RENDERBUFFER_STENCIL_SIZE; + RENDERBUFFER_INTERNAL_FORMAT = GL.GL_RENDERBUFFER_INTERNAL_FORMAT; + + MULTISAMPLE = GL.GL_MULTISAMPLE; + POINT_SMOOTH = GL2ES1.GL_POINT_SMOOTH; + LINE_SMOOTH = GL.GL_LINE_SMOOTH; + POLYGON_SMOOTH = GL2GL3.GL_POLYGON_SMOOTH; + } + + /////////////////////////////////////////////////////////// + + // Special Functions + + @Override + public void flush() { + gl.glFlush(); + } + + @Override + public void finish() { + gl.glFinish(); + } + + @Override + public void hint(int target, int hint) { + gl.glHint(target, hint); + } + + /////////////////////////////////////////////////////////// + + // State and State Requests + + @Override + public void enable(int value) { + if (-1 < value) { + gl.glEnable(value); + } + } + + @Override + public void disable(int value) { + if (-1 < value) { + gl.glDisable(value); + } + } + + @Override + public void getBooleanv(int value, IntBuffer data) { + if (-1 < value) { + if (byteBuffer.capacity() < data.capacity()) { + byteBuffer = allocateDirectByteBuffer(data.capacity()); + } + gl.glGetBooleanv(value, byteBuffer); + for (int i = 0; i < data.capacity(); i++) { + data.put(i, byteBuffer.get(i)); + } + } else { + fillIntBuffer(data, 0, data.capacity() - 1, 0); + } + } + + @Override + public void getIntegerv(int value, IntBuffer data) { + if (-1 < value) { + gl.glGetIntegerv(value, data); + } else { + fillIntBuffer(data, 0, data.capacity() - 1, 0); + } + } + + @Override + public void getFloatv(int value, FloatBuffer data) { + if (-1 < value) { + gl.glGetFloatv(value, data); + } else { + fillFloatBuffer(data, 0, data.capacity() - 1, 0); + } + } + + @Override + public boolean isEnabled(int value) { + return gl.glIsEnabled(value); + } + + @Override + public String getString(int name) { + return gl.glGetString(name); + } + + /////////////////////////////////////////////////////////// + + // Error Handling + + @Override + public int getError() { + return gl.glGetError(); + } + + @Override + public String errorString(int err) { + return glu.gluErrorString(err); + } + + ////////////////////////////////////////////////////////////////////////////// + + // Buffer Objects + + @Override + public void genBuffers(int n, IntBuffer buffers) { + gl.glGenBuffers(n, buffers); + } + + @Override + public void deleteBuffers(int n, IntBuffer buffers) { + gl.glDeleteBuffers(n, buffers); + } + + @Override + public void bindBuffer(int target, int buffer) { + gl.glBindBuffer(target, buffer); + } + + @Override + public void bufferData(int target, int size, Buffer data, int usage) { + gl.glBufferData(target, size, data, usage); + } + + @Override + public void bufferSubData(int target, int offset, int size, Buffer data) { + gl.glBufferSubData(target, offset, size, data); + } + + @Override + public void isBuffer(int buffer) { + gl.glIsBuffer(buffer); + } + + @Override + public void getBufferParameteriv(int target, int value, IntBuffer data) { + gl.glGetBufferParameteriv(target, value, data); + } + + @Override + public ByteBuffer mapBuffer(int target, int access) { + return gl2.glMapBuffer(target, access); + } + + @Override + public ByteBuffer mapBufferRange(int target, int offset, int length, int access) { + if (gl2x != null) { + return gl2x.glMapBufferRange(target, offset, length, access); + } else if (gl3 != null) { + return gl3.glMapBufferRange(target, offset, length, access); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glMapBufferRange()")); + } + } + + @Override + public void unmapBuffer(int target) { + gl2.glUnmapBuffer(target); + } + + ////////////////////////////////////////////////////////////////////////////// + + // Viewport and Clipping + + @Override + public void depthRangef(float n, float f) { + gl.glDepthRangef(n, f); + } + + @Override + public void viewport(int x, int y, int w, int h) { +// gl.glViewport(pixel_scale * x, pixel_scale * y, pixel_scale * w, pixel_scale * h); + gl.glViewport(x, y, w, h); + } + + ////////////////////////////////////////////////////////////////////////////// + + // Reading Pixels + + @Override + protected void readPixelsImpl(int x, int y, int width, int height, int format, int type, Buffer buffer) { + gl.glReadPixels(x, y, width, height, format, type, buffer); + } + + ////////////////////////////////////////////////////////////////////////////// + + // Vertices + + @Override + public void vertexAttrib1f(int index, float value) { + gl2.glVertexAttrib1f(index, value); + } + + @Override + public void vertexAttrib2f(int index, float value0, float value1) { + gl2.glVertexAttrib2f(index, value0, value1); + } + + @Override + public void vertexAttrib3f(int index, float value0, float value1, float value2) { + gl2.glVertexAttrib3f(index, value0, value1, value2); + } + + @Override + public void vertexAttrib4f(int index, float value0, float value1, float value2, float value3) { + gl2.glVertexAttrib4f(index, value0, value1, value2, value3); + } + + @Override + public void vertexAttrib1fv(int index, FloatBuffer values) { + gl2.glVertexAttrib1fv(index, values); + } + + @Override + public void vertexAttrib2fv(int index, FloatBuffer values) { + gl2.glVertexAttrib2fv(index, values); + } + + @Override + public void vertexAttrib3fv(int index, FloatBuffer values) { + gl2.glVertexAttrib3fv(index, values); + } + + @Override + public void vertexAttri4fv(int index, FloatBuffer values) { + gl2.glVertexAttrib4fv(index, values); + } + + @Override + public void vertexAttribPointer(int index, int size, int type, boolean normalized, int stride, int offset) { + gl2.glVertexAttribPointer(index, size, type, normalized, stride, offset); + } + + @Override + public void vertexAttribPointer(int index, int size, int type, boolean normalized, int stride, Buffer data) { + if (gl2x != null) { + gl2x.glVertexAttribPointer(index, size, type, normalized, stride, data); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glVertexAttribPointer()")); + } + } + + @Override + public void enableVertexAttribArray(int index) { + gl2.glEnableVertexAttribArray(index); + } + + @Override + public void disableVertexAttribArray(int index) { + gl2.glDisableVertexAttribArray(index); + } + + @Override + public void drawArrays(int mode, int first, int count) { + gl.glDrawArrays(mode, first, count); + } + + @Override + public void drawElements(int mode, int count, int type, int offset) { + gl.glDrawElements(mode, count, type, offset); + } + + @Override + public void drawElements(int mode, int count, int type, Buffer indices) { + if (gl2x != null) { + gl2x.glDrawElements(mode, count, type, indices); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glDrawElements()")); + } + } + + ////////////////////////////////////////////////////////////////////////////// + + // Rasterization + + @Override + public void lineWidth(float width) { + gl.glLineWidth(width); + } + + @Override + public void frontFace(int dir) { + gl.glFrontFace(dir); + } + + @Override + public void cullFace(int mode) { + gl.glCullFace(mode); + } + + @Override + public void polygonOffset(float factor, float units) { + gl.glPolygonOffset(factor, units); + } + + ////////////////////////////////////////////////////////////////////////////// + + // Pixel Rectangles + + @Override + public void pixelStorei(int pname, int param) { + gl.glPixelStorei(pname, param); + } + + /////////////////////////////////////////////////////////// + + // Texturing + + @Override + public void texImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer data) { + gl.glTexImage2D(target, level, internalFormat, width, height, border, format, type, data); + } + + @Override + public void copyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border) { + gl.glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border); + } + + @Override + public void texSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, Buffer data) { + gl.glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, data); + } + + @Override + public void copyTexSubImage2D(int target, int level, int xOffset, int yOffset, int x, int y, int width, int height) { + gl.glCopyTexSubImage2D(target, level, x, y, xOffset, yOffset, width, height); + } + + @Override + public void compressedTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int imageSize, Buffer data) { + gl.glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data); + } + + @Override + public void compressedTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int imageSize, Buffer data) { + gl.glCompressedTexSubImage2D(target, level, xOffset, yOffset, width, height, format, imageSize, data); + } + + @Override + public void texParameteri(int target, int pname, int param) { + gl.glTexParameteri(target, pname, param); + } + + @Override + public void texParameterf(int target, int pname, float param) { + gl.glTexParameterf(target, pname, param); + } + + @Override + public void texParameteriv(int target, int pname, IntBuffer params) { + gl.glTexParameteriv(target, pname, params); + } + + @Override + public void texParameterfv(int target, int pname, FloatBuffer params) { + gl.glTexParameterfv(target, pname, params); + } + + @Override + public void generateMipmap(int target) { + gl.glGenerateMipmap(target); + } + + @Override + public void genTextures(int n, IntBuffer textures) { + gl.glGenTextures(n, textures); + } + + @Override + public void deleteTextures(int n, IntBuffer textures) { + gl.glDeleteTextures(n, textures); + } + + @Override + public void getTexParameteriv(int target, int pname, IntBuffer params) { + gl.glGetTexParameteriv(target, pname, params); + } + + @Override + public void getTexParameterfv(int target, int pname, FloatBuffer params) { + gl.glGetTexParameterfv(target, pname, params); + } + + @Override + public boolean isTexture(int texture) { + return gl.glIsTexture(texture); + } + + @Override + protected void activeTextureImpl(int texture) { + gl.glActiveTexture(texture); + } + + @Override + protected void bindTextureImpl(int target, int texture) { + gl.glBindTexture(target, texture); + } + + /////////////////////////////////////////////////////////// + + // Shaders and Programs + + @Override + public int createShader(int type) { + return gl2.glCreateShader(type); + } + + @Override + public void shaderSource(int shader, String source) { + gl2.glShaderSource(shader, 1, new String[] { source }, (int[]) null, 0); + } + + @Override + public void compileShader(int shader) { + gl2.glCompileShader(shader); + } + + @Override + public void releaseShaderCompiler() { + gl2.glReleaseShaderCompiler(); + } + + @Override + public void deleteShader(int shader) { + gl2.glDeleteShader(shader); + } + + @Override + public void shaderBinary(int count, IntBuffer shaders, int binaryFormat, Buffer binary, int length) { + gl2.glShaderBinary(count, shaders, binaryFormat, binary, length); + } + + @Override + public int createProgram() { + return gl2.glCreateProgram(); + } + + @Override + public void attachShader(int program, int shader) { + gl2.glAttachShader(program, shader); + } + + @Override + public void detachShader(int program, int shader) { + gl2.glDetachShader(program, shader); + } + + @Override + public void linkProgram(int program) { + gl2.glLinkProgram(program); + } + + @Override + public void useProgram(int program) { + gl2.glUseProgram(program); + } + + @Override + public void deleteProgram(int program) { + gl2.glDeleteProgram(program); + } + + @Override + public String getActiveAttrib(int program, int index, IntBuffer size, IntBuffer type) { + int[] tmp = {0, 0, 0}; + byte[] namebuf = new byte[1024]; + gl2.glGetActiveAttrib(program, index, 1024, tmp, 0, tmp, 1, tmp, 2, namebuf, 0); + size.put(tmp[1]); + type.put(tmp[2]); + String name = new String(namebuf, 0, tmp[0]); + return name; + } + + @Override + public int getAttribLocation(int program, String name) { + return gl2.glGetAttribLocation(program, name); + } + + @Override + public void bindAttribLocation(int program, int index, String name) { + gl2.glBindAttribLocation(program, index, name); + } + + @Override + public int getUniformLocation(int program, String name) { + return gl2.glGetUniformLocation(program, name); + } + + @Override + public String getActiveUniform(int program, int index, IntBuffer size, IntBuffer type) { + int[] tmp= {0, 0, 0}; + byte[] namebuf = new byte[1024]; + gl2.glGetActiveUniform(program, index, 1024, tmp, 0, tmp, 1, tmp, 2, namebuf, 0); + size.put(tmp[1]); + type.put(tmp[2]); + String name = new String(namebuf, 0, tmp[0]); + return name; + } + + @Override + public void uniform1i(int location, int value) { + gl2.glUniform1i(location, value); + } + + @Override + public void uniform2i(int location, int value0, int value1) { + gl2.glUniform2i(location, value0, value1); + } + + @Override + public void uniform3i(int location, int value0, int value1, int value2) { + gl2.glUniform3i(location, value0, value1, value2); + } + + @Override + public void uniform4i(int location, int value0, int value1, int value2, int value3) { + gl2.glUniform4i(location, value0, value1, value2, value3); + } + + @Override + public void uniform1f(int location, float value) { + gl2.glUniform1f(location, value); + } + + @Override + public void uniform2f(int location, float value0, float value1) { + gl2.glUniform2f(location, value0, value1); + } + + @Override + public void uniform3f(int location, float value0, float value1, float value2) { + gl2.glUniform3f(location, value0, value1, value2); + } + + @Override + public void uniform4f(int location, float value0, float value1, float value2, float value3) { + gl2.glUniform4f(location, value0, value1, value2, value3); + } + + @Override + public void uniform1iv(int location, int count, IntBuffer v) { + gl2.glUniform1iv(location, count, v); + } + + @Override + public void uniform2iv(int location, int count, IntBuffer v) { + gl2.glUniform2iv(location, count, v); + } + + @Override + public void uniform3iv(int location, int count, IntBuffer v) { + gl2.glUniform3iv(location, count, v); + } + + @Override + public void uniform4iv(int location, int count, IntBuffer v) { + gl2.glUniform4iv(location, count, v); + } + + @Override + public void uniform1fv(int location, int count, FloatBuffer v) { + gl2.glUniform1fv(location, count, v); + } + + @Override + public void uniform2fv(int location, int count, FloatBuffer v) { + gl2.glUniform2fv(location, count, v); + } + + @Override + public void uniform3fv(int location, int count, FloatBuffer v) { + gl2.glUniform3fv(location, count, v); + } + + @Override + public void uniform4fv(int location, int count, FloatBuffer v) { + gl2.glUniform4fv(location, count, v); + } + + @Override + public void uniformMatrix2fv(int location, int count, boolean transpose, FloatBuffer mat) { + gl2.glUniformMatrix2fv(location, count, transpose, mat); + } + + @Override + public void uniformMatrix3fv(int location, int count, boolean transpose, FloatBuffer mat) { + gl2.glUniformMatrix3fv(location, count, transpose, mat); + } + + @Override + public void uniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer mat) { + gl2.glUniformMatrix4fv(location, count, transpose, mat); + } + + @Override + public void validateProgram(int program) { + gl2.glValidateProgram(program); + } + + @Override + public boolean isShader(int shader) { + return gl2.glIsShader(shader); + } + + @Override + public void getShaderiv(int shader, int pname, IntBuffer params) { + gl2.glGetShaderiv(shader, pname, params); + } + + @Override + public void getAttachedShaders(int program, int maxCount, IntBuffer count, IntBuffer shaders) { + gl2.glGetAttachedShaders(program, maxCount, count, shaders); + } + + @Override + public String getShaderInfoLog(int shader) { + int[] val = { 0 }; + gl2.glGetShaderiv(shader, GL2ES2.GL_INFO_LOG_LENGTH, val, 0); + int length = val[0]; + + byte[] log = new byte[length]; + gl2.glGetShaderInfoLog(shader, length, val, 0, log, 0); + return new String(log); + } + + @Override + public String getShaderSource(int shader) { + int[] len = {0}; + byte[] buf = new byte[1024]; + gl2.glGetShaderSource(shader, 1024, len, 0, buf, 0); + return new String(buf, 0, len[0]); + } + + @Override + public void getShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision) { + gl2.glGetShaderPrecisionFormat(shaderType, precisionType, range, precision); + } + + @Override + public void getVertexAttribfv(int index, int pname, FloatBuffer params) { + gl2.glGetVertexAttribfv(index, pname, params); + } + + @Override + public void getVertexAttribiv(int index, int pname, IntBuffer params) { + gl2.glGetVertexAttribiv(index, pname, params); + } + + @Override + public void getVertexAttribPointerv(int index, int pname, ByteBuffer data) { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glGetVertexAttribPointerv()")); + } + + @Override + public void getUniformfv(int program, int location, FloatBuffer params) { + gl2.glGetUniformfv(program, location, params); + } + + @Override + public void getUniformiv(int program, int location, IntBuffer params) { + gl2.glGetUniformiv(program, location, params); + } + + @Override + public boolean isProgram(int program) { + return gl2.glIsProgram(program); + } + + @Override + public void getProgramiv(int program, int pname, IntBuffer params) { + gl2.glGetProgramiv(program, pname, params); + } + + @Override + public String getProgramInfoLog(int program) { + int[] val = { 0 }; + gl2.glGetShaderiv(program, GL2ES2.GL_INFO_LOG_LENGTH, val, 0); + int length = val[0]; + + if (0 < length) { + byte[] log = new byte[length]; + gl2.glGetProgramInfoLog(program, length, val, 0, log, 0); + return new String(log); + } else { + return "Unknow error"; + } + } + + /////////////////////////////////////////////////////////// + + // Per-Fragment Operations + + @Override + public void scissor(int x, int y, int w, int h) { +// gl.glScissor(pixel_scale * x, pixel_scale * y, pixel_scale * w, pixel_scale * h); + gl.glScissor(x, y, w, h); + } + + @Override + public void sampleCoverage(float value, boolean invert) { + gl2.glSampleCoverage(value, invert); + } + + @Override + public void stencilFunc(int func, int ref, int mask) { + gl2.glStencilFunc(func, ref, mask); + } + + @Override + public void stencilFuncSeparate(int face, int func, int ref, int mask) { + gl2.glStencilFuncSeparate(face, func, ref, mask); + } + + @Override + public void stencilOp(int sfail, int dpfail, int dppass) { + gl2.glStencilOp(sfail, dpfail, dppass); + } + + @Override + public void stencilOpSeparate(int face, int sfail, int dpfail, int dppass) { + gl2.glStencilOpSeparate(face, sfail, dpfail, dppass); + } + + @Override + public void depthFunc(int func) { + gl.glDepthFunc(func); + } + + @Override + public void blendEquation(int mode) { + gl.glBlendEquation(mode); + } + + @Override + public void blendEquationSeparate(int modeRGB, int modeAlpha) { + gl.glBlendEquationSeparate(modeRGB, modeAlpha); + } + + @Override + public void blendFunc(int src, int dst) { + gl.glBlendFunc(src, dst); + } + + @Override + public void blendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { + gl.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + } + + @Override + public void blendColor(float red, float green, float blue, float alpha) { + gl2.glBlendColor(red, green, blue, alpha); + } + + @Override + public void alphaFunc(int func, float ref) { + if (gl2x != null) { + gl2x.glAlphaFunc(func, ref); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glAlphaFunc()")); + } + } + + /////////////////////////////////////////////////////////// + + // Whole Framebuffer Operations + + @Override + public void colorMask(boolean r, boolean g, boolean b, boolean a) { + gl.glColorMask(r, g, b, a); + } + + @Override + public void depthMask(boolean mask) { + gl.glDepthMask(mask); + } + + @Override + public void stencilMask(int mask) { + gl.glStencilMask(mask); + } + + @Override + public void stencilMaskSeparate(int face, int mask) { + gl2.glStencilMaskSeparate(face, mask); + } + + @Override + public void clear(int buf) { + gl.glClear(buf); + } + + @Override + public void clearColor(float r, float g, float b, float a) { + gl.glClearColor(r, g, b, a); + } + + @Override + public void clearDepth(float d) { + gl.glClearDepthf(d); + } + + @Override + public void clearStencil(int s) { + gl.glClearStencil(s); + } + + /////////////////////////////////////////////////////////// + + // Framebuffers Objects + + @Override + protected void bindFramebufferImpl(int target, int framebuffer) { + gl.glBindFramebuffer(target, framebuffer); + } + + @Override + public void deleteFramebuffers(int n, IntBuffer framebuffers) { + gl.glDeleteFramebuffers(n, framebuffers); + } + + @Override + public void genFramebuffers(int n, IntBuffer framebuffers) { + gl.glGenFramebuffers(n, framebuffers); + } + + @Override + public void bindRenderbuffer(int target, int renderbuffer) { + gl.glBindRenderbuffer(target, renderbuffer); + } + + @Override + public void deleteRenderbuffers(int n, IntBuffer renderbuffers) { + gl.glDeleteRenderbuffers(n, renderbuffers); + } + + @Override + public void genRenderbuffers(int n, IntBuffer renderbuffers) { + gl.glGenRenderbuffers(n, renderbuffers); + } + + @Override + public void renderbufferStorage(int target, int internalFormat, int width, int height) { + gl.glRenderbufferStorage(target, internalFormat, width, height); + } + + @Override + public void framebufferRenderbuffer(int target, int attachment, int rendbuferfTarget, int renderbuffer) { + gl.glFramebufferRenderbuffer(target, attachment, rendbuferfTarget, renderbuffer); + } + + @Override + public void framebufferTexture2D(int target, int attachment, int texTarget, int texture, int level) { + gl.glFramebufferTexture2D(target, attachment, texTarget, texture, level); + } + + @Override + public int checkFramebufferStatus(int target) { + return gl.glCheckFramebufferStatus(target); + } + + @Override + public boolean isFramebuffer(int framebuffer) { + return gl2.glIsFramebuffer(framebuffer); + } + + @Override + public void getFramebufferAttachmentParameteriv(int target, int attachment, int pname, IntBuffer params) { + gl2.glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); + } + + @Override + public boolean isRenderbuffer(int renderbuffer) { + return gl2.glIsRenderbuffer(renderbuffer); + } + + @Override + public void getRenderbufferParameteriv(int target, int pname, IntBuffer params) { + gl2.glGetRenderbufferParameteriv(target, pname, params); + } + + @Override + public void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { + if (gl2x != null) { + gl2x.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } else if (gl3 != null) { + gl3.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glBlitFramebuffer()")); + } + } + + @Override + public void renderbufferStorageMultisample(int target, int samples, int format, int width, int height) { + if (gl2x != null) { + gl2x.glRenderbufferStorageMultisample(target, samples, format, width, height); + } else if (gl3 != null) { + gl3.glRenderbufferStorageMultisample(target, samples, format, width, height); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glRenderbufferStorageMultisample()")); + } + } + + @Override + public void readBuffer(int buf) { + if (gl2x != null) { + gl2x.glReadBuffer(buf); + } else if (gl3 != null) { + gl3.glReadBuffer(buf); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glReadBuffer()")); + } + } + + @Override + public void drawBuffer(int buf) { + if (gl2x != null) { + gl2x.glDrawBuffer(buf); + } else if (gl3 != null) { + gl3.glDrawBuffer(buf); + } else { + throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glDrawBuffer()")); + } + } +} diff --git a/core/src/processing/opengl/PLWJGL.java b/core/src/processing/opengl/PLWJGL.java deleted file mode 100644 index 810274b23..000000000 --- a/core/src/processing/opengl/PLWJGL.java +++ /dev/null @@ -1,1703 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import java.awt.Canvas; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Shape; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.geom.PathIterator; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.ShortBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.opengl.ARBES2Compatibility; -import org.lwjgl.opengl.EXTFramebufferObject; -import org.lwjgl.opengl.EXTTextureFilterAnisotropic; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL14; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL20; -import org.lwjgl.opengl.GL30; -import org.lwjgl.opengl.GL31; -import org.lwjgl.util.glu.GLU; -import org.lwjgl.util.glu.GLUtessellator; -import org.lwjgl.util.glu.GLUtessellatorCallbackAdapter; - -import processing.opengl.PGL; -import processing.opengl.PGraphicsOpenGL; - -/** - * Processing-OpenGL abstraction layer. LWJGL implementation. - * - * Some issues: - * http://lwjgl.org/forum/index.php/topic,4711.0.html - * http://www.java-gaming.org/topics/cannot-add-mouselistener-to-java-awt-canvas-with-lwjgl-on-windows/24650/view.html - * - */ -public class PLWJGL extends PGL { - // ........................................................ - - // Public members to access the underlying GL objects and canvas - - /** GLU interface **/ - public static GLU glu; - - /** The canvas where OpenGL rendering takes place */ - public static Canvas canvas; - - // ........................................................ - - // Utility buffers to copy projection/modelview matrices to GL - - protected FloatBuffer projMatrix; - protected FloatBuffer mvMatrix; - - // ........................................................ - - // Static initialization for some parameters that need to be different for - // LWJGL - - static { - MIN_DIRECT_BUFFER_SIZE = 16; - INDEX_TYPE = GL11.GL_UNSIGNED_SHORT; - } - - - /////////////////////////////////////////////////////////// - - // Initialization, finalization - - - public PLWJGL(PGraphicsOpenGL pg) { - super(pg); - if (glu == null) glu = new GLU(); - } - - - public Canvas getCanvas() { - return canvas; - } - - -// protected void setFps(float fps) { -// if (!setFps || targetFps != fps) { -// if (60 < fps) { -// // Disables v-sync -// System.err.println("Disabling VSync"); -// Display.setVSyncEnabled(false); -//// Display.sync((int)fps); -// } else { -// Display.setVSyncEnabled(true); -// } -// targetFps = currentFps = fps; -// setFps = true; -// } -// } - -/* - protected void initSurface(int antialias) { - if (canvas != null) { - keyPoller.requestStop(); - mousePoller.requestStop(); - - try { - Display.setParent(null); - } catch (LWJGLException e) { - e.printStackTrace(); - } - Display.destroy(); - - pg.parent.remove(canvas); - } - - canvas = new Canvas(); - canvas.setFocusable(true); - canvas.requestFocus(); - canvas.setBackground(new Color(pg.backgroundColor, true)); - canvas.setBounds(0, 0, pg.parent.width, pg.parent.height); - - pg.parent.setLayout(new BorderLayout()); - pg.parent.add(canvas, BorderLayout.CENTER); - - try { - DisplayMode[] modes = Display.getAvailableDisplayModes(); - int bpp = 0; - for (int i = 0; i < modes.length; i++) { - bpp = PApplet.max(modes[i].getBitsPerPixel(), bpp); - } - - PixelFormat format; - if (USE_FBOLAYER_BY_DEFAULT) { - format = new PixelFormat(bpp, REQUESTED_ALPHA_BITS, - REQUESTED_DEPTH_BITS, - REQUESTED_STENCIL_BITS, 1); - reqNumSamples = qualityToSamples(antialias); - fboLayerRequested = true; - } else { - format = new PixelFormat(bpp, REQUESTED_ALPHA_BITS, - REQUESTED_DEPTH_BITS, - REQUESTED_STENCIL_BITS, antialias); - fboLayerRequested = false; - } - - Display.setDisplayMode(new DisplayMode(pg.parent.width, pg.parent.height)); - int argb = pg.backgroundColor; - float r = ((argb >> 16) & 0xff) / 255.0f; - float g = ((argb >> 8) & 0xff) / 255.0f; - float b = ((argb) & 0xff) / 255.0f; - Display.setInitialBackground(r, g, b); - Display.setParent(canvas); - Display.create(format); - - // Might be useful later to specify the context attributes. - // http://lwjgl.org/javadoc/org/lwjgl/opengl/ContextAttribs.html -// ContextAttribs contextAtrributes = new ContextAttribs(4, 0); -// contextAtrributes.withForwardCompatible(true); -// contextAtrributes.withProfileCore(true); -// Display.create(pixelFormat, contextAtrributes); - } catch (LWJGLException e) { - e.printStackTrace(); - } - - glContext = Display.getDrawable().hashCode(); - - registerListeners(); - - fboLayerCreated = false; - fboLayerInUse = false; - firstFrame = true; - setFps = false; - } -*/ - -// protected void reinitSurface() { } - - -// protected void registerListeners() { -// keyPoller = new KeyPoller(pg.parent); -// keyPoller.start(); -// -// mousePoller = new MousePoller(pg.parent); -// mousePoller.start(); -// } - - - /////////////////////////////////////////////////////////// - - // Frame rendering - - -// protected boolean canDraw() { -// return pg.initialized && pg.parent.isDisplayable(); -// } -// - -// protected void requestFocus() { } - - -// protected void requestDraw() { -// if (pg.initialized) { -// glThread = Thread.currentThread(); -// pg.parent.handleDraw(); -// Display.update(); -// } -// } -// -// -// protected void swapBuffers() { -// try { -// Display.swapBuffers(); -// } catch (LWJGLException e) { -// e.printStackTrace(); -// } -// } - - - @Override - protected void beginGL() { - if (projMatrix == null) { - projMatrix = allocateFloatBuffer(16); - } - GL11.glMatrixMode(GL11.GL_PROJECTION); - projMatrix.rewind(); - projMatrix.put(pg.projection.m00); - projMatrix.put(pg.projection.m10); - projMatrix.put(pg.projection.m20); - projMatrix.put(pg.projection.m30); - projMatrix.put(pg.projection.m01); - projMatrix.put(pg.projection.m11); - projMatrix.put(pg.projection.m21); - projMatrix.put(pg.projection.m31); - projMatrix.put(pg.projection.m02); - projMatrix.put(pg.projection.m12); - projMatrix.put(pg.projection.m22); - projMatrix.put(pg.projection.m32); - projMatrix.put(pg.projection.m03); - projMatrix.put(pg.projection.m13); - projMatrix.put(pg.projection.m23); - projMatrix.put(pg.projection.m33); - projMatrix.rewind(); - GL11.glLoadMatrixf(projMatrix); - - if (mvMatrix == null) { - mvMatrix = allocateFloatBuffer(16); - } - GL11.glMatrixMode(GL11.GL_MODELVIEW); - mvMatrix.rewind(); - mvMatrix.put(pg.modelview.m00); - mvMatrix.put(pg.modelview.m10); - mvMatrix.put(pg.modelview.m20); - mvMatrix.put(pg.modelview.m30); - mvMatrix.put(pg.modelview.m01); - mvMatrix.put(pg.modelview.m11); - mvMatrix.put(pg.modelview.m21); - mvMatrix.put(pg.modelview.m31); - mvMatrix.put(pg.modelview.m02); - mvMatrix.put(pg.modelview.m12); - mvMatrix.put(pg.modelview.m22); - mvMatrix.put(pg.modelview.m32); - mvMatrix.put(pg.modelview.m03); - mvMatrix.put(pg.modelview.m13); - mvMatrix.put(pg.modelview.m23); - mvMatrix.put(pg.modelview.m33); - mvMatrix.rewind(); - GL11.glLoadMatrixf(mvMatrix); - } - - - /////////////////////////////////////////////////////////// - - // Utility functions - - - protected static ByteBuffer allocateDirectByteBuffer(int size) { - return BufferUtils.createByteBuffer(size); - } - - - protected static ShortBuffer allocateDirectShortBuffer(int size) { - return BufferUtils.createShortBuffer(size); - } - - - protected static IntBuffer allocateDirectIntBuffer(int size) { - return BufferUtils.createIntBuffer(size); - } - - - protected static FloatBuffer allocateDirectFloatBuffer(int size) { - return BufferUtils.createFloatBuffer(size); - } - - - @Override - protected int getFontAscent(Object font) { - return pg.getFontMetrics((Font) font).getAscent(); - } - - - @Override - protected int getFontDescent(Object font) { - return pg.getFontMetrics((Font) font).getDescent(); - } - - - @Override - protected int getTextWidth(Object font, char buffer[], int start, int stop) { - // maybe should use one of the newer/fancier functions for this? - int length = stop - start; - FontMetrics metrics = pg.getFontMetrics((Font) font); - return metrics.charsWidth(buffer, start, length); - } - - - @Override - protected Object getDerivedFont(Object font, float size) { - return ((Font) font).deriveFont(size); - } - - - /////////////////////////////////////////////////////////// - - // Tessellator interface - - - @Override - protected Tessellator createTessellator(TessellatorCallback callback) { - return new Tessellator(callback); - } - - - protected class Tessellator implements PGL.Tessellator { - protected GLUtessellator tess; - protected TessellatorCallback callback; - protected GLUCallback gluCallback; - - public Tessellator(TessellatorCallback callback) { - this.callback = callback; - tess = GLU.gluNewTess(); - gluCallback = new GLUCallback(); - - tess.gluTessCallback(GLU.GLU_TESS_BEGIN, gluCallback); - tess.gluTessCallback(GLU.GLU_TESS_END, gluCallback); - tess.gluTessCallback(GLU.GLU_TESS_VERTEX, gluCallback); - tess.gluTessCallback(GLU.GLU_TESS_COMBINE, gluCallback); - tess.gluTessCallback(GLU.GLU_TESS_ERROR, gluCallback); - } - - public void beginPolygon() { - tess.gluTessBeginPolygon(null); - } - - public void endPolygon() { - tess.gluTessEndPolygon(); - } - - public void setWindingRule(int rule) { - tess.gluTessProperty(GLU.GLU_TESS_WINDING_RULE, rule); - } - - public void beginContour() { - tess.gluTessBeginContour(); - } - - public void endContour() { - tess.gluTessEndContour(); - } - - public void addVertex(double[] v) { - tess.gluTessVertex(v, 0, v); - } - - protected class GLUCallback extends GLUtessellatorCallbackAdapter { - @Override - public void begin(int type) { - callback.begin(type); - } - - @Override - public void end() { - callback.end(); - } - - @Override - public void vertex(Object data) { - callback.vertex(data); - } - - @Override - public void combine(double[] coords, Object[] data, - float[] weight, Object[] outData) { - callback.combine(coords, data, weight, outData); - } - - @Override - public void error(int errnum) { - callback.error(errnum); - } - } - } - - - @Override - protected String tessError(int err) { - return GLU.gluErrorString(err); - } - - - /////////////////////////////////////////////////////////// - - // Font outline - - - static { - SHAPE_TEXT_SUPPORTED = true; - SEG_MOVETO = PathIterator.SEG_MOVETO; - SEG_LINETO = PathIterator.SEG_LINETO; - SEG_QUADTO = PathIterator.SEG_QUADTO; - SEG_CUBICTO = PathIterator.SEG_CUBICTO; - SEG_CLOSE = PathIterator.SEG_CLOSE; - } - - - @Override - protected FontOutline createFontOutline(char ch, Object font) { - return new FontOutline(ch, (Font) font); - } - - - protected class FontOutline implements PGL.FontOutline { - PathIterator iter; - - public FontOutline(char ch, Font font) { - char textArray[] = new char[] { ch }; - FontRenderContext frc = pg.getFontRenderContext(font); - GlyphVector gv = font.createGlyphVector(frc, textArray); - Shape shp = gv.getOutline(); - iter = shp.getPathIterator(null); - } - - public boolean isDone() { - return iter.isDone(); - } - - public int currentSegment(float coords[]) { - return iter.currentSegment(coords); - } - - public void next() { - iter.next(); - } - } - - - /////////////////////////////////////////////////////////// - - // Constants - - static { - FALSE = GL11.GL_FALSE; - TRUE = GL11.GL_TRUE; - - INT = GL11.GL_INT; - BYTE = GL11.GL_BYTE; - SHORT = GL11.GL_SHORT; - FLOAT = GL11.GL_FLOAT; - BOOL = GL20.GL_BOOL; - UNSIGNED_INT = GL11.GL_UNSIGNED_INT; - UNSIGNED_BYTE = GL11.GL_UNSIGNED_BYTE; - UNSIGNED_SHORT = GL11.GL_UNSIGNED_SHORT; - - RGB = GL11.GL_RGB; - RGBA = GL11.GL_RGBA; - ALPHA = GL11.GL_ALPHA; - LUMINANCE = GL11.GL_LUMINANCE; - LUMINANCE_ALPHA = GL11.GL_LUMINANCE_ALPHA; - - UNSIGNED_SHORT_5_6_5 = GL12.GL_UNSIGNED_SHORT_5_6_5; - UNSIGNED_SHORT_4_4_4_4 = GL12.GL_UNSIGNED_SHORT_4_4_4_4; - UNSIGNED_SHORT_5_5_5_1 = GL12.GL_UNSIGNED_SHORT_5_5_5_1; - - RGBA4 = GL11.GL_RGBA4; - RGB5_A1 = GL11.GL_RGB5_A1; - RGB565 = ARBES2Compatibility.GL_RGB565; - RGB8 = GL11.GL_RGB8; - RGBA8 = GL11.GL_RGBA8; - ALPHA8 = GL11.GL_ALPHA8; - - READ_ONLY = GL15.GL_READ_ONLY; - WRITE_ONLY = GL15.GL_WRITE_ONLY; - READ_WRITE = GL15.GL_READ_WRITE; - - TESS_WINDING_NONZERO = GLU.GLU_TESS_WINDING_NONZERO; - TESS_WINDING_ODD = GLU.GLU_TESS_WINDING_ODD; - - GENERATE_MIPMAP_HINT = GL14.GL_GENERATE_MIPMAP_HINT; - FASTEST = GL11.GL_FASTEST; - NICEST = GL11.GL_NICEST; - DONT_CARE = GL11.GL_DONT_CARE; - - VENDOR = GL11.GL_VENDOR; - RENDERER = GL11.GL_RENDERER; - VERSION = GL11.GL_VERSION; - EXTENSIONS = GL11.GL_EXTENSIONS; - SHADING_LANGUAGE_VERSION = GL20.GL_SHADING_LANGUAGE_VERSION; - - MAX_SAMPLES = GL30.GL_MAX_SAMPLES; - SAMPLES = GL13.GL_SAMPLES; - - ALIASED_LINE_WIDTH_RANGE = GL12.GL_ALIASED_LINE_WIDTH_RANGE; - ALIASED_POINT_SIZE_RANGE = GL12.GL_ALIASED_POINT_SIZE_RANGE; - - DEPTH_BITS = GL11.GL_DEPTH_BITS; - STENCIL_BITS = GL11.GL_STENCIL_BITS; - - CCW = GL11.GL_CCW; - CW = GL11.GL_CW; - - VIEWPORT = GL11.GL_VIEWPORT; - - ARRAY_BUFFER = GL15.GL_ARRAY_BUFFER; - ELEMENT_ARRAY_BUFFER = GL15.GL_ELEMENT_ARRAY_BUFFER; - - MAX_VERTEX_ATTRIBS = GL20.GL_MAX_VERTEX_ATTRIBS; - - STATIC_DRAW = GL15.GL_STATIC_DRAW; - DYNAMIC_DRAW = GL15.GL_DYNAMIC_DRAW; - STREAM_DRAW = GL15.GL_STREAM_DRAW; - - BUFFER_SIZE = GL15.GL_BUFFER_SIZE; - BUFFER_USAGE = GL15.GL_BUFFER_USAGE; - - POINTS = GL11.GL_POINTS; - LINE_STRIP = GL11.GL_LINE_STRIP; - LINE_LOOP = GL11.GL_LINE_LOOP; - LINES = GL11.GL_LINES; - TRIANGLE_FAN = GL11.GL_TRIANGLE_FAN; - TRIANGLE_STRIP = GL11.GL_TRIANGLE_STRIP; - TRIANGLES = GL11.GL_TRIANGLES; - - CULL_FACE = GL11.GL_CULL_FACE; - FRONT = GL11.GL_FRONT; - BACK = GL11.GL_BACK; - FRONT_AND_BACK = GL11.GL_FRONT_AND_BACK; - - POLYGON_OFFSET_FILL = GL11.GL_POLYGON_OFFSET_FILL; - - UNPACK_ALIGNMENT = GL11.GL_UNPACK_ALIGNMENT; - PACK_ALIGNMENT = GL11.GL_PACK_ALIGNMENT; - - TEXTURE_2D = GL11.GL_TEXTURE_2D; - TEXTURE_RECTANGLE = GL31.GL_TEXTURE_RECTANGLE; - - TEXTURE_BINDING_2D = GL11.GL_TEXTURE_BINDING_2D; - TEXTURE_BINDING_RECTANGLE = GL31.GL_TEXTURE_BINDING_RECTANGLE; - - MAX_TEXTURE_SIZE = GL11.GL_MAX_TEXTURE_SIZE; - TEXTURE_MAX_ANISOTROPY = EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT; - MAX_TEXTURE_MAX_ANISOTROPY = EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT; - - MAX_VERTEX_TEXTURE_IMAGE_UNITS = GL20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS; - MAX_TEXTURE_IMAGE_UNITS = GL20.GL_MAX_TEXTURE_IMAGE_UNITS; - MAX_COMBINED_TEXTURE_IMAGE_UNITS = GL20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS; - - NUM_COMPRESSED_TEXTURE_FORMATS = GL13.GL_NUM_COMPRESSED_TEXTURE_FORMATS; - COMPRESSED_TEXTURE_FORMATS = GL13.GL_COMPRESSED_TEXTURE_FORMATS; - - NEAREST = GL11.GL_NEAREST; - LINEAR = GL11.GL_LINEAR; - LINEAR_MIPMAP_NEAREST = GL11.GL_LINEAR_MIPMAP_NEAREST; - LINEAR_MIPMAP_LINEAR = GL11.GL_LINEAR_MIPMAP_LINEAR; - - CLAMP_TO_EDGE = GL12.GL_CLAMP_TO_EDGE; - REPEAT = GL11.GL_REPEAT; - - TEXTURE0 = GL13.GL_TEXTURE0; - TEXTURE1 = GL13.GL_TEXTURE1; - TEXTURE2 = GL13.GL_TEXTURE2; - TEXTURE3 = GL13.GL_TEXTURE3; - TEXTURE_MIN_FILTER = GL11.GL_TEXTURE_MIN_FILTER; - TEXTURE_MAG_FILTER = GL11.GL_TEXTURE_MAG_FILTER; - TEXTURE_WRAP_S = GL11.GL_TEXTURE_WRAP_S; - TEXTURE_WRAP_T = GL11.GL_TEXTURE_WRAP_T; - TEXTURE_WRAP_R = GL12.GL_TEXTURE_WRAP_R; - - TEXTURE_CUBE_MAP = GL13.GL_TEXTURE_CUBE_MAP; - TEXTURE_CUBE_MAP_POSITIVE_X = GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X; - TEXTURE_CUBE_MAP_POSITIVE_Y = GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_Y; - TEXTURE_CUBE_MAP_POSITIVE_Z = GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_Z; - TEXTURE_CUBE_MAP_NEGATIVE_X = GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_X; - TEXTURE_CUBE_MAP_NEGATIVE_Y = GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; - TEXTURE_CUBE_MAP_NEGATIVE_Z = GL13.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; - - VERTEX_SHADER = GL20.GL_VERTEX_SHADER; - FRAGMENT_SHADER = GL20.GL_FRAGMENT_SHADER; - INFO_LOG_LENGTH = GL20.GL_INFO_LOG_LENGTH; - SHADER_SOURCE_LENGTH = GL20.GL_SHADER_SOURCE_LENGTH; - COMPILE_STATUS = GL20.GL_COMPILE_STATUS; - LINK_STATUS = GL20.GL_LINK_STATUS; - VALIDATE_STATUS = GL20.GL_VALIDATE_STATUS; - SHADER_TYPE = GL20.GL_SHADER_TYPE; - DELETE_STATUS = GL20.GL_DELETE_STATUS; - - FLOAT_VEC2 = GL20.GL_FLOAT_VEC2; - FLOAT_VEC3 = GL20.GL_FLOAT_VEC3; - FLOAT_VEC4 = GL20.GL_FLOAT_VEC4; - FLOAT_MAT2 = GL20.GL_FLOAT_MAT2; - FLOAT_MAT3 = GL20.GL_FLOAT_MAT3; - FLOAT_MAT4 = GL20.GL_FLOAT_MAT4; - INT_VEC2 = GL20.GL_INT_VEC2; - INT_VEC3 = GL20.GL_INT_VEC3; - INT_VEC4 = GL20.GL_INT_VEC4; - BOOL_VEC2 = GL20.GL_BOOL_VEC2; - BOOL_VEC3 = GL20.GL_BOOL_VEC3; - BOOL_VEC4 = GL20.GL_BOOL_VEC4; - SAMPLER_2D = GL20.GL_SAMPLER_2D; - SAMPLER_CUBE = GL20.GL_SAMPLER_CUBE; - - LOW_FLOAT = ARBES2Compatibility.GL_LOW_FLOAT; - MEDIUM_FLOAT = ARBES2Compatibility.GL_MEDIUM_FLOAT; - HIGH_FLOAT = ARBES2Compatibility.GL_HIGH_FLOAT; - LOW_INT = ARBES2Compatibility.GL_LOW_INT; - MEDIUM_INT = ARBES2Compatibility.GL_MEDIUM_INT; - HIGH_INT = ARBES2Compatibility.GL_HIGH_INT; - - CURRENT_VERTEX_ATTRIB = GL20.GL_CURRENT_VERTEX_ATTRIB; - - VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = GL15.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING; - VERTEX_ATTRIB_ARRAY_ENABLED = GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED; - VERTEX_ATTRIB_ARRAY_SIZE = GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE; - VERTEX_ATTRIB_ARRAY_STRIDE = GL20.GL_VERTEX_ATTRIB_ARRAY_STRIDE; - VERTEX_ATTRIB_ARRAY_TYPE = GL20.GL_VERTEX_ATTRIB_ARRAY_TYPE; - VERTEX_ATTRIB_ARRAY_NORMALIZED = GL20.GL_VERTEX_ATTRIB_ARRAY_NORMALIZED; - VERTEX_ATTRIB_ARRAY_POINTER = GL20.GL_VERTEX_ATTRIB_ARRAY_POINTER; - - BLEND = GL11.GL_BLEND; - ONE = GL11.GL_ONE; - ZERO = GL11.GL_ZERO; - SRC_ALPHA = GL11.GL_SRC_ALPHA; - DST_ALPHA = GL11.GL_DST_ALPHA; - ONE_MINUS_SRC_ALPHA = GL11.GL_ONE_MINUS_SRC_ALPHA; - ONE_MINUS_DST_COLOR = GL11.GL_ONE_MINUS_DST_COLOR; - ONE_MINUS_SRC_COLOR = GL11.GL_ONE_MINUS_SRC_COLOR; - DST_COLOR = GL11.GL_DST_COLOR; - SRC_COLOR = GL11.GL_SRC_COLOR; - - SAMPLE_ALPHA_TO_COVERAGE = GL13.GL_SAMPLE_ALPHA_TO_COVERAGE; - SAMPLE_COVERAGE = GL13.GL_SAMPLE_COVERAGE; - - KEEP = GL11.GL_KEEP; - REPLACE = GL11.GL_REPLACE; - INCR = GL11.GL_INCR; - DECR = GL11.GL_DECR; - INVERT = GL11.GL_INVERT; - INCR_WRAP = GL14.GL_INCR_WRAP; - DECR_WRAP = GL14.GL_DECR_WRAP; - NEVER = GL11.GL_NEVER; - ALWAYS = GL11.GL_ALWAYS; - - EQUAL = GL11.GL_EQUAL; - LESS = GL11.GL_LESS; - LEQUAL = GL11.GL_LEQUAL; - GREATER = GL11.GL_GREATER; - GEQUAL = GL11.GL_GEQUAL; - NOTEQUAL = GL11.GL_NOTEQUAL; - - FUNC_ADD = GL14.GL_FUNC_ADD; - FUNC_MIN = GL14.GL_MIN; - FUNC_MAX = GL14.GL_MAX; - FUNC_REVERSE_SUBTRACT = GL14.GL_FUNC_REVERSE_SUBTRACT; - FUNC_SUBTRACT = GL14.GL_FUNC_SUBTRACT; - - DITHER = GL11.GL_DITHER; - - CONSTANT_COLOR = GL11.GL_CONSTANT_COLOR; - CONSTANT_ALPHA = GL11.GL_CONSTANT_ALPHA; - ONE_MINUS_CONSTANT_COLOR = GL11.GL_ONE_MINUS_CONSTANT_COLOR; - ONE_MINUS_CONSTANT_ALPHA = GL11.GL_ONE_MINUS_CONSTANT_ALPHA; - SRC_ALPHA_SATURATE = GL11.GL_SRC_ALPHA_SATURATE; - - SCISSOR_TEST = GL11.GL_SCISSOR_TEST; - STENCIL_TEST = GL11.GL_STENCIL_TEST; - DEPTH_TEST = GL11.GL_DEPTH_TEST; - DEPTH_WRITEMASK = GL11.GL_DEPTH_WRITEMASK; - ALPHA_TEST = GL11.GL_ALPHA_TEST; - - COLOR_BUFFER_BIT = GL11.GL_COLOR_BUFFER_BIT; - DEPTH_BUFFER_BIT = GL11.GL_DEPTH_BUFFER_BIT; - STENCIL_BUFFER_BIT = GL11.GL_STENCIL_BUFFER_BIT; - - FRAMEBUFFER = GL30.GL_FRAMEBUFFER; - COLOR_ATTACHMENT0 = GL30.GL_COLOR_ATTACHMENT0; - COLOR_ATTACHMENT1 = GL30.GL_COLOR_ATTACHMENT1; - COLOR_ATTACHMENT2 = GL30.GL_COLOR_ATTACHMENT2; - COLOR_ATTACHMENT3 = GL30.GL_COLOR_ATTACHMENT3; - RENDERBUFFER = GL30.GL_RENDERBUFFER; - DEPTH_ATTACHMENT = GL30.GL_DEPTH_ATTACHMENT; - STENCIL_ATTACHMENT = GL30.GL_STENCIL_ATTACHMENT; - READ_FRAMEBUFFER = GL30.GL_READ_FRAMEBUFFER; - DRAW_FRAMEBUFFER = GL30.GL_DRAW_FRAMEBUFFER; - - DEPTH24_STENCIL8 = GL30.GL_DEPTH24_STENCIL8; - - DEPTH_COMPONENT = GL11.GL_DEPTH_COMPONENT; - DEPTH_COMPONENT16 = GL14.GL_DEPTH_COMPONENT16; - DEPTH_COMPONENT24 = GL14.GL_DEPTH_COMPONENT24; - DEPTH_COMPONENT32 = GL14.GL_DEPTH_COMPONENT32; - - STENCIL_INDEX = GL11.GL_STENCIL_INDEX; - STENCIL_INDEX1 = GL30.GL_STENCIL_INDEX1; - STENCIL_INDEX4 = GL30.GL_STENCIL_INDEX4; - STENCIL_INDEX8 = GL30.GL_STENCIL_INDEX8; - - DEPTH_STENCIL = GL30.GL_DEPTH_STENCIL; - - FRAMEBUFFER_COMPLETE = GL30.GL_FRAMEBUFFER_COMPLETE; - FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GL30.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GL30.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; - FRAMEBUFFER_INCOMPLETE_DIMENSIONS = EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; - FRAMEBUFFER_INCOMPLETE_FORMATS = EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; - FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = GL30.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER; - FRAMEBUFFER_INCOMPLETE_READ_BUFFER = GL30.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER; - FRAMEBUFFER_UNSUPPORTED = GL30.GL_FRAMEBUFFER_UNSUPPORTED; - - FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = GL30.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE; - FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = GL30.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME; - FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = GL30.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL; - FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = GL30.GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE; - - RENDERBUFFER_WIDTH = GL30.GL_RENDERBUFFER_WIDTH; - RENDERBUFFER_HEIGHT = GL30.GL_RENDERBUFFER_HEIGHT; - RENDERBUFFER_RED_SIZE = GL30.GL_RENDERBUFFER_RED_SIZE; - RENDERBUFFER_GREEN_SIZE = GL30.GL_RENDERBUFFER_GREEN_SIZE; - RENDERBUFFER_BLUE_SIZE = GL30.GL_RENDERBUFFER_BLUE_SIZE; - RENDERBUFFER_ALPHA_SIZE = GL30.GL_RENDERBUFFER_ALPHA_SIZE; - RENDERBUFFER_DEPTH_SIZE = GL30.GL_RENDERBUFFER_DEPTH_SIZE; - RENDERBUFFER_STENCIL_SIZE = GL30.GL_RENDERBUFFER_STENCIL_SIZE; - RENDERBUFFER_INTERNAL_FORMAT = GL30.GL_RENDERBUFFER_INTERNAL_FORMAT; - - MULTISAMPLE = GL13.GL_MULTISAMPLE; - POINT_SMOOTH = GL11.GL_POINT_SMOOTH; - LINE_SMOOTH = GL11.GL_LINE_SMOOTH; - POLYGON_SMOOTH = GL11.GL_POLYGON_SMOOTH; - } - - /////////////////////////////////////////////////////////// - - // Special Functions - - @Override - public void flush() { - GL11.glFlush(); - } - - @Override - public void finish() { - GL11.glFinish(); - } - - @Override - public void hint(int target, int hint) { - GL11.glHint(target, hint); - } - - /////////////////////////////////////////////////////////// - - // State and State Requests - - @Override - public void enable(int value) { - if (-1 < value) { - GL11.glEnable(value); - } - } - - @Override - public void disable(int value) { - if (-1 < value) { - GL11.glDisable(value); - } - } - - @Override - public void getBooleanv(int value, IntBuffer data) { - if (-1 < value) { - if (byteBuffer.capacity() < data.capacity()) { - byteBuffer = allocateDirectByteBuffer(data.capacity()); - } - GL11.glGetBooleanv(value, byteBuffer); - for (int i = 0; i < data.capacity(); i++) { - data.put(i, byteBuffer.get(i)); - } - } else { - fillIntBuffer(data, 0, data.capacity() - 1, 0); - } - } - - @Override - public void getIntegerv(int value, IntBuffer data) { - if (-1 < value) { - GL11.glGetIntegerv(value, data); - } else { - fillIntBuffer(data, 0, data.capacity() - 1, 0); - } - } - - @Override - public void getFloatv(int value, FloatBuffer data) { - if (-1 < value) { - GL11.glGetFloatv(value, data); - } else { - fillFloatBuffer(data, 0, data.capacity() - 1, 0); - } - } - - @Override - public boolean isEnabled(int value) { - return GL11.glIsEnabled(value); - } - - @Override - public String getString(int name) { - return GL11.glGetString(name); - } - - /////////////////////////////////////////////////////////// - - // Error Handling - - @Override - public int getError() { - return GL11.glGetError(); - } - - @Override - public String errorString(int err) { - return GLU.gluErrorString(err); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Buffer Objects - - @Override - public void genBuffers(int n, IntBuffer buffers) { - GL15.glGenBuffers(buffers); - } - - @Override - public void deleteBuffers(int n, IntBuffer buffers) { - GL15.glDeleteBuffers(buffers); - } - - @Override - public void bindBuffer(int target, int buffer) { - GL15.glBindBuffer(target, buffer); - } - - @Override - public void bufferData(int target, int size, Buffer data, int usage) { - if (data == null) { - FloatBuffer empty = BufferUtils.createFloatBuffer(size); - GL15.glBufferData(target, empty, usage); - } else { - if (data instanceof ByteBuffer) { - GL15.glBufferData(target, (ByteBuffer)data, usage); - } else if (data instanceof ShortBuffer) { - GL15.glBufferData(target, (ShortBuffer)data, usage); - } else if (data instanceof IntBuffer) { - GL15.glBufferData(target, (IntBuffer)data, usage); - } else if (data instanceof FloatBuffer) { - GL15.glBufferData(target, (FloatBuffer)data, usage); - } - } - } - - @Override - public void bufferSubData(int target, int offset, int size, Buffer data) { - if (data instanceof ByteBuffer) { - GL15.glBufferSubData(target, offset, (ByteBuffer)data); - } else if (data instanceof ShortBuffer) { - GL15.glBufferSubData(target, offset, (ShortBuffer)data); - } else if (data instanceof IntBuffer) { - GL15.glBufferSubData(target, offset, (IntBuffer)data); - } else if (data instanceof FloatBuffer) { - GL15.glBufferSubData(target, offset, (FloatBuffer)data); - } - } - - @Override - public void isBuffer(int buffer) { - GL15.glIsBuffer(buffer); - } - - @Override - public void getBufferParameteriv(int target, int value, IntBuffer data) { - if (-1 < value) { - int res = GL15.glGetBufferParameteri(target, value); - data.put(0, res); - } else { - data.put(0, 0); - } - } - - @Override - public ByteBuffer mapBuffer(int target, int access) { - return GL15.glMapBuffer(target, access, null); - } - - @Override - public ByteBuffer mapBufferRange(int target, int offset, int length, int access) { - return GL30.glMapBufferRange(target, offset, length, access, null); - } - - @Override - public void unmapBuffer(int target) { - GL15.glUnmapBuffer(target); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Viewport and Clipping - - @Override - public void depthRangef(float n, float f) { - GL11.glDepthRange(n, f); - } - - @Override - public void viewport(int x, int y, int w, int h) { -// float f = Display.getPixelScaleFactor(); - float f = 1; - GL11.glViewport((int)(f * x), (int)(f * y), (int)f * w, (int)(f * h)); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Reading Pixels - - @Override - protected void readPixelsImpl(int x, int y, int width, int height, int format, int type, Buffer buffer) { - GL11.glReadPixels(x, y, width, height, format, type, (IntBuffer)buffer); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Vertices - - @Override - public void vertexAttrib1f(int index, float value) { - GL20.glVertexAttrib1f(index, value); - } - - @Override - public void vertexAttrib2f(int index, float value0, float value1) { - GL20.glVertexAttrib2f(index, value0, value1); - } - - @Override - public void vertexAttrib3f(int index, float value0, float value1, float value2) { - GL20.glVertexAttrib3f(index, value0, value1, value2); - } - - @Override - public void vertexAttrib4f(int index, float value0, float value1, float value2, float value3) { - GL20.glVertexAttrib4f(index, value0, value1, value2, value3); - } - - @Override - public void vertexAttrib1fv(int index, FloatBuffer values) { - GL20.glVertexAttrib1f(index, values.get()); - } - - @Override - public void vertexAttrib2fv(int index, FloatBuffer values) { - GL20.glVertexAttrib2f(index, values.get(), values.get()); - } - - @Override - public void vertexAttrib3fv(int index, FloatBuffer values) { - GL20.glVertexAttrib3f(index, values.get(), values.get(), values.get()); - } - - @Override - public void vertexAttri4fv(int index, FloatBuffer values) { - GL20.glVertexAttrib4f(index, values.get(), values.get(), values.get(), values.get()); - } - - @Override - public void vertexAttribPointer(int index, int size, int type, boolean normalized, int stride, int offset) { - GL20.glVertexAttribPointer(index, size, type, normalized, stride, offset); - } - - @Override - public void vertexAttribPointer(int index, int size, int type, boolean normalized, int stride, Buffer data) { - if (type == UNSIGNED_INT) { - GL20.glVertexAttribPointer(index, size, normalized, stride, (IntBuffer)data); - } else if (type == UNSIGNED_BYTE) { - GL20.glVertexAttribPointer(index, size, true, normalized, stride, (ByteBuffer)data); - } else if (type == UNSIGNED_SHORT) { - GL20.glVertexAttribPointer(index, size, true, normalized, stride, (ShortBuffer)data); - } else if (type == FLOAT) { - GL20.glVertexAttribPointer(index, size, normalized, stride, (FloatBuffer)data); - } - } - - @Override - public void enableVertexAttribArray(int index) { - GL20.glEnableVertexAttribArray(index); - } - - @Override - public void disableVertexAttribArray(int index) { - GL20.glDisableVertexAttribArray(index); - } - - @Override - public void drawArrays(int mode, int first, int count) { - GL11.glDrawArrays(mode, first, count); - } - - @Override - public void drawElements(int mode, int count, int type, int offset) { - GL11.glDrawElements(mode, count, type, offset); - } - - @Override - public void drawElements(int mode, int count, int type, Buffer indices) { - if (type == UNSIGNED_INT) { - GL11.glDrawElements(mode, (IntBuffer)indices); - } else if (type == UNSIGNED_BYTE) { - GL11.glDrawElements(mode, (ByteBuffer)indices); - } else if (type == UNSIGNED_SHORT) { - GL11.glDrawElements(mode, (ShortBuffer)indices); - } - } - - ////////////////////////////////////////////////////////////////////////////// - - // Rasterization - - @Override - public void lineWidth(float width) { - GL11.glLineWidth(width); - } - - @Override - public void frontFace(int dir) { - GL11.glFrontFace(dir); - } - - @Override - public void cullFace(int mode) { - GL11.glCullFace(mode); - } - - @Override - public void polygonOffset(float factor, float units) { - GL11.glPolygonOffset(factor, units); - } - - ////////////////////////////////////////////////////////////////////////////// - - // Pixel Rectangles - - @Override - public void pixelStorei(int pname, int param) { - GL11.glPixelStorei(pname, param); - } - - /////////////////////////////////////////////////////////// - - // Texturing - - @Override - public void texImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer data) { - GL11.glTexImage2D(target, level, internalFormat, width, height, border, format, type, (IntBuffer)data); - } - - @Override - public void copyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border) { - GL11.glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border); - } - - @Override - public void texSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, Buffer data) { - GL11.glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, (IntBuffer)data); - } - - @Override - public void copyTexSubImage2D(int target, int level, int xOffset, int yOffset, int x, int y, int width, int height) { - GL11.glCopyTexSubImage2D(target, level, x, y, xOffset, yOffset, width, height); - } - - @Override - public void compressedTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int imageSize, Buffer data) { - GL13.glCompressedTexImage2D(target, level, internalFormat, width, height, border, (ByteBuffer)data); - } - - @Override - public void compressedTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int imageSize, Buffer data) { - GL13.glCompressedTexSubImage2D(target, level, xOffset, yOffset, width, height, format, (ByteBuffer)data); - } - - @Override - public void texParameteri(int target, int pname, int param) { - GL11.glTexParameteri(target, pname, param); - } - - @Override - public void texParameterf(int target, int pname, float param) { - GL11.glTexParameterf(target, pname, param); - } - - @Override - public void texParameteriv(int target, int pname, IntBuffer params) { - GL11.glTexParameteri(target, pname, params.get()); - } - - @Override - public void texParameterfv(int target, int pname, FloatBuffer params) { - GL11.glTexParameterf(target, pname, params.get()); - } - - @Override - public void generateMipmap(int target) { - GL30.glGenerateMipmap(target); - } - - @Override - public void genTextures(int n, IntBuffer textures) { - GL11.glGenTextures(textures); - } - - @Override - public void deleteTextures(int n, IntBuffer textures) { - GL11.glDeleteTextures(textures); - } - - @Override - public void getTexParameteriv(int target, int pname, IntBuffer params) { - GL11.glGetTexParameteriv(target, pname, params); - } - - @Override - public void getTexParameterfv(int target, int pname, FloatBuffer params) { - GL11.glGetTexParameterfv(target, pname, params); - } - - @Override - public boolean isTexture(int texture) { - return GL11.glIsTexture(texture); - } - - @Override - protected void activeTextureImpl(int texture) { - GL13.glActiveTexture(texture); - } - - @Override - protected void bindTextureImpl(int target, int texture) { - GL11.glBindTexture(target, texture); - } - - /////////////////////////////////////////////////////////// - - // Shaders and Programs - - @Override - public int createShader(int type) { - return GL20.glCreateShader(type); - } - - @Override - public void shaderSource(int shader, String source) { - GL20.glShaderSource(shader, source); - } - - @Override - public void compileShader(int shader) { - GL20.glCompileShader(shader); - } - - @Override - public void releaseShaderCompiler() { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glReleaseShaderCompiler()")); - } - - @Override - public void deleteShader(int shader) { - GL20.glDeleteShader(shader); - } - - @Override - public void shaderBinary(int count, IntBuffer shaders, int binaryFormat, Buffer binary, int length) { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glShaderBinary()")); - } - - @Override - public int createProgram() { - return GL20.glCreateProgram(); - } - - @Override - public void attachShader(int program, int shader) { - GL20.glAttachShader(program, shader); - } - - @Override - public void detachShader(int program, int shader) { - GL20.glDetachShader(program, shader); - } - - @Override - public void linkProgram(int program) { - GL20.glLinkProgram(program); - } - - @Override - public void useProgram(int program) { - GL20.glUseProgram(program); - } - - @Override - public void deleteProgram(int program) { - GL20.glDeleteProgram(program); - } - - @Override - public String getActiveAttrib(int program, int index, IntBuffer size, IntBuffer type) { -// IntBuffer typeTmp = BufferUtils.createIntBuffer(2); -// String name = GL20.glGetActiveAttrib(program, index, 256, typeTmp); -// size.put(typeTmp.get(0)); -// type.put(typeTmp.get(1)); -// return name; - return GL20.glGetActiveAttrib(program, index, size, type); - } - - @Override - public int getAttribLocation(int program, String name) { - return GL20.glGetAttribLocation(program, name); - } - - @Override - public void bindAttribLocation(int program, int index, String name) { - GL20.glBindAttribLocation(program, index, name); - } - - @Override - public int getUniformLocation(int program, String name) { - return GL20.glGetUniformLocation(program, name); - } - - @Override - public String getActiveUniform(int program, int index, IntBuffer size, IntBuffer type) { -// IntBuffer typeTmp = BufferUtils.createIntBuffer(2); -// String name = GL20.glGetActiveUniform(program, index, 256, typeTmp); -// type.put(typeTmp.get(0)); -// return name; - return GL20.glGetActiveUniform(program, index, size, type); - } - - @Override - public void uniform1i(int location, int value) { - GL20.glUniform1i(location, value); - } - - @Override - public void uniform2i(int location, int value0, int value1) { - GL20.glUniform2i(location, value0, value1); - } - - @Override - public void uniform3i(int location, int value0, int value1, int value2) { - GL20.glUniform3i(location, value0, value1, value2); - } - - @Override - public void uniform4i(int location, int value0, int value1, int value2, int value3) { - GL20.glUniform4i(location, value0, value1, value2, value3); - } - - @Override - public void uniform1f(int location, float value) { - GL20.glUniform1f(location, value); - } - - @Override - public void uniform2f(int location, float value0, float value1) { - GL20.glUniform2f(location, value0, value1); - } - - @Override - public void uniform3f(int location, float value0, float value1, float value2) { - GL20.glUniform3f(location, value0, value1, value2); - } - - @Override - public void uniform4f(int location, float value0, float value1, float value2, float value3) { - GL20.glUniform4f(location, value0, value1, value2, value3); - } - - @Override - public void uniform1iv(int location, int count, IntBuffer v) { - v.limit(count); - GL20.glUniform1iv(location, v); - v.clear(); - } - - @Override - public void uniform2iv(int location, int count, IntBuffer v) { - v.limit(2 * count); - GL20.glUniform2iv(location, v); - v.clear(); - } - - @Override - public void uniform3iv(int location, int count, IntBuffer v) { - v.limit(3 * count); - GL20.glUniform3iv(location, v); - v.clear(); - } - - @Override - public void uniform4iv(int location, int count, IntBuffer v) { - v.limit(4 * count); - GL20.glUniform4iv(location, v); - v.clear(); - } - - @Override - public void uniform1fv(int location, int count, FloatBuffer v) { - v.limit(count); - GL20.glUniform1fv(location, v); - v.clear(); - } - - @Override - public void uniform2fv(int location, int count, FloatBuffer v) { - v.limit(2 * count); - GL20.glUniform2fv(location, v); - v.clear(); - } - - @Override - public void uniform3fv(int location, int count, FloatBuffer v) { - v.limit(3 * count); - GL20.glUniform3fv(location, v); - v.clear(); - } - - @Override - public void uniform4fv(int location, int count, FloatBuffer v) { - v.limit(4 * count); - GL20.glUniform4fv(location, v); - v.clear(); - } - - @Override - public void uniformMatrix2fv(int location, int count, boolean transpose, FloatBuffer mat) { - mat.limit(4); - GL20.glUniformMatrix2fv(location, transpose, mat); - mat.clear(); - } - - @Override - public void uniformMatrix3fv(int location, int count, boolean transpose, FloatBuffer mat) { - mat.limit(9); - GL20.glUniformMatrix3fv(location, transpose, mat); - mat.clear(); - } - - @Override - public void uniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer mat) { - mat.limit(16); - GL20.glUniformMatrix4fv(location, transpose, mat); - mat.clear(); - } - - @Override - public void validateProgram(int program) { - GL20.glValidateProgram(program); - } - - @Override - public boolean isShader(int shader) { - return GL20.glIsShader(shader); - } - - @Override - public void getShaderiv(int shader, int pname, IntBuffer params) { - GL20.glGetShaderiv(shader, pname, params); - } - - @Override - public void getAttachedShaders(int program, int maxCount, IntBuffer count, IntBuffer shaders) { - GL20.glGetAttachedShaders(program, count, shaders); - } - - @Override - public String getShaderInfoLog(int shader) { - int len = GL20.glGetShaderi(shader, GL20.GL_INFO_LOG_LENGTH); - return GL20.glGetShaderInfoLog(shader, len); - } - - @Override - public String getShaderSource(int shader) { - int len = GL20.glGetShaderi(shader, GL20.GL_SHADER_SOURCE_LENGTH); - return GL20.glGetShaderSource(shader, len); - } - - @Override - public void getShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision) { - throw new RuntimeException(String.format(MISSING_GLFUNC_ERROR, "glGetShaderPrecisionFormat()")); - } - - @Override - public void getVertexAttribfv(int index, int pname, FloatBuffer params) { - GL20.glGetVertexAttribfv(index, pname, params); - } - - @Override - public void getVertexAttribiv(int index, int pname, IntBuffer params) { - GL20.glGetVertexAttribiv(index, pname, params); - } - - @Override - public void getVertexAttribPointerv(int index, int pname, ByteBuffer data) { -// int len = data.capacity(); -// ByteBuffer res = GL20.glGetVertexAttribPointer(index, pname, len); -// data.put(res); - GL20.glGetVertexAttribPointerv(index, pname, data); - } - - @Override - public void getUniformfv(int program, int location, FloatBuffer params) { - GL20.glGetUniformfv(program, location, params); - } - - @Override - public void getUniformiv(int program, int location, IntBuffer params) { - GL20.glGetUniformiv(program, location, params); - } - - @Override - public boolean isProgram(int program) { - return GL20.glIsProgram(program); - } - - @Override - public void getProgramiv(int program, int pname, IntBuffer params) { - GL20.glGetProgramiv(program, pname, params); - } - - @Override - public String getProgramInfoLog(int program) { - int len = GL20.glGetProgrami(program, GL20.GL_INFO_LOG_LENGTH); - return GL20.glGetProgramInfoLog(program, len); - } - - /////////////////////////////////////////////////////////// - - // Per-Fragment Operations - - @Override - public void scissor(int x, int y, int w, int h) { -// float f = Display.getPixelScaleFactor(); - float f = 1; - GL11.glScissor((int)(f * x), (int)(f * y), (int)f * w, (int)(f * h)); - } - - @Override - public void sampleCoverage(float value, boolean invert) { - GL13.glSampleCoverage(value, invert); - } - - @Override - public void stencilFunc(int func, int ref, int mask) { - GL11.glStencilFunc(func, ref, mask); - } - - @Override - public void stencilFuncSeparate(int face, int func, int ref, int mask) { - GL20.glStencilFuncSeparate(face, func, ref, mask); - } - - @Override - public void stencilOp(int sfail, int dpfail, int dppass) { - GL11.glStencilOp(sfail, dpfail, dppass); - } - - @Override - public void stencilOpSeparate(int face, int sfail, int dpfail, int dppass) { - GL20.glStencilOpSeparate(face, sfail, dpfail, dppass); - } - - @Override - public void depthFunc(int func) { - GL11.glDepthFunc(func); - } - - @Override - public void blendEquation(int mode) { - GL14.glBlendEquation(mode); - } - - @Override - public void blendEquationSeparate(int modeRGB, int modeAlpha) { - GL20.glBlendEquationSeparate(modeRGB, modeAlpha); - } - - @Override - public void blendFunc(int src, int dst) { - GL11.glBlendFunc(src, dst); - } - - @Override - public void blendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { - GL14.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); - } - - @Override - public void blendColor(float red, float green, float blue, float alpha) { - GL14.glBlendColor(red, green, blue, alpha); - } - - @Override - public void alphaFunc(int func, float ref) { - GL11.glAlphaFunc(func, ref); - } - - /////////////////////////////////////////////////////////// - - // Whole Framebuffer Operations - - @Override - public void colorMask(boolean r, boolean g, boolean b, boolean a) { - GL11.glColorMask(r, g, b, a); - } - - @Override - public void depthMask(boolean mask) { - GL11.glDepthMask(mask); - } - - @Override - public void stencilMask(int mask) { - GL11.glStencilMask(mask); - } - - @Override - public void stencilMaskSeparate(int face, int mask) { - GL20.glStencilMaskSeparate(face, mask); - } - - @Override - public void clear(int buf) { - GL11.glClear(buf); - } - - @Override - public void clearColor(float r, float g, float b, float a) { - GL11.glClearColor(r, g, b, a); - } - - @Override - public void clearDepth(float d) { - GL11.glClearDepth(d); - } - - @Override - public void clearStencil(int s) { - GL11.glClearStencil(s); - } - - /////////////////////////////////////////////////////////// - - // Framebuffers Objects - - @Override - protected void bindFramebufferImpl(int target, int framebuffer) { - GL30.glBindFramebuffer(target, framebuffer); - } - - @Override - public void deleteFramebuffers(int n, IntBuffer framebuffers) { - GL30.glDeleteFramebuffers(framebuffers); - } - - @Override - public void genFramebuffers(int n, IntBuffer framebuffers) { - GL30.glGenFramebuffers(framebuffers); - } - - @Override - public void bindRenderbuffer(int target, int renderbuffer) { - GL30.glBindRenderbuffer(target, renderbuffer); - } - - @Override - public void deleteRenderbuffers(int n, IntBuffer renderbuffers) { - GL30.glDeleteRenderbuffers(renderbuffers); - } - - @Override - public void genRenderbuffers(int n, IntBuffer renderbuffers) { - GL30.glGenRenderbuffers(renderbuffers); - } - - @Override - public void renderbufferStorage(int target, int internalFormat, int width, int height) { - GL30.glRenderbufferStorage(target, internalFormat, width, height); - } - - @Override - public void framebufferRenderbuffer(int target, int attachment, int rendbuferfTarget, int renderbuffer) { - GL30.glFramebufferRenderbuffer(target, attachment, rendbuferfTarget, renderbuffer); - } - - @Override - public void framebufferTexture2D(int target, int attachment, int texTarget, int texture, int level) { - GL30.glFramebufferTexture2D(target, attachment, texTarget, texture, level); - } - - @Override - public int checkFramebufferStatus(int target) { - return GL30.glCheckFramebufferStatus(target); - } - - @Override - public boolean isFramebuffer(int framebuffer) { - return GL30.glIsFramebuffer(framebuffer); - } - - @Override - public void getFramebufferAttachmentParameteriv(int target, int attachment, int pname, IntBuffer params) { - GL30.glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); - } - - @Override - public boolean isRenderbuffer(int renderbuffer) { - return GL30.glIsRenderbuffer(renderbuffer); - } - - @Override - public void getRenderbufferParameteriv(int target, int pname, IntBuffer params) { - GL30.glGetRenderbufferParameteriv(target, pname, params); - } - - @Override - public void blitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { - GL30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - } - - @Override - public void renderbufferStorageMultisample(int target, int samples, int format, int width, int height) { - GL30.glRenderbufferStorageMultisample(target, samples, format, width, height); - } - - @Override - public void readBuffer(int buf) { - GL11.glReadBuffer(buf); - } - - @Override - public void drawBuffer(int buf) { - GL11.glDrawBuffer(buf); - } - - - @Override - protected void getGL(PGL pgl) { - glThread = pgl.glThread; - } -} diff --git a/core/src/processing/opengl/PSurfaceJOGL.java b/core/src/processing/opengl/PSurfaceJOGL.java new file mode 100644 index 000000000..073da73e5 --- /dev/null +++ b/core/src/processing/opengl/PSurfaceJOGL.java @@ -0,0 +1,818 @@ +package processing.opengl; + +import java.awt.Component; +//import java.awt.Dimension; +import java.awt.Point; +//import java.awt.Frame; +import java.awt.Rectangle; +import java.util.ArrayList; + +import com.jogamp.nativewindow.NativeSurface; +import com.jogamp.nativewindow.ScalableSurface; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLProfile; +import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.FPSAnimator; + +import processing.core.PApplet; +import processing.core.PConstants; +import processing.core.PGraphics; +import processing.core.PImage; +import processing.core.PSurface; +import processing.event.KeyEvent; +import processing.event.MouseEvent; +import processing.opengl.PGraphicsOpenGL; +import processing.opengl.PGL; + +public class PSurfaceJOGL implements PSurface { + /** Selected GL profile */ + public static GLProfile profile; + + PJOGL pgl; + + GLWindow window; +// Frame frame; + FPSAnimator animator; + Rectangle screenRect; + + PApplet sketch; + PGraphics graphics; + + int sketchX; + int sketchY; + int sketchWidth; + int sketchHeight; + + MonitorDevice displayDevice; + Throwable drawException; + Object waitObject = new Object(); + + NewtCanvasAWT canvas; + + + public PSurfaceJOGL(PGraphics graphics) { + this.graphics = graphics; + this.pgl = (PJOGL) ((PGraphicsOpenGL)graphics).pgl; + } + + + public void initOffscreen(PApplet sketch) { + this.sketch = sketch; + + sketchWidth = sketch.sketchWidth(); + sketchHeight = sketch.sketchHeight(); + + if (window != null) { + canvas = new NewtCanvasAWT(window); + canvas.setBounds(0, 0, window.getWidth(), window.getHeight()); +// canvas.setBackground(new Color(pg.backgroundColor, true)); + canvas.setFocusable(true); + } + } + + + public void initFrame(PApplet sketch, int backgroundColor, + int deviceIndex, boolean fullScreen, + boolean spanDisplays) { + this.sketch = sketch; + + Display display = NewtFactory.createDisplay(null); + display.addReference(); + Screen screen = NewtFactory.createScreen(display, 0); + screen.addReference(); + + ArrayList monitors = new ArrayList(); + for (int i = 0; i < screen.getMonitorDevices().size(); i++) { + MonitorDevice monitor = screen.getMonitorDevices().get(i); + System.out.println("Monitor " + monitor.getId() + " ************"); + System.out.println(monitor.toString()); + System.out.println(monitor.getViewportInWindowUnits()); + System.out.println(monitor.getViewport()); + + monitors.add(monitor); + } + System.out.println("*******************************"); + + if (deviceIndex >= 0) { // if -1, use the default device + if (deviceIndex < monitors.size()) { + displayDevice = monitors.get(deviceIndex); + } else { + System.err.format("Display %d does not exist, " + + "using the default display instead.", deviceIndex); + for (int i = 0; i < monitors.size(); i++) { + System.err.format("Display %d is %s\n", i, monitors.get(i)); + } + } + } + + if (profile == null) { + if (PJOGL.PROFILE == 2) { + try { + profile = GLProfile.getGL2ES1(); + } catch (GLException ex) { + profile = GLProfile.getMaxFixedFunc(true); + } + } else if (PJOGL.PROFILE == 3) { + try { + profile = GLProfile.getGL2GL3(); + } catch (GLException ex) { + profile = GLProfile.getMaxProgrammable(true); + } + if (!profile.isGL3()) { + PGraphics.showWarning("Requested profile GL3 but is not available, got: " + profile); + } + } else if (PJOGL.PROFILE == 4) { + try { + profile = GLProfile.getGL4ES3(); + } catch (GLException ex) { + profile = GLProfile.getMaxProgrammable(true); + } + if (!profile.isGL4()) { + PGraphics.showWarning("Requested profile GL4 but is not available, got: " + profile); + } + } else throw new RuntimeException(PGL.UNSUPPORTED_GLPROF_ERROR); + } + + // Setting up the desired capabilities; + GLCapabilities caps = new GLCapabilities(profile); + caps.setAlphaBits(PGL.REQUESTED_ALPHA_BITS); + caps.setDepthBits(PGL.REQUESTED_DEPTH_BITS); + caps.setStencilBits(PGL.REQUESTED_STENCIL_BITS); + +// caps.setPBuffer(false); +// caps.setFBO(false); + + pgl.reqNumSamples = graphics.quality; + caps.setSampleBuffers(true); + caps.setNumSamples(pgl.reqNumSamples); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + pgl.capabilities = caps; + System.err.println("0. create window"); + window = GLWindow.create(screen, caps); + + sketchWidth = sketch.sketchWidth(); + sketchHeight = sketch.sketchHeight(); + + if (displayDevice == null) { + displayDevice = window.getMainMonitor(); + } + sketchX = displayDevice.getViewportInWindowUnits().getX(); + sketchY = displayDevice.getViewportInWindowUnits().getY(); + + int screenWidth = screen.getWidth(); + int screenHeight = screen.getHeight(); + + screenRect = spanDisplays ? new Rectangle(0, 0, screen.getWidth(), screen.getHeight()) : + new Rectangle(0, 0, displayDevice.getViewportInWindowUnits().getWidth(), + displayDevice.getViewportInWindowUnits().getHeight()); + + sketch.displayWidth = screenRect.width; + sketch.displayHeight = screenRect.height; + + // Sketch has already requested to be the same as the screen's + // width and height, so let's roll with full screen mode. + if (screenRect.width == sketchWidth && + screenRect.height == sketchHeight) { + fullScreen = true; + } + +// if (fullScreen || spanDisplays) { + if (spanDisplays) { + sketchWidth = screenRect.width; + sketchHeight = screenRect.height; + } + +// window..setBackground(new Color(backgroundColor, true)); + window.setSize(sketchWidth, sketchHeight); + + System.out.println("deviceIndex: " + deviceIndex); + System.out.println(displayDevice); + System.out.println("Screen res " + screenWidth + "x" + screenHeight); + + // This example could be useful: + // com.jogamp.opengl.test.junit.newt.mm.TestScreenMode01cNEWT + if (fullScreen) { + PApplet.hideMenuBar(); + if (spanDisplays) { + window.setFullscreen(monitors); + } else { + window.setFullscreen(true); + } + } + + float[] reqSurfacePixelScale; + if (graphics.is2X()) { + // Retina + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, + ScalableSurface.AUTOMAX_PIXELSCALE }; +// pgl.pixel_scale = 2; + } else { + // Non-retina + reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, + ScalableSurface.IDENTITY_PIXELSCALE }; +// pgl.pixel_scale = 1; + } + window.setSurfaceScale(reqSurfacePixelScale); + + NEWTMouseListener mouseListener = new NEWTMouseListener(); + window.addMouseListener(mouseListener); + NEWTKeyListener keyListener = new NEWTKeyListener(); + window.addKeyListener(keyListener); + NEWTWindowListener winListener = new NEWTWindowListener(); + window.addWindowListener(winListener); + + DrawListener drawlistener = new DrawListener(); + window.addGLEventListener(drawlistener); + + System.err.println("1. create animator"); + animator = new FPSAnimator(window, 60); + drawException = null; + animator.setUncaughtExceptionHandler(new GLAnimatorControl.UncaughtExceptionHandler() { + @Override + public void uncaughtException(final GLAnimatorControl animator, + final GLAutoDrawable drawable, + final Throwable cause) { + synchronized (waitObject) { +// System.err.println("Caught exception: " + cause.getMessage()); + drawException = cause; + waitObject.notify(); + } + } + }); + + new Thread(new Runnable() { + public void run() { + synchronized (waitObject) { + try { + if (drawException == null) waitObject.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } +// System.err.println("Caught exception: " + drawException.getMessage()); + if (drawException instanceof RuntimeException) { + throw (RuntimeException)drawException.getCause(); + } else { + throw new RuntimeException(drawException.getCause()); + } + } + } + }).start(); + + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowDestroyNotify(final WindowEvent e) { + animator.stop(); + PSurfaceJOGL.this.sketch.exit(); + window.destroy(); + } + }); + + + window.setVisible(true); + System.err.println("4. set visible"); + + /* + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + window.setVisible(true); + System.err.println("1. set visible"); + }}); + } catch (Exception ex) { + // error setting the window visible, should quit... + } +*/ + +// frame = new DummyFrame(); +// return frame; + } + + @Override + public void setTitle(String title) { + window.setTitle(title); + } + + @Override + public void setVisible(boolean visible) { + window.setVisible(visible); + } + + @Override + public void setResizable(boolean resizable) { + // TODO Auto-generated method stub + + } + + private void setFrameCentered() { + // Can't use frame.setLocationRelativeTo(null) because it sends the + // frame to the main display, which undermines the --display setting. + int sketchX = displayDevice.getViewportInWindowUnits().getX(); + int sketchY = displayDevice.getViewportInWindowUnits().getY(); + System.err.println("just center on the screen at " + sketchX + screenRect.x + (screenRect.width - sketchWidth) / 2 + ", " + + sketchY + screenRect.y + (screenRect.height - sketchHeight) / 2); + + System.err.println(" Display starts at " + sketchX + ", " + sketchY); + System.err.println(" Screen rect pos: " + screenRect.x + ", " + screenRect.y); + System.err.println(" Screen rect w/h: " + screenRect.width + ", " + screenRect.height); + System.err.println(" Sketch w/h: " + sketchWidth + ", " + sketchHeight); + + int w = sketchWidth; + int h = sketchHeight; + if (graphics.is2X()) { + w /= 2; + h /= 2; + } + + window.setPosition(sketchX + screenRect.x + (screenRect.width - w) / 2, + sketchY + screenRect.y + (screenRect.height - h) / 2); + } + + + @Override + public void placeWindow(int[] location, int[] editorLocation) { +// Dimension dim = new Dimension(sketchWidth, sketchHeight); +// int contentW = Math.max(sketchWidth, MIN_WINDOW_WIDTH); +// int contentH = Math.max(sketchHeight, MIN_WINDOW_HEIGHT); + + if (location != null) { + System.err.println("place window at " + location[0] + ", " + location[1]); + // a specific location was received from the Runner + // (applet has been run more than once, user placed window) +// frame.setLocation(location[0], location[1]); + window.setPosition(location[0], location[1]); + + } else if (editorLocation != null) { + System.err.println("place window at editor location " + editorLocation[0] + ", " + editorLocation[1]); + int locationX = editorLocation[0] - 20; + int locationY = editorLocation[1]; + + if (locationX - window.getWidth() > 10) { + // if it fits to the left of the window + window.setPosition(locationX - window.getWidth(), locationY); + + } else { // doesn't fit + // if it fits inside the editor window, + // offset slightly from upper lefthand corner + // so that it's plunked inside the text area + locationX = editorLocation[0] + 66; + locationY = editorLocation[1] + 66; + + if ((locationX + window.getWidth() > sketch.displayWidth - 33) || + (locationY + window.getHeight() > sketch.displayHeight - 33)) { + // otherwise center on screen + locationX = (sketch.displayWidth - window.getWidth()) / 2; + locationY = (sketch.displayHeight - window.getHeight()) / 2; + } + window.setPosition(locationX, locationY); + } + } else { // just center on screen + setFrameCentered(); + } + Point frameLoc = new Point(window.getX(), window.getY()); + if (frameLoc.y < 0) { + // Windows actually allows you to place frames where they can't be + // closed. Awesome. http://dev.processing.org/bugs/show_bug.cgi?id=1508 + window.setPosition(frameLoc.x, 30); + } + +// canvas.setBounds((contentW - sketchWidth)/2, +// (contentH - sketchHeight)/2, +// sketchWidth, sketchHeight); + + + + } + + boolean presentMode = false; + float offsetX; + float offsetY; + public void placePresent(int stopColor) { + if (sketchWidth < screenRect.width || sketchHeight < screenRect.height) { + System.err.println("Present mode"); +// System.err.println("WILL USE FBO"); + presentMode = pgl.presentMode = true; + offsetX = pgl.offsetX = 0.5f * (screenRect.width - sketchWidth); + offsetY = pgl.offsetY = 0.5f * (screenRect.height - sketchHeight); + pgl.requestFBOLayer(); + } + } + + public void setupExternalMessages() { + // TODO Auto-generated method stub + + } + + public void startThread() { + if (animator != null) { + System.err.println("5. start animator"); + animator.start(); + + if (0 < sketchX && 0 < sketchY) { + System.err.println("5.1 set inital window position"); + window.setPosition(sketchX, sketchY); + sketchX = sketchY = 0; + } +// animator.getThread().setName("Processing-GL-draw"); + } + } + + public void pauseThread() { + if (animator != null) { + animator.pause(); + } + } + + public void resumeThread() { + if (animator != null) { + animator.resume(); + } + } + + public boolean stopThread() { + if (animator != null) { + return animator.stop(); + } else { + return false; + } + } + + public boolean isStopped() { + if (animator != null) { + return !animator.isAnimating(); + } else { + return true; + } + } + + public void setSize(int width, int height) { +// if (frame != null) { + System.err.println("3. set size"); + + sketchWidth = sketch.width = width; + sketchHeight = sketch.height = height; + graphics.setSize(width, height); +// } + } + + public Component getComponent() { + return canvas; + } + + public void setSmooth(int level) { + pgl.reqNumSamples = level; + GLCapabilities caps = new GLCapabilities(profile); + caps.setAlphaBits(PGL.REQUESTED_ALPHA_BITS); + caps.setDepthBits(PGL.REQUESTED_DEPTH_BITS); + caps.setStencilBits(PGL.REQUESTED_STENCIL_BITS); + caps.setSampleBuffers(true); + caps.setNumSamples(pgl.reqNumSamples); + caps.setBackgroundOpaque(true); + caps.setOnscreen(true); + NativeSurface target = window.getNativeSurface(); + MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); + config.setChosenCapabilities(caps); + } + + public void setFrameRate(float fps) { + if (animator != null) { + animator.stop(); + animator.setFPS((int)fps); + pgl.setFps(fps); + animator.start(); + } + } + + public void requestFocus() { + window.requestFocus(); + + } + + class DrawListener implements GLEventListener { + public void display(GLAutoDrawable drawable) { + pgl.getGL(drawable); +// System.out.println(" - " + sketch.frameCount); + sketch.handleDraw(); + + if (sketch.frameCount == 1) { + requestFocus(); + } + } + public void dispose(GLAutoDrawable drawable) { + pgl.getGL(drawable); + sketch.dispose(); + if (sketch.exitCalled()) { + sketch.exitActual(); + } + } + public void init(GLAutoDrawable drawable) { + System.err.println("2. init drawable"); + pgl.getGL(drawable); + pgl.init(drawable); + sketch.start(); +// setSize(sketchWidth, sketchHeight); + + int c = graphics.backgroundColor; + pgl.clearColor(((c >> 16) & 0xff) / 255f, + ((c >> 8) & 0xff) / 255f, + ((c >> 0) & 0xff) / 255f, + ((c >> 24) & 0xff) / 255f); + pgl.clear(PGL.COLOR_BUFFER_BIT); + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { + + final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale = window.getCurrentSurfaceScale(new float[2]); + final float[] nativeSurfacePixelScale = window.getMaximumSurfaceScale(new float[2]); + System.err.println("[set PixelScale post]: "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+" (has), "+ + nativeSurfacePixelScale[0]+"x"+nativeSurfacePixelScale[1]+" (native)"); + + + + + System.out.println("reshape: " + w + ", " + h); + pgl.getGL(drawable); + if (!graphics.is2X() && 1 < hasSurfacePixelScale[0]) { + setSize(w/2, h/2); + } else { + setSize(w, h); + } + } + } + + protected class NEWTWindowListener implements com.jogamp.newt.event.WindowListener { + public NEWTWindowListener() { + super(); + } + @Override + public void windowGainedFocus(com.jogamp.newt.event.WindowEvent arg0) { +// pg.parent.focusGained(null); + } + + @Override + public void windowLostFocus(com.jogamp.newt.event.WindowEvent arg0) { +// pg.parent.focusLost(null); + } + + @Override + public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent arg0) { + } + + @Override + public void windowDestroyed(com.jogamp.newt.event.WindowEvent arg0) { + } + + @Override + public void windowMoved(com.jogamp.newt.event.WindowEvent arg0) { + } + + @Override + public void windowRepaint(com.jogamp.newt.event.WindowUpdateEvent arg0) { + } + + @Override + public void windowResized(com.jogamp.newt.event.WindowEvent arg0) { } + } + + // NEWT mouse listener + protected class NEWTMouseListener extends com.jogamp.newt.event.MouseAdapter { + public NEWTMouseListener() { + super(); + } + @Override + public void mousePressed(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.PRESS); + } + @Override + public void mouseReleased(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.RELEASE); + } + @Override + public void mouseClicked(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.CLICK); + } + @Override + public void mouseDragged(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.DRAG); + } + @Override + public void mouseMoved(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.MOVE); + } + @Override + public void mouseWheelMoved(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.WHEEL); + } + @Override + public void mouseEntered(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.ENTER); + } + @Override + public void mouseExited(com.jogamp.newt.event.MouseEvent e) { + nativeMouseEvent(e, MouseEvent.EXIT); + } + } + + // NEWT key listener + protected class NEWTKeyListener extends com.jogamp.newt.event.KeyAdapter { + public NEWTKeyListener() { + super(); + } + @Override + public void keyPressed(com.jogamp.newt.event.KeyEvent e) { + nativeKeyEvent(e, KeyEvent.PRESS); + } + @Override + public void keyReleased(com.jogamp.newt.event.KeyEvent e) { + nativeKeyEvent(e, KeyEvent.RELEASE); + } + public void keyTyped(com.jogamp.newt.event.KeyEvent e) { + nativeKeyEvent(e, KeyEvent.TYPE); + } + } + + protected void nativeMouseEvent(com.jogamp.newt.event.MouseEvent nativeEvent, + int peAction) { + int modifiers = nativeEvent.getModifiers(); + int peModifiers = modifiers & + (InputEvent.SHIFT_MASK | + InputEvent.CTRL_MASK | + InputEvent.META_MASK | + InputEvent.ALT_MASK); + + int peButton = 0; + if ((modifiers & InputEvent.BUTTON1_MASK) != 0) { + peButton = PConstants.LEFT; + } else if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { + peButton = PConstants.CENTER; + } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { + peButton = PConstants.RIGHT; + } + + if (PApplet.platform == PConstants.MACOSX) { + //if (nativeEvent.isPopupTrigger()) { + if ((modifiers & InputEvent.CTRL_MASK) != 0) { + peButton = PConstants.RIGHT; + } + } + + int peCount = 0; + if (peAction == MouseEvent.WHEEL) { + peCount = nativeEvent.isShiftDown() ? (int)nativeEvent.getRotation()[0] : + (int)nativeEvent.getRotation()[1]; + } else { + peCount = nativeEvent.getClickCount(); + } + + + if (presentMode) { + if (20 < nativeEvent.getX() && nativeEvent.getX() < 20 + 100 && + screenRect.height - 70 < nativeEvent.getY() && nativeEvent.getY() < screenRect.height - 20) { + System.err.println("clicked on exit button"); +// if (externalMessages) { +// System.err.println(PApplet.EXTERNAL_QUIT); +// System.err.flush(); // important +// } + animator.stop(); + PSurfaceJOGL.this.sketch.exit(); + window.destroy(); + } + } + + final float[] hasSurfacePixelScale = window.getCurrentSurfaceScale(new float[2]); + int x = nativeEvent.getX() - (int)offsetX; + int y = nativeEvent.getY() - (int)offsetY; + if (!graphics.is2X() && 1 < hasSurfacePixelScale[0]) { + x /= 2; + y /= 2; + } + + MouseEvent me = new MouseEvent(nativeEvent, nativeEvent.getWhen(), + peAction, peModifiers, + x, y, + peButton, + peCount); + + sketch.postEvent(me); + } + + protected void nativeKeyEvent(com.jogamp.newt.event.KeyEvent nativeEvent, + int peAction) { + int peModifiers = nativeEvent.getModifiers() & + (InputEvent.SHIFT_MASK | + InputEvent.CTRL_MASK | + InputEvent.META_MASK | + InputEvent.ALT_MASK); + + short code = nativeEvent.getKeyCode(); + char keyChar; + int keyCode; + if (isPCodedKey(code)) { + keyCode = mapToPConst(code); + keyChar = PConstants.CODED; + } else { + keyCode = code; + keyChar = nativeEvent.getKeyChar(); + } + + // From http://jogamp.org/deployment/v2.1.0/javadoc/jogl/javadoc/com/jogamp/newt/event/KeyEvent.html + // public final short getKeySymbol() + // Returns the virtual key symbol reflecting the current keyboard layout. + // public final short getKeyCode() + // Returns the virtual key code using a fixed mapping to the US keyboard layout. + // In contrast to key symbol, key code uses a fixed US keyboard layout and therefore is keyboard layout independent. + // E.g. virtual key code VK_Y denotes the same physical key regardless whether keyboard layout QWERTY or QWERTZ is active. The key symbol of the former is VK_Y, where the latter produces VK_Y. + KeyEvent ke = new KeyEvent(nativeEvent, nativeEvent.getWhen(), + peAction, peModifiers, + keyChar, + keyCode); +// nativeEvent.getKeySymbol()); + + sketch.postEvent(ke); + } + + // Why do we need this mapping? + // Relevant discussion and links here: + // http://forum.jogamp.org/Newt-wrong-keycode-for-key-td4033690.html#a4033697 + // (I don't think this is a complete solution). + private static int mapToPConst(short code) { + if (code == com.jogamp.newt.event.KeyEvent.VK_UP) { + return PConstants.UP; + } else if (code == com.jogamp.newt.event.KeyEvent.VK_DOWN) { + return PConstants.DOWN; + } else if (code == com.jogamp.newt.event.KeyEvent.VK_LEFT) { + return PConstants.LEFT; + } else if (code == com.jogamp.newt.event.KeyEvent.VK_RIGHT) { + return PConstants.RIGHT; + } else if (code == com.jogamp.newt.event.KeyEvent.VK_ALT) { + return PConstants.ALT; + } else if (code == com.jogamp.newt.event.KeyEvent.VK_CONTROL) { + return PConstants.CONTROL; + } else if (code == com.jogamp.newt.event.KeyEvent.VK_SHIFT) { + return PConstants.SHIFT; + } + return code; + } + + private static boolean isPCodedKey(short code) { + return code == com.jogamp.newt.event.KeyEvent.VK_UP || + code == com.jogamp.newt.event.KeyEvent.VK_DOWN || + code == com.jogamp.newt.event.KeyEvent.VK_LEFT || + code == com.jogamp.newt.event.KeyEvent.VK_RIGHT || + code == com.jogamp.newt.event.KeyEvent.VK_ALT || + code == com.jogamp.newt.event.KeyEvent.VK_CONTROL || + code == com.jogamp.newt.event.KeyEvent.VK_SHIFT; + } + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + public void setCursor(int kind) { + System.err.println("Cursor types not supported in OpenGL, provide your cursor image"); + } + + + public void setCursor(PImage image, int hotspotX, int hotspotY) { + final Display disp = window.getScreen().getDisplay(); + disp.createNative(); + +// BufferedImage jimg = (BufferedImage)image.getNative(); +// IntBuffer buf = IntBuffer.wrap(jimg.getRGB(0, 0, jimg.getWidth(), jimg.getHeight(), +// null, 0, jimg.getWidth())); +// +// final PixelRectangle pixelrect = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), +// srcStrideBytes, srcIsGLOriented, srcPixels); +// +// PointerIcon pi = disp.createPointerIcon(PixelRectangle pixelrect, +// hotspotX, +// hotspotY); +// +// window.setPointerIcon(pi); + + } + + public void showCursor() { + window.setPointerVisible(true); + } + + public void hideCursor() { + window.setPointerVisible(false); + } +} diff --git a/core/src/processing/opengl/PSurfaceLWJGL.java b/core/src/processing/opengl/PSurfaceLWJGL.java deleted file mode 100644 index c3218f6c1..000000000 --- a/core/src/processing/opengl/PSurfaceLWJGL.java +++ /dev/null @@ -1,1173 +0,0 @@ -package processing.opengl; - -import static org.lwjgl.glfw.Callbacks.errorCallbackPrint; -import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE; -import static org.lwjgl.glfw.GLFW.GLFW_RELEASE; -import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE; -import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE; -import static org.lwjgl.glfw.GLFW.glfwCreateWindow; -import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints; -import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor; -import static org.lwjgl.glfw.GLFW.glfwGetVideoMode; -import static org.lwjgl.glfw.GLFW.glfwInit; -import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent; -import static org.lwjgl.glfw.GLFW.glfwPollEvents; -import static org.lwjgl.glfw.GLFW.glfwSetCursorPosCallback; -import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback; -import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback; -import static org.lwjgl.glfw.GLFW.glfwSetMouseButtonCallback; -import static org.lwjgl.glfw.GLFW.glfwSetScrollCallback; -import static org.lwjgl.glfw.GLFW.glfwSetWindowPos; -import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose; -import static org.lwjgl.glfw.GLFW.glfwShowWindow; -import static org.lwjgl.glfw.GLFW.glfwSwapBuffers; -import static org.lwjgl.glfw.GLFW.glfwSwapInterval; -import static org.lwjgl.glfw.GLFW.glfwWindowHint; -import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose; -import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; -import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; -import static org.lwjgl.opengl.GL11.GL_FALSE; -import static org.lwjgl.opengl.GL11.GL_TRUE; -import static org.lwjgl.opengl.GL11.glClear; -import static org.lwjgl.opengl.GL11.glClearColor; -import static org.lwjgl.system.MemoryUtil.NULL; - -import java.awt.Component; -import java.awt.Frame; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; -import java.awt.geom.Rectangle2D; -import java.nio.ByteBuffer; - -import org.lwjgl.glfw.GLFWCursorPosCallback; -import org.lwjgl.glfw.GLFWErrorCallback; -import org.lwjgl.glfw.GLFWKeyCallback; -import org.lwjgl.glfw.GLFWMouseButtonCallback; -import org.lwjgl.glfw.GLFWScrollCallback; -import org.lwjgl.glfw.GLFWvidmode; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GLContext; - -import processing.core.PApplet; -import processing.core.PConstants; -import processing.core.PGraphics; -import processing.core.PImage; -import processing.core.PSurface; -import processing.event.MouseEvent; - - -public class PSurfaceLWJGL implements PSurface { - GraphicsDevice displayDevice; - PApplet sketch; - PGraphics graphics; - - int sketchWidth; - int sketchHeight; - - Frame frame; - // Note that x and y may not be zero, depending on the display configuration - Rectangle screenRect; - - PLWJGL pgl; - - private GLFWMouseButtonCallback mouseCallback; - private GLFWCursorPosCallback posCallback; - private GLFWKeyCallback keyCallback; - private GLFWScrollCallback scrollCallback; - private GLFWErrorCallback errorCallback; - //The window handle - private long window; - - int cursorType = PConstants.ARROW; // cursor type - boolean cursorVisible = true; // cursor visibility flag -// Cursor invisibleCursor; -// Cursor currentCursor; - - // ........................................................ - - // Event handling - - boolean externalMessages = false; - - /** Poller threads to get the keyboard/mouse events from LWJGL */ -// protected static KeyPoller keyPoller; -// protected static MousePoller mousePoller; - - Thread thread; - boolean paused; - Object pauseObject = new Object(); - - /** As of release 0116, frameRate(60) is called as a default */ - protected float frameRateTarget = 60; - - - PSurfaceLWJGL(PGraphics graphics) { - this.graphics = graphics; - this.pgl = (PLWJGL) ((PGraphicsOpenGL)graphics).pgl; - } - - - @Override - public void initOffscreen(PApplet sketch) { - } - - - /* - @Override - public Canvas initComponent(PApplet sketch) { - this.sketch = sketch; - - sketchWidth = sketch.sketchWidth(); - sketchHeight = sketch.sketchHeight(); - - Canvas canvas = new Canvas(); - canvas.setFocusable(true); - canvas.requestFocus(); - canvas.setBounds(0, 0, sketchWidth, sketchHeight); - try { - Display.setParent(canvas); - return canvas; - } catch (LWJGLException e) { - e.printStackTrace(); - } - return null; - } - */ - - - @Override - public void initFrame(PApplet sketch, int backgroundColor, - int deviceIndex, boolean fullScreen, boolean spanDisplays) { - this.sketch = sketch; - sketchWidth = sketch.sketchWidth(); - sketchHeight = sketch.sketchHeight(); - - - // Setup an error callback. The default implementation - // will print the error message in System.err. - glfwSetErrorCallback(errorCallback = errorCallbackPrint(System.err)); - - // Initialize GLFW. Most GLFW functions will not work before doing this. - if (glfwInit() != GL11.GL_TRUE) - throw new IllegalStateException("Unable to initialize GLFW"); - - // Configure our window - glfwDefaultWindowHints(); // optional, the current window hints are already - // the default - glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // the window will stay hidden after - // creation - glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // the window will be resizable - - /* - GraphicsEnvironment environment = - GraphicsEnvironment.getLocalGraphicsEnvironment(); - -// DisplayMode desktopMode = Display.getDesktopDisplayMode(); -// PApplet.println("DESKTOP MODES"); -// PApplet.println(desktopMode); -// PApplet.println("ALL MODES"); - -// try { -// DisplayMode[] allModes = Display.getAvailableDisplayModes(); -// for (DisplayMode mode: allModes) { -// PApplet.println(mode); -// } -// } catch (LWJGLException e) { -// e.printStackTrace(); -// } - - if (deviceIndex >= 0) { // if -1, use the default device - GraphicsDevice[] devices = environment.getScreenDevices(); - if (deviceIndex < devices.length) { - displayDevice = devices[deviceIndex]; - } else { - System.err.format("Display %d does not exist, " + - "using the default display instead.", deviceIndex); - for (int i = 0; i < devices.length; i++) { - System.err.format("Display %d is %s\n", i, devices[i]); - } - } - } - if (displayDevice == null) { - displayDevice = environment.getDefaultScreenDevice(); - } - - // Need to save the window bounds at full screen, - // because pack() will cause the bounds to go to zero. - // http://dev.processing.org/bugs/show_bug.cgi?id=923 - screenRect = spanDisplays ? getDisplaySpan() : - displayDevice.getDefaultConfiguration().getBounds(); - - // Set the displayWidth/Height variables inside PApplet, so that they're - // usable and can even be returned by the sketchWidth()/Height() methods. - sketch.displayWidth = screenRect.width; - sketch.displayHeight = screenRect.height; - - sketchWidth = sketch.sketchWidth(); - sketchHeight = sketch.sketchHeight(); - - // Sketch has already requested to be the same as the screen's - // width and height, so let's roll with full screen mode. - if (screenRect.width == sketchWidth && - screenRect.height == sketchHeight) { - fullScreen = true; - } - -// if (fullScreen || spanDisplays) { - if (spanDisplays) { - sketchWidth = screenRect.width; - sketchHeight = screenRect.height; - } - - if (fullScreen) { - // Called here because the graphics device is needed before we can - // determine whether the sketch wants size(displayWidth, displayHeight), - // and getting the graphics device will be PSurface-specific. - PApplet.hideMenuBar(); - - // Useful hidden switches: - // http://wiki.lwjgl.org/index.php?title=LWJGL_Hidden_Switches - System.setProperty("org.lwjgl.opengl.Window.undecorated", "true"); - } - - if (graphics.is2X()) { - // http://forum.lwjgl.org/index.php?topic=5084.0 - System.setProperty("org.lwjgl.opengl.Display.enableHighDPI", "true"); -// pgl.pixel_scale = 2; - } - - pgl.reqNumSamples = graphics.quality; - -// System.err.println("DISPLAY PARENT: " + Display.getParent()); -// System.err.println("DISPLAY SMOOTH: " + pgl.reqNumSamples); - - try { - int argb = graphics.backgroundColor; - float r = ((argb >> 16) & 0xff) / 255.0f; - float g = ((argb >> 8) & 0xff) / 255.0f; - float b = ((argb) & 0xff) / 255.0f; - Display.setInitialBackground(r, g, b); - if (fullScreen) { - Display.setDisplayMode(new DisplayMode(screenRect.width, screenRect.height)); - } else { - Display.setDisplayMode(new DisplayMode(sketchWidth, sketchHeight)); - } - -// System.err.println(sketchWidth + " " + sketchHeight); - if (fullScreen) { - Display.setFullscreen(true); - } - } catch (LWJGLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } -*/ - -// sketchWidth = sketch.width = sketch.sketchWidth(); -// sketchHeight = sketch.height = sketch.sketchHeight(); - -// frame = new DummyFrame(); -// return frame; - } - - - // get the bounds for all displays - static Rectangle getDisplaySpan() { - Rectangle bounds = new Rectangle(); - GraphicsEnvironment environment = - GraphicsEnvironment.getLocalGraphicsEnvironment(); - for (GraphicsDevice device : environment.getScreenDevices()) { - for (GraphicsConfiguration config : device.getConfigurations()) { - Rectangle2D.union(bounds, config.getBounds(), bounds); - } - } - return bounds; - } - - - @Override - public void setTitle(String title) { -// Display.setTitle(title); - } - - - @Override - public void setVisible(boolean visible) { - // Apparently not possible: - // http://forum.lwjgl.org/index.php?topic=5388.0 -// System.err.println("Cannot set visibility of window in OpenGL"); - } - - - @Override - public void setResizable(boolean resizable) { -// Display.setResizable(resizable); - } - - - /* - @Override - public void placeWindow(int[] location) { - if (location != null) { - // a specific location was received from the Runner - // (applet has been run more than once, user placed window) - Display.setLocation(location[0], location[1]); - } else { // just center on screen - // Can't use frame.setLocationRelativeTo(null) because it sends the - // frame to the main display, which undermines the --display setting. - setFrameCentered(); - } - - if (Display.getY() < 0) { - // Windows actually allows you to place frames where they can't be - // closed. Awesome. http://dev.processing.org/bugs/show_bug.cgi?id=1508 - Display.setLocation(Display.getX(), 30); - } - } - */ - - - @Override - public void placeWindow(int[] location, int[] editorLocation) { - /* - if (location != null) { - // a specific location was received from the Runner - // (the sketch has been run more than once/the user moved the window) - frame.setLocation(location[0], location[1]); - - } else if (editorLocation != null) { - Dimension window = new Dimension(sketchWidth, sketchHeight); - - int locationX = editorLocation[0] - 20; - int locationY = editorLocation[1]; - - if (locationX - window.width > 10) { - // if it fits to the left of the window - Display.setLocation(locationX - window.width, locationY); - - } else { // doesn't fit - // if it fits inside the editor window, - // offset slightly from upper lefthand corner - // so that it's plunked inside the text area - locationX = editorLocation[0] + 66; - locationY = editorLocation[1] + 66; - - if ((locationX + window.width > sketch.displayWidth - 33) || - (locationY + window.height > sketch.displayHeight - 33)) { - // otherwise center on screen - locationX = (sketch.displayWidth - window.width) / 2; - locationY = (sketch.displayHeight - window.height) / 2; - } - Display.setLocation(locationX, locationY); - } - } else { // just center on screen - setFrameCentered(); - } - - if (Display.getY() < 0) { - // Windows actually allows you to place frames where they can't be - // closed. Awesome. http://dev.processing.org/bugs/show_bug.cgi?id=1508 - Display.setLocation(Display.getX(), 30); - } - */ - } - - - boolean presentMode = false; - float offsetX; - float offsetY; - @Override - public void placePresent(int stopColor) { - - if (sketchWidth < screenRect.width || sketchHeight < screenRect.height) { -// System.err.println("WILL USE FBO"); - - presentMode = pgl.presentMode = true; - offsetX = pgl.offsetX = 0.5f * (screenRect.width - sketchWidth); - offsetY = pgl.offsetY = 0.5f * (screenRect.height - sketchHeight); - pgl.requestFBOLayer(); - } - } - - - @Override - public void setupExternalMessages() { - externalMessages = true; - } - - /* - private void setFrameCentered() { - - // Can't use frame.setLocationRelativeTo(null) because it sends the - // frame to the main display, which undermines the --display setting. - Display.setLocation(screenRect.x + (screenRect.width - sketchWidth) / 2, - screenRect.y + (screenRect.height - sketchHeight) / 2); - } -*/ - - - @Override - public void startThread() { - if (thread == null) { - thread = new AnimationThread(); - thread.start(); - } else { - throw new IllegalStateException("Thread already started in PSurfaceLWJGL"); - } - } - - - @Override - public void pauseThread() { - PApplet.debug("PApplet.run() paused, calling object wait..."); - paused = true; - } - - - // halts the animation thread if the pause flag is set - protected void checkPause() { - if (paused) { - synchronized (pauseObject) { - try { - pauseObject.wait(); -// PApplet.debug("out of wait"); - } catch (InterruptedException e) { - // waiting for this interrupt on a start() (resume) call - } - } - } -// PApplet.debug("done with pause"); - } - - - @Override - public void resumeThread() { - paused = false; - synchronized (pauseObject) { - pauseObject.notifyAll(); // wake up the animation thread - } - } - - - @Override - public boolean stopThread() { - if (thread == null) { - return false; - } - thread = null; - return true; - } - - - @Override - public boolean isStopped() { - return thread == null; - } - - - @Override - public void setSize(int width, int height) { - if (frame != null) { - sketchWidth = sketch.width = width; - sketchHeight = sketch.height = height; - graphics.setSize(width, height); - } - } - - -// @Override -// public void initImage(PGraphics graphics) { -// // TODO not sure yet how to implement [fry] -// } - public Component getComponent() { - return frame; - } - - - @Override - public void setSmooth(int level) { - System.err.println("set smooth " + level); - pgl.reqNumSamples = level; - } - - - @Override - public void setFrameRate(float fps) { - /* - frameRateTarget = fps; - if (60 < fps) { - // Disables v-sync - System.err.println("Disabling VSync"); - Display.setVSyncEnabled(false); - } else { - Display.setVSyncEnabled(true); - } - */ - } - - - @Override - public void requestFocus() { - // seems there is no way of request focus on the LWJGL Display, unless - // it is parented inside a Canvas: - // http://www.java-gaming.org/index.php?topic=31158.0 - } - - -// @Override -// public void blit() { -// // Nothing to do here -// } - - - @Override - public void setCursor(int kind) { - System.err.println("Cursor types not supported in OpenGL, provide your cursor image"); - } - - - @Override - public void setCursor(PImage image, int hotspotX, int hotspotY) { - /* - BufferedImage jimg = (BufferedImage)image.getNative(); - IntBuffer buf = IntBuffer.wrap(jimg.getRGB(0, 0, jimg.getWidth(), jimg.getHeight(), - null, 0, jimg.getWidth())); - try { - currentCursor = new Cursor(jimg.getWidth(), jimg.getHeight(), - hotspotX, hotspotY, 1, buf, null); - Mouse.setNativeCursor(currentCursor); - cursorVisible = true; - } catch (LWJGLException e) { - e.printStackTrace(); - } - */ - } - - - @Override - public void showCursor() { - if (!cursorVisible) { - /* - try { - Mouse.setNativeCursor(currentCursor); - cursorVisible = true; - } catch (LWJGLException e) { - e.printStackTrace(); - } - */ - } - } - - - @Override - public void hideCursor() { - /* - if (invisibleCursor == null) { - try { - invisibleCursor = new Cursor(1, 1, 0, 0, 1, BufferUtils.createIntBuffer(1), null); - } catch (LWJGLException e1) { - e1.printStackTrace(); - } - } - try { - Mouse.setNativeCursor(invisibleCursor); - cursorVisible = false; - } catch (LWJGLException e) { - e.printStackTrace(); - } - */ - } - - - class AnimationThread extends Thread { - public AnimationThread() { - super("Animation Thread"); - } - - /** - * Main method for the primary animation thread. - * Painting in AWT and Swing - */ - @Override - public void run() { // not good to make this synchronized, locks things up - int WIDTH = sketchWidth; - int HEIGHT = sketchHeight; - - // Create the window - window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL); - if (window == NULL) - throw new RuntimeException("Failed to create the GLFW window"); - - - // Event handling in LWJGL3: - // https://github.com/LWJGL/lwjgl3-wiki/wiki/2.6.3-Input-handling-with-GLFW - - glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() { - @Override - public void invoke(long window, int key, int scancode, int action, - int mods) { - System.out.println("Key pressed: " + key + ", " + scancode + " " + action); - if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) - glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in - // our rendering loop - } - }); - - glfwSetMouseButtonCallback(window, mouseCallback = new GLFWMouseButtonCallback() { - @Override - public void invoke(long window, int button, int action, int mods) { - System.out.println("mouse pressed: " + button + ", " + action + " " + mods); - } - }); - - glfwSetCursorPosCallback(window, posCallback = new GLFWCursorPosCallback() { - @Override - public void invoke(long window, double xpos, double ypos) { - System.out.println("mouse moved: " + xpos + " " + ypos); - - - long millis = System.currentTimeMillis(); - - int modifiers = 0; -// if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || -// Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { -// modifiers |= Event.SHIFT; -// } -// if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || -// Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) { -// modifiers |= Event.CTRL; -// } -// if (Keyboard.isKeyDown(Keyboard.KEY_LMETA) || -// Keyboard.isKeyDown(Keyboard.KEY_RMETA)) { -// modifiers |= Event.META; -// } -// if (Keyboard.isKeyDown(Keyboard.KEY_LMENU) || -// Keyboard.isKeyDown(Keyboard.KEY_RMENU)) { -// // LWJGL maps the menu key and the alt key to the same value. -// modifiers |= Event.ALT; -// } - - int x = (int)xpos; - int y = (int)ypos; - int button = 0; -// if (Mouse.isButtonDown(0)) { -// button = PConstants.LEFT; -// } else if (Mouse.isButtonDown(1)) { -// button = PConstants.RIGHT; -// } else if (Mouse.isButtonDown(2)) { -// button = PConstants.CENTER; -// } - - int action = 0; -// if (button != 0) { -// if (pressed) { -// action = MouseEvent.DRAG; -// } else { -// action = MouseEvent.PRESS; -// pressed = true; -// } -// } else if (pressed) { -// action = MouseEvent.RELEASE; -// } else { -// action = MouseEvent.MOVE; -// } - action = MouseEvent.MOVE; - -// if (inside) { -// if (!Mouse.isInsideWindow()) { -// inside = false; -// action = MouseEvent.EXIT; -// } -// } else { -// if (Mouse.isInsideWindow()) { -// inside = true; -// action = MouseEvent.ENTER; -// } -// } -// - int count = 0; -// if (Mouse.getEventButtonState()) { -// startedClickTime = millis; -// startedClickButton = button; -// } else { -// if (action == MouseEvent.RELEASE) { -// boolean clickDetected = millis - startedClickTime < 500; -// if (clickDetected) { -// // post a RELEASE event, in addition to the CLICK event. -// MouseEvent me = new MouseEvent(null, millis, action, modifiers, -// x, y, button, count); -// parent.postEvent(me); -// action = MouseEvent.CLICK; -// count = 1; -// } -// } -// } - - - - MouseEvent me = new MouseEvent(null, millis, action, modifiers, - x, y, button, count); - sketch.postEvent(me); - - - } - }); - - glfwSetScrollCallback(window, scrollCallback = new GLFWScrollCallback() { - @Override - public void invoke(long window, double xoffset, double yoffset) { - System.out.println("mouse scrolled: " + xoffset + " " + yoffset); - } - }); - - - - // Get the resolution of the primary monitor - ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - // Center our window - glfwSetWindowPos(window, (GLFWvidmode.width(vidmode) - WIDTH) / 2, - (GLFWvidmode.height(vidmode) - HEIGHT) / 2); - - // Make the OpenGL context current - glfwMakeContextCurrent(window); - // Enable v-sync - glfwSwapInterval(1); - - // Make the window visible - glfwShowWindow(window); - - - GLContext.createFromCurrent(); - - // Set the clear color - glClearColor(1.0f, 0.0f, 0.0f, 0.0f); - - // Run the rendering loop until the user has attempted to close - // the window or has pressed the ESCAPE key. - while (glfwWindowShouldClose(window) == GL_FALSE) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the - // framebuffer - - pgl.setThread(thread); - checkPause(); - sketch.handleDraw(); - - glfwSwapBuffers(window); // swap the color buffers - - // Poll for window events. The key callback above will only be - // invoked during this call. - glfwPollEvents(); - } - - - /* - try { -// System.err.println("CREATE THE DISPLAY"); - PixelFormat format = new PixelFormat(PGL.REQUESTED_ALPHA_BITS, - PGL.REQUESTED_DEPTH_BITS, - PGL.REQUESTED_STENCIL_BITS, pgl.reqNumSamples); - Display.create(format); - } catch (LWJGLException e) { - e.printStackTrace(); - System.exit(0); - } - - keyPoller = new KeyPoller(sketch); - keyPoller.start(); - - mousePoller = new MousePoller(sketch); - mousePoller.start(); - - setSize(sketchWidth, sketchHeight); - sketch.start(); - - int x0 = Display.getX(); - int y0 = Display.getY(); - while ((Thread.currentThread() == thread) && !sketch.finished) { - if (Display.wasResized()) { - setSize(Display.getWidth(), Display.getHeight()); - } - pgl.setThread(thread); - checkPause(); - sketch.handleDraw(); - Display.update(); - - if (sketch.frameCount == 1) { - requestFocus(); - } - - Display.sync((int)frameRateTarget); - - int x = Display.getX(); - int y = Display.getY(); - if (externalMessages && (x != x0 || y0 != y)) { - System.err.println(PApplet.EXTERNAL_MOVE + " " + x + " " + y); - System.err.flush(); // doesn't seem to help or hurt - } - x0 = x; - y0 = y; - - if (Display.isCloseRequested()) { -// if (externalMessages) { -// System.err.println(PApplet.EXTERNAL_QUIT); -// System.err.flush(); // important -// } - sketch.exit(); - break; - } - } - -// System.err.println("DESTROY"); - keyPoller.requestStop(); - mousePoller.requestStop(); - - while (true) { -// graphics.beginDraw(); -//// System.out.println("update"); -// graphics.endDraw(); - if (Display.isCloseRequested() || sketch.exitCalled()) { - sketch.dispose(); // call to shutdown libs? - Display.destroy(); - frame.dispose(); - break; - } - Display.update(); - Display.sync((int)frameRateTarget); - } - - // If the user called the exit() function, the window should close, - // rather than the sketch just halting. - if (sketch.exitCalled()) { - sketch.exitActual(); - } - */ - } - } - - -// @SuppressWarnings("serial") -// class DummyFrame extends Frame { -// -// public DummyFrame() { -// super(); -// } -// -// @Override -// public void setResizable(boolean resizable) { -// Display.setResizable(resizable); -// } -// -// @Override -// public void setVisible(boolean visible) { -// System.err.println("Cannot set visibility of window in OpenGL"); -// } -// -// @Override -// public void setTitle(String title) { -// Display.setTitle(title); -// } -// } - - - - /////////////////////////////////////////////////////////// - - // LWJGL event handling - -/* - protected class KeyPoller extends Thread { - protected PApplet parent; - protected boolean stopRequested; - protected boolean[] pressedKeys; - protected char[] charCheys; - - KeyPoller(PApplet parent) { - this.parent = parent; - stopRequested = false; - try { - Keyboard.create(); - } catch (LWJGLException e) { - e.printStackTrace(); - } - } - - @Override - public void run() { - pressedKeys = new boolean[256]; - charCheys = new char[256]; - Keyboard.enableRepeatEvents(true); - while (true) { - if (stopRequested) break; - - Keyboard.poll(); - while (Keyboard.next()) { - if (stopRequested) break; - - long millis = Keyboard.getEventNanoseconds() / 1000000L; - char keyChar = Keyboard.getEventCharacter(); - int keyCode = Keyboard.getEventKey(); - - if (keyCode >= pressedKeys.length) continue; - - int modifiers = 0; - if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || - Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { - modifiers |= Event.SHIFT; - } - if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || - Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) { - modifiers |= Event.CTRL; - } - if (Keyboard.isKeyDown(Keyboard.KEY_LMETA) || - Keyboard.isKeyDown(Keyboard.KEY_RMETA)) { - modifiers |= Event.META; - } - if (Keyboard.isKeyDown(Keyboard.KEY_LMENU) || - Keyboard.isKeyDown(Keyboard.KEY_RMENU)) { - // LWJGL maps the menu key and the alt key to the same value. - modifiers |= Event.ALT; - } - - int keyPCode = LWJGLtoAWTCode(keyCode); - if ((short)(keyChar) <= 0) { - keyChar = PConstants.CODED; - } - - int action = 0; - if (Keyboard.getEventKeyState()) { - action = KeyEvent.PRESS; - pressedKeys[keyCode] = true; - charCheys[keyCode] = keyChar; - } else if (pressedKeys[keyCode]) { - action = KeyEvent.RELEASE; - pressedKeys[keyCode] = false; - keyChar = charCheys[keyCode]; - } - - KeyEvent ke = new KeyEvent(null, millis, - action, modifiers, - keyChar, keyPCode); - parent.postEvent(ke); - } - try { - Thread.sleep(10); - } catch (InterruptedException e) { - // http://stackoverflow.com/questions/1024651/do-i-have-to-worry-about-interruptedexceptions-if-i-dont-interrupt-anything-mys/1024719#1024719 -// e.printStackTrace(); - Thread.currentThread().interrupt(); // restore interrupted status - break; - } - } - } - - public void requestStop() { - stopRequested = true; - } - } -*/ - - /* - protected class MousePoller extends Thread { - protected PApplet parent; - protected boolean stopRequested; - protected boolean pressed; - protected boolean inside; - protected long startedClickTime; - protected int startedClickButton; - - MousePoller(PApplet parent) { - this.parent = parent; - stopRequested = false; - try { - Mouse.create(); - } catch (LWJGLException e) { - e.printStackTrace(); - } - } - - @Override - public void run() { - while (true) { - if (stopRequested) break; - - Mouse.poll(); - while (Mouse.next()) { - if (stopRequested) break; - - long millis = Mouse.getEventNanoseconds() / 1000000L; - - int modifiers = 0; - if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || - Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { - modifiers |= Event.SHIFT; - } - if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || - Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) { - modifiers |= Event.CTRL; - } - if (Keyboard.isKeyDown(Keyboard.KEY_LMETA) || - Keyboard.isKeyDown(Keyboard.KEY_RMETA)) { - modifiers |= Event.META; - } - if (Keyboard.isKeyDown(Keyboard.KEY_LMENU) || - Keyboard.isKeyDown(Keyboard.KEY_RMENU)) { - // LWJGL maps the menu key and the alt key to the same value. - modifiers |= Event.ALT; - } - -// PApplet.println(Mouse.getX(), Mouse.getY(), offsetX, offsetY); - int x = Mouse.getX() - (int)offsetX; - int y = sketchHeight - (Mouse.getY() - (int)offsetY); - int button = 0; - if (Mouse.isButtonDown(0)) { - button = PConstants.LEFT; - } else if (Mouse.isButtonDown(1)) { - button = PConstants.RIGHT; - } else if (Mouse.isButtonDown(2)) { - button = PConstants.CENTER; - } - - int action = 0; - if (button != 0) { - if (pressed) { - action = MouseEvent.DRAG; - } else { - action = MouseEvent.PRESS; - pressed = true; - } - } else if (pressed) { - action = MouseEvent.RELEASE; - - if (presentMode) { - if (20 < Mouse.getX() && Mouse.getX() < 20 + 100 && - 20 < Mouse.getY() && Mouse.getY() < 20 + 50) { - System.err.println("clicked on exit button"); -// if (externalMessages) { -// System.err.println(PApplet.EXTERNAL_QUIT); -// System.err.flush(); // important -// } - sketch.exit(); - } - } - - pressed = false; - } else { - action = MouseEvent.MOVE; - } - - if (inside) { - if (!Mouse.isInsideWindow()) { - inside = false; - action = MouseEvent.EXIT; - } - } else { - if (Mouse.isInsideWindow()) { - inside = true; - action = MouseEvent.ENTER; - } - } - - int count = 0; - if (Mouse.getEventButtonState()) { - startedClickTime = millis; - startedClickButton = button; - } else { - if (action == MouseEvent.RELEASE) { - boolean clickDetected = millis - startedClickTime < 500; - if (clickDetected) { - // post a RELEASE event, in addition to the CLICK event. - MouseEvent me = new MouseEvent(null, millis, action, modifiers, - x, y, button, count); - parent.postEvent(me); - action = MouseEvent.CLICK; - count = 1; - } - } - } - - MouseEvent me = new MouseEvent(null, millis, action, modifiers, - x, y, button, count); - parent.postEvent(me); - } - try { - Thread.sleep(10); - } catch (InterruptedException e) { -// e.printStackTrace(); - Thread.currentThread().interrupt(); // restore interrupted status - break; - } - } - } - - public void requestStop() { - stopRequested = true; - } - } - - // AWT to LWJGL key constants conversion. - protected static final int[] LWJGL_KEY_CONVERSION; - // Conversion LWJGL -> AWT keycode. Taken from GTGE library - // https://code.google.com/p/gtge/ - static { - // LWJGL -> AWT conversion - // used for keypressed and keyreleased - // mapping Keyboard.KEY_ -> KeyEvent.VK_ - LWJGL_KEY_CONVERSION = new int[Keyboard.KEYBOARD_SIZE]; - - // loops through all of the registered keys in KeyEvent - Field[] keys = java.awt.event.KeyEvent.class.getFields(); - for (int i = 0; i < keys.length; i++) { - try { - // Converts the KeyEvent constant name to the LWJGL constant - // name - String field = "KEY_" + keys[i].getName().substring(3); - Field lwjglKey = Keyboard.class.getField(field); - - // print key mapping - // System.out.println(field + " " + lwjglKey.getInt(null) + "=" - // + keys[i].getInt(null)); - - // Sets LWJGL index to be the KeyCode value - LWJGL_KEY_CONVERSION[lwjglKey.getInt(null)] = keys[i].getInt(null); - - } catch (Exception e) { - } - } - - try { - LWJGL_KEY_CONVERSION[Keyboard.KEY_BACK] = java.awt.event.KeyEvent.VK_BACK_SPACE; - LWJGL_KEY_CONVERSION[Keyboard.KEY_LBRACKET] = java.awt.event.KeyEvent.VK_BRACELEFT; - LWJGL_KEY_CONVERSION[Keyboard.KEY_RBRACKET] = java.awt.event.KeyEvent.VK_BRACERIGHT; - LWJGL_KEY_CONVERSION[Keyboard.KEY_APOSTROPHE] = java.awt.event.KeyEvent.VK_QUOTE; - LWJGL_KEY_CONVERSION[Keyboard.KEY_GRAVE] = java.awt.event.KeyEvent.VK_BACK_QUOTE; - LWJGL_KEY_CONVERSION[Keyboard.KEY_BACKSLASH] = java.awt.event.KeyEvent.VK_BACK_SLASH; - LWJGL_KEY_CONVERSION[Keyboard.KEY_CAPITAL] = java.awt.event.KeyEvent.VK_CAPS_LOCK; - LWJGL_KEY_CONVERSION[Keyboard.KEY_NUMLOCK] = java.awt.event.KeyEvent.VK_NUM_LOCK; - LWJGL_KEY_CONVERSION[Keyboard.KEY_SCROLL] = java.awt.event.KeyEvent.VK_SCROLL_LOCK; - - // two to one buttons mapping - LWJGL_KEY_CONVERSION[Keyboard.KEY_RETURN] = java.awt.event.KeyEvent.VK_ENTER; - LWJGL_KEY_CONVERSION[Keyboard.KEY_NUMPADENTER] = java.awt.event.KeyEvent.VK_ENTER; - LWJGL_KEY_CONVERSION[Keyboard.KEY_LCONTROL] = java.awt.event.KeyEvent.VK_CONTROL; - LWJGL_KEY_CONVERSION[Keyboard.KEY_RCONTROL] = java.awt.event.KeyEvent.VK_CONTROL; - LWJGL_KEY_CONVERSION[Keyboard.KEY_LSHIFT] = java.awt.event.KeyEvent.VK_SHIFT; - LWJGL_KEY_CONVERSION[Keyboard.KEY_RSHIFT] = java.awt.event.KeyEvent.VK_SHIFT; - } - catch (Exception e) { - } - } - - - protected int LWJGLtoAWTCode(int code) { - try { - return LWJGL_KEY_CONVERSION[code]; - } - catch (ArrayIndexOutOfBoundsException e) { - System.err.println("ERROR: Invalid LWJGL KeyCode " + code); - return -1; - } - } - */ -}