use weak references to PGraphicsOpenGL instances in resource classes

(framebuffers, texture, etc), should take care of #3858
This commit is contained in:
codeanticode
2015-09-24 16:51:44 -05:00
parent 4755283b3e
commit f379d4dd2f
8 changed files with 567 additions and 425 deletions

View File

@@ -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<PGraphicsOpenGL> 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<PGraphicsOpenGL>(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);