diff --git a/android/core/src/processing/opengl/PGraphicsOpenGL.java b/android/core/src/processing/opengl/PGraphicsOpenGL.java index 92f84deab..e79a4a13b 100644 --- a/android/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/android/core/src/processing/opengl/PGraphicsOpenGL.java @@ -543,26 +543,6 @@ public class PGraphicsOpenGL extends PGraphics { tessGeo = newTessGeometry(IMMEDIATE); texCache = newTexCache(); - glPolyVertex = 0; - glPolyColor = 0; - glPolyNormal = 0; - glPolyTexcoord = 0; - glPolyAmbient = 0; - glPolySpecular = 0; - glPolyEmissive = 0; - glPolyShininess = 0; - glPolyIndex = 0; - - glLineVertex = 0; - glLineColor = 0; - glLineAttrib = 0; - glLineIndex = 0; - - glPointVertex = 0; - glPointColor = 0; - glPointAttrib = 0; - glPointIndex = 0; - initialized = false; } @@ -578,7 +558,6 @@ public class PGraphicsOpenGL extends PGraphics { public void setPrimary(boolean primary) { super.setPrimary(primary); format = ARGB; - pgPrimary = this; } @@ -657,13 +636,11 @@ public class PGraphicsOpenGL extends PGraphics { @Override public void dispose() { // PGraphics super.dispose(); - deleteFinalizedGLResources(); deletePolyBuffers(); deleteLineBuffers(); deletePointBuffers(); deleteDefaultShaders(); - pgl.deleteSurface(); } @@ -1616,8 +1593,8 @@ public class PGraphicsOpenGL extends PGraphics { beginOffscreenDraw(); } setDefaults(); - pgCurrent = this; + pgCurrent = this; drawing = true; report("bot beginDraw()"); @@ -1661,9 +1638,7 @@ public class PGraphicsOpenGL extends PGraphics { // Done with an offscreen surface, going back to onscreen drawing. pgCurrent = pgPrimary; } - drawing = false; - pgCurrent = null; report("bot endDraw()"); } @@ -5801,6 +5776,7 @@ public class PGraphicsOpenGL extends PGraphics { pgPrimary.removeCache(this); texture = ptexture = null; } + pgPrimary = this; initialized = true; } diff --git a/android/core/src/processing/opengl/PShader.java b/android/core/src/processing/opengl/PShader.java index 1d580c97f..d9f167746 100644 --- a/android/core/src/processing/opengl/PShader.java +++ b/android/core/src/processing/opengl/PShader.java @@ -103,7 +103,7 @@ public class PShader { firstTexUnit = 0; intBuffer = PGL.allocateIntBuffer(1); - floatBuffer = PGL.allocateDirectFloatBuffer(1); + floatBuffer = PGL.allocateFloatBuffer(1); bound = false; } diff --git a/core/src/processing/opengl/PGL.java b/core/src/processing/opengl/PGL.java index 59b82da52..4d85d58f4 100644 --- a/core/src/processing/opengl/PGL.java +++ b/core/src/processing/opengl/PGL.java @@ -73,6 +73,10 @@ import com.jogamp.opengl.util.AnimatorBase; */ @SuppressWarnings("static-access") public class PGL { + public static final boolean USE_DIRECT_BUFFERS = true; + public static final int MIN_DIRECT_BUFFER_SIZE = 1; + public static final boolean SAVE_SURFACE_TO_PIXELS = true; + // The two windowing toolkits available to use in JOGL: protected static final int AWT = 0; // http://jogamp.org/wiki/index.php/Using_JOGL_in_AWT_SWT_and_Swing protected static final int NEWT = 1; // http://jogamp.org/jogl/doc/NEWT-Overview.html @@ -358,9 +362,6 @@ public class PGL { /** The PGraphics object using this interface */ protected PGraphicsOpenGL pg; - /** Whether OpenGL has been initialized or not */ - protected boolean initialized; - /** Flag to signal rendering of first frame */ protected boolean firstFrame; @@ -509,13 +510,9 @@ public class PGL { if (glu == null) { glu = new GLU(); } - if (byteBuffer == null) { - byteBuffer = allocateDirectByteBuffer(1); - } - if (intBuffer == null) { - intBuffer = allocateDirectIntBuffer(1); - } - initialized = false; + + byteBuffer = allocateByteBuffer(1); + intBuffer = allocateIntBuffer(1); } @@ -534,7 +531,7 @@ public class PGL { // Enabling/disabling v-sync, we force a // surface reinitialization to avoid screen // no-paint issue observed on MacOSX. - initialized = false; + pg.initialized = false; } targetFramerate = framerate; setFramerate = true; @@ -638,7 +635,21 @@ public class PGL { } firstFrame = true; - initialized = true; + } + + + protected void deleteSurface() { + /* + if (glColorTex != null) { + deleteTextures(2, glColorTex); + deleteFramebuffers(1, glColorFbo); + deleteRenderbuffers(1, glDepthStencil); + deleteRenderbuffers(1, glDepth); + deleteRenderbuffers(1, glStencil); + } + fboLayerCreated = false; + glInitialized = false; + */ } @@ -709,10 +720,24 @@ public class PGL { } + protected boolean getDepthTest() { + intBuffer.rewind(); + getBooleanv(DEPTH_TEST, intBuffer); + return intBuffer.get(0) == 0 ? false : true; + } + + + protected boolean getDepthWriteMask() { + intBuffer.rewind(); + getBooleanv(DEPTH_WRITEMASK, intBuffer); + return intBuffer.get(0) == 0 ? false : true; + } + + protected Texture wrapBackTexture() { Texture tex = new Texture(pg.parent); - tex.init(backTex.getName(), - GL.GL_TEXTURE_2D, GL.GL_RGBA, + tex.init(pg.width, pg.height, + backTex.getName(), GL.GL_TEXTURE_2D, GL.GL_RGBA, backTex.getWidth(), backTex.getHeight(), backTex.minFilter, backTex.magFilter, backTex.wrapS, backTex.wrapT); @@ -725,8 +750,8 @@ public class PGL { protected Texture wrapFrontTexture() { Texture tex = new Texture(pg.parent); - tex.init(backTex.getName(), - GL.GL_TEXTURE_2D, GL.GL_RGBA, + tex.init(pg.width, pg.height, + backTex.getName(), GL.GL_TEXTURE_2D, GL.GL_RGBA, frontTex.getWidth(), frontTex.getHeight(), frontTex.minFilter, frontTex.magFilter, frontTex.wrapS, frontTex.wrapT); @@ -813,12 +838,12 @@ public class PGL { protected boolean canDraw() { - return initialized && pg.parent.isDisplayable(); + return pg.initialized && pg.parent.isDisplayable(); } protected void requestDraw() { - if (initialized) { + if (pg.initialized) { try { if (useAnimator) { animator.requestDisplay(); @@ -842,6 +867,12 @@ public class PGL { } + protected static boolean glThreadIsCurrent() { + return Thread.currentThread() == glThread; + } + + + ////////////////////////////////////////////////////////////////////////////// // Caps query @@ -852,47 +883,24 @@ public class PGL { } -// public void getIntegerv(int name, int[] values, int offset) { -// gl.glGetIntegerv(name, values, offset); -// } - - public void getIntegerv(int name, IntBuffer values) { if (-1 < name) { gl.glGetIntegerv(name, values); } else { - fillBuffer(values, 0, values.capacity() - 1, 0); + fillIntBuffer(values, 0, values.capacity() - 1, 0); } } -// public void getFloatv(int name, float[] values, int offset) { -// gl.glGetFloatv(name, values, offset); -// } - - public void getFloatv(int name, FloatBuffer values) { if (-1 < name) { gl.glGetFloatv(name, values); } else { - fillBuffer(values, 0, values.capacity() - 1, 0); + fillFloatBuffer(values, 0, values.capacity() - 1, 0); } } -// public void getBooleanv(int name, boolean[] values, int offset) { -// if (-1 < name) { -// byte[] bvalues = new byte[values.length]; -// gl.glGetBooleanv(name, bvalues, offset); -// for (int i = 0; i < values.length; i++) { -// values[i] = bvalues[i] != 0; -// } -// } else { -// Arrays.fill(values, false); -// } -// } - - public void getBooleanv(int name, IntBuffer values) { if (-1 < name) { if (byteBuffer.capacity() < values.capacity()) { @@ -903,7 +911,7 @@ public class PGL { values.put(i, byteBuffer.get(i)); } } else { - fillBuffer(values, 0, values.capacity() - 1, 0); + fillIntBuffer(values, 0, values.capacity() - 1, 0); } } @@ -987,21 +995,11 @@ public class PGL { // Textures -// public void genTextures(int n, int[] ids, int offset) { -// gl.glGenTextures(n, ids, offset); -// } - - public void genTextures(int n, IntBuffer ids) { gl.glGenTextures(n, ids); } -// public void deleteTextures(int n, int[] ids, int offset) { -// gl.glDeleteTextures(n, ids, offset); -// } - - public void deleteTextures(int n, IntBuffer ids) { gl.glDeleteTextures(n, ids); } @@ -1048,12 +1046,6 @@ public class PGL { } -// public void getTexParameteriv(int target, int param, int[] values, -// int offset) { -// gl.glGetTexParameteriv(target, param, values, offset); -// } - - public void getTexParameteriv(int target, int param, IntBuffer values) { gl.glGetTexParameteriv(target, param, values); } @@ -1069,21 +1061,11 @@ public class PGL { // Vertex Buffers -// public void genBuffers(int n, int[] ids, int offset) { -// gl.glGenBuffers(n, ids, offset); -// } - - public void genBuffers(int n, IntBuffer ids) { gl.glGenBuffers(n, ids); } -// public void deleteBuffers(int n, int[] ids, int offset) { -// gl.glDeleteBuffers(n, ids, offset); -// } - - public void deleteBuffers(int n, IntBuffer ids) { gl.glDeleteBuffers(n, ids); } @@ -1161,41 +1143,21 @@ public class PGL { // Framebuffers, renderbuffers -// public void genFramebuffers(int n, int[] ids, int offset) { -// gl.glGenFramebuffers(n, ids, offset); -// } - - public void genFramebuffers(int n, IntBuffer ids) { gl.glGenFramebuffers(n, ids); } -// public void deleteFramebuffers(int n, int[] ids, int offset) { -// gl.glDeleteFramebuffers(n, ids, offset); -// } - - public void deleteFramebuffers(int n, IntBuffer ids) { gl.glDeleteFramebuffers(n, ids); } -// public void genRenderbuffers(int n, int[] ids, int offset) { -// gl.glGenRenderbuffers(n, ids, offset); -// } - - public void genRenderbuffers(int n, IntBuffer ids) { gl.glGenRenderbuffers(n, ids); } -// public void deleteRenderbuffers(int n, int[] ids, int offset) { -// gl.glDeleteRenderbuffers(n, ids, offset); -// } - - public void deleteRenderbuffers(int n, IntBuffer ids) { gl.glDeleteRenderbuffers(n, ids); } @@ -1345,116 +1307,58 @@ public class PGL { } -// public void uniform1iv(int loc, int count, int[] v, int offset) { -// gl2.glUniform1iv(loc, count, v, offset); -// } - - public void uniform1iv(int loc, int count, IntBuffer v) { gl2.glUniform1iv(loc, count, v); } -// public void uniform2iv(int loc, int count, int[] v, int offset) { -// gl2.glUniform2iv(loc, count, v, offset); -// } - - public void uniform2iv(int loc, int count, IntBuffer v) { gl2.glUniform2iv(loc, count, v); } -// public void uniform3iv(int loc, int count, int[] v, int offset) { -// gl2.glUniform3iv(loc, count, v, offset); -// } - - public void uniform3iv(int loc, int count, IntBuffer v) { gl2.glUniform3iv(loc, count, v); } -// public void uniform4iv(int loc, int count, int[] v, int offset) { -// gl2.glUniform4iv(loc, count, v, offset); -// } - - public void uniform4iv(int loc, int count, IntBuffer v) { gl2.glUniform4iv(loc, count, v); } -// public void uniform1fv(int loc, int count, float[] v, int offset) { -// gl2.glUniform1fv(loc, count, v, offset); -// } - - public void uniform1fv(int loc, int count, FloatBuffer v) { gl2.glUniform1fv(loc, count, v); } -// public void uniform2fv(int loc, int count, float[] v, int offset) { -// gl2.glUniform2fv(loc, count, v, offset); -// } - - public void uniform2fv(int loc, int count, FloatBuffer v) { gl2.glUniform2fv(loc, count, v); } -// public void uniform3fv(int loc, int count, float[] v, int offset) { -// gl2.glUniform3fv(loc, count, v, offset); -// } - - public void uniform3fv(int loc, int count, FloatBuffer v) { gl2.glUniform3fv(loc, count, v); } -// public void uniform4fv(int loc, int count, float[] v, int offset) { -// gl2.glUniform4fv(loc, count, v, offset); -// } - - public void uniform4fv(int loc, int count, FloatBuffer v) { gl2.glUniform4fv(loc, count, v); } -// public void uniformMatrix2fv(int loc, int count, boolean transpose, -// float[] mat, int offset) { -// gl2.glUniformMatrix2fv(loc, count, transpose, mat, offset); -// } - - public void uniformMatrix2fv(int loc, int count, boolean transpose, FloatBuffer mat) { gl2.glUniformMatrix2fv(loc, count, transpose, mat); } -// public void uniformMatrix3fv(int loc, int count, boolean transpose, -// float[] mat, int offset) { -// gl2.glUniformMatrix3fv(loc, count, transpose, mat, offset); -// } - - public void uniformMatrix3fv(int loc, int count, boolean transpose, FloatBuffer mat) { gl2.glUniformMatrix3fv(loc, count, transpose, mat); } -// public void uniformMatrix4fv(int loc, int count, boolean transpose, -// float[] mat, int offset) { -// gl2.glUniformMatrix4fv(loc, count, transpose, mat, offset); -// } - - public void uniformMatrix4fv(int loc, int count, boolean transpose, FloatBuffer mat) { gl2.glUniformMatrix4fv(loc, count, transpose, mat); @@ -1482,41 +1386,21 @@ public class PGL { } -// public void vertexAttrib1fv(int loc, float[] v, int offset) { -// gl2.glVertexAttrib1fv(loc, v, offset); -// } - - public void vertexAttrib1fv(int loc, FloatBuffer v) { gl2.glVertexAttrib1fv(loc, v); } -// public void vertexAttrib2fv(int loc, float[] v, int offset) { -// gl2.glVertexAttrib2fv(loc, v, offset); -// } - - public void vertexAttrib2fv(int loc, FloatBuffer v) { gl2.glVertexAttrib2fv(loc, v); } -// public void vertexAttrib3fv(int loc, float[] v, int offset) { -// gl2.glVertexAttrib3fv(loc, v, offset); -// } - - public void vertexAttrib3fv(int loc, FloatBuffer v) { gl2.glVertexAttrib3fv(loc, v); } -// public void vertexAttrib4fv(int loc, float[] v, int offset) { -// gl2.glVertexAttrib4fv(loc, v, offset); -// } - - public void vertexAttri4fv(int loc, FloatBuffer v) { gl2.glVertexAttrib4fv(loc, v); } @@ -1537,11 +1421,6 @@ public class PGL { } -// public void getShaderiv(int shader, int pname, int[] params, int offset) { -// gl2.glGetShaderiv(shader, pname, params, offset); -// } - - public void getShaderiv(int shader, int pname, IntBuffer params) { gl2.glGetShaderiv(shader, pname, params); } @@ -1558,11 +1437,6 @@ public class PGL { } -// public void getProgramiv(int prog, int pname, int[] params, int offset) { -// gl2.glGetProgramiv(prog, pname, params, offset); -// } - - public void getProgramiv(int prog, int pname, IntBuffer params) { gl2.glGetProgramiv(prog, pname, params); } @@ -1938,16 +1812,14 @@ public class PGL { if (0 < tex2DShaderProgram) { // The texture overwrites anything drawn earlier. - getBooleanv(DEPTH_TEST, intBuffer); - boolean depthTest = intBuffer.get(0) == 0 ? false : true; + boolean depthTest = getDepthTest(); disable(DEPTH_TEST); // When drawing the texture we don't write to the // depth mask, so the texture remains in the background // and can be occluded by anything drawn later, even if // if it is behind it. - getBooleanv(DEPTH_WRITEMASK, intBuffer); - boolean depthMask = intBuffer.get(0) == 0 ? false : true; + boolean depthMask = getDepthWriteMask(); depthMask(false); useProgram(tex2DShaderProgram); @@ -2045,16 +1917,14 @@ public class PGL { if (0 < texRectShaderProgram) { // The texture overwrites anything drawn earlier. - getBooleanv(DEPTH_TEST, intBuffer); - boolean depthTest = intBuffer.get(0) == 0 ? false : true; + boolean depthTest = getDepthTest(); disable(DEPTH_TEST); // When drawing the texture we don't write to the // depth mask, so the texture remains in the background // and can be occluded by anything drawn later, even if // if it is behind it. - getBooleanv(DEPTH_WRITEMASK, intBuffer); - boolean depthMask = intBuffer.get(0) == 0 ? false : true; + boolean depthMask = getDepthWriteMask(); depthMask(false); useProgram(texRectShaderProgram); @@ -2471,9 +2341,7 @@ public class PGL { if (shader != 0) { shaderSource(shader, source); compileShader(shader); - getShaderiv(shader, COMPILE_STATUS, intBuffer); - boolean compiled = intBuffer.get(0) == 0 ? false : true; - if (!compiled) { + if (!compiled(shader)) { System.err.println("Could not compile shader " + shaderType + ":"); System.err.println(getShaderInfoLog(shader)); deleteShader(shader); @@ -2490,9 +2358,7 @@ public class PGL { attachShader(program, vertexShader); attachShader(program, fragmentShader); linkProgram(program); - getProgramiv(program, LINK_STATUS, intBuffer); - boolean linked = intBuffer.get(0) == 0 ? false : true; - if (!linked) { + if (!linked(program)) { System.err.println("Could not link program: "); System.err.println(getProgramInfoLog(program)); deleteProgram(program); @@ -2503,6 +2369,20 @@ public class PGL { } + protected boolean compiled(int shader) { + intBuffer.rewind(); + getShaderiv(shader, COMPILE_STATUS, intBuffer); + return intBuffer.get(0) == 0 ? false : true; + } + + + protected boolean linked(int program) { + intBuffer.rewind(); + getProgramiv(program, LINK_STATUS, intBuffer); + return intBuffer.get(0) == 0 ? false : true; + } + + protected boolean validateFramebuffer() { int status = checkFramebufferStatus(FRAMEBUFFER); if (status == FRAMEBUFFER_COMPLETE) { @@ -2559,30 +2439,74 @@ public class PGL { protected static ByteBuffer allocateDirectByteBuffer(int size) { - return ByteBuffer.allocateDirect(size * SIZEOF_BYTE). - order(ByteOrder.nativeOrder()); + int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_BYTE; + return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()); } - protected static ShortBuffer allocateDirectShortBuffer(int size) { - return ByteBuffer.allocateDirect(size * SIZEOF_SHORT). - order(ByteOrder.nativeOrder()).asShortBuffer(); + protected static ByteBuffer allocateByteBuffer(int size) { + if (USE_DIRECT_BUFFERS) { + return allocateDirectByteBuffer(size); + } else { + return ByteBuffer.allocate(size); + } } - protected static IntBuffer allocateDirectIntBuffer(int size) { - return ByteBuffer.allocateDirect(size * SIZEOF_INT). - order(ByteOrder.nativeOrder()).asIntBuffer(); + protected static ByteBuffer allocateByteBuffer(byte[] arr) { + if (USE_DIRECT_BUFFERS) { + return PGL.allocateDirectByteBuffer(arr.length); + } else { + return ByteBuffer.wrap(arr); + } } - protected static FloatBuffer allocateDirectFloatBuffer(int size) { - return ByteBuffer.allocateDirect(size * SIZEOF_FLOAT). - order(ByteOrder.nativeOrder()).asFloatBuffer(); + protected static ByteBuffer updateByteBuffer(ByteBuffer buf, byte[] arr, + boolean wrap) { + if (USE_DIRECT_BUFFERS) { + if (buf == null || buf.capacity() < arr.length) { + buf = PGL.allocateDirectByteBuffer(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } else { + if (wrap) { + buf = ByteBuffer.wrap(arr); + } else { + if (buf == null || buf.capacity() < arr.length) { + buf = ByteBuffer.allocate(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + return buf; } - protected static void fillBuffer(ByteBuffer buf, int i0, int i1, byte val) { + protected static void getByteArray(ByteBuffer buf, byte[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.get(arr); + buf.rewind(); + } + } + + + protected static void putByteArray(ByteBuffer buf, byte[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + + + protected static void fillByteBuffer(ByteBuffer buf, int i0, int i1, + byte val) { int n = i1 - i0; byte[] temp = new byte[n]; Arrays.fill(temp, 0, n, val); @@ -2592,7 +2516,76 @@ public class PGL { } - protected static void fillBuffer(ShortBuffer buf, int i0, int i1, short val) { + protected static ShortBuffer allocateDirectShortBuffer(int size) { + int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_SHORT; + return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()). + asShortBuffer(); + } + + + protected static ShortBuffer allocateShortBuffer(int size) { + if (USE_DIRECT_BUFFERS) { + return allocateDirectShortBuffer(size); + } else { + return ShortBuffer.allocate(size); + } + } + + + protected static ShortBuffer allocateShortBuffer(short[] arr) { + if (USE_DIRECT_BUFFERS) { + return PGL.allocateDirectShortBuffer(arr.length); + } else { + return ShortBuffer.wrap(arr); + } + } + + + protected static ShortBuffer updateShortBuffer(ShortBuffer buf, short[] arr, + boolean wrap) { + if (USE_DIRECT_BUFFERS) { + if (buf == null || buf.capacity() < arr.length) { + buf = PGL.allocateDirectShortBuffer(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } else { + if (wrap) { + buf = ShortBuffer.wrap(arr); + } else { + if (buf == null || buf.capacity() < arr.length) { + buf = ShortBuffer.allocate(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + return buf; + } + + + protected static void getShortArray(ShortBuffer buf, short[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.get(arr); + buf.rewind(); + } + } + + + protected static void putShortArray(ShortBuffer buf, short[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + + + protected static void fillShortBuffer(ShortBuffer buf, int i0, int i1, + short val) { int n = i1 - i0; short[] temp = new short[n]; Arrays.fill(temp, 0, n, val); @@ -2602,7 +2595,75 @@ public class PGL { } - protected static void fillBuffer(IntBuffer buf, int i0, int i1, int val) { + protected static IntBuffer allocateDirectIntBuffer(int size) { + int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_INT; + return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()). + asIntBuffer(); + } + + + protected static IntBuffer allocateIntBuffer(int size) { + if (USE_DIRECT_BUFFERS) { + return allocateDirectIntBuffer(size); + } else { + return IntBuffer.allocate(size); + } + } + + + protected static IntBuffer allocateIntBuffer(int[] arr) { + if (USE_DIRECT_BUFFERS) { + return PGL.allocateDirectIntBuffer(arr.length); + } else { + return IntBuffer.wrap(arr); + } + } + + + protected static IntBuffer updateIntBuffer(IntBuffer buf, int[] arr, + boolean wrap) { + if (USE_DIRECT_BUFFERS) { + if (buf == null || buf.capacity() < arr.length) { + buf = PGL.allocateDirectIntBuffer(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } else { + if (wrap) { + buf = IntBuffer.wrap(arr); + } else { + if (buf == null || buf.capacity() < arr.length) { + buf = IntBuffer.allocate(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + return buf; + } + + + protected static void getIntArray(IntBuffer buf, int[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.get(arr); + buf.rewind(); + } + } + + + protected static void putIntArray(IntBuffer buf, int[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + + + protected static void fillIntBuffer(IntBuffer buf, int i0, int i1, int val) { int n = i1 - i0; int[] temp = new int[n]; Arrays.fill(temp, 0, n, val); @@ -2612,7 +2673,76 @@ public class PGL { } - protected static void fillBuffer(FloatBuffer buf, int i0, int i1, float val) { + protected static FloatBuffer allocateDirectFloatBuffer(int size) { + int bytes = PApplet.max(MIN_DIRECT_BUFFER_SIZE, size) * SIZEOF_FLOAT; + return ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()). + asFloatBuffer(); + } + + + protected static FloatBuffer allocateFloatBuffer(int size) { + if (USE_DIRECT_BUFFERS) { + return allocateDirectFloatBuffer(size); + } else { + return FloatBuffer.allocate(size); + } + } + + + protected static FloatBuffer allocateFloatBuffer(float[] arr) { + if (USE_DIRECT_BUFFERS) { + return PGL.allocateDirectFloatBuffer(arr.length); + } else { + return FloatBuffer.wrap(arr); + } + } + + + protected static FloatBuffer updateFloatBuffer(FloatBuffer buf, float[] arr, + boolean wrap) { + if (USE_DIRECT_BUFFERS) { + if (buf == null || buf.capacity() < arr.length) { + buf = PGL.allocateDirectFloatBuffer(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } else { + if (wrap) { + buf = FloatBuffer.wrap(arr); + } else { + if (buf == null || buf.capacity() < arr.length) { + buf = FloatBuffer.allocate(arr.length); + } + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + return buf; + } + + + protected static void getFloatArray(FloatBuffer buf, float[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.get(arr); + buf.rewind(); + } + } + + + protected static void putFloatArray(FloatBuffer buf, float[] arr) { + if (!buf.hasArray() || buf.array() != arr) { + buf.position(0); + buf.put(arr); + buf.rewind(); + } + } + + + protected static void fillFloatBuffer(FloatBuffer buf, int i0, int i1, + float val) { int n = i1 - i0; float[] temp = new float[n]; Arrays.fill(temp, 0, n, val); @@ -2622,11 +2752,6 @@ public class PGL { } - protected static boolean glThreadIsCurrent() { - return Thread.currentThread() == glThread; - } - - /////////////////////////////////////////////////////////// // Java specific stuff diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 8485da8ce..e79a4a13b 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -106,6 +106,9 @@ public class PGraphicsOpenGL extends PGraphics { // Basic rendering parameters: + /** Whether the PGraphics object is ready to render or not. */ + protected boolean initialized; + /** Flush modes: continuously (geometry is flushed after each call to * endShape) when-full (geometry is accumulated until a maximum size is * reached. */ @@ -425,7 +428,6 @@ public class PGraphicsOpenGL extends PGraphics { // Offscreen rendering: - protected boolean initializedOffscreen; protected FrameBuffer offscreenFramebuffer; protected FrameBuffer multisampleFramebuffer; protected boolean offscreenMultisample; @@ -451,6 +453,12 @@ public class PGraphicsOpenGL extends PGraphics { /** IntBuffer wrapping the native pixels array. */ protected IntBuffer nativePixelBuffer; + /** texture used to apply a filter on the screen image. */ + protected Texture filterTexture; + + /** PImage that wraps filterTexture. */ + protected PImage filterImage; + /** Flag to indicate if the user is manipulating the * pixels array through the set()/get() methods */ protected boolean setgetPixels; @@ -527,35 +535,15 @@ public class PGraphicsOpenGL extends PGraphics { tessellator = new Tessellator(); } - - intBuffer = PGL.allocateDirectIntBuffer(2); - floatBuffer = PGL.allocateDirectFloatBuffer(2); - - viewport = PGL.allocateDirectIntBuffer(4); + intBuffer = PGL.allocateIntBuffer(2); + floatBuffer = PGL.allocateFloatBuffer(2); + viewport = PGL.allocateIntBuffer(4); inGeo = newInGeometry(IMMEDIATE); tessGeo = newTessGeometry(IMMEDIATE); texCache = newTexCache(); - glPolyVertex = 0; - glPolyColor = 0; - glPolyNormal = 0; - glPolyTexcoord = 0; - glPolyAmbient = 0; - glPolySpecular = 0; - glPolyEmissive = 0; - glPolyShininess = 0; - glPolyIndex = 0; - - glLineVertex = 0; - glLineColor = 0; - glLineAttrib = 0; - glLineIndex = 0; - - glPointVertex = 0; - glPointColor = 0; - glPointAttrib = 0; - glPointIndex = 0; + initialized = false; } @@ -603,7 +591,6 @@ public class PGraphicsOpenGL extends PGraphics { cameraAspect = (float) width / (float) height; // Forces a restart of OpenGL so the canvas has the right size. - //pgl.initialized = false; restartPGL(); // set this flag so that beginDraw() will do an update to the camera. @@ -653,6 +640,8 @@ public class PGraphicsOpenGL extends PGraphics { deletePolyBuffers(); deleteLineBuffers(); deletePointBuffers(); + deleteDefaultShaders(); + pgl.deleteSurface(); } @@ -718,10 +707,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = intBuffer.get(0); GLResource res = new GLResource(id, context); - - if (glTextureObjects.containsKey(res)) { - throw new RuntimeException("Adding same texture twice"); - } else { + if (!glTextureObjects.containsKey(res)) { glTextureObjects.put(res, false); } @@ -785,10 +771,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = intBuffer.get(0); GLResource res = new GLResource(id, context); - - if (glVertexBuffers.containsKey(res)) { - throw new RuntimeException("Adding same VBO twice"); - } else { + if (!glVertexBuffers.containsKey(res)) { glVertexBuffers.put(res, false); } @@ -852,10 +835,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = intBuffer.get(0); GLResource res = new GLResource(id, context); - - if (glFrameBuffers.containsKey(res)) { - throw new RuntimeException("Adding same FBO twice"); - } else { + if (!glFrameBuffers.containsKey(res)) { glFrameBuffers.put(res, false); } @@ -919,10 +899,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = intBuffer.get(0); GLResource res = new GLResource(id, context); - - if (glRenderBuffers.containsKey(res)) { - throw new RuntimeException("Adding same renderbuffer twice"); - } else { + if (!glRenderBuffers.containsKey(res)) { glRenderBuffers.put(res, false); } @@ -985,10 +962,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = pgl.createProgram(); GLResource res = new GLResource(id, context); - - if (glslPrograms.containsKey(res)) { - throw new RuntimeException("Adding same glsl program twice"); - } else { + if (!glslPrograms.containsKey(res)) { glslPrograms.put(res, false); } @@ -1048,10 +1022,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = pgl.createShader(PGL.VERTEX_SHADER); GLResource res = new GLResource(id, context); - - if (glslVertexShaders.containsKey(res)) { - throw new RuntimeException("Adding same glsl vertex shader twice"); - } else { + if (!glslVertexShaders.containsKey(res)) { glslVertexShaders.put(res, false); } @@ -1112,10 +1083,7 @@ public class PGraphicsOpenGL extends PGraphics { int id = pgl.createShader(PGL.FRAGMENT_SHADER); GLResource res = new GLResource(id, context); - - if (glslFragmentShaders.containsKey(res)) { - throw new RuntimeException("Adding same glsl fragment shader twice"); - } else { + if (!glslFragmentShaders.containsKey(res)) { glslFragmentShaders.put(res, false); } @@ -1583,7 +1551,7 @@ public class PGraphicsOpenGL extends PGraphics { @Override public void requestDraw() { if (primarySurface) { - if (pgl.initialized) { + if (initialized) { pgl.requestDraw(); } else { initPrimary(); @@ -1624,8 +1592,8 @@ public class PGraphicsOpenGL extends PGraphics { updateOffscreen(); beginOffscreenDraw(); } - setDefaults(); + pgCurrent = this; drawing = true; @@ -1645,14 +1613,15 @@ public class PGraphicsOpenGL extends PGraphics { // Flushing any remaining geometry. flush(); - if (!pgPrimary.pgl.initialized || parent.frameCount == 0) { + if (PGL.SAVE_SURFACE_TO_PIXELS && + (!pgPrimary.initialized || parent.frameCount == 0)) { // Smooth was disabled/enabled at some point during drawing. We save // the current contents of the back buffer (because the buffers haven't // been swapped yet) to the pixels array. The frameCount == 0 condition // is to handle the situation when no smooth is called in setup in the // PDE, but the OpenGL appears to be recreated due to the size() nastiness. -// saveSurfaceToPixels(); -// restoreSurface = true; + saveSurfaceToPixels(); + restoreSurface = true; } if (primarySurface) { @@ -1695,7 +1664,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void restartPGL() { - pgl.initialized = false; + initialized = false; } @@ -5041,7 +5010,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void allocatePixels() { if ((pixels == null) || (pixels.length != width * height)) { pixels = new int[width * height]; - pixelBuffer = PGL.allocateDirectIntBuffer(width * height); + pixelBuffer = PGL.allocateIntBuffer(pixels); } } @@ -5059,7 +5028,6 @@ public class PGraphicsOpenGL extends PGraphics { protected void readPixels() { beginPixelsOp(OP_READ); - pixelBuffer.rewind(); try { // The readPixels() call in inside a try/catch block because it appears // that (only sometimes) JOGL will run beginDraw/endDraw on the EDT @@ -5074,9 +5042,7 @@ public class PGraphicsOpenGL extends PGraphics { endPixelsOp(); try { // Idem... - pixelBuffer.position(0); - pixelBuffer.get(pixels); - pixelBuffer.rewind(); + PGL.getIntArray(pixelBuffer, pixels); PGL.nativeToJavaARGB(pixels, width, height); } catch (ArrayIndexOutOfBoundsException e) { } @@ -5087,7 +5053,7 @@ public class PGraphicsOpenGL extends PGraphics { int len = w * h; if (nativePixels == null || nativePixels.length < len) { nativePixels = new int[len]; - nativePixelBuffer = PGL.allocateDirectIntBuffer(len); + nativePixelBuffer = PGL.allocateIntBuffer(nativePixels); } try { @@ -5109,7 +5075,7 @@ public class PGraphicsOpenGL extends PGraphics { PGL.javaToNativeARGB(nativePixels, w, h); } catch (ArrayIndexOutOfBoundsException e) { } - + PGL.putIntArray(nativePixelBuffer, nativePixels); // Copying pixel buffer to screen texture... if (primarySurface && !pgl.isFBOBacked()) { // First making sure that the screen texture is valid. Only in the case @@ -5117,11 +5083,6 @@ public class PGraphicsOpenGL extends PGraphics { loadTextureImpl(POINT, false); } - // Put native pixels in direct buffer for copy. - nativePixelBuffer.position(0); - nativePixelBuffer.put(nativePixels); - nativePixelBuffer.rewind(); - boolean needToDrawTex = primarySurface && (!pgl.isFBOBacked() || (pgl.isFBOBacked() && pgl.isMultisampled())) || offscreenMultisample; @@ -5224,13 +5185,12 @@ public class PGraphicsOpenGL extends PGraphics { // then copy this array into the texture. if (nativePixels == null || nativePixels.length < width * height) { nativePixels = new int[width * height]; - nativePixelBuffer = PGL.allocateDirectIntBuffer(width * height); + nativePixelBuffer = PGL.allocateIntBuffer(nativePixels); } beginPixelsOp(OP_READ); try { // Se comments in readPixels() for the reason for this try/catch. - nativePixelBuffer.rewind(); pgl.readPixels(0, 0, width, height, PGL.RGBA, PGL.UNSIGNED_BYTE, nativePixelBuffer); } catch (IndexOutOfBoundsException e) { @@ -5295,7 +5255,6 @@ public class PGraphicsOpenGL extends PGraphics { protected void loadTextureImpl(int sampling, boolean mipmap) { - if (width == 0 || height == 0) return; if (texture == null || texture.contextIsOutdated()) { Texture.Parameters params = new Texture.Parameters(ARGB, @@ -5410,6 +5369,13 @@ public class PGraphicsOpenGL extends PGraphics { } loadTexture(); + if (filterTexture == null || filterTexture.contextIsOutdated()) { + filterTexture = new Texture(parent, texture.width, texture.height, + texture.getParameters()); + filterTexture.invertedY(true); + filterImage = wrapTexture(filterTexture); + } + filterTexture.set(texture); // Disable writing to the depth buffer, so that after applying the filter we // can still use the depth information to keep adding geometry to the scene. @@ -5433,7 +5399,7 @@ public class PGraphicsOpenGL extends PGraphics { PolyTexShader prevTexShader = polyTexShader; polyTexShader = (PolyTexShader) shader; beginShape(QUADS); - texture(this); + texture(filterImage); vertex(0, 0, 0, 0); vertex(width, 0, 1, 0); vertex(width, height, 1, 1); @@ -5806,13 +5772,12 @@ public class PGraphicsOpenGL extends PGraphics { protected void initPrimary() { pgl.initSurface(quality); - if (pgPrimary == null) { - pgPrimary = this; - } if (texture != null) { pgPrimary.removeCache(this); texture = ptexture = null; } + pgPrimary = this; + initialized = true; } @@ -5846,7 +5811,6 @@ public class PGraphicsOpenGL extends PGraphics { protected void initOffscreen() { // Getting the context and capabilities from the main renderer. - pgPrimary = (PGraphicsOpenGL)parent.g; loadTextureImpl(Texture.BILINEAR, false); // In case of reinitialization (for example, when the smooth level @@ -5887,12 +5851,12 @@ public class PGraphicsOpenGL extends PGraphics { offscreenFramebuffer.setColorBuffer(texture); offscreenFramebuffer.clear(); - initializedOffscreen = true; + initialized = true; } protected void updateOffscreen() { - if (!initializedOffscreen) { + if (!initialized) { initOffscreen(); } else { boolean outdated = offscreenFramebuffer != null && @@ -6342,6 +6306,20 @@ public class PGraphicsOpenGL extends PGraphics { } + protected void deleteDefaultShaders() { + // The default shaders contains references to the PGraphics object that + // creates them, so when restarting the renderer, those references should + // dissapear. + defPolyColorShader = null; + defPolyTexShader = null; + defPolyLightShader = null; + defPolyTexlightShader = null; + defLineShader = null; + defPointShader = null; + maskShader = null; + } + + protected BaseShader getPolyShader(boolean lit, boolean tex) { BaseShader shader; if (lit) { @@ -7275,14 +7253,6 @@ public class PGraphicsOpenGL extends PGraphics { hasTexture = false; } - void dispose() { - textures = null; - firstIndex = null; - lastIndex = null; - firstCache = null; - lastCache = null; - } - void beginRender() { tex0 = null; } @@ -7577,21 +7547,6 @@ public class PGraphicsOpenGL extends PGraphics { clear(); } - void dispose() { - breaks = null; - vertices = null; - colors = null; - normals = null; - texcoords = null; - strokeColors = null; - strokeWeights = null; - ambient = null; - specular = null; - emissive = null; - shininess = null; - edges = null; - } - void vertexCheck() { if (vertexCount == vertices.length / 3) { int newSize = vertexCount << 1; @@ -9024,26 +8979,6 @@ public class PGraphicsOpenGL extends PGraphics { // Allocate/dispose void allocate() { - polyVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * PGL.DEFAULT_TESS_VERTICES); - polyColorsBuffer = PGL.allocateDirectIntBuffer(PGL.DEFAULT_TESS_VERTICES); - polyNormalsBuffer = PGL.allocateDirectFloatBuffer(3 * PGL.DEFAULT_TESS_VERTICES); - polyTexcoordsBuffer = PGL.allocateDirectFloatBuffer(2 * PGL.DEFAULT_TESS_VERTICES); - polyAmbientBuffer = PGL.allocateDirectIntBuffer(PGL.DEFAULT_TESS_VERTICES); - polySpecularBuffer = PGL.allocateDirectIntBuffer(PGL.DEFAULT_TESS_VERTICES); - polyEmissiveBuffer = PGL.allocateDirectIntBuffer(PGL.DEFAULT_TESS_VERTICES); - polyShininessBuffer = PGL.allocateDirectFloatBuffer(PGL.DEFAULT_TESS_VERTICES); - polyIndicesBuffer = PGL.allocateDirectShortBuffer(PGL.DEFAULT_TESS_VERTICES); - - lineVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * PGL.DEFAULT_TESS_VERTICES); - lineColorsBuffer = PGL.allocateDirectIntBuffer(PGL.DEFAULT_TESS_VERTICES); - lineAttribsBuffer = PGL.allocateDirectFloatBuffer(4 * PGL.DEFAULT_TESS_VERTICES); - lineIndicesBuffer = PGL.allocateDirectShortBuffer(PGL.DEFAULT_TESS_VERTICES); - - pointVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * PGL.DEFAULT_TESS_VERTICES); - pointColorsBuffer = PGL.allocateDirectIntBuffer(PGL.DEFAULT_TESS_VERTICES); - pointAttribsBuffer = PGL.allocateDirectFloatBuffer(2 * PGL.DEFAULT_TESS_VERTICES); - pointIndicesBuffer = PGL.allocateDirectShortBuffer(PGL.DEFAULT_TESS_VERTICES); - polyVertices = new float[4 * PGL.DEFAULT_TESS_VERTICES]; polyColors = new int[PGL.DEFAULT_TESS_VERTICES]; polyNormals = new float[3 * PGL.DEFAULT_TESS_VERTICES]; @@ -9064,6 +8999,26 @@ public class PGraphicsOpenGL extends PGraphics { pointAttribs = new float[2 * PGL.DEFAULT_TESS_VERTICES]; pointIndices = new short[PGL.DEFAULT_TESS_VERTICES]; + polyVerticesBuffer = PGL.allocateFloatBuffer(polyVertices); + polyColorsBuffer = PGL.allocateIntBuffer(polyColors); + polyNormalsBuffer = PGL.allocateFloatBuffer(polyNormals); + polyTexcoordsBuffer = PGL.allocateFloatBuffer(polyTexcoords); + polyAmbientBuffer = PGL.allocateIntBuffer(polyAmbient); + polySpecularBuffer = PGL.allocateIntBuffer(polySpecular); + polyEmissiveBuffer = PGL.allocateIntBuffer(polyEmissive); + polyShininessBuffer = PGL.allocateFloatBuffer(polyShininess); + polyIndicesBuffer = PGL.allocateShortBuffer(polyIndices); + + lineVerticesBuffer = PGL.allocateFloatBuffer(lineVertices); + lineColorsBuffer = PGL.allocateIntBuffer(lineColors); + lineAttribsBuffer = PGL.allocateFloatBuffer(lineAttribs); + lineIndicesBuffer = PGL.allocateShortBuffer(lineIndices); + + pointVerticesBuffer = PGL.allocateFloatBuffer(pointVertices); + pointColorsBuffer = PGL.allocateIntBuffer(pointColors); + pointAttribsBuffer = PGL.allocateFloatBuffer(pointAttribs); + pointIndicesBuffer = PGL.allocateShortBuffer(pointIndices); + clear(); } @@ -9082,47 +9037,6 @@ public class PGraphicsOpenGL extends PGraphics { pointIndexCache.clear(); } - void dipose() { - polyVerticesBuffer = null; - polyColorsBuffer = null; - polyNormalsBuffer = null; - polyTexcoordsBuffer = null; - polyAmbientBuffer = null; - polySpecularBuffer = null; - polyEmissiveBuffer = null; - polyShininessBuffer = null; - polyIndicesBuffer = null; - - lineVerticesBuffer = null; - lineColorsBuffer = null; - lineAttribsBuffer = null; - lineIndicesBuffer = null; - - pointVerticesBuffer = null; - pointColorsBuffer = null; - pointAttribsBuffer = null; - pointIndicesBuffer = null; - - polyVertices = null; - polyColors = null; - polyNormals = null; - polyTexcoords = null; - polyAmbient = null; - polySpecular = null; - polyEmissive = null; - polyShininess = null; - polyIndices = null; - - lineVertices = null; - lineColors = null; - lineAttribs = null; - lineIndices = null; - - pointVertices = null; - pointColors = null; - pointAttribs = null; - pointIndices = null; - } void polyVertexCheck() { if (polyVertexCount == polyVertices.length / 4) { @@ -9517,139 +9431,122 @@ public class PGraphicsOpenGL extends PGraphics { // Expand arrays void expandPolyVertices(int n) { - polyVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * n); - float temp[] = new float[4 * n]; PApplet.arrayCopy(polyVertices, 0, temp, 0, 4 * polyVertexCount); polyVertices = temp; + polyVerticesBuffer = PGL.allocateFloatBuffer(polyVertices); } void expandPolyColors(int n) { - polyColorsBuffer = PGL.allocateDirectIntBuffer(n); - int temp[] = new int[n]; PApplet.arrayCopy(polyColors, 0, temp, 0, polyVertexCount); polyColors = temp; + polyColorsBuffer = PGL.allocateIntBuffer(polyColors); } void expandPolyNormals(int n) { - polyNormalsBuffer = PGL.allocateDirectFloatBuffer(3 * n); - float temp[] = new float[3 * n]; PApplet.arrayCopy(polyNormals, 0, temp, 0, 3 * polyVertexCount); polyNormals = temp; + polyNormalsBuffer = PGL.allocateFloatBuffer(polyNormals); } void expandPolyTexcoords(int n) { - polyTexcoordsBuffer = PGL.allocateDirectFloatBuffer(2 * n); - float temp[] = new float[2 * n]; PApplet.arrayCopy(polyTexcoords, 0, temp, 0, 2 * polyVertexCount); polyTexcoords = temp; + polyTexcoordsBuffer = PGL.allocateFloatBuffer(polyTexcoords); } void expandPolyAmbient(int n) { - polyAmbientBuffer = PGL.allocateDirectIntBuffer(n); - int temp[] = new int[n]; PApplet.arrayCopy(polyAmbient, 0, temp, 0, polyVertexCount); polyAmbient = temp; + polyAmbientBuffer = PGL.allocateIntBuffer(polyAmbient); } void expandPolySpecular(int n) { - polySpecularBuffer = PGL.allocateDirectIntBuffer(n); - int temp[] = new int[n]; PApplet.arrayCopy(polySpecular, 0, temp, 0, polyVertexCount); polySpecular = temp; + polySpecularBuffer = PGL.allocateIntBuffer(polySpecular); } void expandPolyEmissive(int n) { - polyEmissiveBuffer = PGL.allocateDirectIntBuffer(n); - int temp[] = new int[n]; PApplet.arrayCopy(polyEmissive, 0, temp, 0, polyVertexCount); polyEmissive = temp; + polyEmissiveBuffer = PGL.allocateIntBuffer(polyEmissive); } void expandPolyShininess(int n) { - polyShininessBuffer = PGL.allocateDirectFloatBuffer(n); - float temp[] = new float[n]; PApplet.arrayCopy(polyShininess, 0, temp, 0, polyVertexCount); polyShininess = temp; + polyShininessBuffer = PGL.allocateFloatBuffer(polyShininess); } void expandPolyIndices(int n) { - polyIndicesBuffer = PGL.allocateDirectShortBuffer(n); - short temp[] = new short[n]; PApplet.arrayCopy(polyIndices, 0, temp, 0, polyIndexCount); polyIndices = temp; + polyIndicesBuffer = PGL.allocateShortBuffer(polyIndices); } void expandLineVertices(int n) { - lineVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * n); - float temp[] = new float[4 * n]; PApplet.arrayCopy(lineVertices, 0, temp, 0, 4 * lineVertexCount); lineVertices = temp; + lineVerticesBuffer = PGL.allocateFloatBuffer(lineVertices); } void expandLineColors(int n) { - lineColorsBuffer = PGL.allocateDirectIntBuffer(n); - int temp[] = new int[n]; PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount); lineColors = temp; + lineColorsBuffer = PGL.allocateIntBuffer(lineColors); } void expandLineAttribs(int n) { - lineAttribsBuffer = PGL.allocateDirectFloatBuffer(4 * n); - float temp[] = new float[4 * n]; PApplet.arrayCopy(lineAttribs, 0, temp, 0, 4 * lineVertexCount); lineAttribs = temp; + lineAttribsBuffer = PGL.allocateFloatBuffer(lineAttribs); } void expandLineIndices(int n) { - lineIndicesBuffer = PGL.allocateDirectShortBuffer(n); - short temp[] = new short[n]; PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount); lineIndices = temp; + lineIndicesBuffer = PGL.allocateShortBuffer(lineIndices); } void expandPointVertices(int n) { - pointVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * n); - float temp[] = new float[4 * n]; PApplet.arrayCopy(pointVertices, 0, temp, 0, 4 * pointVertexCount); pointVertices = temp; + pointVerticesBuffer = PGL.allocateFloatBuffer(pointVertices); } void expandPointColors(int n) { - pointColorsBuffer = PGL.allocateDirectIntBuffer(n); - int temp[] = new int[n]; PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount); pointColors = temp; + pointColorsBuffer = PGL.allocateIntBuffer(pointColors); } void expandPointAttribs(int n) { - pointAttribsBuffer = PGL.allocateDirectFloatBuffer(2 * n); - float temp[] = new float[2 * n]; PApplet.arrayCopy(pointAttribs, 0, temp, 0, 2 * pointVertexCount); pointAttribs = temp; + pointAttribsBuffer = PGL.allocateFloatBuffer(pointAttribs); } void expandPointIndices(int n) { - pointIndicesBuffer = PGL.allocateDirectShortBuffer(n); - short temp[] = new short[n]; PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount); pointIndices = temp; + pointIndicesBuffer = PGL.allocateShortBuffer(pointIndices); } // ----------------------------------------------------------------- @@ -9694,139 +9591,122 @@ public class PGraphicsOpenGL extends PGraphics { } void trimPolyVertices() { - polyVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * polyVertexCount); - float temp[] = new float[4 * polyVertexCount]; PApplet.arrayCopy(polyVertices, 0, temp, 0, 4 * polyVertexCount); polyVertices = temp; + polyVerticesBuffer = PGL.allocateFloatBuffer(polyVertices); } void trimPolyColors() { - polyColorsBuffer = PGL.allocateDirectIntBuffer(polyVertexCount); - int temp[] = new int[polyVertexCount]; PApplet.arrayCopy(polyColors, 0, temp, 0, polyVertexCount); polyColors = temp; + polyColorsBuffer = PGL.allocateIntBuffer(polyColors); } void trimPolyNormals() { - polyNormalsBuffer = PGL.allocateDirectFloatBuffer(3 * polyVertexCount); - float temp[] = new float[3 * polyVertexCount]; PApplet.arrayCopy(polyNormals, 0, temp, 0, 3 * polyVertexCount); polyNormals = temp; + polyNormalsBuffer = PGL.allocateFloatBuffer(polyNormals); } void trimPolyTexcoords() { - polyTexcoordsBuffer = PGL.allocateDirectFloatBuffer(2 * polyVertexCount); - float temp[] = new float[2 * polyVertexCount]; PApplet.arrayCopy(polyTexcoords, 0, temp, 0, 2 * polyVertexCount); polyTexcoords = temp; + polyTexcoordsBuffer = PGL.allocateFloatBuffer(polyTexcoords); } void trimPolyAmbient() { - polyAmbientBuffer = PGL.allocateDirectIntBuffer(polyVertexCount); - int temp[] = new int[polyVertexCount]; PApplet.arrayCopy(polyAmbient, 0, temp, 0, polyVertexCount); polyAmbient = temp; + polyAmbientBuffer = PGL.allocateIntBuffer(polyAmbient); } void trimPolySpecular() { - polySpecularBuffer = PGL.allocateDirectIntBuffer(polyVertexCount); - int temp[] = new int[polyVertexCount]; PApplet.arrayCopy(polySpecular, 0, temp, 0, polyVertexCount); polySpecular = temp; + polySpecularBuffer = PGL.allocateIntBuffer(polySpecular); } void trimPolyEmissive() { - polyEmissiveBuffer = PGL.allocateDirectIntBuffer(polyVertexCount); - int temp[] = new int[polyVertexCount]; PApplet.arrayCopy(polyEmissive, 0, temp, 0, polyVertexCount); polyEmissive = temp; + polyEmissiveBuffer = PGL.allocateIntBuffer(polyEmissive); } void trimPolyShininess() { - polyShininessBuffer = PGL.allocateDirectFloatBuffer(polyVertexCount); - float temp[] = new float[polyVertexCount]; PApplet.arrayCopy(polyShininess, 0, temp, 0, polyVertexCount); polyShininess = temp; + polyShininessBuffer = PGL.allocateFloatBuffer(polyShininess); } void trimPolyIndices() { - polyIndicesBuffer = PGL.allocateDirectShortBuffer(polyIndexCount); - short temp[] = new short[polyIndexCount]; PApplet.arrayCopy(polyIndices, 0, temp, 0, polyIndexCount); polyIndices = temp; + polyIndicesBuffer = PGL.allocateShortBuffer(polyIndices); } void trimLineVertices() { - lineVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * lineVertexCount); - float temp[] = new float[4 * lineVertexCount]; PApplet.arrayCopy(lineVertices, 0, temp, 0, 4 * lineVertexCount); lineVertices = temp; + lineVerticesBuffer = PGL.allocateFloatBuffer(lineVertices); } void trimLineColors() { - lineColorsBuffer = PGL.allocateDirectIntBuffer(lineVertexCount); - int temp[] = new int[lineVertexCount]; PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount); lineColors = temp; + lineColorsBuffer = PGL.allocateIntBuffer(lineColors); } void trimLineAttribs() { - lineAttribsBuffer = PGL.allocateDirectFloatBuffer(4 * lineVertexCount); - float temp[] = new float[4 * lineVertexCount]; PApplet.arrayCopy(lineAttribs, 0, temp, 0, 4 * lineVertexCount); lineAttribs = temp; + lineAttribsBuffer = PGL.allocateFloatBuffer(lineAttribs); } void trimLineIndices() { - lineIndicesBuffer = PGL.allocateDirectShortBuffer(lineIndexCount); - short temp[] = new short[lineIndexCount]; PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount); lineIndices = temp; + lineIndicesBuffer = PGL.allocateShortBuffer(lineIndices); } void trimPointVertices() { - pointVerticesBuffer = PGL.allocateDirectFloatBuffer(4 * pointVertexCount); - float temp[] = new float[4 * pointVertexCount]; PApplet.arrayCopy(pointVertices, 0, temp, 0, 4 * pointVertexCount); pointVertices = temp; + pointVerticesBuffer = PGL.allocateFloatBuffer(pointVertices); } void trimPointColors() { - pointColorsBuffer = PGL.allocateDirectIntBuffer(pointVertexCount); - int temp[] = new int[pointVertexCount]; PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount); pointColors = temp; + pointColorsBuffer = PGL.allocateIntBuffer(pointColors); } void trimPointAttribs() { - pointAttribsBuffer = PGL.allocateDirectFloatBuffer(2 * pointVertexCount); - float temp[] = new float[2 * pointVertexCount]; PApplet.arrayCopy(pointAttribs, 0, temp, 0, 2 * pointVertexCount); pointAttribs = temp; + pointAttribsBuffer = PGL.allocateFloatBuffer(pointAttribs); } void trimPointIndices() { - pointIndicesBuffer = PGL.allocateDirectShortBuffer(pointIndexCount); - short temp[] = new short[pointIndexCount]; PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount); pointIndices = temp; + pointIndicesBuffer = PGL.allocateShortBuffer(pointIndices); } // ----------------------------------------------------------------- diff --git a/core/src/processing/opengl/PShader.java b/core/src/processing/opengl/PShader.java index acba492c4..d9f167746 100644 --- a/core/src/processing/opengl/PShader.java +++ b/core/src/processing/opengl/PShader.java @@ -102,8 +102,8 @@ public class PShader { firstTexUnit = 0; - intBuffer = PGL.allocateDirectIntBuffer(1); - floatBuffer = PGL.allocateDirectFloatBuffer(1); + intBuffer = PGL.allocateIntBuffer(1); + floatBuffer = PGL.allocateFloatBuffer(1); bound = false; } @@ -141,8 +141,8 @@ public class PShader { glVertex = 0; glFragment = 0; - intBuffer = PGL.allocateDirectIntBuffer(1); - floatBuffer = PGL.allocateDirectFloatBuffer(1); + intBuffer = PGL.allocateIntBuffer(1); + floatBuffer = PGL.allocateFloatBuffer(1); } /** @@ -163,8 +163,8 @@ public class PShader { glVertex = 0; glFragment = 0; - intBuffer = PGL.allocateDirectIntBuffer(1); - floatBuffer = PGL.allocateDirectFloatBuffer(1); + intBuffer = PGL.allocateIntBuffer(1); + floatBuffer = PGL.allocateFloatBuffer(1); } @@ -474,7 +474,7 @@ public class PShader { protected void setUniformVector(int loc, int[] vec, int ncoords, int length) { if (-1 < loc) { - copyToIntBuffer(vec); + updateIntBuffer(vec); if (ncoords == 1) { pgl.uniform1iv(loc, length, intBuffer); } else if (ncoords == 2) { @@ -491,7 +491,7 @@ public class PShader { protected void setUniformVector(int loc, float[] vec, int ncoords, int length) { if (-1 < loc) { - copyToFloatBuffer(vec); + updateFloatBuffer(vec); if (ncoords == 1) { pgl.uniform1fv(loc, length, floatBuffer); } else if (ncoords == 2) { @@ -507,7 +507,7 @@ public class PShader { protected void setUniformMatrix(int loc, float[] mat) { if (-1 < loc) { - copyToFloatBuffer(mat); + updateFloatBuffer(mat); if (mat.length == 4) { pgl.uniformMatrix2fv(loc, 1, false, floatBuffer); } else if (mat.length == 9) { @@ -604,47 +604,47 @@ public class PShader { pgl.uniform4f(loc, v[0], v[1], v[2], v[3]); } else if (val.type == UniformValue.INT1VEC) { int[] v = ((int[])val.value); - copyToIntBuffer(v); + updateIntBuffer(v); pgl.uniform1iv(loc, v.length, intBuffer); } else if (val.type == UniformValue.INT2VEC) { int[] v = ((int[])val.value); - copyToIntBuffer(v); + updateIntBuffer(v); pgl.uniform2iv(loc, v.length / 2, intBuffer); } else if (val.type == UniformValue.INT3VEC) { int[] v = ((int[])val.value); - copyToIntBuffer(v); + updateIntBuffer(v); pgl.uniform3iv(loc, v.length / 3, intBuffer); } else if (val.type == UniformValue.INT4VEC) { int[] v = ((int[])val.value); - copyToIntBuffer(v); + updateIntBuffer(v); pgl.uniform4iv(loc, v.length / 4, intBuffer); } else if (val.type == UniformValue.FLOAT1VEC) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniform1fv(loc, v.length, floatBuffer); } else if (val.type == UniformValue.FLOAT2VEC) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniform2fv(loc, v.length / 2, floatBuffer); } else if (val.type == UniformValue.FLOAT3VEC) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniform3fv(loc, v.length / 3, floatBuffer); } else if (val.type == UniformValue.FLOAT4VEC) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniform4fv(loc, v.length / 4, floatBuffer); } else if (val.type == UniformValue.MAT2) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniformMatrix2fv(loc, 1, false, floatBuffer); } else if (val.type == UniformValue.MAT3) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniformMatrix3fv(loc, 1, false, floatBuffer); } else if (val.type == UniformValue.MAT4) { float[] v = ((float[])val.value); - copyToFloatBuffer(v); + updateFloatBuffer(v); pgl.uniformMatrix4fv(loc, 1, false, floatBuffer); } else if (val.type == UniformValue.SAMPLER2D) { PImage img = (PImage)val.value; @@ -662,23 +662,13 @@ public class PShader { } - protected void copyToIntBuffer(int[] vec) { - if (intBuffer.capacity() < vec.length) { - intBuffer = PGL.allocateDirectIntBuffer(vec.length); - } - intBuffer.rewind(); - intBuffer.put(vec, 0, vec.length); - intBuffer.rewind(); + protected void updateIntBuffer(int[] vec) { + intBuffer = PGL.updateIntBuffer(intBuffer, vec, false); } - protected void copyToFloatBuffer(float[] vec) { - if (floatBuffer.capacity() < vec.length) { - floatBuffer = PGL.allocateDirectFloatBuffer(vec.length); - } - floatBuffer.rewind(); - floatBuffer.put(vec, 0, vec.length); - floatBuffer.rewind(); + protected void updateFloatBuffer(float[] vec) { + floatBuffer = PGL.updateFloatBuffer(floatBuffer, vec, false); } diff --git a/core/src/processing/opengl/Texture.java b/core/src/processing/opengl/Texture.java index 0b38e6192..df96ddddc 100644 --- a/core/src/processing/opengl/Texture.java +++ b/core/src/processing/opengl/Texture.java @@ -93,6 +93,7 @@ public class Texture implements PConstants { protected boolean invertedX; protected boolean invertedY; + protected int[] rgbaPixels = null; protected IntBuffer pixelBuffer = null; protected FrameBuffer tempFbo = null; @@ -211,6 +212,37 @@ public class Texture implements PConstants { } + /** + * Initializes the texture using GL parameters + */ + public void init(int width, int height, + int glName, int glTarget, int glFormat, + int glWidth, int glHeight, + int glMinFilter, int glMagFilter, + int glWrapS, int glWrapT) { + this.width = width; + this.height = height; + + this.glName = glName; + this.glTarget = glTarget; + this.glFormat = glFormat; + this.glWidth = glWidth; + this.glHeight = glHeight; + this.glMinFilter = glMinFilter; + this.glMagFilter = glMagFilter; + this.glWrapS = glWrapS; + this.glWrapT = glWrapT; + + maxTexcoordU = (float)width / glWidth; + maxTexcoordV = (float)height / glHeight; + + usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST || + glMinFilter == PGL.LINEAR_MIPMAP_LINEAR; + + usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT; + } + + public void resize(int wide, int high) { // Marking the texture object as finalized so it is deleted // when creating the new texture. @@ -239,31 +271,6 @@ public class Texture implements PConstants { return 0 < glName; } - /** - * Initializes the texture using GL parameters - */ - public void init(int glName, int glTarget, int glFormat, int glWidth, int glHeight, - int glMinFilter, int glMagFilter, int glWrapS, int glWrapT) { - this.glName = glName; - this.glTarget = glTarget; - this.glFormat = glFormat; - this.glWidth = glWidth; - this.glHeight = glHeight; - this.glMinFilter = glMinFilter; - this.glMagFilter = glMagFilter; - this.glWrapS = glWrapS; - this.glWrapT = glWrapT; - - width = glWidth; - height = glHeight; - maxTexcoordU = 1; - maxTexcoordV = 1; - - usingMipmaps = glMinFilter == PGL.LINEAR_MIPMAP_NEAREST || - glMinFilter == PGL.LINEAR_MIPMAP_LINEAR; - - usingRepeat = glWrapS == PGL.REPEAT || glWrapT == PGL.REPEAT; - } //////////////////////////////////////////////////////////// @@ -347,13 +354,12 @@ public class Texture implements PConstants { if (usingMipmaps) { if (PGraphicsOpenGL.autoMipmapGenSupported) { // Automatic mipmap generation. - int[] rgbaPixels = new int[w * h]; + loadPixels(w * h); convertToRGBA(pixels, rgbaPixels, format, w, h); updatePixelBuffer(rgbaPixels); pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, pixelBuffer); pgl.generateMipmap(glTarget); - rgbaPixels = null; } else { // TODO: finish manual mipmap generation, replacing Bitmap with AWT's BufferedImage, // making it work in npot textures (embed npot tex into larger pot tex?), subregions, @@ -409,20 +415,18 @@ public class Texture implements PConstants { } */ - int[] rgbaPixels = new int[w * h]; + loadPixels(w * h); convertToRGBA(pixels, rgbaPixels, format, w, h); updatePixelBuffer(rgbaPixels); pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, pixelBuffer); - rgbaPixels = null; } } else { - int[] rgbaPixels = new int[w * h]; + loadPixels(w * h); convertToRGBA(pixels, rgbaPixels, format, w, h); updatePixelBuffer(rgbaPixels); pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, pixelBuffer); - rgbaPixels = null; } pgl.bindTexture(glTarget, 0); @@ -844,13 +848,15 @@ public class Texture implements PConstants { } - protected void updatePixelBuffer(int[] pixels) { - if (pixelBuffer == null || pixelBuffer.capacity() < pixels.length) { - pixelBuffer = PGL.allocateDirectIntBuffer(pixels.length); + protected void loadPixels(int len) { + if (rgbaPixels == null || rgbaPixels.length < len) { + rgbaPixels = new int[len]; } - pixelBuffer.position(0); - pixelBuffer.put(pixels); - pixelBuffer.rewind(); + } + + + protected void updatePixelBuffer(int[] pixels) { + pixelBuffer = PGL.updateIntBuffer(pixelBuffer, pixels, true); } ////////////////////////////////////////////////////////////