diff --git a/core/src/processing/opengl/FontTexture.java b/core/src/processing/opengl/FontTexture.java index 350b93677..77e84d864 100644 --- a/core/src/processing/opengl/FontTexture.java +++ b/core/src/processing/opengl/FontTexture.java @@ -64,7 +64,6 @@ class FontTexture implements PConstants { protected TextureInfo[] glyphTexinfos; protected HashMap texinfoMap; - public FontTexture(PGraphicsOpenGL pg, PFont font, boolean is3D) { pgl = pg.pgl; this.is3D = is3D; @@ -156,10 +155,13 @@ class FontTexture implements PConstants { // REPLACE to preserve color of transparent pixels. Texture tex0 = textures[currentTex]; - tex.pg.pushStyle(); - tex.pg.blendMode(REPLACE); - tex.put(tex0); - tex.pg.popStyle(); + PGraphicsOpenGL g = tex.pg.get(); + if (g != null) { + g.pushStyle(); + g.blendMode(REPLACE); + tex.put(tex0); + g.popStyle(); + } textures[currentTex] = tex; diff --git a/core/src/processing/opengl/FrameBuffer.java b/core/src/processing/opengl/FrameBuffer.java index e591290a8..8f8fda489 100644 --- a/core/src/processing/opengl/FrameBuffer.java +++ b/core/src/processing/opengl/FrameBuffer.java @@ -28,6 +28,7 @@ import processing.core.PApplet; import processing.core.PConstants; import processing.opengl.PGraphicsOpenGL.GLResourceFrameBuffer; +import java.lang.ref.WeakReference; import java.nio.IntBuffer; /** @@ -42,7 +43,7 @@ import java.nio.IntBuffer; */ public class FrameBuffer implements PConstants { - protected PGraphicsOpenGL pg; + protected WeakReference pg; protected PGL pgl; protected int context; // The context that created this framebuffer. @@ -72,7 +73,7 @@ public class FrameBuffer implements PConstants { FrameBuffer(PGraphicsOpenGL pg) { - this.pg = pg; + this.pg = new WeakReference(pg); pgl = pg.pgl; context = pgl.createEmptyContext(); } @@ -152,15 +153,17 @@ public class FrameBuffer implements PConstants { public void clear() { - pg.pushFramebuffer(); - pg.setFramebuffer(this); + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + g.pushFramebuffer(); + g.setFramebuffer(this); pgl.clearDepth(1); pgl.clearStencil(0); pgl.clearColor(0, 0, 0, 0); pgl.clear(PGL.DEPTH_BUFFER_BIT | PGL.STENCIL_BUFFER_BIT | PGL.COLOR_BUFFER_BIT); - pg.popFramebuffer(); + g.popFramebuffer(); } public void copyColor(FrameBuffer dest) { @@ -176,12 +179,14 @@ public class FrameBuffer implements PConstants { } public void copy(FrameBuffer dest, int mask) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; pgl.bindFramebufferImpl(PGL.READ_FRAMEBUFFER, this.glFbo); pgl.bindFramebufferImpl(PGL.DRAW_FRAMEBUFFER, dest.glFbo); pgl.blitFramebuffer(0, 0, this.width, this.height, 0, 0, dest.width, dest.height, mask, PGL.NEAREST); - pgl.bindFramebufferImpl(PGL.READ_FRAMEBUFFER, pg.getCurrentFB().glFbo); - pgl.bindFramebufferImpl(PGL.DRAW_FRAMEBUFFER, pg.getCurrentFB().glFbo); + pgl.bindFramebufferImpl(PGL.READ_FRAMEBUFFER, g.getCurrentFB().glFbo); + pgl.bindFramebufferImpl(PGL.DRAW_FRAMEBUFFER, g.getCurrentFB().glFbo); } public void bind() { @@ -193,9 +198,11 @@ public class FrameBuffer implements PConstants { } public void finish() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; if (noDepth) { // No need to clear depth buffer because depth testing was disabled. - if (pg.getHint(ENABLE_DEPTH_TEST)) { + if (g.getHint(ENABLE_DEPTH_TEST)) { pgl.enable(PGL.DEPTH_TEST); } else { pgl.disable(PGL.DEPTH_TEST); @@ -251,6 +258,8 @@ public class FrameBuffer implements PConstants { public void setColorBuffers(Texture[] textures, int n) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; if (screenFb) return; if (numColorBuffers != PApplet.min(n, textures.length)) { @@ -262,8 +271,8 @@ public class FrameBuffer implements PConstants { colorBufferTex[i] = textures[i]; } - pg.pushFramebuffer(); - pg.setFramebuffer(this); + g.pushFramebuffer(); + g.setFramebuffer(this); // Making sure nothing is attached. for (int i = 0; i < numColorBuffers; i++) { @@ -279,11 +288,14 @@ public class FrameBuffer implements PConstants { pgl.validateFramebuffer(); - pg.popFramebuffer(); + g.popFramebuffer(); } public void swapColorBuffers() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + for (int i = 0; i < numColorBuffers - 1; i++) { int i1 = (i + 1); Texture tmp = colorBufferTex[i]; @@ -291,8 +303,8 @@ public class FrameBuffer implements PConstants { colorBufferTex[i1] = tmp; } - pg.pushFramebuffer(); - pg.setFramebuffer(this); + g.pushFramebuffer(); + g.setFramebuffer(this); for (int i = 0; i < numColorBuffers; i++) { pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0 + i, colorBufferTex[i].glTarget, @@ -300,7 +312,7 @@ public class FrameBuffer implements PConstants { } pgl.validateFramebuffer(); - pg.popFramebuffer(); + g.popFramebuffer(); } @@ -421,10 +433,12 @@ public class FrameBuffer implements PConstants { protected void initColorBufferMultisample() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; if (screenFb) return; - pg.pushFramebuffer(); - pg.setFramebuffer(this); + g.pushFramebuffer(); + g.setFramebuffer(this); // glMultisample = PGraphicsOpenGL.createRenderBufferObject(context, pgl); pgl.bindRenderbuffer(PGL.RENDERBUFFER, glMultisample); @@ -433,19 +447,21 @@ public class FrameBuffer implements PConstants { pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0, PGL.RENDERBUFFER, glMultisample); - pg.popFramebuffer(); + g.popFramebuffer(); } protected void initPackedDepthStencilBuffer() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; if (screenFb) return; if (width == 0 || height == 0) { throw new RuntimeException("PFramebuffer: size undefined."); } - pg.pushFramebuffer(); - pg.setFramebuffer(this); + g.pushFramebuffer(); + g.setFramebuffer(this); // glDepthStencil = PGraphicsOpenGL.createRenderBufferObject(context, pgl); pgl.bindRenderbuffer(PGL.RENDERBUFFER, glDepthStencil); @@ -463,19 +479,21 @@ public class FrameBuffer implements PConstants { pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.STENCIL_ATTACHMENT, PGL.RENDERBUFFER, glDepthStencil); - pg.popFramebuffer(); + g.popFramebuffer(); } protected void initDepthBuffer() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; if (screenFb) return; if (width == 0 || height == 0) { throw new RuntimeException("PFramebuffer: size undefined."); } - pg.pushFramebuffer(); - pg.setFramebuffer(this); + g.pushFramebuffer(); + g.setFramebuffer(this); // glDepth = PGraphicsOpenGL.createRenderBufferObject(context, pgl); pgl.bindRenderbuffer(PGL.RENDERBUFFER, glDepth); @@ -499,19 +517,21 @@ public class FrameBuffer implements PConstants { pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.DEPTH_ATTACHMENT, PGL.RENDERBUFFER, glDepth); - pg.popFramebuffer(); + g.popFramebuffer(); } protected void initStencilBuffer() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; if (screenFb) return; if (width == 0 || height == 0) { throw new RuntimeException("PFramebuffer: size undefined."); } - pg.pushFramebuffer(); - pg.setFramebuffer(this); + g.pushFramebuffer(); + g.setFramebuffer(this); // glStencil = PGraphicsOpenGL.createRenderBufferObject(context, pgl); pgl.bindRenderbuffer(PGL.RENDERBUFFER, glStencil); @@ -534,7 +554,7 @@ public class FrameBuffer implements PConstants { pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.STENCIL_ATTACHMENT, PGL.RENDERBUFFER, glStencil); - pg.popFramebuffer(); + g.popFramebuffer(); } diff --git a/core/src/processing/opengl/PGL.java b/core/src/processing/opengl/PGL.java index 37094c6c8..863f420e3 100644 --- a/core/src/processing/opengl/PGL.java +++ b/core/src/processing/opengl/PGL.java @@ -25,6 +25,7 @@ package processing.opengl; import java.io.IOException; +import java.lang.ref.WeakReference; import java.net.URL; import java.nio.Buffer; import java.nio.ByteBuffer; @@ -51,7 +52,7 @@ public abstract class PGL { // Basic fields /** The PGraphics and PApplet objects using this interface */ - protected PGraphicsOpenGL graphics; + protected WeakReference graphics; protected PApplet sketch; /** OpenGL thread */ @@ -427,7 +428,7 @@ public abstract class PGL { public PGL(PGraphicsOpenGL pg) { - this.graphics = pg; + this.graphics = new WeakReference(pg); if (glColorTex == null) { glColorFbo = allocateIntBuffer(1); glColorTex = allocateIntBuffer(2); @@ -562,14 +563,16 @@ public abstract class PGL { protected Texture wrapBackTexture(Texture texture) { if (texture == null) { - texture = new Texture(graphics); - texture.init(graphics.width, graphics.height, + PGraphicsOpenGL g = graphics.get(); + if (g == null) return null; + texture = new Texture(g); + texture.init(g.width, g.height, glColorTex.get(backTex), TEXTURE_2D, RGBA, fboWidth, fboHeight, NEAREST, NEAREST, CLAMP_TO_EDGE, CLAMP_TO_EDGE); texture.invertedY(true); texture.colorBuffer(true); - graphics.setCache(graphics, texture); + g.setCache(g, texture); } else { texture.glName = glColorTex.get(backTex); } @@ -579,8 +582,10 @@ public abstract class PGL { protected Texture wrapFrontTexture(Texture texture) { if (texture == null) { - texture = new Texture(graphics); - texture.init(graphics.width, graphics.height, + PGraphicsOpenGL g = graphics.get(); + if (g == null) return null; + texture = new Texture(g); + texture.init(g.width, g.height, glColorTex.get(frontTex), TEXTURE_2D, RGBA, fboWidth, fboHeight, NEAREST, NEAREST, CLAMP_TO_EDGE, CLAMP_TO_EDGE); @@ -623,7 +628,8 @@ public abstract class PGL { bindFramebufferImpl(READ_FRAMEBUFFER, glMultiFbo.get(0)); bindFramebufferImpl(DRAW_FRAMEBUFFER, glColorFbo.get(0)); int mask = COLOR_BUFFER_BIT; - if (graphics.getHint(PConstants.ENABLE_BUFFER_READING)) { + PGraphicsOpenGL g = graphics.get(); + if (g != null && g.getHint(PConstants.ENABLE_BUFFER_READING)) { mask |= DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT; } blitFramebuffer(0, 0, fboWidth, fboHeight, @@ -688,8 +694,11 @@ public abstract class PGL { protected void beginRender() { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return; + if (sketch == null) { - sketch = graphics.parent; + sketch = g.parent; } pgeomCount = geomCount; @@ -723,12 +732,11 @@ public abstract class PGL { if (sketch.frameCount == 0) { // No need to draw back color buffer because we are in the first frame. - int argb = graphics.backgroundColor; - float a = ((argb >> 24) & 0xff) / 255.0f; - float r = ((argb >> 16) & 0xff) / 255.0f; - float g = ((argb >> 8) & 0xff) / 255.0f; - float b = ((argb) & 0xff) / 255.0f; - clearColor(r, g, b, a); + float ba = ((g.backgroundColor >> 24) & 0xff) / 255.0f; + float br = ((g.backgroundColor >> 16) & 0xff) / 255.0f; + float bg = ((g.backgroundColor >> 8) & 0xff) / 255.0f; + float bb = ((g.backgroundColor) & 0xff) / 255.0f; + clearColor(br, bg, bb, ba); clear(COLOR_BUFFER_BIT); } else if (!pclearColor || !sketch.isLooping()) { // Render previous back texture (now is the front) as background, @@ -741,15 +749,18 @@ public abstract class PGL { } float scale = getPixelScale(); drawTexture(TEXTURE_2D, glColorTex.get(frontTex), fboWidth, fboHeight, - x, y, graphics.width, graphics.height, - 0, 0, (int)(scale * graphics.width), (int)(scale * graphics.height), - 0, 0, graphics.width, graphics.height); + x, y, g.width, g.height, + 0, 0, (int)(scale * g.width), (int)(scale * g.height), + 0, 0, g.width, g.height); } } } protected void endRender(int windowColor) { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return; + if (fboLayerEnabled) { syncBackTexture(); @@ -757,13 +768,12 @@ public abstract class PGL { bindFramebufferImpl(FRAMEBUFFER, 0); if (presentMode) { - int argb = windowColor; - float a = ((argb >> 24) & 0xff) / 255.0f; - float r = ((argb >> 16) & 0xff) / 255.0f; - float g = ((argb >> 8) & 0xff) / 255.0f; - float b = (argb & 0xff) / 255.0f; + float wa = ((windowColor >> 24) & 0xff) / 255.0f; + float wr = ((windowColor >> 16) & 0xff) / 255.0f; + float wg = ((windowColor >> 8) & 0xff) / 255.0f; + float wb = (windowColor & 0xff) / 255.0f; clearDepth(1); - clearColor(r, g, b, a); + clearColor(wr, wg, wb, wa); clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT); if (closeBtnTex == null) { @@ -800,9 +810,9 @@ public abstract class PGL { float scale = getPixelScale(); drawTexture(TEXTURE_2D, glColorTex.get(backTex), fboWidth, fboHeight, - x, y, graphics.width, graphics.height, - 0, 0, (int)(scale * graphics.width), (int)(scale * graphics.height), - 0, 0, graphics.width, graphics.height); + x, y, g.width, g.height, + 0, 0, (int)(scale * g.width), (int)(scale * g.height), + 0, 0, g.width, g.height); // Swapping front and back textures. int temp = frontTex; @@ -855,14 +865,17 @@ public abstract class PGL { private void createFBOLayer() { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return; + float scale = getPixelScale(); if (hasNpotTexSupport()) { - fboWidth = (int)(scale * graphics.width); - fboHeight = (int)(scale * graphics.height); + fboWidth = (int)(scale * g.width); + fboHeight = (int)(scale * g.height); } else { - fboWidth = nextPowerOfTwo((int)(scale * graphics.width)); - fboHeight = nextPowerOfTwo((int)(scale * graphics.height)); + fboWidth = nextPowerOfTwo((int)(scale * g.width)); + fboHeight = nextPowerOfTwo((int)(scale * g.height)); } int maxs = maxSamples(); @@ -886,7 +899,7 @@ public abstract class PGL { texParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE); texImage2D(TEXTURE_2D, 0, RGBA, fboWidth, fboHeight, 0, RGBA, UNSIGNED_BYTE, null); - initTexture(TEXTURE_2D, RGBA, fboWidth, fboHeight, graphics.backgroundColor); + initTexture(TEXTURE_2D, RGBA, fboWidth, fboHeight, g.backgroundColor); } bindTexture(TEXTURE_2D, 0); @@ -898,7 +911,7 @@ public abstract class PGL { framebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, glColorTex.get(backTex), 0); - if (!multisample || graphics.getHint(PConstants.ENABLE_BUFFER_READING)) { + if (!multisample || g.getHint(PConstants.ENABLE_BUFFER_READING)) { // If not multisampled, this is the only depth and stencil buffer. // If multisampled and depth reading enabled, these are going to // hold downsampled depth and stencil buffers. @@ -927,12 +940,11 @@ public abstract class PGL { // Clear all buffers. clearDepth(1); clearStencil(0); - int argb = graphics.backgroundColor; - float a = ((argb >> 24) & 0xff) / 255.0f; - float r = ((argb >> 16) & 0xff) / 255.0f; - float g = ((argb >> 8) & 0xff) / 255.0f; - float b = ((argb) & 0xff) / 255.0f; - clearColor(r, g, b, a); + float ba = ((g.backgroundColor >> 24) & 0xff) / 255.0f; + float br = ((g.backgroundColor >> 16) & 0xff) / 255.0f; + float bg = ((g.backgroundColor >> 8) & 0xff) / 255.0f; + float bb = ((g.backgroundColor) & 0xff) / 255.0f; + clearColor(br, bg, bb, ba); clear(DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT | COLOR_BUFFER_BIT); bindFramebufferImpl(FRAMEBUFFER, 0); @@ -1194,7 +1206,9 @@ public abstract class PGL { protected PGL initTex2DShader() { - PGL ppgl = primaryPGL ? this : graphics.getPrimaryPGL(); + PGraphicsOpenGL g = graphics.get(); + if (g == null) return null; + PGL ppgl = primaryPGL ? this : g.getPrimaryPGL(); if (!ppgl.loadedTex2DShader || ppgl.tex2DShaderContext != ppgl.glContext) { String[] preprocVertSrc = preprocessVertexSource(texVertShaderSource, getGLSLVersion()); @@ -1326,7 +1340,9 @@ public abstract class PGL { protected PGL initTexRectShader() { - PGL ppgl = primaryPGL ? this : graphics.getPrimaryPGL(); + PGraphicsOpenGL g = graphics.get(); + if (g == null) return null; + PGL ppgl = primaryPGL ? this : g.getPrimaryPGL(); if (!ppgl.loadedTexRectShader || ppgl.texRectShaderContext != ppgl.glContext) { String[] preprocVertSrc = preprocessVertexSource(texVertShaderSource, getGLSLVersion()); @@ -1459,33 +1475,42 @@ public abstract class PGL { protected int getColorValue(int scrX, int scrY) { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return 0; + if (colorBuffer == null) { colorBuffer = IntBuffer.allocate(1); } colorBuffer.rewind(); - readPixels(scrX, graphics.height - scrY - 1, 1, 1, RGBA, UNSIGNED_BYTE, + readPixels(scrX, g.height - scrY - 1, 1, 1, RGBA, UNSIGNED_BYTE, colorBuffer); return colorBuffer.get(); } protected float getDepthValue(int scrX, int scrY) { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return 0; + if (depthBuffer == null) { depthBuffer = FloatBuffer.allocate(1); } depthBuffer.rewind(); - readPixels(scrX, graphics.height - scrY - 1, 1, 1, DEPTH_COMPONENT, FLOAT, + readPixels(scrX, g.height - scrY - 1, 1, 1, DEPTH_COMPONENT, FLOAT, depthBuffer); return depthBuffer.get(0); } protected byte getStencilValue(int scrX, int scrY) { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return 0; + if (stencilBuffer == null) { stencilBuffer = ByteBuffer.allocate(1); } stencilBuffer.rewind(); - readPixels(scrX, graphics.height - scrY - 1, 1, 1, STENCIL_INDEX, + readPixels(scrX, g.height - scrY - 1, 1, 1, STENCIL_INDEX, UNSIGNED_BYTE, stencilBuffer); return stencilBuffer.get(0); } @@ -2935,8 +2960,11 @@ public abstract class PGL { // to glReadPixels() should be done in readPixelsImpl(). public void readPixels(int x, int y, int width, int height, int format, int type, Buffer buffer){ - boolean multisampled = isMultisampled() || graphics.offscreenMultisample; - boolean depthReadingEnabled = graphics.getHint(PConstants.ENABLE_BUFFER_READING); + PGraphicsOpenGL g = graphics.get(); + if (g == null) return; + + boolean multisampled = isMultisampled() || g.offscreenMultisample; + boolean depthReadingEnabled = g.getHint(PConstants.ENABLE_BUFFER_READING); boolean depthRequested = format == STENCIL_INDEX || format == DEPTH_COMPONENT || format == DEPTH_STENCIL; if (multisampled && depthRequested && !depthReadingEnabled) { @@ -2944,9 +2972,9 @@ public abstract class PGL { return; } - graphics.beginReadPixels(); + g.beginReadPixels(); readPixelsImpl(x, y, width, height, format, type, buffer); - graphics.endReadPixels(); + g.endReadPixels(); } protected abstract void readPixelsImpl(int x, int y, int width, int height, int format, int type, Buffer buffer); @@ -3138,9 +3166,12 @@ public abstract class PGL { // Framebuffers Objects public void bindFramebuffer(int target, int framebuffer) { - graphics.beginBindFramebuffer(target, framebuffer); + PGraphicsOpenGL g = graphics.get(); + if (g == null) return; + + g.beginBindFramebuffer(target, framebuffer); bindFramebufferImpl(target, framebuffer); - graphics.endBindFramebuffer(target, framebuffer); + g.endBindFramebuffer(target, framebuffer); } protected abstract void bindFramebufferImpl(int target, int framebuffer); diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index cfa93cccd..c01cdd423 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -41,7 +41,7 @@ public class PGraphicsOpenGL extends PGraphics { public PGL pgl; /** The renderer currently in use. */ - protected PGraphicsOpenGL currentPG; + public PGraphicsOpenGL currentPG; /** Font cache for texture objects. */ protected WeakHashMap fontMap; @@ -344,10 +344,8 @@ public class PGraphicsOpenGL extends PGraphics { // Offscreen rendering: - protected WeakReference offscreenFramebuffer = - new WeakReference(null); - protected WeakReference multisampleFramebuffer = - new WeakReference(null); + protected FrameBuffer offscreenFramebuffer; + protected FrameBuffer multisampleFramebuffer; protected boolean offscreenMultisample; protected boolean pixOpChangedFB; @@ -357,10 +355,10 @@ public class PGraphicsOpenGL extends PGraphics { // Screen surface: /** Texture containing the current frame */ - protected WeakReference texture = new WeakReference(null); + protected Texture texture = null; /** Texture containing the previous frame */ - protected WeakReference ptexture = new WeakReference(null); + protected Texture ptexture = null; /** IntBuffer wrapping the pixels array. */ protected IntBuffer pixelBuffer; @@ -372,7 +370,7 @@ public class PGraphicsOpenGL extends PGraphics { protected IntBuffer nativePixelBuffer; /** texture used to apply a filter on the screen image. */ - protected WeakReference filterTexture = new WeakReference(null); + protected Texture filterTexture = null; /** PImage that wraps filterTexture. */ protected PImage filterImage; @@ -602,8 +600,8 @@ public class PGraphicsOpenGL extends PGraphics { if (primaryGraphics) { deleteDefaultShaders(); } else { - FrameBuffer ofb = offscreenFramebuffer.get(); - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; + FrameBuffer mfb = multisampleFramebuffer; if (ofb != null) { ofb.dispose(); } @@ -1493,7 +1491,7 @@ public class PGraphicsOpenGL extends PGraphics { if (primaryGraphics) { setCurrentPG(null); } else { - getPrimaryPG().setCurrentPG(getPrimaryPG()); + getPrimaryPG().setCurrentPG(); } drawing = false; @@ -1513,6 +1511,10 @@ public class PGraphicsOpenGL extends PGraphics { currentPG = pg; } + protected void setCurrentPG() { + currentPG = this; + } + protected PGraphicsOpenGL getCurrentPG() { return currentPG; } @@ -1636,8 +1638,8 @@ public class PGraphicsOpenGL extends PGraphics { pixfb = drawFramebuffer; } } else { - FrameBuffer ofb = offscreenFramebuffer.get(); - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; + FrameBuffer mfb = multisampleFramebuffer; if (op == OP_READ) { if (offscreenMultisample) { // Making sure the offscreen FBO is up-to-date @@ -5413,8 +5415,7 @@ public class PGraphicsOpenGL extends PGraphics { boolean needToDrawTex = primaryGraphics && (!pgl.isFBOBacked() || (pgl.isFBOBacked() && pgl.isMultisampled())) || offscreenMultisample; - Texture tex = texture.get(); - if (tex == null) return; + if (texture == null) return; if (needToDrawTex) { // The texture to screen needs to be drawn only if we are on the primary // surface w/out FBO-layer, or with FBO-layer and multisampling. Or, we @@ -5424,9 +5425,9 @@ public class PGraphicsOpenGL extends PGraphics { // (off)screen buffer. // First, copy the pixels to the texture. We don't need to invert the // pixel copy because the texture will be drawn inverted. - int tw = PApplet.min(tex.glWidth - f * x, f * w); - int th = PApplet.min(tex.glHeight - f * y, f * h); - pgl.copyToTexture(tex.glTarget, tex.glFormat, tex.glName, + int tw = PApplet.min(texture.glWidth - f * x, f * w); + int th = PApplet.min(texture.glHeight - f * y, f * h); + pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glName, f * x, f * y, tw, th, nativePixelBuffer); beginPixelsOp(OP_WRITE); drawTexture(x, y, w, h); @@ -5435,7 +5436,7 @@ public class PGraphicsOpenGL extends PGraphics { // We only need to copy the pixels to the back texture where we are // currently drawing to. Because the texture is invertex along Y, we // need to reflect that in the vertical arguments. - pgl.copyToTexture(tex.glTarget, tex.glFormat, tex.glName, + pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glName, f * x, f * (height - (y + h)), f * w, f * h, nativePixelBuffer); } } @@ -5559,16 +5560,15 @@ public class PGraphicsOpenGL extends PGraphics { } endPixelsOp(); - Texture tex = texture.get(); - if (tex != null) { - tex.setNative(nativePixelBuffer, 0, 0, pixelWidth, pixelHeight); + if (texture != null) { + texture.setNative(nativePixelBuffer, 0, 0, pixelWidth, pixelHeight); } } } else if (offscreenMultisample) { // We need to copy the contents of the multisampled buffer to the color // buffer, so the later is up-to-date with the last drawing. - FrameBuffer ofb = offscreenFramebuffer.get(); - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; + FrameBuffer mfb = multisampleFramebuffer; if (ofb != null && mfb != null) { mfb.copyColor(ofb); } @@ -5582,9 +5582,8 @@ public class PGraphicsOpenGL extends PGraphics { // Just marks the whole texture as updated public void updateTexture() { - Texture tex = texture.get(); - if (tex != null) { - tex.updateTexels(); + if (texture != null) { + texture.updateTexels(); } } @@ -5592,9 +5591,8 @@ public class PGraphicsOpenGL extends PGraphics { // Marks the specified rectanglular subregion in the texture as // updated. public void updateTexture(int x, int y, int w, int h) { - Texture tex = texture.get(); - if (tex != null) { - tex.updateTexels(x, y, w, h); + if (texture != null) { + texture.updateTexels(x, y, w, h); } } @@ -5611,52 +5609,45 @@ public class PGraphicsOpenGL extends PGraphics { protected void loadTextureImpl(int sampling, boolean mipmap) { updatePixelSize(); if (pixelWidth == 0 || pixelHeight == 0) return; - Texture tex = texture.get(); - if (tex == null || tex.contextIsOutdated()) { + if (texture == null || texture.contextIsOutdated()) { Texture.Parameters params = new Texture.Parameters(ARGB, sampling, mipmap); - tex = new Texture(this, pixelWidth, pixelHeight, params); - tex.invertedY(true); - tex.colorBuffer(true); - setCache(this, tex); - texture = new WeakReference(tex); + texture = new Texture(this, pixelWidth, pixelHeight, params); + texture.invertedY(true); + texture.colorBuffer(true); + setCache(this, texture); } } protected void createPTexture() { updatePixelSize(); - Texture tex = texture.get(); - if (tex != null) { - Texture ptex = new Texture(this, pixelWidth, pixelHeight, tex.getParameters()); - ptex.invertedY(true); - ptex.colorBuffer(true); - ptexture = new WeakReference(ptex); + if (texture != null) { + texture = new Texture(this, pixelWidth, pixelHeight, texture.getParameters()); + ptexture.invertedY(true); + ptexture.colorBuffer(true); } } protected void swapOffscreenTextures() { - Texture tex = texture.get(); - Texture ptex = ptexture.get(); - FrameBuffer ofb = offscreenFramebuffer.get(); - if (tex != null && ptex != null && ofb != null) { - int temp = tex.glName; - tex.glName = ptex.glName; - ptex.glName = temp; - ofb.setColorBuffer(tex); + FrameBuffer ofb = offscreenFramebuffer; + if (texture != null && ptexture != null && ofb != null) { + int temp = texture.glName; + texture.glName = ptexture.glName; + ptexture.glName = temp; + ofb.setColorBuffer(texture); } } protected void drawTexture() { - Texture tex = texture.get(); - if (tex != null) { + if (texture != null) { // No blend so the texure replaces wherever is on the screen, // irrespective of the alpha pgl.disable(PGL.BLEND); - pgl.drawTexture(tex.glTarget, tex.glName, - tex.glWidth, tex.glHeight, + pgl.drawTexture(texture.glTarget, texture.glName, + texture.glWidth, texture.glHeight, 0, 0, width, height); pgl.enable(PGL.BLEND); } @@ -5664,13 +5655,12 @@ public class PGraphicsOpenGL extends PGraphics { protected void drawTexture(int x, int y, int w, int h) { - Texture tex = texture.get(); - if (tex != null) { + if (texture != null) { // Processing Y axis is inverted with respect to OpenGL, so we need to // invert the y coordinates of the screen rectangle. pgl.disable(PGL.BLEND); - pgl.drawTexture(tex.glTarget, tex.glName, - tex.glWidth, tex.glHeight, + pgl.drawTexture(texture.glTarget, texture.glName, + texture.glWidth, texture.glHeight, 0, 0, width, height, x, y, x + w, y + h, x, height - (y + h), x + w, height - y); @@ -5680,13 +5670,12 @@ public class PGraphicsOpenGL extends PGraphics { protected void drawPTexture() { - Texture ptex = ptexture.get(); - if (ptex != null) { + if (ptexture != null) { // No blend so the texure replaces wherever is on the screen, // irrespective of the alpha pgl.disable(PGL.BLEND); - pgl.drawTexture(ptex.glTarget, ptex.glName, - ptex.glWidth, ptex.glHeight, + pgl.drawTexture(ptexture.glTarget, ptexture.glName, + ptexture.glWidth, ptexture.glHeight, 0, 0, width, height); pgl.enable(PGL.BLEND); } @@ -5772,16 +5761,13 @@ public class PGraphicsOpenGL extends PGraphics { } loadTexture(); - Texture tex = texture.get(); - Texture ftex = filterTexture.get(); - if (ftex == null || ftex.contextIsOutdated()) { - ftex = new Texture(this, tex.width, tex.height, - tex.getParameters()); - ftex.invertedY(true); - filterImage = wrapTexture(ftex); - filterTexture = new WeakReference(ftex); + if (filterTexture == null || filterTexture.contextIsOutdated()) { + filterTexture = new Texture(this, texture.width, texture.height, + texture.getParameters()); + filterTexture.invertedY(true); + filterImage = wrapTexture(filterTexture); } - ftex.set(tex); + 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. @@ -5846,15 +5832,12 @@ public class PGraphicsOpenGL extends PGraphics { int dx, int dy, int dw, int dh) { if (primaryGraphics) pgl.enableFBOLayer(); loadTexture(); - Texture tex = texture.get(); - Texture ftex = filterTexture.get(); - if (ftex == null || ftex.contextIsOutdated()) { - ftex = new Texture(this, tex.width, tex.height, tex.getParameters()); - ftex.invertedY(true); - filterImage = wrapTexture(ftex); - filterTexture = new WeakReference(ftex); + if (filterTexture == null || filterTexture.contextIsOutdated()) { + filterTexture = new Texture(this, texture.width, texture.height, texture.getParameters()); + filterTexture.invertedY(true); + filterImage = wrapTexture(filterTexture); } - ftex.put(tex, sx, height - (sy + sh), sw, height - sy); + filterTexture.put(texture, sx, height - (sy + sh), sw, height - sy); copy(filterImage, sx, sy, sw, sh, dx, dy, dw, dh); } @@ -6060,7 +6043,7 @@ public class PGraphicsOpenGL extends PGraphics { */ public Texture getTexture(boolean load) { if (load) loadTexture(); - return texture.get(); + return texture; } @@ -6103,9 +6086,9 @@ public class PGraphicsOpenGL extends PGraphics { public FrameBuffer getFrameBuffer(boolean multi) { if (multi) { - return multisampleFramebuffer.get(); + return multisampleFramebuffer; } else { - return offscreenFramebuffer.get(); + return offscreenFramebuffer; } } @@ -6132,12 +6115,10 @@ public class PGraphicsOpenGL extends PGraphics { if (primaryGraphics) { pgl.bindFrontTexture(); } else { - Texture ptex = ptexture.get(); - if (ptex == null) { + if (ptexture == null) { createPTexture(); - ptex = ptexture.get(); } - ptex.bind(); + ptexture.bind(); } } @@ -6146,8 +6127,7 @@ public class PGraphicsOpenGL extends PGraphics { if (primaryGraphics) { pgl.unbindFrontTexture(); } else { - Texture ptex = ptexture.get(); - ptex.unbind(); + ptexture.unbind(); } } @@ -6230,24 +6210,15 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteSurfaceTextures() { if (texture != null) { - Texture tex = texture.get(); - if (tex != null) { - tex.dispose(); - } + texture.dispose(); } if (ptexture != null) { - Texture ptex = ptexture.get(); - if (ptex != null) { - ptex.dispose(); - } + ptexture.dispose(); } if (filterTexture != null) { - Texture ftex = filterTexture.get(); - if (ftex != null) { - ftex.dispose(); - } + filterTexture.dispose(); } } @@ -6282,8 +6253,8 @@ public class PGraphicsOpenGL extends PGraphics { pgl.initSurface(smooth); if (texture != null) { removeCache(this); - texture = new WeakReference(null); - ptexture = new WeakReference(null); + texture = null; + ptexture = null; } initialized = true; } @@ -6307,17 +6278,8 @@ public class PGraphicsOpenGL extends PGraphics { } if (pgl.isFBOBacked()) { - Texture tex0 = texture.get(); - Texture tex1 = pgl.wrapBackTexture(tex0); - if (tex0 != tex1) { - texture = new WeakReference(tex1); - } - - Texture ptex0 = ptexture.get(); - Texture ptex1 = pgl.wrapFrontTexture(ptex0); - if (ptex0 != ptex1) { - ptexture = new WeakReference(ptex1); - } + texture = pgl.wrapBackTexture(texture); + ptexture = pgl.wrapFrontTexture(ptexture); } } @@ -6331,9 +6293,8 @@ public class PGraphicsOpenGL extends PGraphics { // Getting the context and capabilities from the main renderer. loadTextureImpl(textureSampling, false); - Texture tex = texture.get(); - FrameBuffer ofb = offscreenFramebuffer.get(); - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; + FrameBuffer mfb = multisampleFramebuffer; // In case of re-initialization (for example, when the smooth level // is changed), we make sure that all the OpenGL resources associated @@ -6350,31 +6311,31 @@ public class PGraphicsOpenGL extends PGraphics { boolean packed = depthBits == 24 && stencilBits == 8 && packedDepthStencilSupported; if (PGraphicsOpenGL.fboMultisampleSupported && 1 < PGL.smoothToSamples(smooth)) { - mfb = new FrameBuffer(this, tex.glWidth, tex.glHeight, PGL.smoothToSamples(smooth), 0, + mfb = new FrameBuffer(this, texture.glWidth, texture.glHeight, PGL.smoothToSamples(smooth), 0, depthBits, stencilBits, packed, false); mfb.clear(); - multisampleFramebuffer = new WeakReference(mfb); + multisampleFramebuffer = mfb; offscreenMultisample = true; // The offscreen framebuffer where the multisampled image is finally drawn // to. If depth reading is disabled it doesn't need depth and stencil buffers // since they are part of the multisampled framebuffer. if (hints[ENABLE_BUFFER_READING]) { - ofb = new FrameBuffer(this, tex.glWidth, tex.glHeight, 1, 1, + ofb = new FrameBuffer(this, texture.glWidth, texture.glHeight, 1, 1, depthBits, stencilBits, packed, false); } else { - ofb = new FrameBuffer(this, tex.glWidth, tex.glHeight, 1, 1, + ofb = new FrameBuffer(this, texture.glWidth, texture.glHeight, 1, 1, 0, 0, false, false); } } else { smooth = 0; - ofb = new FrameBuffer(this, tex.glWidth, tex.glHeight, 1, 1, + ofb = new FrameBuffer(this, texture.glWidth, texture.glHeight, 1, 1, depthBits, stencilBits, packed, false); offscreenMultisample = false; } - ofb.setColorBuffer(tex); + ofb.setColorBuffer(texture); ofb.clear(); - offscreenFramebuffer = new WeakReference(ofb); + offscreenFramebuffer = ofb; initialized = true; } @@ -6384,8 +6345,8 @@ public class PGraphicsOpenGL extends PGraphics { if (!initialized) { initOffscreen(); } else { - FrameBuffer ofb = offscreenFramebuffer.get(); - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; + FrameBuffer mfb = multisampleFramebuffer; boolean outdated = ofb != null && ofb.contextIsOutdated(); boolean outdatedMulti = mfb != null && mfb.contextIsOutdated(); if (outdated || outdatedMulti) { @@ -6401,12 +6362,12 @@ public class PGraphicsOpenGL extends PGraphics { pushFramebuffer(); if (offscreenMultisample) { - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer mfb = multisampleFramebuffer; if (mfb != null) { setFramebuffer(mfb); } } else { - FrameBuffer ofb = offscreenFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; if (ofb != null) { setFramebuffer(ofb); } @@ -6427,8 +6388,8 @@ public class PGraphicsOpenGL extends PGraphics { protected void endOffscreenDraw() { if (offscreenMultisample) { - FrameBuffer ofb = offscreenFramebuffer.get(); - FrameBuffer mfb = multisampleFramebuffer.get(); + FrameBuffer ofb = offscreenFramebuffer; + FrameBuffer mfb = multisampleFramebuffer; if (ofb != null && mfb != null) { mfb.copyColor(ofb); } @@ -6446,9 +6407,8 @@ public class PGraphicsOpenGL extends PGraphics { pgl.colorMask(true, true, true, true); } - Texture tex = texture.get(); - if (tex != null) { - tex.updateTexels(); // Mark all texels in screen texture as modified. + if (texture != null) { + texture.updateTexels(); // Mark all texels in screen texture as modified. } getPrimaryPG().restoreGL(); @@ -7113,9 +7073,9 @@ public class PGraphicsOpenGL extends PGraphics { // Holds an array of textures and the range of vertex // indices each texture applies to. static protected class TexCache { - PGraphicsOpenGL pg; int size; - PImage[] textures; + WeakReference pg; + WeakReference[] textures; int[] firstIndex; int[] lastIndex; int[] firstCache; @@ -7123,12 +7083,13 @@ public class PGraphicsOpenGL extends PGraphics { boolean hasTextures; TexCache(PGraphicsOpenGL pg) { - this.pg = pg; + this.pg = new WeakReference(pg); allocate(); } + @SuppressWarnings("unchecked") void allocate() { - textures = new PImage[PGL.DEFAULT_IN_TEXTURES]; + textures = new WeakReference[PGL.DEFAULT_IN_TEXTURES]; firstIndex = new int[PGL.DEFAULT_IN_TEXTURES]; lastIndex = new int[PGL.DEFAULT_IN_TEXTURES]; firstCache = new int[PGL.DEFAULT_IN_TEXTURES]; @@ -7145,21 +7106,22 @@ public class PGraphicsOpenGL extends PGraphics { boolean containsTexture(PImage img) { for (int i = 0; i < size; i++) { - if (textures[i] == img) return true; + if (textures[i].get() == img) return true; } return false; } PImage getTextureImage(int i) { - return textures[i]; + return textures[i].get(); } Texture getTexture(int i) { - PImage img = textures[i]; + PGraphicsOpenGL g = pg.get(); + PImage img = textures[i].get(); Texture tex = null; - if (img != null) { - tex = pg.getTexture(img); + if (img != null && g != null) { + tex = g.getTexture(img); } return tex; @@ -7168,7 +7130,7 @@ public class PGraphicsOpenGL extends PGraphics { void addTexture(PImage img, int firsti, int firstb, int lasti, int lastb) { arrayCheck(); - textures[size] = img; + textures[size] = new WeakReference(img); firstIndex[size] = firsti; lastIndex[size] = lasti; firstCache[size] = firstb; @@ -7197,8 +7159,9 @@ public class PGraphicsOpenGL extends PGraphics { } } + @SuppressWarnings("unchecked") void expandTextures(int n) { - PImage[] temp = new PImage[n]; + WeakReference[] temp = new WeakReference[n]; PApplet.arrayCopy(textures, 0, temp, 0, size); textures = temp; } @@ -7338,7 +7301,7 @@ public class PGraphicsOpenGL extends PGraphics { // Holds the input vertices: xyz coordinates, fill/tint color, // normal, texture coordinates and stroke color and weight. static protected class InGeometry { - PGraphicsOpenGL pg; + WeakReference pg; int renderMode; AttributeMap attribs; @@ -7381,7 +7344,7 @@ public class PGraphicsOpenGL extends PGraphics { float normalX, normalY, normalZ; InGeometry(PGraphicsOpenGL pg, AttributeMap attr, int mode) { - this.pg = pg; + this.pg = new WeakReference(pg); this.attribs = attr; renderMode = mode; allocate(); @@ -8437,6 +8400,9 @@ public class PGraphicsOpenGL extends PGraphics { void addEllipse(float x, float y, float w, float h, boolean fill, boolean stroke) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + float radiusH = w / 2; float radiusV = h / 2; @@ -8444,10 +8410,10 @@ public class PGraphicsOpenGL extends PGraphics { float centerY = y + radiusV; // should call screenX/Y using current renderer. - float sx1 = pg.screenX(x, y); - float sy1 = pg.screenY(x, y); - float sx2 = pg.screenX(x + w, y + h); - float sy2 = pg.screenY(x + w, y + h); + float sx1 = g.screenX(x, y); + float sy1 = g.screenY(x, y); + float sx2 = g.screenX(x + w, y + h); + float sy2 = g.screenY(x + w, y + h); int accuracy = PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, @@ -8489,6 +8455,9 @@ public class PGraphicsOpenGL extends PGraphics { void addArc(float x, float y, float w, float h, float start, float stop, boolean fill, boolean stroke, int arcMode) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + float hr = w / 2f; float vr = h / 2f; @@ -8531,10 +8500,10 @@ public class PGraphicsOpenGL extends PGraphics { int inc; { // initializes inc the same way ellipse does - float sx1 = pg.screenX(x, y); - float sy1 = pg.screenY(x, y); - float sx2 = pg.screenX(x + w, y + h); - float sy2 = pg.screenY(x + w, y + h); + float sx1 = g.screenX(x, y); + float sy1 = g.screenY(x, y); + float sx2 = g.screenX(x + w, y + h); + float sy2 = g.screenY(x + w, y + h); int accuracy = PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, @@ -8697,6 +8666,9 @@ public class PGraphicsOpenGL extends PGraphics { // any vertex or edge. int[] addSphere(float r, int detailU, int detailV, boolean fill, boolean stroke) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return null; + int nind = 3 * detailU + (6 * detailU + 3) * (detailV - 2) + 3 * detailU; int[] indices = new int[nind]; @@ -8723,15 +8695,15 @@ public class PGraphicsOpenGL extends PGraphics { vert0 = vertCount; u = 1; v -= dv; for (int i = 0; i < detailU; i++) { - setNormal(pg.sphereX[i], pg.sphereY[i], pg.sphereZ[i]); - addVertex(r*pg.sphereX[i], r*pg.sphereY[i], r*pg.sphereZ[i], u , v, + setNormal(g.sphereX[i], g.sphereY[i], g.sphereZ[i]); + addVertex(r*g.sphereX[i], r*g.sphereY[i], r*g.sphereZ[i], u , v, VERTEX, false); u -= du; } vertCount += detailU; vert1 = vertCount; - setNormal(pg.sphereX[0], pg.sphereY[0], pg.sphereZ[0]); - addVertex(r*pg.sphereX[0], r*pg.sphereY[0], r*pg.sphereZ[0], u, v, + setNormal(g.sphereX[0], g.sphereY[0], g.sphereZ[0]); + addVertex(r*g.sphereX[0], r*g.sphereY[0], r*g.sphereZ[0], u, v, VERTEX, false); vertCount++; @@ -8757,15 +8729,15 @@ public class PGraphicsOpenGL extends PGraphics { u = 1; v -= dv; for (int i = 0; i < detailU; i++) { int ioff = offset + i; - setNormal(pg.sphereX[ioff], pg.sphereY[ioff], pg.sphereZ[ioff]); - addVertex(r*pg.sphereX[ioff], r*pg.sphereY[ioff], r*pg.sphereZ[ioff], + setNormal(g.sphereX[ioff], g.sphereY[ioff], g.sphereZ[ioff]); + addVertex(r*g.sphereX[ioff], r*g.sphereY[ioff], r*g.sphereZ[ioff], u , v, VERTEX, false); u -= du; } vertCount += detailU; vert1 = vertCount; - setNormal(pg.sphereX[offset], pg.sphereY[offset], pg.sphereZ[offset]); - addVertex(r*pg.sphereX[offset], r*pg.sphereY[offset], r*pg.sphereZ[offset], + setNormal(g.sphereX[offset], g.sphereY[offset], g.sphereZ[offset]); + addVertex(r*g.sphereX[offset], r*g.sphereY[offset], r*g.sphereZ[offset], u, v, VERTEX, false); vertCount++; @@ -8826,7 +8798,7 @@ public class PGraphicsOpenGL extends PGraphics { // Holds tessellated data for polygon, line and point geometry. static protected class TessGeometry { int renderMode; - PGraphicsOpenGL pg; + WeakReference pg; AttributeMap polyAttribs; // Tessellated polygon data @@ -8906,7 +8878,7 @@ public class PGraphicsOpenGL extends PGraphics { HashMap bpolyAttribs = new HashMap(); TessGeometry(PGraphicsOpenGL pg, AttributeMap attr, int mode) { - this.pg = pg; + this.pg = new WeakReference(pg); this.polyAttribs = attr; renderMode = mode; allocate(); @@ -9820,6 +9792,9 @@ public class PGraphicsOpenGL extends PGraphics { // Sets point vertex with index tessIdx using the data from input vertex // inIdx. void setPointVertex(int tessIdx, InGeometry in, int inIdx) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int index; index = 3 * inIdx; @@ -9827,8 +9802,8 @@ public class PGraphicsOpenGL extends PGraphics { float y = in.vertices[index++]; float z = in.vertices[index ]; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { + PMatrix3D mm = g.modelview; index = 4 * tessIdx; pointVertices[index++] = x*mm.m00 + y*mm.m01 + z*mm.m02 + mm.m03; @@ -9851,6 +9826,9 @@ public class PGraphicsOpenGL extends PGraphics { // Add line geometry void setLineVertex(int tessIdx, float[] vertices, int inIdx0, int rgba) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int index; index = 3 * inIdx0; @@ -9858,8 +9836,8 @@ public class PGraphicsOpenGL extends PGraphics { float y0 = vertices[index++]; float z0 = vertices[index ]; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { + PMatrix3D mm = g.modelview; index = 4 * tessIdx; lineVertices[index++] = x0*mm.m00 + y0*mm.m01 + z0*mm.m02 + mm.m03; @@ -9886,6 +9864,9 @@ public class PGraphicsOpenGL extends PGraphics { // inIdx0 and inIdx1. void setLineVertex(int tessIdx, float[] vertices, int inIdx0, int inIdx1, int rgba, float weight) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int index; index = 3 * inIdx0; @@ -9902,8 +9883,8 @@ public class PGraphicsOpenGL extends PGraphics { float dy = y1 - y0; float dz = z1 - z0; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { + PMatrix3D mm = g.modelview; index = 4 * tessIdx; lineVertices[index++] = x0*mm.m00 + y0*mm.m01 + z0*mm.m02 + mm.m03; @@ -9937,6 +9918,9 @@ public class PGraphicsOpenGL extends PGraphics { // Add poly geometry void addPolyVertex(double[] d, boolean clampXY) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int fcolor = (int)d[ 3] << 24 | (int)d[ 4] << 16 | (int)d[ 5] << 8 | (int)d[ 6]; int acolor = @@ -9956,8 +9940,8 @@ public class PGraphicsOpenGL extends PGraphics { if (25 < d.length) { // Add the values of the custom attributes... - PMatrix3D mm = pg.modelview; - PMatrix3D nm = pg.modelviewInv; + PMatrix3D mm = g.modelview; + PMatrix3D nm = g.modelviewInv; int tessIdx = polyVertexCount - 1; int index; int pos = 25; @@ -9977,7 +9961,7 @@ public class PGraphicsOpenGL extends PGraphics { float x = (float)d[pos++]; float y = (float)d[pos++]; float z = (float)d[pos++]; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { if (clampXY) { // ceil emulates the behavior of JAVA2D farray[index++] = @@ -10001,7 +9985,7 @@ public class PGraphicsOpenGL extends PGraphics { float x = (float)d[pos + 0]; float y = (float)d[pos + 1]; float z = (float)d[pos + 2]; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { farray[index++] = x*nm.m00 + y*nm.m10 + z*nm.m20; farray[index++] = x*nm.m01 + y*nm.m11 + z*nm.m21; farray[index ] = x*nm.m02 + y*nm.m12 + z*nm.m22; @@ -10064,11 +10048,14 @@ public class PGraphicsOpenGL extends PGraphics { float u, float v, int am, int sp, int em, float shine, boolean clampXY) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int index; - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; - PMatrix3D nm = pg.modelviewInv; + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { + PMatrix3D mm = g.modelview; + PMatrix3D nm = g.modelviewInv; index = 4 * tessIdx; if (clampXY) { @@ -10122,14 +10109,17 @@ public class PGraphicsOpenGL extends PGraphics { } void addPolyVertices(InGeometry in, int i0, int i1, boolean clampXY) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int index; int nvert = i1 - i0 + 1; polyVertexCheck(nvert); - if (renderMode == IMMEDIATE && pg.flushMode == FLUSH_WHEN_FULL) { - PMatrix3D mm = pg.modelview; - PMatrix3D nm = pg.modelviewInv; + if (renderMode == IMMEDIATE && g.flushMode == FLUSH_WHEN_FULL) { + PMatrix3D mm = g.modelview; + PMatrix3D nm = g.modelviewInv; for (int i = 0; i < nvert; i++) { int inIdx = i0 + i; @@ -10589,6 +10579,8 @@ public class PGraphicsOpenGL extends PGraphics { // Generates tessellated geometry given a batch of input vertices. static protected class Tessellator { + WeakReference pg; + InGeometry in; TessGeometry tess; TexCache texCache; @@ -10611,7 +10603,6 @@ public class PGraphicsOpenGL extends PGraphics { PMatrix transform; float transformScale; boolean is2D, is3D; - protected PGraphicsOpenGL pg; int[] rawIndices; int rawSize; @@ -10649,9 +10640,10 @@ public class PGraphicsOpenGL extends PGraphics { } void initGluTess() { - if (gluTess == null) { + PGraphicsOpenGL g = pg.get(); + if (g != null && gluTess == null) { callback = new TessellatorCallback(tess.polyAttribs); - gluTess = pg.pgl.createTessellator(callback); + gluTess = g.pgl.createTessellator(callback); } } @@ -10704,7 +10696,7 @@ public class PGraphicsOpenGL extends PGraphics { } protected void setRenderer(PGraphicsOpenGL pg) { - this.pg = pg; + this.pg = new WeakReference(pg); } void set3D(boolean value) { @@ -10723,7 +10715,10 @@ public class PGraphicsOpenGL extends PGraphics { } void resetCurveVertexCount() { - pg.curveVertexCount = 0; + PGraphicsOpenGL g = pg.get(); + if (g != null) { + g.curveVertexCount = 0; + } } // ----------------------------------------------------------------- @@ -11003,8 +10998,9 @@ public class PGraphicsOpenGL extends PGraphics { } boolean clamp2D() { - return is2D && tess.renderMode == IMMEDIATE && - zero(pg.modelview.m01) && zero(pg.modelview.m10); + PGraphicsOpenGL g = pg.get(); + return is2D && tess.renderMode == IMMEDIATE && g != null && + zero(g.modelview.m01) && zero(g.modelview.m10); } boolean clampSquarePoints2D() { @@ -11679,10 +11675,13 @@ public class PGraphicsOpenGL extends PGraphics { } void unclampLine2D(int tessIdx, float x, float y) { - PMatrix3D mm = pg.modelview; - int index = 4 * tessIdx; - tess.polyVertices[index++] = x*mm.m00 + y*mm.m01 + mm.m03; - tess.polyVertices[index++] = x*mm.m10 + y*mm.m11 + mm.m13; + PGraphicsOpenGL g = pg.get(); + if (g != null) { + PMatrix3D mm = g.modelview; + int index = 4 * tessIdx; + tess.polyVertices[index++] = x*mm.m00 + y*mm.m01 + mm.m03; + tess.polyVertices[index++] = x*mm.m10 + y*mm.m11 + mm.m13; + } } boolean noCapsJoins(int nInVert) { @@ -12305,11 +12304,14 @@ public class PGraphicsOpenGL extends PGraphics { } void addBezierVertex(int i) { - pg.curveVertexCount = 0; - pg.bezierInitCheck(); - pg.bezierVertexCheck(POLYGON, i); + PGraphicsOpenGL g = pg.get(); + if (g == null) return; - PMatrix3D draw = pg.bezierDrawMatrix; + g.curveVertexCount = 0; + g.bezierInitCheck(); + g.bezierVertexCheck(POLYGON, i); + + PMatrix3D draw = g.bezierDrawMatrix; int i1 = i - 1; float x1 = in.vertices[3*i1 + 0]; @@ -12347,7 +12349,7 @@ public class PGraphicsOpenGL extends PGraphics { float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - for (int j = 0; j < pg.bezierDetail; j++) { + for (int j = 0; j < g.bezierDetail; j++) { x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; z1 += zplot1; zplot1 += zplot2; zplot2 += zplot3; @@ -12363,11 +12365,14 @@ public class PGraphicsOpenGL extends PGraphics { } void addQuadraticVertex(int i) { - pg.curveVertexCount = 0; - pg.bezierInitCheck(); - pg.bezierVertexCheck(POLYGON, i); + PGraphicsOpenGL g = pg.get(); + if (g == null) return; - PMatrix3D draw = pg.bezierDrawMatrix; + g.curveVertexCount = 0; + g.bezierInitCheck(); + g.bezierVertexCheck(POLYGON, i); + + PMatrix3D draw = g.bezierDrawMatrix; int i1 = i - 1; float x1 = in.vertices[3*i1 + 0]; @@ -12412,7 +12417,7 @@ public class PGraphicsOpenGL extends PGraphics { float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - for (int j = 0; j < pg.bezierDetail; j++) { + for (int j = 0; j < g.bezierDetail; j++) { x1 += xplot1; xplot1 += xplot2; xplot2 += xplot3; y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; z1 += zplot1; zplot1 += zplot2; zplot2 += zplot3; @@ -12428,24 +12433,27 @@ public class PGraphicsOpenGL extends PGraphics { } void addCurveVertex(int i) { - pg.curveVertexCheck(POLYGON); + PGraphicsOpenGL g = pg.get(); + if (g == null) return; - float[] vertex = pg.curveVertices[pg.curveVertexCount]; + g.curveVertexCheck(POLYGON); + + float[] vertex = g.curveVertices[g.curveVertexCount]; vertex[X] = in.vertices[3*i + 0]; vertex[Y] = in.vertices[3*i + 1]; vertex[Z] = in.vertices[3*i + 2]; - pg.curveVertexCount++; + g.curveVertexCount++; // draw a segment if there are enough points - if (pg.curveVertexCount == 3) { - float[] v = pg.curveVertices[pg.curveVertexCount - 2]; + if (g.curveVertexCount == 3) { + float[] v = g.curveVertices[g.curveVertexCount - 2]; addCurveInitialVertex(i, v[X], v[Y], v[Z]); } - if (pg.curveVertexCount > 3) { - float[] v1 = pg.curveVertices[pg.curveVertexCount - 4]; - float[] v2 = pg.curveVertices[pg.curveVertexCount - 3]; - float[] v3 = pg.curveVertices[pg.curveVertexCount - 2]; - float[] v4 = pg.curveVertices[pg.curveVertexCount - 1]; + if (g.curveVertexCount > 3) { + float[] v1 = g.curveVertices[g.curveVertexCount - 4]; + float[] v2 = g.curveVertices[g.curveVertexCount - 3]; + float[] v3 = g.curveVertices[g.curveVertexCount - 2]; + float[] v4 = g.curveVertices[g.curveVertexCount - 1]; addCurveVertexSegment(i, v1[X], v1[Y], v1[Z], v2[X], v2[Y], v2[Z], v3[X], v3[Y], v3[Z], @@ -12470,6 +12478,9 @@ public class PGraphicsOpenGL extends PGraphics { float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int strokeColor = 0; float strokeWeight = 0; if (stroke) { @@ -12483,7 +12494,7 @@ public class PGraphicsOpenGL extends PGraphics { float y = y2; float z = z2; - PMatrix3D draw = pg.curveDrawMatrix; + PMatrix3D draw = g.curveDrawMatrix; float xplot1 = draw.m10*x1 + draw.m11*x2 + draw.m12*x3 + draw.m13*x4; float xplot2 = draw.m20*x1 + draw.m21*x2 + draw.m22*x3 + draw.m23*x4; @@ -12497,7 +12508,7 @@ public class PGraphicsOpenGL extends PGraphics { float zplot2 = draw.m20*z1 + draw.m21*z2 + draw.m22*z3 + draw.m23*z4; float zplot3 = draw.m30*z1 + draw.m31*z2 + draw.m32*z3 + draw.m33*z4; - for (int j = 0; j < pg.curveDetail; j++) { + for (int j = 0; j < g.curveDetail; j++) { x += xplot1; xplot1 += xplot2; xplot2 += xplot3; y += yplot1; yplot1 += yplot2; yplot2 += yplot3; z += zplot1; zplot1 += zplot2; zplot2 += zplot3; @@ -12513,7 +12524,10 @@ public class PGraphicsOpenGL extends PGraphics { } void addVertex(int i) { - pg.curveVertexCount = 0; + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + + g.curveVertexCount = 0; float x = in.vertices[3*i + 0]; float y = in.vertices[3*i + 1]; @@ -12888,8 +12902,11 @@ public class PGraphicsOpenGL extends PGraphics { } public void error(int errnum) { - String estring = pg.pgl.tessError(errnum); - PGraphics.showWarning(TESSELLATION_ERROR, estring); + PGraphicsOpenGL g = pg.get(); + if (g != null) { + String estring = g.pgl.tessError(errnum); + PGraphics.showWarning(TESSELLATION_ERROR, estring); + } } /** diff --git a/core/src/processing/opengl/PJOGL.java b/core/src/processing/opengl/PJOGL.java index 5b5ed498b..d93cbc2f3 100644 --- a/core/src/processing/opengl/PJOGL.java +++ b/core/src/processing/opengl/PJOGL.java @@ -209,9 +209,12 @@ public class PJOGL extends PGL { @Override protected float getPixelScale() { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return 0; + PSurface surf = sketch.getSurface(); if (surf == null) { - return graphics.pixelDensity; + return g.pixelDensity; } else if (surf instanceof PSurfaceJOGL) { return ((PSurfaceJOGL)surf).getPixelScale(); } else { @@ -316,49 +319,52 @@ public class PJOGL extends PGL { @Override protected void beginGL() { + PGraphicsOpenGL g = graphics.get(); + if (g == null) return; + if (gl2x != null) { if (projMatrix == null) { projMatrix = new float[16]; } gl2x.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - projMatrix[ 0] = graphics.projection.m00; - projMatrix[ 1] = graphics.projection.m10; - projMatrix[ 2] = graphics.projection.m20; - projMatrix[ 3] = graphics.projection.m30; - projMatrix[ 4] = graphics.projection.m01; - projMatrix[ 5] = graphics.projection.m11; - projMatrix[ 6] = graphics.projection.m21; - projMatrix[ 7] = graphics.projection.m31; - projMatrix[ 8] = graphics.projection.m02; - projMatrix[ 9] = graphics.projection.m12; - projMatrix[10] = graphics.projection.m22; - projMatrix[11] = graphics.projection.m32; - projMatrix[12] = graphics.projection.m03; - projMatrix[13] = graphics.projection.m13; - projMatrix[14] = graphics.projection.m23; - projMatrix[15] = graphics.projection.m33; + projMatrix[ 0] = g.projection.m00; + projMatrix[ 1] = g.projection.m10; + projMatrix[ 2] = g.projection.m20; + projMatrix[ 3] = g.projection.m30; + projMatrix[ 4] = g.projection.m01; + projMatrix[ 5] = g.projection.m11; + projMatrix[ 6] = g.projection.m21; + projMatrix[ 7] = g.projection.m31; + projMatrix[ 8] = g.projection.m02; + projMatrix[ 9] = g.projection.m12; + projMatrix[10] = g.projection.m22; + projMatrix[11] = g.projection.m32; + projMatrix[12] = g.projection.m03; + projMatrix[13] = g.projection.m13; + projMatrix[14] = g.projection.m23; + projMatrix[15] = g.projection.m33; gl2x.glLoadMatrixf(projMatrix, 0); if (mvMatrix == null) { mvMatrix = new float[16]; } gl2x.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - mvMatrix[ 0] = graphics.modelview.m00; - mvMatrix[ 1] = graphics.modelview.m10; - mvMatrix[ 2] = graphics.modelview.m20; - mvMatrix[ 3] = graphics.modelview.m30; - mvMatrix[ 4] = graphics.modelview.m01; - mvMatrix[ 5] = graphics.modelview.m11; - mvMatrix[ 6] = graphics.modelview.m21; - mvMatrix[ 7] = graphics.modelview.m31; - mvMatrix[ 8] = graphics.modelview.m02; - mvMatrix[ 9] = graphics.modelview.m12; - mvMatrix[10] = graphics.modelview.m22; - mvMatrix[11] = graphics.modelview.m32; - mvMatrix[12] = graphics.modelview.m03; - mvMatrix[13] = graphics.modelview.m13; - mvMatrix[14] = graphics.modelview.m23; - mvMatrix[15] = graphics.modelview.m33; + mvMatrix[ 0] = g.modelview.m00; + mvMatrix[ 1] = g.modelview.m10; + mvMatrix[ 2] = g.modelview.m20; + mvMatrix[ 3] = g.modelview.m30; + mvMatrix[ 4] = g.modelview.m01; + mvMatrix[ 5] = g.modelview.m11; + mvMatrix[ 6] = g.modelview.m21; + mvMatrix[ 7] = g.modelview.m31; + mvMatrix[ 8] = g.modelview.m02; + mvMatrix[ 9] = g.modelview.m12; + mvMatrix[10] = g.modelview.m22; + mvMatrix[11] = g.modelview.m32; + mvMatrix[12] = g.modelview.m03; + mvMatrix[13] = g.modelview.m13; + mvMatrix[14] = g.modelview.m23; + mvMatrix[15] = g.modelview.m33; gl2x.glLoadMatrixf(mvMatrix, 0); } } diff --git a/core/src/processing/opengl/PShader.java b/core/src/processing/opengl/PShader.java index d24d1ae0a..310840779 100644 --- a/core/src/processing/opengl/PShader.java +++ b/core/src/processing/opengl/PShader.java @@ -27,6 +27,7 @@ package processing.opengl; import processing.core.*; import processing.opengl.PGraphicsOpenGL.GLResourceShader; +import java.lang.ref.WeakReference; import java.net.URL; import java.nio.FloatBuffer; import java.nio.IntBuffer; @@ -79,8 +80,8 @@ public class PShader implements PConstants { // be called by different renderers within a single application // (the one corresponding to the main surface, or other offscreen // renderers). - protected PGraphicsOpenGL primaryPG; - protected PGraphicsOpenGL currentPG; + protected WeakReference primaryPG; + protected WeakReference currentPG; protected PGL pgl; protected int context; // The context that created this shader. @@ -184,8 +185,9 @@ public class PShader implements PConstants { public PShader(PApplet parent) { this(); this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; + PGraphicsOpenGL g = (PGraphicsOpenGL)parent.g; + primaryPG = new WeakReference(g); + pgl = g.pgl; context = pgl.createEmptyContext(); } @@ -200,8 +202,9 @@ public class PShader implements PConstants { */ public PShader(PApplet parent, String vertFilename, String fragFilename) { this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; + PGraphicsOpenGL g = (PGraphicsOpenGL)parent.g; + primaryPG = new WeakReference(g); + pgl = g.pgl; this.vertexURL = null; this.fragmentURL = null; @@ -239,8 +242,9 @@ public class PShader implements PConstants { */ public PShader(PApplet parent, URL vertURL, URL fragURL) { this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; + PGraphicsOpenGL g = (PGraphicsOpenGL)parent.g; + primaryPG = new WeakReference(g); + pgl = g.pgl; this.vertexURL = vertURL; this.fragmentURL = fragURL; @@ -273,8 +277,9 @@ public class PShader implements PConstants { public PShader(PApplet parent, String[] vertSource, String[] fragSource) { this.parent = parent; - primaryPG = (PGraphicsOpenGL)parent.g; - pgl = primaryPG.pgl; + PGraphicsOpenGL g = (PGraphicsOpenGL)parent.g; + primaryPG = new WeakReference(g); + pgl = g.pgl; this.vertexURL = null; this.fragmentURL = null; @@ -819,7 +824,9 @@ public class PShader implements PConstants { pgl.uniformMatrix4fv(loc, 1, false, floatBuffer); } else if (val.type == UniformValue.SAMPLER2D) { PImage img = (PImage)val.value; - Texture tex = currentPG.getTexture(img); + PGraphicsOpenGL g = currentPG.get(); + if (g == null) return; + Texture tex = g.getTexture(img); if (textures == null) textures = new HashMap(); textures.put(loc, tex); @@ -1126,7 +1133,7 @@ public class PShader implements PConstants { protected void setRenderer(PGraphicsOpenGL pg) { - this.currentPG = pg; + this.currentPG = new WeakReference(pg); } @@ -1199,26 +1206,29 @@ public class PShader implements PConstants { protected void setCommonUniforms() { + PGraphicsOpenGL g = currentPG.get(); + if (g == null) return; + if (-1 < transformMatLoc) { - currentPG.updateGLProjmodelview(); - setUniformMatrix(transformMatLoc, currentPG.glProjmodelview); + g.updateGLProjmodelview(); + setUniformMatrix(transformMatLoc, g.glProjmodelview); } if (-1 < modelviewMatLoc) { - currentPG.updateGLModelview(); - setUniformMatrix(modelviewMatLoc, currentPG.glModelview); + g.updateGLModelview(); + setUniformMatrix(modelviewMatLoc, g.glModelview); } if (-1 < projectionMatLoc) { - currentPG.updateGLProjection(); - setUniformMatrix(projectionMatLoc, currentPG.glProjection); + g.updateGLProjection(); + setUniformMatrix(projectionMatLoc, g.glProjection); } if (-1 < viewportLoc) { - float x = currentPG.viewport.get(0); - float y = currentPG.viewport.get(1); - float w = currentPG.viewport.get(2); - float h = currentPG.viewport.get(3); + float x = g.viewport.get(0); + float y = g.viewport.get(1); + float w = g.viewport.get(2); + float h = g.viewport.get(3); setUniformValue(viewportLoc, x, y, w, h); } @@ -1226,7 +1236,7 @@ public class PShader implements PConstants { ppixelsUnit = getLastTexUnit() + 1; setUniformValue(ppixelsLoc, ppixelsUnit); pgl.activeTexture(PGL.TEXTURE0 + ppixelsUnit); - currentPG.bindFrontTexture(); + g.bindFrontTexture(); } else { ppixelsUnit = -1; } @@ -1234,12 +1244,15 @@ public class PShader implements PConstants { protected void bindTyped() { + PGraphicsOpenGL pg = primaryPG.get(); if (currentPG == null) { - setRenderer(primaryPG.getCurrentPG()); + setRenderer(pg.getCurrentPG()); loadAttributes(); loadUniforms(); } setCommonUniforms(); + PGraphicsOpenGL g = currentPG.get(); + if (g == null) return; if (-1 < vertexLoc) pgl.enableVertexAttribArray(vertexLoc); if (-1 < colorLoc) pgl.enableVertexAttribArray(colorLoc); @@ -1247,8 +1260,8 @@ public class PShader implements PConstants { if (-1 < normalLoc) pgl.enableVertexAttribArray(normalLoc); if (-1 < normalMatLoc) { - currentPG.updateGLNormal(); - setUniformMatrix(normalMatLoc, currentPG.glNormal); + g.updateGLNormal(); + setUniformMatrix(normalMatLoc, g.glNormal); } if (-1 < ambientLoc) pgl.enableVertexAttribArray(ambientLoc); @@ -1256,17 +1269,17 @@ public class PShader implements PConstants { if (-1 < emissiveLoc) pgl.enableVertexAttribArray(emissiveLoc); if (-1 < shininessLoc) pgl.enableVertexAttribArray(shininessLoc); - int count = currentPG.lightCount; + int count = g.lightCount; setUniformValue(lightCountLoc, count); if (0 < count) { - setUniformVector(lightPositionLoc, currentPG.lightPosition, 4, count); - setUniformVector(lightNormalLoc, currentPG.lightNormal, 3, count); - setUniformVector(lightAmbientLoc, currentPG.lightAmbient, 3, count); - setUniformVector(lightDiffuseLoc, currentPG.lightDiffuse, 3, count); - setUniformVector(lightSpecularLoc, currentPG.lightSpecular, 3, count); - setUniformVector(lightFalloffLoc, currentPG.lightFalloffCoefficients, + setUniformVector(lightPositionLoc, g.lightPosition, 4, count); + setUniformVector(lightNormalLoc, g.lightNormal, 3, count); + setUniformVector(lightAmbientLoc, g.lightAmbient, 3, count); + setUniformVector(lightDiffuseLoc, g.lightDiffuse, 3, count); + setUniformVector(lightSpecularLoc, g.lightSpecular, 3, count); + setUniformVector(lightFalloffLoc, g.lightFalloffCoefficients, 3, count); - setUniformVector(lightSpotLoc, currentPG.lightSpotParameters, 2, count); + setUniformVector(lightSpotLoc, g.lightSpotParameters, 2, count); } if (-1 < directionLoc) pgl.enableVertexAttribArray(directionLoc); @@ -1274,8 +1287,8 @@ public class PShader implements PConstants { if (-1 < offsetLoc) pgl.enableVertexAttribArray(offsetLoc); if (-1 < perspectiveLoc) { - if (currentPG.getHint(ENABLE_STROKE_PERSPECTIVE) && - currentPG.nonOrthoProjection()) { + if (g.getHint(ENABLE_STROKE_PERSPECTIVE) && + g.nonOrthoProjection()) { setUniformValue(perspectiveLoc, 1); } else { setUniformValue(perspectiveLoc, 0); @@ -1283,11 +1296,11 @@ public class PShader implements PConstants { } if (-1 < scaleLoc) { - if (currentPG.getHint(DISABLE_OPTIMIZED_STROKE)) { + if (g.getHint(DISABLE_OPTIMIZED_STROKE)) { setUniformValue(scaleLoc, 1.0f, 1.0f, 1.0f); } else { float f = PGL.STROKE_DISPLACEMENT; - if (currentPG.orthoProjection()) { + if (g.orthoProjection()) { setUniformValue(scaleLoc, 1, 1, f); } else { setUniformValue(scaleLoc, f, f, f); @@ -1297,6 +1310,9 @@ public class PShader implements PConstants { } protected void unbindTyped() { + PGraphicsOpenGL g = currentPG.get(); + if (g == null) return; + if (-1 < offsetLoc) pgl.disableVertexAttribArray(offsetLoc); if (-1 < directionLoc) pgl.disableVertexAttribArray(directionLoc); @@ -1321,7 +1337,7 @@ public class PShader implements PConstants { if (-1 < ppixelsLoc) { pgl.enableFBOLayer(); pgl.activeTexture(PGL.TEXTURE0 + ppixelsUnit); - currentPG.unbindFrontTexture(); + g.unbindFrontTexture(); pgl.activeTexture(PGL.TEXTURE0); } diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index 2c9492ec2..a9defa8d5 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -40,6 +40,7 @@ import processing.opengl.PGraphicsOpenGL.TessGeometry; import processing.opengl.PGraphicsOpenGL.Tessellator; import processing.opengl.PGraphicsOpenGL.VertexAttribute; +import java.lang.ref.WeakReference; import java.nio.Buffer; import java.util.Arrays; import java.util.HashSet; @@ -75,7 +76,7 @@ public class PShapeOpenGL extends PShape { static protected final int SCALE = 2; static protected final int MATRIX = 3; - protected PGraphicsOpenGL pg; + protected WeakReference pg; protected PGL pgl; protected int context; // The context that created this shape. @@ -325,7 +326,7 @@ public class PShapeOpenGL extends PShape { public PShapeOpenGL(PGraphicsOpenGL pg, int family) { - this.pg = pg; + this.pg = new WeakReference(pg); this.family = family; pgl = pg.pgl; @@ -1127,13 +1128,16 @@ public class PShapeOpenGL extends PShape { protected VertexAttribute attribImpl(String name, int kind, int type, int size) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return null; + if (4 < size) { PGraphics.showWarning("Vertex attributes cannot have more than 4 values"); return null; } VertexAttribute attrib = polyAttribs.get(name); if (attrib == null) { - attrib = new VertexAttribute(pg, name, kind, type, size); + attrib = new VertexAttribute(g, name, kind, type, size); polyAttribs.put(name, attrib); inGeo.initAttrib(attrib); } @@ -2485,6 +2489,9 @@ public class PShapeOpenGL extends PShape { @Override public PShape getTessellation() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return null; + updateTessellation(); float[] vertices = tessGeo.polyVertices; @@ -2504,7 +2511,7 @@ public class PShapeOpenGL extends PShape { // PGraphics.showWarning("This shape is not either 2D or 3D!"); // return null; // } - tess = pg.createShapeFamily(PShape.GEOMETRY); + tess = g.createShapeFamily(PShape.GEOMETRY); tess.set3D(is3D); // if this is a 3D shape, make the new shape 3D as well tess.beginShape(TRIANGLES); tess.noStroke(); @@ -2754,6 +2761,9 @@ public class PShapeOpenGL extends PShape { protected void tessellate() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + if (root == this && parent == null) { // Root shape if (polyAttribs == null) { polyAttribs = PGraphicsOpenGL.newAttributeMap(); @@ -2761,7 +2771,7 @@ public class PShapeOpenGL extends PShape { } if (tessGeo == null) { - tessGeo = PGraphicsOpenGL.newTessGeometry(pg, polyAttribs, PGraphicsOpenGL.RETAINED); + tessGeo = PGraphicsOpenGL.newTessGeometry(g, polyAttribs, PGraphicsOpenGL.RETAINED); } tessGeo.clear(); for (int i = 0; i < polyAttribs.size(); i++) { @@ -2804,6 +2814,9 @@ public class PShapeOpenGL extends PShape { } protected void tessellateImpl() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + tessGeo = root.tessGeo; firstPolyIndexCache = -1; @@ -2835,7 +2848,7 @@ public class PShapeOpenGL extends PShape { tessellator.setStrokeWeight(strokeWeight); tessellator.setStrokeCap(strokeCap); tessellator.setStrokeJoin(strokeJoin); - tessellator.setRenderer(pg); + tessellator.setRenderer(g); tessellator.setTransform(matrix); tessellator.set3D(is3D()); @@ -3245,6 +3258,9 @@ public class PShapeOpenGL extends PShape { protected void tessellateSphere() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + float r = 0; int nu = sphereDetailU; int nv = sphereDetailV; @@ -3261,10 +3277,10 @@ public class PShapeOpenGL extends PShape { if (nu < 3 || nv < 2) { nu = nv = 30; } - int savedDetailU = pg.sphereDetailU; - int savedDetailV = pg.sphereDetailV; - if (pg.sphereDetailU != nu || pg.sphereDetailV != nv) { - pg.sphereDetail(nu, nv); + int savedDetailU = g.sphereDetailU; + int savedDetailV = g.sphereDetailV; + if (g.sphereDetailU != nu || g.sphereDetailV != nv) { + g.sphereDetail(nu, nv); } inGeo.setMaterial(fillColor, strokeColor, strokeWeight, @@ -3273,7 +3289,7 @@ public class PShapeOpenGL extends PShape { tessellator.tessellateTriangles(indices); if (savedDetailU != nu || savedDetailV != nv) { - pg.sphereDetail(savedDetailU, savedDetailV); + g.sphereDetail(savedDetailU, savedDetailV); } } @@ -3405,35 +3421,47 @@ public class PShapeOpenGL extends PShape { } protected void saveBezierVertexSettings() { - savedBezierDetail = pg.bezierDetail; - if (pg.bezierDetail != bezierDetail) { - pg.bezierDetail(bezierDetail); + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + + savedBezierDetail = g.bezierDetail; + if (g.bezierDetail != bezierDetail) { + g.bezierDetail(bezierDetail); } } protected void restoreBezierVertexSettings() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + if (savedBezierDetail != bezierDetail) { - pg.bezierDetail(savedBezierDetail); + g.bezierDetail(savedBezierDetail); } } protected void saveCurveVertexSettings() { - savedCurveDetail = pg.curveDetail; - savedCurveTightness = pg.curveTightness; - if (pg.curveDetail != curveDetail) { - pg.curveDetail(curveDetail); + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + + savedCurveDetail = g.curveDetail; + savedCurveTightness = g.curveTightness; + if (g.curveDetail != curveDetail) { + g.curveDetail(curveDetail); } - if (pg.curveTightness != curveTightness) { - pg.curveTightness(curveTightness); + if (g.curveTightness != curveTightness) { + g.curveTightness(curveTightness); } } protected void restoreCurveVertexSettings() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + if (savedCurveDetail != curveDetail) { - pg.curveDetail(savedCurveDetail); + g.curveDetail(savedCurveDetail); } if (savedCurveTightness != curveTightness) { - pg.curveTightness(savedCurveTightness); + g.curveTightness(savedCurveTightness); } } @@ -3830,6 +3858,9 @@ public class PShapeOpenGL extends PShape { protected void initPolyBuffers() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int size = tessGeo.polyVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; @@ -3837,7 +3868,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyVerticesBuffer(); if (bufPolyVertex == null) // glPolyVertex = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyVertex = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); + bufPolyVertex = new VertexBuffer(g, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyVertex.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, tessGeo.polyVerticesBuffer, glUsage); @@ -3845,7 +3876,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyColorsBuffer(); if (bufPolyColor == null) // glPolyColor = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyColor = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); + bufPolyColor = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyColor.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, tessGeo.polyColorsBuffer, glUsage); @@ -3853,7 +3884,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyNormalsBuffer(); if (bufPolyNormal == null) // glPolyNormal = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyNormal = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); + bufPolyNormal = new VertexBuffer(g, PGL.ARRAY_BUFFER, 3, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyNormal.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 3 * sizef, tessGeo.polyNormalsBuffer, glUsage); @@ -3861,7 +3892,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyTexCoordsBuffer(); if (bufPolyTexcoord == null) // glPolyTexcoord = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyTexcoord = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); + bufPolyTexcoord = new VertexBuffer(g, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyTexcoord.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, tessGeo.polyTexCoordsBuffer, glUsage); @@ -3869,7 +3900,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyAmbientBuffer(); if (bufPolyAmbient == null) // glPolyAmbient = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyAmbient = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); + bufPolyAmbient = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyAmbient.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, tessGeo.polyAmbientBuffer, glUsage); @@ -3877,7 +3908,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolySpecularBuffer(); if (bufPolySpecular == null) // glPolySpecular = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolySpecular = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); + bufPolySpecular = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolySpecular.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, tessGeo.polySpecularBuffer, glUsage); @@ -3885,7 +3916,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyEmissiveBuffer(); if (bufPolyEmissive == null) // glPolyEmissive = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyEmissive = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); + bufPolyEmissive = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyEmissive.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, tessGeo.polyEmissiveBuffer, glUsage); @@ -3893,7 +3924,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyShininessBuffer(); if (bufPolyShininess == null) // glPolyShininess = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyShininess = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_FLOAT); + bufPolyShininess = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPolyShininess.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizef, tessGeo.polyShininessBuffer, glUsage); @@ -3912,7 +3943,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePolyIndicesBuffer(); if (bufPolyIndex == null) // glPolyIndex = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPolyIndex = new VertexBuffer(pg, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); + bufPolyIndex = new VertexBuffer(g, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufPolyIndex.glId); pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, tessGeo.polyIndexCount * PGL.SIZEOF_INDEX, @@ -3923,6 +3954,9 @@ public class PShapeOpenGL extends PShape { protected void initLineBuffers() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int size = tessGeo.lineVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; @@ -3930,7 +3964,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updateLineVerticesBuffer(); if (bufLineVertex == null) // glLineVertex = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufLineVertex = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); + bufLineVertex = new VertexBuffer(g, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineVertex.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, tessGeo.lineVerticesBuffer, glUsage); @@ -3938,7 +3972,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updateLineColorsBuffer(); if (bufLineColor == null) // glLineColor = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufLineColor = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); + bufLineColor = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineColor.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, tessGeo.lineColorsBuffer, glUsage); @@ -3946,7 +3980,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updateLineDirectionsBuffer(); if (bufLineAttrib == null) // glLineAttrib = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufLineAttrib = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); + bufLineAttrib = new VertexBuffer(g, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufLineAttrib.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, tessGeo.lineDirectionsBuffer, glUsage); @@ -3956,7 +3990,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updateLineIndicesBuffer(); if (bufLineIndex == null) // glLineIndex = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufLineIndex = new VertexBuffer(pg, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); + bufLineIndex = new VertexBuffer(g, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufLineIndex.glId); pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, tessGeo.lineIndexCount * PGL.SIZEOF_INDEX, @@ -3967,6 +4001,9 @@ public class PShapeOpenGL extends PShape { protected void initPointBuffers() { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + int size = tessGeo.pointVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; @@ -3974,7 +4011,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePointVerticesBuffer(); if (bufPointVertex == null) // glPointVertex = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPointVertex = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); + bufPointVertex = new VertexBuffer(g, PGL.ARRAY_BUFFER, 4, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointVertex.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 4 * sizef, tessGeo.pointVerticesBuffer, glUsage); @@ -3982,7 +4019,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePointColorsBuffer(); if (bufPointColor == null) // glPointColor = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPointColor = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); + bufPointColor = new VertexBuffer(g, PGL.ARRAY_BUFFER, 1, PGL.SIZEOF_INT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointColor.glId); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, tessGeo.pointColorsBuffer, glUsage); @@ -3990,7 +4027,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePointOffsetsBuffer(); if (bufPointAttrib == null) // glPointAttrib = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPointAttrib = new VertexBuffer(pg, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); + bufPointAttrib = new VertexBuffer(g, PGL.ARRAY_BUFFER, 2, PGL.SIZEOF_FLOAT); pgl.bindBuffer(PGL.ARRAY_BUFFER, bufPointAttrib.glId); pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, tessGeo.pointOffsetsBuffer, glUsage); @@ -4000,7 +4037,7 @@ public class PShapeOpenGL extends PShape { tessGeo.updatePointIndicesBuffer(); if (bufPointIndex == null) // glPointIndex = PGraphicsOpenGL.createVertexBufferObject(context, pgl); - bufPointIndex = new VertexBuffer(pg, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); + bufPointIndex = new VertexBuffer(g, PGL.ELEMENT_ARRAY_BUFFER, 1, PGL.SIZEOF_INDEX, true); pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, bufPointIndex.glId); pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, tessGeo.pointIndexCount * PGL.SIZEOF_INDEX, diff --git a/core/src/processing/opengl/Texture.java b/core/src/processing/opengl/Texture.java index 4c5b85641..aecf87689 100644 --- a/core/src/processing/opengl/Texture.java +++ b/core/src/processing/opengl/Texture.java @@ -29,6 +29,7 @@ import processing.core.PConstants; import processing.core.PGraphics; import processing.opengl.PGraphicsOpenGL.GLResourceTexture; +import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -90,7 +91,7 @@ public class Texture implements PConstants { public int glHeight; private GLResourceTexture glres; - protected PGraphicsOpenGL pg; + protected WeakReference pg; protected PGL pgl; // The interface between Processing and OpenGL. protected int context; // The context that created this texture. protected boolean colorBuffer; // true if it is the color attachment of @@ -131,7 +132,7 @@ public class Texture implements PConstants { public Texture(PGraphicsOpenGL pg) { - this.pg = pg; + this.pg = new WeakReference(pg); pgl = pg.pgl; context = pgl.createEmptyContext(); @@ -160,7 +161,7 @@ public class Texture implements PConstants { * @param params Parameters */ public Texture(PGraphicsOpenGL pg, int width, int height, Object params) { - this.pg = pg; + this.pg = new WeakReference(pg); pgl = pg.pgl; context = pgl.createEmptyContext(); @@ -246,12 +247,15 @@ public class Texture implements PConstants { public void resize(int wide, int high) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + // Marking the texture object as finalized so it is deleted // when creating the new texture. dispose(); // Creating new texture with the appropriate size. - Texture tex = new Texture(pg, wide, high, getParameters()); + Texture tex = new Texture(g, wide, high, getParameters()); // Copying the contents of this texture into tex. tex.set(this); @@ -437,6 +441,9 @@ public class Texture implements PConstants { * Copy texture to pixels. Involves video memory to main memory transfer (slow). */ public void get(int[] pixels) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + if (pixels == null) { throw new RuntimeException("Trying to copy texture to null pixels array"); } @@ -446,17 +453,17 @@ public class Texture implements PConstants { } if (tempFbo == null) { - tempFbo = new FrameBuffer(pg, glWidth, glHeight); + tempFbo = new FrameBuffer(g, glWidth, glHeight); } // Attaching the texture to the color buffer of a FBO, binding the FBO and // reading the pixels from the current draw buffer (which is the color // buffer of the FBO). tempFbo.setColorBuffer(this); - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); + g.pushFramebuffer(); + g.setFramebuffer(tempFbo); tempFbo.readPixels(); - pg.popFramebuffer(); + g.popFramebuffer(); tempFbo.getPixels(pixels); convertToARGB(pixels); @@ -1214,12 +1221,15 @@ public class Texture implements PConstants { // Copies source texture tex into this. protected void copyTexture(Texture tex, int x, int y, int w, int h, boolean scale) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + if (tex == null) { throw new RuntimeException("Source texture is null"); } if (tempFbo == null) { - tempFbo = new FrameBuffer(pg, glWidth, glHeight); + tempFbo = new FrameBuffer(g, glWidth, glHeight); } // This texture is the color (destination) buffer of the FBO. @@ -1227,8 +1237,8 @@ public class Texture implements PConstants { tempFbo.disableDepthTest(); // FBO copy: - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); + g.pushFramebuffer(); + g.setFramebuffer(tempFbo); // Clear the color buffer to make sure that the alpha channel is set to // full transparency pgl.clearColor(0, 0, 0, 0); @@ -1248,7 +1258,7 @@ public class Texture implements PConstants { 0, 0, tempFbo.width, tempFbo.height, 1, x, y, x + w, y + h, x, y, x + w, y + h); } - pg.popFramebuffer(); + g.popFramebuffer(); updateTexels(x, y, w, h); } @@ -1258,8 +1268,11 @@ public class Texture implements PConstants { protected void copyTexture(int texTarget, int texName, int texWidth, int texHeight, int x, int y, int w, int h, boolean scale) { + PGraphicsOpenGL g = pg.get(); + if (g == null) return; + if (tempFbo == null) { - tempFbo = new FrameBuffer(pg, glWidth, glHeight); + tempFbo = new FrameBuffer(g, glWidth, glHeight); } // This texture is the color (destination) buffer of the FBO. @@ -1267,8 +1280,8 @@ public class Texture implements PConstants { tempFbo.disableDepthTest(); // FBO copy: - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); + g.pushFramebuffer(); + g.setFramebuffer(tempFbo); if (scale) { // Rendering tex into "this", and scaling the source rectangle // to cover the entire destination region. @@ -1284,7 +1297,7 @@ public class Texture implements PConstants { 0, 0, tempFbo.width, tempFbo.height, x, y, w, h, x, y, w, h); } - pg.popFramebuffer(); + g.popFramebuffer(); updateTexels(x, y, w, h); }