Fixed some issues in the reallocation/refreshing mechanism

This commit is contained in:
codeanticode
2011-07-02 08:32:53 +00:00
parent 28b9ee81bb
commit ae2ff779c2
5 changed files with 235 additions and 175 deletions

View File

@@ -86,7 +86,7 @@ class PFontTexture implements PConstants {
public void refresh() {
// loop over current glyphs.
for (int i = 0; i < font.getGlyphCount(); i++) {
for (int i = 0; i < PApplet.min(font.getGlyphCount(), glyphTexinfos.length); i++) {
TextureInfo tinfo = glyphTexinfos[i];
textures[tinfo.texIndex].bind();
tinfo.updateTex();

View File

@@ -60,8 +60,6 @@ public class PFramebuffer implements PConstants {
protected int numColorBuffers;
protected int[] colorBufferAttchPoints;
protected int[] glColorBufferTargets; // should remove this?
protected int[] glColorBufferIDs; // should remove this?
protected PTexture[] colorBufferTex;
protected boolean screenFb;
@@ -94,8 +92,46 @@ public class PFramebuffer implements PConstants {
fboMode = PGraphicsOpenGL.fboSupported;
allocate(w, h, samples, colorBuffers, depthBits, stencilBits,
combinedDepthStencil, screen);
width = w;
height = h;
if (1 < samples) {
multisample = true;
nsamples = samples;
} else {
multisample = false;
nsamples = 1;
}
numColorBuffers = colorBuffers;
colorBufferAttchPoints = new int[numColorBuffers];
colorBufferTex = new PTexture[numColorBuffers];
for (int i = 0; i < numColorBuffers; i++) {
colorBufferAttchPoints[i] = GL.GL_COLOR_ATTACHMENT0 + i;
colorBufferTex[i] = null;
}
if (depthBits < 1 && stencilBits < 1) {
this.depthBits = 0;
this.stencilBits = 0;
this.combinedDepthStencil = false;
} else {
if (combinedDepthStencil) {
// When combined depth/stencil format is required, the depth and stencil bits
// are overriden and the 24/8 combination for a 32 bits surface is used.
this.depthBits = 24;
this.stencilBits = 8;
this.combinedDepthStencil = true;
} else {
this.depthBits = depthBits;
this.stencilBits = stencilBits;
this.combinedDepthStencil = false;
}
}
screenFb = screen;
allocate();
noDepth = false;
pixelBuffer = null;
@@ -149,7 +185,7 @@ public class PFramebuffer implements PConstants {
if (0 < numColorBuffers) {
// Drawing the current contents of the first color buffer to emulate
// front-back buffer swap.
ogl.drawTexture(glColorBufferTargets[0], glColorBufferIDs[0], width, height, 0, 0, width, height, 0, 0, width, height);
ogl.drawTexture(colorBufferTex[0].glTarget, colorBufferTex[0].glID, width, height, 0, 0, width, height, 0, 0, width, height);
}
if (noDepth) {
@@ -206,7 +242,7 @@ public class PFramebuffer implements PConstants {
if (pixelBuffer == null) createPixelBuffer();
getGl().glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixelBuffer);
for (int i = 0; i < numColorBuffers; i++) {
copyToTexture(pixelBuffer, glColorBufferIDs[i], glColorBufferTargets[i]);
copyToTexture(pixelBuffer, colorBufferTex[i].glID, colorBufferTex[i].glTarget);
}
}
@@ -248,11 +284,15 @@ public class PFramebuffer implements PConstants {
public void setColorBuffers(PTexture[] textures, int n) {
if (screenFb) return;
if (numColorBuffers != PApplet.min(n, textures.length)) {
throw new RuntimeException("Wrong number of textures to set the color buffers.");
}
for (int i = 0; i < numColorBuffers; i++) {
colorBufferTex[i] = textures[i];
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
@@ -264,11 +304,8 @@ public class PFramebuffer implements PConstants {
}
for (int i = 0; i < numColorBuffers; i++) {
this.colorBufferTex[i] = textures[i];
glColorBufferTargets[i] = textures[i].glTarget;
glColorBufferIDs[i] = textures[i].glID;
getGl().glFramebufferTexture2D(GL.GL_FRAMEBUFFER, colorBufferAttchPoints[i],
glColorBufferTargets[i], glColorBufferIDs[i], 0);
colorBufferTex[i].glTarget, colorBufferTex[i].glID, 0);
}
if (validFbo() && textures != null && 0 < textures.length) {
@@ -277,11 +314,6 @@ public class PFramebuffer implements PConstants {
}
ogl.popFramebuffer();
} else {
for (int i = 0; i < numColorBuffers; i++) {
glColorBufferTargets[i] = textures[i].glTarget;
glColorBufferIDs[i] = textures[i].glID;
}
}
}
@@ -290,52 +322,8 @@ public class PFramebuffer implements PConstants {
// Allocate/release framebuffer.
protected void allocate(int w, int h, int samples, int colorBuffers,
int depthBits, int stencilBits, boolean combinedDepthStencil,
boolean screen) {
release(); // Just in the case this object is being re-allocated.
width = w;
height = h;
if (1 < samples) {
multisample = true;
nsamples = samples;
} else {
multisample = false;
nsamples = 1;
}
numColorBuffers = colorBuffers;
colorBufferAttchPoints = new int[numColorBuffers];
glColorBufferTargets = new int[numColorBuffers];
glColorBufferIDs = new int[numColorBuffers];
colorBufferTex = new PTexture[numColorBuffers];
for (int i = 0; i < numColorBuffers; i++) {
colorBufferAttchPoints[i] = GL.GL_COLOR_ATTACHMENT0 + i;
glColorBufferIDs[i] = 0;
colorBufferTex[i] = null;
}
if (depthBits < 1 && stencilBits < 1) {
this.depthBits = 0;
this.stencilBits = 0;
this.combinedDepthStencil = false;
} else {
if (combinedDepthStencil) {
// When combined depth/stencil format is required, the depth and stencil bits
// are overriden and the 24/8 combination for a 32 bits surface is used.
this.depthBits = 24;
this.stencilBits = 8;
this.combinedDepthStencil = true;
} else {
this.depthBits = depthBits;
this.stencilBits = stencilBits;
this.combinedDepthStencil = false;
}
}
screenFb = screen;
protected void allocate() {
release(); // Just in the case this object is being re-allocated.
if (screenFb) {
glFboID = 0;
@@ -359,23 +347,16 @@ public class PFramebuffer implements PConstants {
if (0 < stencilBits) {
createStencilBuffer();
}
}
}
}
protected void reallocate() {
allocate(width, height, nsamples, numColorBuffers,
depthBits, stencilBits, combinedDepthStencil,
screenFb);
}
protected void release() {
deleteFbo();
deleteDepthBuffer();
deleteStencilBuffer();
deleteCombinedDepthStencilBuffer();
deleteColorBufferMultisample();
width = height = 0;
deleteColorBufferMultisample();
}
@@ -426,15 +407,11 @@ public class PFramebuffer implements PConstants {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
numColorBuffers = 1;
colorBufferAttchPoints = new int[numColorBuffers];
colorBufferAttchPoints[0] = GL.GL_COLOR_ATTACHMENT0;
glColorBufferMultisampleID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glColorBufferMultisampleID);
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples,
GL.GL_RGBA8, width, height);
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, colorBufferAttchPoints[0],
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0,
GL.GL_RENDERBUFFER, glColorBufferMultisampleID);
ogl.popFramebuffer();

View File

@@ -680,7 +680,7 @@ public class PGraphicsOpenGL extends PGraphics {
// that the context has been recreated, so we need to re-allocate them in
// order to be able to keep using them. This step doesn't refresh their data, this
// is, they are empty after re-allocation.
reallocateGLObjects();
allocateGLObjects();
} else {
reapplySettings();
}
@@ -719,16 +719,16 @@ public class PGraphicsOpenGL extends PGraphics {
// RESOURCE HANDLING
protected void reallocateGLObjects() {
protected void allocateGLObjects() {
if (!glObjects.isEmpty()) {
Object[] globjs = glObjects.toArray();
for (int i = 0; i < globjs.length; i++) {
if (globjs[i] instanceof PTexture) {
((PTexture)globjs[i]).reallocate();
((PTexture)globjs[i]).allocate();
} else if (globjs[i] instanceof PShape3D) {
((PShape3D)globjs[i]).reallocate();
((PShape3D)globjs[i]).allocate();
} else if (globjs[i] instanceof PFramebuffer) {
((PFramebuffer)globjs[i]).reallocate();
((PFramebuffer)globjs[i]).allocate();
} else if (globjs[i] instanceof PFontTexture) {
// No need to do reallocation for a PFontTexture, since its
// textures will reallocate themselves.
@@ -737,6 +737,40 @@ public class PGraphicsOpenGL extends PGraphics {
}
}
protected void updateGLObjects() {
if (!glObjects.isEmpty()) {
Object[] globjs = glObjects.toArray();
for (int i = 0; i < globjs.length; i++) {
if (globjs[i] instanceof PTexture) {
((PTexture)globjs[i]).update();
} else if (globjs[i] instanceof PShape3D) {
//((PShape3D)globjs[i]).refresh();
} else if (globjs[i] instanceof PFramebuffer) {
//((PFramebuffer)globjs[i]).refresh();
} else if (globjs[i] instanceof PFontTexture) {
//((PFontTexture)globjs[i]).refresh();
}
}
}
}
protected void refreshGLObjects() {
if (!glObjects.isEmpty()) {
Object[] globjs = glObjects.toArray();
for (int i = 0; i < globjs.length; i++) {
if (globjs[i] instanceof PTexture) {
((PTexture)globjs[i]).refresh();
} else if (globjs[i] instanceof PShape3D) {
((PShape3D)globjs[i]).refresh();
} else if (globjs[i] instanceof PFramebuffer) {
((PFramebuffer)globjs[i]).refresh();
} else if (globjs[i] instanceof PFontTexture) {
((PFontTexture)globjs[i]).refresh();
}
}
}
}
protected void registerGLObject(Object obj) {
glObjects.add(obj);
}
@@ -1126,26 +1160,16 @@ public class PGraphicsOpenGL extends PGraphics {
}
public void reallocateGL() {
reallocateGLObjects();
public void allocateGL() {
allocateGLObjects();
}
public void updateGL() {
updateGLObjects();
}
public void refreshGL() {
if (!glObjects.isEmpty()) {
Object[] globjs = glObjects.toArray();
for (int i = 0; i < globjs.length; i++) {
if (globjs[i] instanceof PTexture) {
((PTexture)globjs[i]).refresh();
} else if (globjs[i] instanceof PShape3D) {
((PShape3D)globjs[i]).refresh();
} else if (globjs[i] instanceof PFramebuffer) {
((PFramebuffer)globjs[i]).refresh();
} else if (globjs[i] instanceof PFontTexture) {
((PFontTexture)globjs[i]).refresh();
}
}
}
refreshGLObjects();
}
protected void saveGLState() {
@@ -5724,7 +5748,18 @@ return width * (1 + ox) / 2.0f;
pixelBuffer.rewind();
}
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
pushFramebuffer();
setFramebuffer(offscreenFramebuffer);
}
gl.glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixelBuffer);
if (notCurrent) {
popFramebuffer();
}
pixelBuffer.get(pixels);
pixelBuffer.rewind();
@@ -6004,8 +6039,24 @@ return width * (1 + ox) / 2.0f;
// Copying pixel buffer to screen texture...
copyToTexture(pixelBuffer);
// ...and drawing the texture to screen.
drawTexture(texture, texCrop, 0, 0, width, height);
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
// If this is an offscreen surface that is not current, then the offscreen framebuffer
// is bound so the texture is drawn to it instead to the main surface. Even if the
// surface in antialiased we don't need to bind the multisample framebuffer, we
// just draw to the regular offscreen framebuffer.
pushFramebuffer();
setFramebuffer(offscreenFramebuffer);
}
drawTexture(texture, texCrop, 0, 0, width, height);
if (notCurrent) {
popFramebuffer();
}
}
//////////////////////////////////////////////////////////////
@@ -6028,6 +6079,7 @@ return width * (1 + ox) / 2.0f;
texture.setFlippedY(true);
this.setCache(ogl, texture);
this.setParams(ogl, params);
texture.setImage(this);
texCrop = new int[4];
texCrop[0] = 0;
@@ -6039,7 +6091,17 @@ return width * (1 + ox) / 2.0f;
// Draws wherever it is in the screen texture right now to the screen.
public void updateTexture() {
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
pushFramebuffer();
setFramebuffer(offscreenFramebuffer);
}
drawTexture();
if (notCurrent) {
popFramebuffer();
}
}
protected void drawTexture() {
@@ -6083,8 +6145,8 @@ return width * (1 + ox) / 2.0f;
getsetBuffer.rewind();
}
boolean nonCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (nonCurrent) {
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
// If the surface is not primary and multisampling is on, then the framebuffer
// will be switched momentarily from offscreenFramebufferMultisample to offscreenFramebuffer.
// This is in fact correct, because the glReadPixels() function doesn't work with
@@ -6095,7 +6157,7 @@ return width * (1 + ox) / 2.0f;
gl.glReadPixels(x, height - y - 1, 1, 1, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, getsetBuffer);
if (nonCurrent) {
if (notCurrent) {
popFramebuffer();
}
@@ -6118,21 +6180,21 @@ return width * (1 + ox) / 2.0f;
IntBuffer newbieBuffer = IntBuffer.allocate(w * h);
boolean nonCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (nonCurrent) {
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
pushFramebuffer();
setFramebuffer(offscreenFramebuffer);
}
gl.glReadPixels(x, height - y - h, w, h, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, newbieBuffer);
if (nonCurrent) {
if (notCurrent) {
popFramebuffer();
}
copyToTexture(newbieTex, newbieBuffer, 0, 0, w, h);
newbie.loadPixels();
newbieTex.flippedY = true;
newbieTex.setFlippedY(true);
newbieTex.get(newbie.pixels);
return newbie;
@@ -6166,8 +6228,19 @@ return width * (1 + ox) / 2.0f;
getsetTexture = new PTexture(parent, 1, 1, new PTexture.Parameters(ARGB, POINT));
}
copyToTexture(getsetTexture, getsetBuffer, 0, 0, 1, 1);
copyToTexture(getsetTexture, getsetBuffer, 0, 0, 1, 1);
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
pushFramebuffer();
setFramebuffer(offscreenFramebuffer);
}
drawTexture(getsetTexture, 0, 0, 1, 1, x, height - y, 1, 1);
if (notCurrent) {
popFramebuffer();
}
}
/**
@@ -6180,9 +6253,21 @@ return width * (1 + ox) / 2.0f;
if (tex != null) {
int w = source.width;
int h = source.height;
boolean notCurrent = !primarySurface && offscreenFramebuffer != currentFramebuffer;
if (notCurrent) {
pushFramebuffer();
setFramebuffer(offscreenFramebuffer);
}
// The crop region and draw rectangle are given like this to take into account
// inverted y-axis in Processin with respect to OpenGL.
drawTexture(tex, 0, h, w, -h, x, height - y, w, h);
if (notCurrent) {
popFramebuffer();
}
}
}
@@ -7046,14 +7131,6 @@ return width * (1 + ox) / 2.0f;
offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, nsamples, 0,
offscreenDepthBits, offscreenStencilBits,
offscreenDepthBits == 24 && offscreenStencilBits == 8, false);
/*
try {
offscreenFramebufferMultisample.addColorBufferMultisample(nsamples);
offscreenMultisample = true;
} catch (GLException e) {
PGraphics.showWarning("Unable to create antialised offscreen surface.");
}
*/
offscreenFramebufferMultisample.clear();
offscreenMultisample = true;

View File

@@ -2154,7 +2154,9 @@ public class PShape3D extends PShape {
}
setParameters(params);
allocate(numVert);
setSize(numVert);
allocate();
initChildrenData();
updateElement = -1;
resetBounds();
@@ -2200,15 +2202,17 @@ public class PShape3D extends PShape {
// Allocate/release shape.
protected void allocate(int numVert) {
release(); // Just in the case this object is being re-allocated.
protected void setSize(int numVert) {
vertexCount = numVert;
numTexBuffers = 1;
firstVertex = 0;
lastVertex = numVert - 1;
firstVertex = 0;
lastVertex = numVert - 1;
}
protected void allocate() {
release(); // Just in the case this object is being re-allocated.
initVertexData();
createVertexBuffer();
initColorData();
@@ -2217,12 +2221,6 @@ public class PShape3D extends PShape {
createNormalBuffer();
initTexCoordData();
createTexCoordBuffer();
initChildrenData();
}
protected void reallocate() {
allocate(vertexCount);
}
protected void release() {
@@ -2382,7 +2380,7 @@ public class PShape3D extends PShape {
protected void deleteTexCoordBuffer() {
for (int i = 0; i < numTexBuffers; i++) {
for (int i = 0; i < glTexCoordBufferID.length; i++) {
deleteTexCoordBuffer(i);
}
}
@@ -3087,7 +3085,9 @@ public class PShape3D extends PShape {
}
// Allocate space for the geometry that the triangulator has generated from the OBJ model.
allocate(ogl.recordedVertices.size());
setSize(ogl.recordedVertices.size());
allocate();
initChildrenData();
updateElement = -1;
width = height = depth = 0;

View File

@@ -89,16 +89,13 @@ public class PTexture implements PConstants {
*/
public PTexture(PApplet parent, int width, int height, Object params) {
this.parent = parent;
this.width = width;
this.height = height;
ogl = (PGraphicsOpenGL)parent.g;
ogl.registerGLObject(this);
glID = 0;
setParameters((Parameters)params);
allocate(width, height);
init(width, height, (Parameters)params);
}
@@ -107,17 +104,19 @@ public class PTexture implements PConstants {
* @param parent PApplet
* @param filename String
*/
/*
public PTexture(PApplet parent, String filename) {
this(parent, filename, new Parameters());
}
*/
/**
* Creates an instance of PTexture using image file filename as source and the specified texture parameters.
* @param parent PApplet
* @param filename String
* @param params Parameters
*/
*/
/*
public PTexture(PApplet parent, String filename, Object params) {
this.parent = parent;
@@ -128,9 +127,9 @@ public class PTexture implements PConstants {
PImage img = parent.loadImage(filename);
setParameters((Parameters)params);
set(img);
set(img);
}
*/
public void delete() {
release();
@@ -138,6 +137,18 @@ public class PTexture implements PConstants {
ogl.unregisterGLObject(this);
}
public void update() {
if (img != null) {
//if (img.pixels == null) {
img.loadPixels();
// }
//get(img.pixels);
//img.updatePixels();
}
}
public void refresh() {
if (img != null && img.pixels != null) {
set(img.pixels);
@@ -179,10 +190,9 @@ public class PTexture implements PConstants {
* @param params GLTextureParameters
*/
public void init(int width, int height, Parameters params) {
this.width = width;
this.height = height;
setParameters(params);
allocate(width, height);
setSize(width, height);
allocate();
}
@@ -266,10 +276,6 @@ public class PTexture implements PConstants {
throw new RuntimeException("PTexture: wrong length of pixels array");
}
if (glID == 0) {
allocate(width, height);
}
getGl().glEnable(glTarget);
getGl().glBindTexture(glTarget, glID);
@@ -695,15 +701,10 @@ public class PTexture implements PConstants {
// Allocate/release texture.
protected void setSize(int w, int h) {
width = w;
height = h;
/**
* Allocates the opengl texture object.
* @param w int
* @param h int
*/
protected void allocate(int w, int h) {
release(); // Just in the case this object is being re-allocated.
if (PGraphicsOpenGL.npotTexSupported) {
glWidth = w;
glHeight = h;
@@ -717,9 +718,23 @@ public class PTexture implements PConstants {
throw new RuntimeException("Image width and height cannot be" +
" larger than " + PGraphicsOpenGL.maxTextureSize +
" with this graphics card.");
}
}
usingMipmaps = glMinFilter == GL.GL_LINEAR_MIPMAP_LINEAR;
// If non-power-of-two textures are not supported, and the specified width or height
// is non-power-of-two, then glWidth (glHeight) will be greater than w (h) because it
// is chosen to be the next power of two, and this quotient will give the appropriate
// maximum texture coordinate value given this situation.
maxTexCoordU = (float)width / glWidth;
maxTexCoordV = (float)height / glHeight;
}
/**
* Allocates the opengl texture object.
* @param w int
* @param h int
*/
protected void allocate() {
release(); // Just in the case this object is being re-allocated.
getGl().glEnable(glTarget);
glID = ogl.createGLResource(PGraphicsOpenGL.GL_TEXTURE_OBJECT);
@@ -735,28 +750,14 @@ public class PTexture implements PConstants {
GL.GL_UNSIGNED_BYTE, null);
// Once OpenGL knows the size of the new texture, we make sure it doesn't
// contain any garbage in the region of interest (0, 0, w, h):
int[] texels = new int[w * h];
java.util.Arrays.fill(texels, 0, w * h, 0x00000000);
setTexels(0, 0, w, h, texels);
// contain any garbage in the region of interest (0, 0, width, height):
int[] texels = new int[width * height];
java.util.Arrays.fill(texels, 0, width * height, 0x00000000);
setTexels(0, 0, width, height, texels);
texels = null;
getGl().glBindTexture(glTarget, 0);
getGl().glDisable(glTarget);
flippedX = false;
flippedY = false;
// If non-power-of-two textures are not supported, and the specified width or height
// is non-power-of-two, then glWidth (glHeight) will be greater than w (h) because it
// is chosen to be the next power of two, and this quotient will give the appropriate
// maximum texture coordinate value given this situation.
maxTexCoordU = (float)w / glWidth;
maxTexCoordV = (float)h / glHeight;
}
protected void reallocate() {
allocate(width, height);
getGl().glDisable(glTarget);
}
/**
@@ -934,6 +935,11 @@ public class PTexture implements PConstants {
} else {
throw new RuntimeException("OPENGL2: Unknown wrapping mode");
}
usingMipmaps = glMinFilter == GL.GL_LINEAR_MIPMAP_LINEAR;
flippedX = false;
flippedY = false;
}
///////////////////////////////////////////////////////////////////////////