From 81ece7e4f13848c8b4575591727db8effba45f09 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Sat, 27 Nov 2010 04:17:53 +0000 Subject: [PATCH] New OpenGL resource creation/deletion method in A3D. Takes care of issue 456 --- android/core/src/processing/core/PApplet.java | 4 +- android/core/src/processing/core/PFont.java | 11 +- .../src/processing/core/PFramebuffer.java | 71 ++--- .../processing/core/PGraphicsAndroid3D.java | 243 +++++++++++++----- android/core/src/processing/core/PImage.java | 7 + .../core/src/processing/core/PShape3D.java | 159 +++++------- .../core/src/processing/core/PTexture.java | 47 +--- 7 files changed, 302 insertions(+), 240 deletions(-) diff --git a/android/core/src/processing/core/PApplet.java b/android/core/src/processing/core/PApplet.java index d76d2dc39..8d9a16011 100644 --- a/android/core/src/processing/core/PApplet.java +++ b/android/core/src/processing/core/PApplet.java @@ -546,6 +546,7 @@ public class PApplet extends Activity implements PConstants, Runnable { protected void onPause() { super.onPause(); + // TODO need to save all application state here! // System.out.println("PApplet.onPause() called"); @@ -795,7 +796,6 @@ public class PApplet extends Activity implements PConstants, Runnable { if (DEBUG) { System.out.println("surfaceDestroyed()"); } - g3.dispose(); } @@ -2500,7 +2500,7 @@ public class PApplet extends Activity implements PConstants, Runnable { // don't run stop and disposers twice if (thread == null) return; thread = null; - + // call to shut down renderer, in case it needs it (pdf does) if (g != null) g.dispose(); disposeMethods.handle(); diff --git a/android/core/src/processing/core/PFont.java b/android/core/src/processing/core/PFont.java index d7cd4a5e3..c57bba2fd 100644 --- a/android/core/src/processing/core/PFont.java +++ b/android/core/src/processing/core/PFont.java @@ -330,6 +330,13 @@ public class PFont implements PConstants { } + public void delete() { + for (int i = 0; i < textures.length; i++) { + textures[i].delete(); + } + } + + /** * Write this PFont to an OutputStream. *

@@ -758,9 +765,7 @@ public class PFont implements PConstants { } } - - protected void recreateResource(PGraphicsAndroid3D renderer) { - } + ///////////////////////////////////////////////////////////// diff --git a/android/core/src/processing/core/PFramebuffer.java b/android/core/src/processing/core/PFramebuffer.java index 4dde7551c..5e1de3c05 100644 --- a/android/core/src/processing/core/PFramebuffer.java +++ b/android/core/src/processing/core/PFramebuffer.java @@ -22,7 +22,6 @@ package processing.core; -import java.lang.reflect.Method; import java.nio.IntBuffer; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11ExtensionPack; @@ -48,8 +47,6 @@ public class PFramebuffer implements PConstants { protected int glStencilBufferID; protected int width; protected int height; - - protected int recreateResourceIdx; protected int numColorBuffers; protected int[] colorBufferAttchPoints; @@ -75,6 +72,9 @@ public class PFramebuffer implements PConstants { this.parent = parent; a3d = (PGraphicsAndroid3D)parent.g; + glFboID = 0; + glDepthBufferID = 0; + glStencilBufferID = 0; screenFb = screen; noDepth = false; FboMode = PGraphicsAndroid3D.fboSupported; @@ -88,7 +88,7 @@ public class PFramebuffer implements PConstants { throw new RuntimeException("PFramebuffer: OpenGL ES 1.1 Extension Pack required"); } - initFramebuffer(w, h); + createFramebuffer(w, h); pixelBuffer = IntBuffer.allocate(width * height); pixelBuffer.rewind(); @@ -99,30 +99,22 @@ public class PFramebuffer implements PConstants { // buffer to the texture bound as color buffer to this PFramebuffer object and then drawing // the backup texture back on the screen. backupTexture = new PTexture(parent, width, height, new PTexture.Parameters(ARGB, NEAREST)); - } - - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } + } } - protected void finalize() { - a3d.removeRecreateResourceMethod(recreateResourceIdx); - //deleteFramebuffer(); + public void delete() { + deleteFramebuffer(); } - void setColorBuffer(PTexture tex) { + public void setColorBuffer(PTexture tex) { setColorBuffers(new PTexture[] { tex }, 1); } - void setColorBuffers(PTexture[] textures) { + public void setColorBuffers(PTexture[] textures) { setColorBuffers(textures, textures.length); } - void setColorBuffers(PTexture[] textures, int n) { + public void setColorBuffers(PTexture[] textures, int n) { if (screenFb) return; if (FboMode) { @@ -176,10 +168,7 @@ public class PFramebuffer implements PConstants { a3d.pushFramebuffer(); a3d.setFramebuffer(this); - int[] temp = new int[1]; - gl11xp.glGenRenderbuffersOES(1, temp, 0); - glDepthBufferID = temp[0]; - + glDepthBufferID = a3d.createGLResource(PGraphicsAndroid3D.GL_RENDER_BUFFER); gl11xp.glBindRenderbufferOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, glDepthBufferID); int glConst = GL11ExtensionPack.GL_DEPTH_COMPONENT16; @@ -211,10 +200,7 @@ public class PFramebuffer implements PConstants { a3d.pushFramebuffer(); a3d.setFramebuffer(this); - int[] temp = new int[1]; - gl11xp.glGenRenderbuffersOES(1, temp, 0); - glStencilBufferID = temp[0]; - + glStencilBufferID = a3d.createGLResource(PGraphicsAndroid3D.GL_RENDER_BUFFER); gl11xp.glBindRenderbufferOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, glStencilBufferID); int glConst = GL11ExtensionPack.GL_STENCIL_INDEX1_OES; @@ -321,45 +307,38 @@ public class PFramebuffer implements PConstants { gl.glDisable(gltarget); } - protected void initFramebuffer(int w, int h) { + protected void createFramebuffer(int w, int h) { + deleteFramebuffer(); // Just in the case this object is being re-initialized. + width = w; height = h; if (screenFb) { glFboID = 0; - } else if (FboMode) { - int[] temp = new int[1]; - gl11xp.glGenFramebuffersOES(1, temp, 0); - glFboID = temp[0]; + } else if (FboMode) { + glFboID = a3d.createGLResource(PGraphicsAndroid3D.GL_FRAME_BUFFER); } else { glFboID = 0; } } - + protected void deleteFramebuffer() { if (glFboID != 0) { - int[] temp = { glFboID }; - gl11xp.glDeleteFramebuffersOES(1, temp, 0); + a3d.deleteGLResource(glFboID, PGraphicsAndroid3D.GL_FRAME_BUFFER); glFboID = 0; } - if (glDepthBufferID != 0) { - int[] temp = { glDepthBufferID }; - gl11xp.glDeleteRenderbuffersOES(1, temp, 0); + if (glDepthBufferID != 0) { + a3d.deleteGLResource(glDepthBufferID, PGraphicsAndroid3D.GL_RENDER_BUFFER); glDepthBufferID = 0; - } + } - if (glStencilBufferID != 0) { - int[] temp = { glStencilBufferID }; - gl11xp.glDeleteRenderbuffersOES(1, temp, 0); + if (glStencilBufferID != 0) { + a3d.deleteGLResource(glStencilBufferID, PGraphicsAndroid3D.GL_RENDER_BUFFER); glStencilBufferID = 0; } - width = height = 0; - } - - protected void recreateResource(PGraphicsAndroid3D renderer) { - // Recreate GL resources (buffers, etc). + width = height = 0; } public boolean validFbo() { diff --git a/android/core/src/processing/core/PGraphicsAndroid3D.java b/android/core/src/processing/core/PGraphicsAndroid3D.java index 8b60afabe..28232c085 100644 --- a/android/core/src/processing/core/PGraphicsAndroid3D.java +++ b/android/core/src/processing/core/PGraphicsAndroid3D.java @@ -29,6 +29,8 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.EmptyStackException; +import java.util.Set; +import java.util.HashSet; import java.util.Stack; import android.opengl.GLU; @@ -190,6 +192,8 @@ public class PGraphicsAndroid3D extends PGraphics { // Used to detect changes in the current texture images. protected PImage multitextureImages0[] = new PImage[MAX_TEXTURES]; + protected PImage textureImage0; + // Current multitexture UV coordinates. protected float[] multitextureU = new float[MAX_TEXTURES]; protected float[] multitextureV = new float[MAX_TEXTURES]; @@ -309,14 +313,17 @@ public class PGraphicsAndroid3D extends PGraphics { // ........................................................ - // This array contains the recreateResource methods of all the GL objects - // created in Processing. These methods are used to recreate the open GL - // data when there is a context change or surface creation in Android. - // TODO: Check the resource recreation method. - protected ArrayList recreateResourceMethods; - - // This is only used by non primary surfaces. - protected int recreateResourceIdx; + // OpenGL resources + + static protected final int GL_TEXTURE_OBJECT = 0; + static protected final int GL_VERTEX_BUFFER = 1; + static protected final int GL_FRAME_BUFFER = 2; + static protected final int GL_RENDER_BUFFER = 3; + + Set glTextureObjects; + Set glVertexBuffers; + Set glFrameBuffers; + Set glRenderBuffers; // ........................................................ @@ -404,7 +411,11 @@ public class PGraphicsAndroid3D extends PGraphics { public PGraphicsAndroid3D() { renderer = new A3DRenderer(); - recreateResourceMethods = new ArrayList(); + + glTextureObjects = new HashSet(); + glVertexBuffers = new HashSet(); + glFrameBuffers = new HashSet(); + glRenderBuffers = new HashSet(); } // public void setParent(PApplet parent) @@ -509,49 +520,99 @@ public class PGraphicsAndroid3D extends PGraphics { } } - public void dispose() { + public void dispose() { + // Releasing any remaining OpenGL resources. + if (!glTextureObjects.isEmpty()) { + Object[] glids = glTextureObjects.toArray(); + for (int i = 0; i < glids.length; i++) { + int id = ((Integer)glids[i]).intValue(); + int[] temp = { id }; + gl.glDeleteTextures(1, temp, 0); + } + } + if (!glVertexBuffers.isEmpty()) { + Object[] glids = glVertexBuffers.toArray(); + for (int i = 0; i < glids.length; i++) { + int id = ((Integer)glids[i]).intValue(); + int[] temp = { id }; + gl11.glDeleteBuffers(1, temp, 0); + } + } + + if (!glFrameBuffers.isEmpty()) { + Object[] glids = glFrameBuffers.toArray(); + for (int i = 0; i < glids.length; i++) { + int id = ((Integer)glids[i]).intValue(); + int[] temp = { id }; + gl11xp.glDeleteFramebuffersOES(1, temp, 0); + } + } + + if (!glRenderBuffers.isEmpty()) { + Object[] glids = glRenderBuffers.toArray(); + for (int i = 0; i < glids.length; i++) { + int id = ((Integer)glids[i]).intValue(); + int[] temp = { id }; + gl11xp.glDeleteRenderbuffersOES(1, temp, 0); + } + } } - // TODO: finalize or dispose to clean up opengl resources? - protected void finalize() { - if (!primarySurface) { - PGraphicsAndroid3D a3d = (PGraphicsAndroid3D)parent.g; - if (a3d != null) { - a3d.removeRecreateResourceMethod(recreateResourceIdx); + protected int createGLResource(int type) { + int id = 0; + if (type == GL_TEXTURE_OBJECT) { + int[] temp = new int[1]; + gl.glGenTextures(1, temp, 0); + id = temp[0]; + glTextureObjects.add(id); + } else if (type == GL_VERTEX_BUFFER) { + int[] temp = new int[1]; + gl11.glGenBuffers(1, temp, 0); + id = temp[0]; + glVertexBuffers.add(id); + } else if (type == GL_FRAME_BUFFER) { + int[] temp = new int[1]; + gl11xp.glGenFramebuffersOES(1, temp, 0); + id = temp[0]; + glFrameBuffers.add(id); + } else if (type == GL_RENDER_BUFFER) { + int[] temp = new int[1]; + gl11xp.glGenRenderbuffersOES(1, temp, 0); + id = temp[0]; + glRenderBuffers.add(id); + } + + return id; + } + + protected void deleteGLResource(int id, int type) { + if (type == GL_TEXTURE_OBJECT) { + if (glTextureObjects.contains(id)) { + int[] temp = { id }; + gl.glDeleteTextures(1, temp, 0); + glTextureObjects.remove(id); } - } - } - - public void recreateResources() { - // Recreate the openGL resources of the registered GL objects (PTexture, - // PShape3D, PFramebuffer, PFont) - for (int i = 0; i < recreateResourceMethods.size(); i++) { - GLResource resource = (GLResource) recreateResourceMethods.get(i); - try { - resource.method.invoke(resource.object, new Object[] { this }); - } catch (Exception e) { - System.err.println("A3D: Error, opengl resources in " + resource.object - + " cannot be recreated."); - e.printStackTrace(); + } else if (type == GL_VERTEX_BUFFER) { + if (glVertexBuffers.contains(id)) { + int[] temp = { id }; + gl11.glDeleteBuffers(1, temp, 0); + glVertexBuffers.remove(id); } + } else if (type == GL_FRAME_BUFFER) { + if (glFrameBuffers.contains(id)) { + int[] temp = { id }; + gl11xp.glDeleteFramebuffersOES(1, temp, 0); + glFrameBuffers.remove(id); + } + } else if (type == GL_RENDER_BUFFER) { + if (glRenderBuffers.contains(id)) { + int[] temp = { id }; + gl11xp.glDeleteRenderbuffersOES(1, temp, 0); + glRenderBuffers.remove(id); + } } - } - - protected int addRecreateResourceMethod(Object obj, Method meth) { - recreateResourceMethods.add(new GLResource(obj, meth)); - return recreateResourceMethods.size() - 1; - } - - protected void removeRecreateResourceMethod(int idx) { - if (-1 < idx && idx < recreateResourceMethods.size()) { - recreateResourceMethods.remove(idx); - } - } - - protected void recreateResource(PGraphicsAndroid3D renderer) { - } // //////////////////////////////////////////////////////////// @@ -847,6 +908,7 @@ public class PGraphicsAndroid3D extends PGraphics { // Each frame starts with multitexturing disabled. usingMultitexture = false; + textureImage0 = null; clearMultitextures(); clearMultitextures0(); @@ -1097,16 +1159,6 @@ public class PGraphicsAndroid3D extends PGraphics { // easiest for beginners textureMode(IMAGE); - - if (!primarySurface) { - PGraphicsAndroid3D a3d = (PGraphicsAndroid3D)parent.g; - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } - } } // reapplySettings @@ -1242,6 +1294,7 @@ public class PGraphicsAndroid3D extends PGraphics { clearMultitextures(); clearMultitextures0(); + textureImage0 = null; } // public void edge(boolean e) @@ -1259,10 +1312,12 @@ public class PGraphicsAndroid3D extends PGraphics { public void texture(PImage image) { super.texture(image); usingMultitexture = false; + multitextureImages[0] = image; for (int t = 1; t < maxTextureUnits; t++) { multitextureImages[t] = null; } + } public void texture(PImage image0, PImage image1) { @@ -1276,7 +1331,7 @@ public class PGraphicsAndroid3D extends PGraphics { } for (int t = 2; t < maxTextureUnits; t++) { multitextureImages[t] = null; - } + } } else { System.err.println("A3D: insufficient texture units."); } @@ -1307,6 +1362,9 @@ public class PGraphicsAndroid3D extends PGraphics { usingMultitexture = true; if (numTexBuffers < 4) { addTexBuffers(4 - numTexBuffers); + } + for (int t = 4; t < maxTextureUnits; t++) { + multitextureImages[t] = null; } } else { System.err.println("A3D: insufficient texture units."); @@ -1320,7 +1378,10 @@ public class PGraphicsAndroid3D extends PGraphics { usingMultitexture = true; if (numTexBuffers < images.length) { addTexBuffers(images.length - numTexBuffers); - } + } + for (int t = images.length; t < maxTextureUnits; t++) { + multitextureImages[t] = null; + } } else { System.err.println("A3D: insufficient texture units."); } @@ -1484,14 +1545,18 @@ public class PGraphicsAndroid3D extends PGraphics { } } + /* public void vertex(float x, float y, float z, float u, float v) { vertexTexture(u, v, 0); vertex(x, y, z); + int n = vertexCount - 1; vertexTex[n][0] = multitextureImages[0]; vertexU[n][0] = multitextureU[0]; vertexV[n][0] = multitextureV[0]; + } + */ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1) { if (2 <= maxTextureUnits) { @@ -2297,7 +2362,13 @@ public class PGraphicsAndroid3D extends PGraphics { triangles[triangleCount][VERTEX2] = b; triangles[triangleCount][VERTEX3] = c; - PImage[] images = vertexTex[a]; + /* + PImage[] images; + if (usingMultitexture) { + images = vertexTex[a]; + } else { + images = new PImage[] {textureImage}; + } boolean firstFace = triangleCount == 0; if (diffFromMultitextures0(images) || firstFace) { // A new face starts at the first triangle or when the texture changes. @@ -2307,8 +2378,36 @@ public class PGraphicsAndroid3D extends PGraphics { faceLength[faceCount - 1]++; } triangleCount++; - setMultitextures0(images); + */ + + + if (usingMultitexture) { + PImage[] images = vertexTex[a]; + boolean firstFace = triangleCount == 0; + if (diffFromMultitextures0(images) || firstFace) { + // A new face starts at the first triangle or when the texture changes. + addNewFace(firstFace, images); + } else { + // mark this triangle as being part of the current face. + faceLength[faceCount - 1]++; + } + triangleCount++; + setMultitextures0(images); + } else { + + PImage image = textureImage; + boolean firstFace = triangleCount == 0; + if (image != textureImage0 || firstFace) { + // A new face starts at the first triangle or when the texture changes. + addNewFace(firstFace, image); + } else { + // mark this triangle as being part of the current face. + faceLength[faceCount - 1]++; + } + triangleCount++; + textureImage0 = textureImage; + } } // New "face" starts. A face is just a range of consecutive triangles @@ -2335,6 +2434,27 @@ public class PGraphicsAndroid3D extends PGraphics { faceCount++; } + + + protected void addNewFace(boolean firstFace, PImage image) { + if (faceCount == faceOffset.length) { + faceOffset = PApplet.expand(faceOffset); + faceLength = PApplet.expand(faceLength); + + PImage tempi[][] = new PImage[faceCount << 1][MAX_TEXTURES]; + System.arraycopy(faceTextures, 0, tempi, 0, faceCount); + faceTextures = tempi; + } + faceOffset[faceCount] = firstFace ? 0 : triangleCount; + faceLength[faceCount] = 1; + + PImage p[] = faceTextures[faceCount]; + p[0] = image; + + faceCount++; + } + + protected void renderTriangles(int start, int stop) { report("render_triangles in"); @@ -2371,6 +2491,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } else if (images[0] != null) { PTexture tex = images[0].getTexture(); + if (tex != null) { gl.glEnable(tex.getGLTarget()); gl.glActiveTexture(GL10.GL_TEXTURE0); @@ -2381,6 +2502,7 @@ public class PGraphicsAndroid3D extends PGraphics { // Null PTexture field in A3D? no good! throw new RuntimeException("A3D: missing image texture"); } + } if (0 < numTextures) { @@ -5909,8 +6031,7 @@ public class PGraphicsAndroid3D extends PGraphics { gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_UNITS, temp, 0); maxTextureUnits = PApplet.min(MAX_TEXTURES, temp[0]); - - recreateResources(); + gl = null; gl11 = null; gl11x = null; diff --git a/android/core/src/processing/core/PImage.java b/android/core/src/processing/core/PImage.java index a98c58ac5..a6669a4c4 100644 --- a/android/core/src/processing/core/PImage.java +++ b/android/core/src/processing/core/PImage.java @@ -139,6 +139,13 @@ public class PImage implements PConstants, Cloneable { // this.cache = null; } + + public void delete() { + if (texture != null) { + texture.delete(); + } + } + /** * Check the alpha on an image, using a really primitive loop. diff --git a/android/core/src/processing/core/PShape3D.java b/android/core/src/processing/core/PShape3D.java index db2fc4776..196d87ce9 100644 --- a/android/core/src/processing/core/PShape3D.java +++ b/android/core/src/processing/core/PShape3D.java @@ -30,7 +30,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Hashtable; import java.io.BufferedReader; -import java.lang.reflect.Method; /** * This class holds a 3D model composed of vertices, normals, colors (per vertex) and @@ -52,11 +51,11 @@ public class PShape3D extends PShape implements PConstants { protected int glUsage; protected boolean pointSprites; - protected int[] glVertexBufferID = new int[1]; - protected int[] glColorBufferID = new int[1]; - protected int[] glNormalBufferID = new int[1]; + protected int glVertexBufferID; + protected int glColorBufferID; + protected int glNormalBufferID; protected int[] glTexCoordBufferID = new int[PGraphicsAndroid3D.MAX_TEXTURES]; - + protected FloatBuffer vertexBuffer; protected FloatBuffer colorBuffer; protected FloatBuffer normalBuffer; @@ -77,8 +76,6 @@ public class PShape3D extends PShape implements PConstants { protected boolean firstSetGroup; protected int grIdx0; protected int grIdx1; - - protected int recreateResourceIdx; protected float xmin, xmax; protected float ymin, ymax; @@ -91,8 +88,7 @@ public class PShape3D extends PShape implements PConstants { protected int TEXTURESMAX; - protected static final int SIZEOF_FLOAT = Float.SIZE / 8; - + protected static final int SIZEOF_FLOAT = Float.SIZE / 8; //////////////////////////////////////////////////////////// @@ -101,15 +97,13 @@ public class PShape3D extends PShape implements PConstants { public PShape3D(PApplet parent) { this.parent = parent; a3d = (PGraphicsAndroid3D)parent.g; - - TEXTURESMAX = TEXTURES0 + PGraphicsAndroid3D.maxTextureUnits; + + glVertexBufferID = 0; + glColorBufferID = 0; + glNormalBufferID = 0; + java.util.Arrays.fill(glTexCoordBufferID, 0); - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } + TEXTURESMAX = TEXTURES0 + PGraphicsAndroid3D.maxTextureUnits; } public PShape3D(PApplet parent, int numVert) { @@ -119,6 +113,11 @@ public class PShape3D extends PShape implements PConstants { public PShape3D(PApplet parent, String filename, int mode) { this.parent = parent; a3d = (PGraphicsAndroid3D)parent.g; + + glVertexBufferID = 0; + glColorBufferID = 0; + glNormalBufferID = 0; + java.util.Arrays.fill(glTexCoordBufferID, 0); TEXTURESMAX = TEXTURES0 + PGraphicsAndroid3D.maxTextureUnits; @@ -148,13 +147,6 @@ public class PShape3D extends PShape implements PConstants { parseOBJ(reader, vertices, normals, textures, faces, materials); recordOBJ(vertices, normals, textures, faces, materials); centerAt(0, 0, 0); - - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } } @@ -162,22 +154,18 @@ public class PShape3D extends PShape implements PConstants { this.parent = parent; a3d = (PGraphicsAndroid3D)parent.g; + glVertexBufferID = 0; + glColorBufferID = 0; + glNormalBufferID = 0; + java.util.Arrays.fill(glTexCoordBufferID, 0); + TEXTURESMAX = TEXTURES0 + PGraphicsAndroid3D.maxTextureUnits; initShape(numVert, params); - - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } } - protected void finalize() { - a3d.removeRecreateResourceMethod(recreateResourceIdx); - + public void delete() { //deleteVertexBuffer(); //deleteColorBuffer(); //deleteTexCoordBuffer(); @@ -261,7 +249,7 @@ public class PShape3D extends PShape implements PConstants { lastUpdateIdx = -1; if (updateElement == VERTICES) { - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glVertexBufferID[0]); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glVertexBufferID); int offset = first * 3; int size = (last - first + 1) * 3; @@ -273,7 +261,7 @@ public class PShape3D extends PShape implements PConstants { creatingGroup = false; firstSetGroup = true; } else if (updateElement == COLORS) { - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glColorBufferID[0]); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glColorBufferID); int offset = first * 4; int size = (last - first + 1) * 4; @@ -281,7 +269,7 @@ public class PShape3D extends PShape implements PConstants { colorBuffer.rewind(); colorBuffer.get(colorArray, offset, size); } else if (updateElement == NORMALS) { - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glNormalBufferID[0]); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glNormalBufferID); int offset = first * 3; int size = (last - first + 1) * 3; @@ -1746,10 +1734,10 @@ public class PShape3D extends PShape implements PConstants { protected void createVertexBuffer() { - deleteVertexBuffer(); // Just in case. + deleteVertexBuffer(); // Just in the case this object is being re-initialized. - gl.glGenBuffers(1, glVertexBufferID, 0); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glVertexBufferID[0]); + glVertexBufferID = a3d.createGLResource(PGraphicsAndroid3D.GL_VERTEX_BUFFER); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glVertexBufferID); final int bufferSize = vertexBuffer.capacity() * SIZEOF_FLOAT; gl.glBufferData(GL11.GL_ARRAY_BUFFER, bufferSize, vertexBuffer, glUsage); gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0); @@ -1772,10 +1760,10 @@ public class PShape3D extends PShape implements PConstants { protected void createColorBuffer() { - deleteColorBuffer(); // Just in case. + deleteColorBuffer(); - gl.glGenBuffers(1, glColorBufferID, 0); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glColorBufferID[0]); + glColorBufferID = a3d.createGLResource(PGraphicsAndroid3D.GL_VERTEX_BUFFER); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glColorBufferID); final int bufferSize = colorBuffer.capacity() * SIZEOF_FLOAT; gl.glBufferData(GL11.GL_ARRAY_BUFFER, bufferSize, colorBuffer, glUsage); gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0); @@ -1794,10 +1782,10 @@ public class PShape3D extends PShape implements PConstants { protected void createNormalBuffer() { - deleteNormalBuffer(); // Just in case. + deleteNormalBuffer(); - gl.glGenBuffers(1, glNormalBufferID, 0); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glNormalBufferID[0]); + glNormalBufferID = a3d.createGLResource(PGraphicsAndroid3D.GL_VERTEX_BUFFER); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glNormalBufferID); final int bufferSize = normalBuffer.capacity() * SIZEOF_FLOAT; gl.glBufferData(GL11.GL_ARRAY_BUFFER, bufferSize, normalBuffer, glUsage); gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0); @@ -1816,9 +1804,9 @@ public class PShape3D extends PShape implements PConstants { protected void createTexCoordBuffer() { - deleteTexCoordBuffer(); // Just in case. + deleteTexCoordBuffer(); - gl.glGenBuffers(1, glTexCoordBufferID, 0); + glTexCoordBufferID[0] = a3d.createGLResource(PGraphicsAndroid3D.GL_VERTEX_BUFFER); gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glTexCoordBufferID[0]); final int bufferSize = texCoordBuffer.capacity() * SIZEOF_FLOAT; gl.glBufferData(GL11.GL_ARRAY_BUFFER, bufferSize, texCoordBuffer, glUsage); @@ -1828,15 +1816,14 @@ public class PShape3D extends PShape implements PConstants { protected void addTexBuffers(int more) { for (int i = 0; i < more; i++) { - deleteTexCoordBuffer(numTexBuffers + i); // Just in case. + int t = numTexBuffers + i; + deleteTexCoordBuffer(t); - int[] temp = {0}; - gl.glGenBuffers(1, temp, 0); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, temp[0]); + glTexCoordBufferID[t] = a3d.createGLResource(PGraphicsAndroid3D.GL_VERTEX_BUFFER); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glTexCoordBufferID[t]); final int bufferSize = texCoordBuffer.capacity() * SIZEOF_FLOAT; gl.glBufferData(GL11.GL_ARRAY_BUFFER, bufferSize, texCoordBuffer, glUsage); gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0); - glTexCoordBufferID[numTexBuffers + i] = temp[0]; } numTexBuffers += more; @@ -1844,25 +1831,25 @@ public class PShape3D extends PShape implements PConstants { protected void deleteVertexBuffer() { - if (glVertexBufferID[0] != 0) { - gl.glDeleteBuffers(1, glVertexBufferID, 0); - glVertexBufferID[0] = 0; + if (glVertexBufferID != 0) { + a3d.deleteGLResource(glVertexBufferID, PGraphicsAndroid3D.GL_VERTEX_BUFFER); + glVertexBufferID = 0; } } protected void deleteColorBuffer() { - if (glColorBufferID[0] != 0) { - gl.glDeleteBuffers(1, glColorBufferID, 0); - glColorBufferID[0] = 0; + if (glColorBufferID != 0) { + a3d.deleteGLResource(glColorBufferID, PGraphicsAndroid3D.GL_VERTEX_BUFFER); + glColorBufferID = 0; } } protected void deleteNormalBuffer() { - if (glNormalBufferID[0] != 0) { - gl.glDeleteBuffers(1, glNormalBufferID, 0); - glNormalBufferID[0] = 0; + if (glNormalBufferID != 0) { + a3d.deleteGLResource(glNormalBufferID, PGraphicsAndroid3D.GL_VERTEX_BUFFER); + glNormalBufferID = 0; } } @@ -1875,26 +1862,16 @@ public class PShape3D extends PShape implements PConstants { protected void deleteTexCoordBuffer(int idx) { - if (glTexCoordBufferID[idx] != 0) { - int[] temp = {glTexCoordBufferID[idx]}; - gl.glDeleteBuffers(1, temp, 0); + if (glTexCoordBufferID[idx] != 0) { + a3d.deleteGLResource(glTexCoordBufferID[idx], PGraphicsAndroid3D.GL_VERTEX_BUFFER); glTexCoordBufferID[idx] = 0; } } - - - protected void recreateResource(PGraphicsAndroid3D renderer) { - createVertexBuffer(); - createColorBuffer(); - createNormalBuffer(); - createTexCoordBuffer(); - } - - + /////////////////////////////////////////////////////////// - // Reimplementing methods inherited from PShape. + // Re-implementing methods inherited from PShape. public void translate(float tx, float ty) { @@ -2070,7 +2047,7 @@ public class PShape3D extends PShape implements PConstants { public void draw(PGraphics g, int gr0, int gr1) { - PImage[] imgs = null; + PImage[] images = null; boolean textured = false; float pointSize; @@ -2086,17 +2063,17 @@ public class PShape3D extends PShape implements PConstants { gl.glPointSize(pointSize); gl.glEnableClientState(GL11.GL_NORMAL_ARRAY); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glNormalBufferID[0]); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glNormalBufferID); gl.glNormalPointer(GL11.GL_FLOAT, 0, 0); if (vertexColor) { gl.glEnableClientState(GL11.GL_COLOR_ARRAY); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glColorBufferID[0]); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glColorBufferID); gl.glColorPointer(4, GL11.GL_FLOAT, 0, 0); } gl.glEnableClientState(GL11.GL_VERTEX_ARRAY); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glVertexBufferID[0]); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glVertexBufferID); gl.glVertexPointer(3, GL11.GL_FLOAT, 0, 0); VertexGroup group; @@ -2106,13 +2083,13 @@ public class PShape3D extends PShape implements PConstants { if (group.hasTexture()) { textured = true; // Binding texture units. - imgs = group.textures; - for (int n = 0; n < imgs.length; n++) { - if (imgs[n] != null && imgs[n].getTexture() != null) { - PTexture tex = imgs[n].getTexture(); + images = group.textures; + for (int t = 0; t < images.length; t++) { + if (images[t] != null && images[t].getTexture() != null) { + PTexture tex = images[t].getTexture(); int texTarget = tex.getGLTarget(); gl.glEnable(texTarget); - gl.glActiveTexture(GL10.GL_TEXTURE0 + n); + gl.glActiveTexture(GL10.GL_TEXTURE0 + t); gl.glBindTexture(texTarget, tex.getGLID()); } } @@ -2140,9 +2117,9 @@ public class PShape3D extends PShape implements PConstants { } else { // Regular texturing. gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); - for (int n = 0; n < numTexBuffers; n++) { - gl.glClientActiveTexture(GL11.GL_TEXTURE0 + n); - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glTexCoordBufferID[n]); + for (int t = 0; t < numTexBuffers; t++) { + gl.glClientActiveTexture(GL11.GL_TEXTURE0 + t); + gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, glTexCoordBufferID[t]); gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0); } } @@ -2183,9 +2160,9 @@ public class PShape3D extends PShape implements PConstants { gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); } - for (int n = 0; n < numTexBuffers; n++) { - if (imgs[n] != null && imgs[n].getTexture() != null) { - PTexture tex = imgs[n].getTexture(); + for (int t = 0; t < numTexBuffers; t++) { + if (images[t] != null && images[t].getTexture() != null) { + PTexture tex = images[t].getTexture(); int texTarget = tex.getGLTarget(); gl.glDisable(texTarget); } diff --git a/android/core/src/processing/core/PTexture.java b/android/core/src/processing/core/PTexture.java index dd7909f2b..06ed6c4c9 100644 --- a/android/core/src/processing/core/PTexture.java +++ b/android/core/src/processing/core/PTexture.java @@ -68,8 +68,6 @@ public class PTexture implements PConstants { protected int[] tmpPixels = null; protected PFramebuffer tmpFbo = null; - protected int recreateResourceIdx; - //////////////////////////////////////////////////////////// // Constructors. @@ -106,14 +104,7 @@ public class PTexture implements PConstants { glID = 0; setParameters(params); - createTexture(width, height); - - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } + createTexture(width, height); } @@ -143,20 +134,12 @@ public class PTexture implements PConstants { PImage img = parent.loadImage(filename); setParameters(params); - set(img); - - try { - Method meth = this.getClass().getMethod("recreateResource", new Class[] { PGraphicsAndroid3D.class }); - recreateResourceIdx = a3d.addRecreateResourceMethod(this, meth); - } catch (Exception e) { - recreateResourceIdx = -1; - } + set(img); } - protected void finalize() { - a3d.removeRecreateResourceMethod(recreateResourceIdx); - //deleteTexture(); + public void delete() { + deleteTexture(); } @@ -889,7 +872,7 @@ public class PTexture implements PConstants { * @param h int */ protected void createTexture(int w, int h) { - deleteTexture(); + deleteTexture(); // Just in the case this object is being re-initialized. if (PGraphicsAndroid3D.npotTexSupported) { glWidth = w; @@ -912,9 +895,7 @@ public class PTexture implements PConstants { (glMinFilter == GL10.GL_LINEAR_MIPMAP_LINEAR)); gl.glEnable(glTarget); - int[] tmp = new int[1]; - gl.glGenTextures(1, tmp, 0); - glID = tmp[0]; + glID = a3d.createGLResource(PGraphicsAndroid3D.GL_TEXTURE_OBJECT); gl.glBindTexture(glTarget, glID); gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MIN_FILTER, glMinFilter); gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MAG_FILTER, glMagFilter); @@ -941,18 +922,11 @@ public class PTexture implements PConstants { */ protected void deleteTexture() { if (glID != 0) { - int[] tmp = { glID }; - gl.glDeleteTextures(1, tmp, 0); + a3d.deleteGLResource(glID, PGraphicsAndroid3D.GL_TEXTURE_OBJECT); glID = 0; } } - - protected void recreateResource(PGraphicsAndroid3D renderer) { - createTexture(width, height); - } - - // Copies source texture to this. protected void copyTexels(PTexture tex, int x, int y, int w, int h, boolean scale) { if (tex == null) { @@ -991,8 +965,9 @@ public class PTexture implements PConstants { } protected void copyObject(PTexture src) { - a3d.removeRecreateResourceMethod(recreateResourceIdx); - deleteTexture(); + // The OpenGL texture of this object is replaced with the one from the source object, + // so we delete the former to avoid resource wasting. + deleteTexture(); width = src.width; height = src.height; @@ -1016,8 +991,6 @@ public class PTexture implements PConstants { flippedX = src.flippedX; flippedY = src.flippedY; - - recreateResourceIdx = src.recreateResourceIdx; } ///////////////////////////////////////////////////////////