diff --git a/java/libraries/opengl/src/processing/opengl/PGL.java b/java/libraries/opengl/src/processing/opengl/PGL.java index 78495eebe..e9ae6b364 100644 --- a/java/libraries/opengl/src/processing/opengl/PGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGL.java @@ -343,6 +343,7 @@ public class PGL { protected int texShaderProgram; protected int texVertShader; protected int texFragShader; + protected GLContext texShaderContext; protected int texVertLoc; protected int texTCoordLoc; @@ -379,6 +380,7 @@ public class PGL { protected int rectShaderProgram; protected int rectVertShader; protected int rectFragShader; + protected GLContext rectShaderContext; protected int rectVertLoc; protected int rectColorLoc; @@ -1288,7 +1290,7 @@ public class PGL { public void drawTexture(int target, int id, int width, int height, int texX0, int texY0, int texX1, int texY1, int scrX0, int scrY0, int scrX1, int scrY1) { - if (!loadedTexShader) { + if (!loadedTexShader || texShaderContext.hashCode() != context.hashCode()) { texVertShader = createShader(GL_VERTEX_SHADER, texVertShaderSource); texFragShader = createShader(GL_FRAGMENT_SHADER, texFragShaderSource); if (0 < texVertShader && 0 < texFragShader) { @@ -1300,8 +1302,9 @@ public class PGL { } texData = ByteBuffer.allocateDirect(texCoords.length * SIZEOF_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer(); loadedTexShader = true; + texShaderContext = context; } - + if (0 < texShaderProgram) { // When drawing the texture we don't write to the // depth mask, so the texture remains in the background @@ -1311,9 +1314,9 @@ public class PGL { glGetBooleanv(GL_DEPTH_WRITEMASK, val, 0); boolean writeMask = val[0]; glDepthMask(false); - + glUseProgram(texShaderProgram); - + glEnableVertexAttribArray(texVertLoc); glEnableVertexAttribArray(texTCoordLoc); @@ -1346,18 +1349,18 @@ public class PGL { texData.rewind(); texData.put(texCoords); - + enableTexturing(target); glActiveTexture(GL_TEXTURE0); glBindTexture(target, id); - + texData.position(0); glVertexAttribPointer(texVertLoc, 2, GL_FLOAT, false, 4 * SIZEOF_FLOAT, texData); texData.position(2); glVertexAttribPointer(texTCoordLoc, 2, GL_FLOAT, false, 4 * SIZEOF_FLOAT, texData); - + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - + glBindTexture(target, 0); disableTexturing(target); @@ -1373,7 +1376,7 @@ public class PGL { public void drawRectangle(float r, float g, float b, float a, int scrX0, int scrY0, int scrX1, int scrY1) { - if (!loadedRectShader) { + if (!loadedRectShader || rectShaderContext.hashCode() != context.hashCode()) { rectVertShader = createShader(GL_VERTEX_SHADER, rectVertShaderSource); rectFragShader = createShader(GL_FRAGMENT_SHADER, rectFragShaderSource); if (0 < rectVertShader && 0 < rectFragShader) { @@ -1385,6 +1388,7 @@ public class PGL { } rectData = ByteBuffer.allocateDirect(rectCoords.length * SIZEOF_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer(); loadedRectShader = true; + rectShaderContext = context; } if (0 < rectShaderProgram) { diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index e1f92837e..ce7da93a4 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -41,8 +41,6 @@ import java.util.Set; import java.util.Stack; // TODO: -// 0) Make sure to delete finalized resources. -// 1) fix get/set pixels, doesn't seem to work. // 2) non-interactive mode problem? /** @@ -88,21 +86,21 @@ public class PGraphicsOpenGL extends PGraphics { public int glFillEmissiveBufferID; public int glFillShininessBufferID; public int glFillIndexBufferID; - protected boolean fillVBOsCreated = false; + protected boolean fillBuffersCreated = false; protected PGL.Context fillBuffersContext; public int glLineVertexBufferID; public int glLineColorBufferID; public int glLineDirWidthBufferID; public int glLineIndexBufferID; - protected boolean lineVBOsCreated = false; + protected boolean lineBuffersCreated = false; protected PGL.Context lineBuffersContext; public int glPointVertexBufferID; public int glPointColorBufferID; public int glPointSizeBufferID; public int glPointIndexBufferID; - protected boolean pointVBOsCreated = false; + protected boolean pointBuffersCreated = false; protected PGL.Context pointBuffersContext; // ........................................................ @@ -350,6 +348,9 @@ public class PGraphicsOpenGL extends PGraphics { /** True if we are inside a beginDraw()/endDraw() block. */ protected boolean drawing = false; + /** Used to indicate an OpenGL surface recreation */ + protected boolean restoreSurface = false; + /** Type of pixels operation. */ static protected final int OP_NONE = 0; static protected final int OP_READ = 1; @@ -1026,7 +1027,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void createFillBuffers() { - if (!fillVBOsCreated || fillBuffersContextIsOutdated()) { + if (!fillBuffersCreated || fillBuffersContextIsOutdated()) { fillBuffersContext = pgl.getContext(); int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; @@ -1073,7 +1074,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - fillVBOsCreated = true; + fillBuffersCreated = true; } } @@ -1132,7 +1133,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteFillBuffers() { - if (fillVBOsCreated) { + if (fillBuffersCreated) { deleteVertexBufferObject(glFillVertexBufferID); glFillVertexBufferID = 0; @@ -1160,13 +1161,13 @@ public class PGraphicsOpenGL extends PGraphics { deleteVertexBufferObject(glFillIndexBufferID); glFillIndexBufferID = 0; - fillVBOsCreated = false; + fillBuffersCreated = false; } } protected void createLineBuffers() { - if (!lineVBOsCreated || lineBufferContextIsOutdated()) { + if (!lineBuffersCreated || lineBufferContextIsOutdated()) { lineBuffersContext = pgl.getContext(); int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; @@ -1194,7 +1195,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - lineVBOsCreated = true; + lineBuffersCreated = true; } } @@ -1233,7 +1234,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteLineBuffers() { - if (lineVBOsCreated) { + if (lineBuffersCreated) { deleteVertexBufferObject(glLineVertexBufferID); glLineVertexBufferID = 0; @@ -1246,13 +1247,13 @@ public class PGraphicsOpenGL extends PGraphics { deleteVertexBufferObject(glLineIndexBufferID); glLineIndexBufferID = 0; - lineVBOsCreated = false; + lineBuffersCreated = false; } } protected void createPointBuffers() { - if (!pointVBOsCreated || pointBuffersContextIsOutdated()) { + if (!pointBuffersCreated || pointBuffersContextIsOutdated()) { pointBuffersContext = pgl.getContext(); int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; @@ -1279,7 +1280,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - pointVBOsCreated = true; + pointBuffersCreated = true; } } @@ -1318,7 +1319,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void deletePointBuffers() { - if (pointVBOsCreated) { + if (pointBuffersCreated) { deleteVertexBufferObject(glPointVertexBufferID); glPointVertexBufferID = 0; @@ -1331,7 +1332,7 @@ public class PGraphicsOpenGL extends PGraphics { deleteVertexBufferObject(glPointIndexBufferID); glPointIndexBufferID = 0; - pointVBOsCreated = false; + pointBuffersCreated = false; } } @@ -1509,6 +1510,11 @@ public class PGraphicsOpenGL extends PGraphics { if (primarySurface) { pgl.beginOnscreenDraw(clearColorBuffer); + + if (restoreSurface) { + restoreSurfaceFromPixels(); + restoreSurface = false; + } } else { pgl.beginOffscreenDraw(pg.clearColorBuffer); @@ -1534,7 +1540,7 @@ public class PGraphicsOpenGL extends PGraphics { report("bot beginDraw()"); } - + public void endDraw() { report("top endDraw()"); @@ -1555,6 +1561,15 @@ public class PGraphicsOpenGL extends PGraphics { if (primarySurface) { pgl.endOnscreenDraw(clearColorBuffer0); + + if (!pgl.initialized) { + // Smooth was called 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. + saveSurfaceToPixels(); + restoreSurface = true; + } + pgl.glFlush(); } else { if (offscreenMultisample) { @@ -1627,8 +1642,10 @@ public class PGraphicsOpenGL extends PGraphics { protected void beginPixelsOp(int op) { if (primarySurface) { + // We read or write from the back buffer, where all the + // drawing in the current frame is taking place. if (op == OP_READ) { - pgl.glReadBuffer(PGL.GL_FRONT); + pgl.glReadBuffer(PGL.GL_BACK); } else { pgl.glDrawBuffer(PGL.GL_BACK); } @@ -2418,6 +2435,8 @@ public class PGraphicsOpenGL extends PGraphics { endPixelsOp(); } + report("here"); + modified = false; } @@ -2495,9 +2514,9 @@ public class PGraphicsOpenGL extends PGraphics { // Utility function to render current tessellated geometry, under the assumption that // the texture is already bound. protected void renderTexFill(PTexture tex) { - if (!fillVBOsCreated) { + if (!fillBuffersCreated) { createFillBuffers(); - fillVBOsCreated = true; + fillBuffersCreated = true; } updateFillBuffers(lights, true); @@ -2846,8 +2865,6 @@ public class PGraphicsOpenGL extends PGraphics { // requestDraw() is called. pgl.initialized = false; } - - PApplet.println("setting smooth at " + level); } @@ -4475,18 +4492,10 @@ public class PGraphicsOpenGL extends PGraphics { flush(); } - if ((pixels == null) || (pixels.length != width * height)) { - pixels = new int[width * height]; - pixelBuffer = IntBuffer.wrap(pixels); - } + allocatePixels(); if (!setgetPixels) { - beginPixelsOp(OP_READ); - pixelBuffer.rewind(); - pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer); - endPixelsOp(); - - PGL.nativeToJavaARGB(pixels, width, height); + readPixels(); if (primarySurface) { loadTextureImpl(POINT); @@ -4589,8 +4598,45 @@ public class PGraphicsOpenGL extends PGraphics { protected void textureToPixels() { texture.get(pixels); } + + + protected void saveSurfaceToPixels() { + if (primarySurface) { + allocatePixels(); + readPixels(); + } + } + + protected void restoreSurfaceFromPixels() { + if (primarySurface) { + loadTextureImpl(POINT); + pixelsToTexture(); + + beginPixelsOp(OP_WRITE); + drawTexture(); + endPixelsOp(); + } + } - + + protected void allocatePixels() { + if ((pixels == null) || (pixels.length != width * height)) { + pixels = new int[width * height]; + pixelBuffer = IntBuffer.wrap(pixels); + } + } + + + protected void readPixels() { + beginPixelsOp(OP_READ); + pixelBuffer.rewind(); + pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer); + endPixelsOp(); + + PGL.nativeToJavaARGB(pixels, width, height); + } + + ////////////////////////////////////////////////////////////// // IMAGE CONVERSION @@ -5153,7 +5199,7 @@ public class PGraphicsOpenGL extends PGraphics { if (defFillShaderFull == null || defFillShaderFull.contextIsOutdated()) { defFillShaderFull = new FillShaderFull(parent, defFillShaderVertFullURL, defFillShaderFragTexURL); } - if (fillShaderFull == null) { + if (fillShaderFull == null || fillShaderFull.contextIsOutdated()) { fillShaderFull = defFillShaderFull; } shader = fillShaderFull; @@ -5161,7 +5207,7 @@ public class PGraphicsOpenGL extends PGraphics { if (defFillShaderLit == null || defFillShaderLit.contextIsOutdated()) { defFillShaderLit = new FillShaderLit(parent, defFillShaderVertLitURL, defFillShaderFragNoTexURL); } - if (fillShaderLit == null) { + if (fillShaderLit == null || fillShaderLit.contextIsOutdated()) { fillShaderLit = defFillShaderLit; } shader = fillShaderLit; @@ -5171,7 +5217,7 @@ public class PGraphicsOpenGL extends PGraphics { if (defFillShaderTex == null || defFillShaderTex.contextIsOutdated()) { defFillShaderTex = new FillShaderTex(parent, defFillShaderVertTexURL, defFillShaderFragTexURL); } - if (fillShaderTex == null) { + if (fillShaderTex == null || fillShaderTex.contextIsOutdated()) { fillShaderTex = defFillShaderTex; } shader = fillShaderTex; @@ -5179,7 +5225,7 @@ public class PGraphicsOpenGL extends PGraphics { if (defFillShaderSimple == null || defFillShaderSimple.contextIsOutdated()) { defFillShaderSimple = new FillShaderSimple(parent, defFillShaderVertSimpleURL, defFillShaderFragNoTexURL); } - if (fillShaderSimple == null) { + if (fillShaderSimple == null || fillShaderSimple.contextIsOutdated()) { fillShaderSimple = defFillShaderSimple; } shader = fillShaderSimple; @@ -5196,7 +5242,7 @@ public class PGraphicsOpenGL extends PGraphics { if (defLineShader == null || defLineShader.contextIsOutdated()) { defLineShader = new LineShader(parent, defLineShaderVertURL, defLineShaderFragURL); } - if (lineShader == null) { + if (lineShader == null || lineShader.contextIsOutdated()) { lineShader = defLineShader; } lineShader.setRenderer(this); @@ -5210,7 +5256,7 @@ public class PGraphicsOpenGL extends PGraphics { if (defPointShader == null || defPointShader.contextIsOutdated()) { defPointShader = new PointShader(parent, defPointShaderVertURL, defPointShaderFragURL); } - if (pointShader == null) { + if (pointShader == null || pointShader.contextIsOutdated()) { pointShader = defPointShader; } pointShader.setRenderer(this);