diff --git a/android/.classpath b/android/.classpath index a8b730424..4c0a3df47 100644 --- a/android/.classpath +++ b/android/.classpath @@ -2,5 +2,6 @@ + diff --git a/android/core/src/processing/core/PApplet.java b/android/core/src/processing/core/PApplet.java index 312a3e0c9..d14bc0406 100644 --- a/android/core/src/processing/core/PApplet.java +++ b/android/core/src/processing/core/PApplet.java @@ -8060,8 +8060,8 @@ public class PApplet extends Activity implements PConstants, Runnable { // A3D-only functions // TODO: Discuss proper integration into PApplet API. - public PImage getLastFrame() { - return g.getLastFrame(); + public PImage getOffscreenImage() { + return g.getOffscreenImage(); } public void blend(int mode) { diff --git a/android/core/src/processing/core/PGraphics.java b/android/core/src/processing/core/PGraphics.java index 2d6363d59..e3c6d7f57 100644 --- a/android/core/src/processing/core/PGraphics.java +++ b/android/core/src/processing/core/PGraphics.java @@ -5069,9 +5069,9 @@ public class PGraphics extends PImage implements PConstants { // TODO: Discuss proper integration into PGraphics API. - public PImage getLastFrame() { + public PImage getOffscreenImage() { if (!(this instanceof PGraphicsAndroid3D)) { - showMissingWarning("getLastFrame"); + showMissingWarning("getOffscreenImage"); } return null; } diff --git a/android/core/src/processing/core/PGraphicsAndroid3D.java b/android/core/src/processing/core/PGraphicsAndroid3D.java index 44120fbc9..1e95f5480 100644 --- a/android/core/src/processing/core/PGraphicsAndroid3D.java +++ b/android/core/src/processing/core/PGraphicsAndroid3D.java @@ -48,7 +48,6 @@ import processing.core.PShape3D.VertexGroup; // drawPixels is missing...calls to glDrawPixels are commented out // setRasterPos() is also commented out -// remove the BufferUtil class at the end (verify the endian order, rewind, etc) /* * Android 3D renderer implemented with pure OpenGL ES 1.0/1.1 @@ -220,6 +219,7 @@ public class PGraphicsAndroid3D extends PGraphics { protected PImage textureImagePrev; protected IntBuffer getsetBuffer; + protected PTexture getsetTex; protected boolean buffersAllocated = false; // ........................................................ @@ -464,6 +464,7 @@ public class PGraphicsAndroid3D extends PGraphics { getsetBuffer = IntBuffer.allocate(1); getsetBuffer.rewind(); + getsetTex = new PTexture(parent, 1, 1, new PTexture.Parameters(ARGB, NEAREST)); buffersAllocated = true; } @@ -531,87 +532,17 @@ public class PGraphicsAndroid3D extends PGraphics { } protected void drawScreenTexture() { - gl.glEnable(texture.getGLTarget()); - gl.glBindTexture(texture.getGLTarget(), texture.getGLTextureID()); - gl.glDepthMask(false); - gl.glDisable(GL10.GL_BLEND); - - // There is no need to setup orthographic projection or any related matrix set/restore - // operations here because glDrawTexiOES operates on window coordinates: - // "glDrawTexiOES takes window coordinates and bypasses the transform pipeline - // (except for mapping Z to the depth range), so there is no need for any - // matrix setup/restore code." - // (from https://www.khronos.org/message_boards/viewtopic.php?f=4&t=948&p=2553). - - // This is the right texture environment mode to ignore the fill color when drawing the texture: - // http://www.khronos.org/opengles/documentation/opengles1_0/html/glTexEnv.html - gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); - - gl11.glTexParameteriv(texture.getGLTarget(), GL11Ext.GL_TEXTURE_CROP_RECT_OES, screenTexCrop, 0); - gl11x.glDrawTexiOES(0, 0, 0, width, height); - - // Returning to the default texture environment mode, GL_MODULATE. This allows tinting a texture - // with the current fill color. - gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE); - - gl.glDisable(texture.getGLTarget()); - - if (hints[DISABLE_DEPTH_MASK]) { - gl.glDepthMask(false); - } else { - gl.glDepthMask(true); - } - - if (blend) { - blend(blendMode); - } else { - noBlend(); - } + drawTexture(texture, screenTexCrop, 0, 0, width, height); } protected void copyToScreenTexture(IntBuffer buffer) { - gl.glEnable(texture.getGLTarget()); - gl.glBindTexture(texture.getGLTarget(), texture.getGLTextureID()); - gl.glTexSubImage2D(texture.getGLTarget(), 0, 0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer); - gl.glDisable(texture.getGLTarget()); + copyToTexture(texture, buffer, 0, 0, width, height); } protected void copyFrameToScreenTexture() { gl.glFinish(); // Make sure that the execution off all the openGL commands // is finished. - - loadTexture(); - - /* - // gl.glCopyTexImage2D method. Doesn't work on Galaxy S (powerSVG 540). - gl.glEnable(texture.getGLTarget()); - gl.glBindTexture(texture.getGLTarget(), texture.getGLTextureID()); - gl.glCopyTexImage2D(texture.getGLTarget(), 0, GL10.GL_RGB, 0, 0, width, height, 0); - gl.glDisable(texture.getGLTarget()); - */ - } - - // //////////////////////////////////////////////////////////// - - // FRAMEBUFFERS - - public void pushFramebuffer() { - fbStack.push(currentFramebuffer); - } - - public void setFramebuffer(PFramebuffer fbo) { - currentFramebuffer = fbo; - currentFramebuffer.bind(); - } - - public void popFramebuffer() { - try { - currentFramebuffer.finish(); - currentFramebuffer = fbStack.pop(); - currentFramebuffer.bind(); - } catch (EmptyStackException e) { - PGraphics.showWarning("A3D: Empty framebuffer stack"); - } + loadTexture(); } // //////////////////////////////////////////////////////////// @@ -662,37 +593,7 @@ public class PGraphicsAndroid3D extends PGraphics { protected void drawOffscreenTexture(int idx) { - PTexture tex = offscreenTextures[idx]; - - gl.glEnable(tex.getGLTarget()); - gl.glBindTexture(tex.getGLTarget(), tex.getGLTextureID()); - gl.glDepthMask(false); - gl.glDisable(GL10.GL_BLEND); - - // This is the right texture environment mode to ignore the fill color when drawing the texture: - // http://www.khronos.org/opengles/documentation/opengles1_0/html/glTexEnv.html - gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); - - gl11.glTexParameteriv(tex.getGLTarget(), GL11Ext.GL_TEXTURE_CROP_RECT_OES, offscreenTexCrop, 0); - gl11x.glDrawTexiOES(0, 0, 0, width, height); - - // Returning to the default texture environment mode, GL_MODULATE. This allows tinting a texture - // with the current fill color. - gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE); - - gl.glDisable(tex.getGLTarget()); - - if (hints[DISABLE_DEPTH_MASK]) { - gl.glDepthMask(false); - } else { - gl.glDepthMask(true); - } - - if (blend) { - blend(blendMode); - } else { - noBlend(); - } + drawTexture(offscreenTextures[idx], offscreenTexCrop, 0, 0, width, height); } @@ -701,6 +602,29 @@ public class PGraphicsAndroid3D extends PGraphics { } + // //////////////////////////////////////////////////////////// + + // FRAMEBUFFERS + + public void pushFramebuffer() { + fbStack.push(currentFramebuffer); + } + + public void setFramebuffer(PFramebuffer fbo) { + currentFramebuffer = fbo; + currentFramebuffer.bind(); + } + + public void popFramebuffer() { + try { + currentFramebuffer.finish(); + currentFramebuffer = fbStack.pop(); + currentFramebuffer.bind(); + } catch (EmptyStackException e) { + PGraphics.showWarning("A3D: Empty framebuffer stack"); + } + } + // //////////////////////////////////////////////////////////// // FRAME @@ -948,7 +872,7 @@ public class PGraphicsAndroid3D extends PGraphics { gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); } else { // We need to save the color buffer after finishing with the rendering of the this frame, - // to use is as the background for the next frame (incremental rendering). + // to use is as the background for the next frame (I call this "incremental rendering"). if (fboSupported) { if (offscreenFramebuffer != null) { @@ -4798,7 +4722,7 @@ public class PGraphicsAndroid3D extends PGraphics { } - public PImage getLastFrame() { + public PImage getOffscreenImage() { return offscreenImages[(offscreenIndex + 1) % 2]; } @@ -4880,112 +4804,62 @@ public class PGraphicsAndroid3D extends PGraphics { if (BIG_ENDIAN) { // convert ARGB to RGBA getset = (argb << 8) | 0xff; - } else { // convert ARGB to ABGR getset = (argb & 0xff00ff00) | ((argb << 16) & 0xff0000) | ((argb >> 16) & 0xff); } getsetBuffer.put(0, getset); - getsetBuffer.rewind(); - // gl.glRasterPos2f(x + EPSILON, y + EPSILON); - setRasterPos(x, (height - y) - 1); - // TODO whither drawPixels? - // gl.glDrawPixels(1, 1, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, getsetBuffer); + getsetBuffer.rewind(); + + copyToTexture(getsetTex, getsetBuffer, 0, 0, 1, 1); + + drawTexture(getsetTex, 0, 0, 1, 1, x, y, 1, 1); } /** * Set an image directly to the screen. - *

- * TODO not optimized properly, creates multiple temporary buffers the size of - * the image. Needs to instead use image cache, but that requires two types of - * image cache. One for power of 2 textures and another for - * glReadPixels/glDrawPixels data that's flipped vertically. Both have their - * components all swapped to native. + * */ public void set(int x, int y, PImage source) { - int[] backup = new int[source.pixels.length]; - System.arraycopy(source.pixels, 0, backup, 0, source.pixels.length); - javaToNativeARGB(source); - - // TODO is this possible without intbuffer? - IntBuffer setBuffer = IntBuffer.allocate(source.pixels.length); - setBuffer.rewind(); - - setBuffer.put(source.pixels); - setBuffer.rewind(); - - setRasterPos(x, (height - y) - source.height); // +source.height); - // gl.glDrawPixels(source.width, source.height, - // GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, setBuffer); - source.pixels = backup; - } - - // TODO remove the implementation above and use setImpl instead, - // since it'll be more efficient - // http://dev.processing.org/bugs/show_bug.cgi?id=943 - // protected void setImpl(int dx, int dy, int sx, int sy, int sw, int sh, - // PImage src) - - /** - * Definitive method for setting raster pos, including offscreen locations. - * The raster position is tricky because it's affected by the modelview and - * projection matrices. Further, offscreen coords won't properly set the - * raster position. This code gets around both issues. - * http://www.mesa3d.org/brianp/sig97/gotchas.htm - * - * @param y - * the Y-coordinate, which is flipped upside down in OpenGL - */ - protected void setRasterPos(float x, float y) { - //float z = 0; - //float w = 1; - - //float fx, fy; - - // // Push current matrix mode and viewport attributes - // gl.glPushAttrib(GL.GL_TRANSFORM_BIT | GL.GL_VIEWPORT_BIT); - - // // Setup projection parameters - //gl.glMatrixMode(GL10.GL_PROJECTION); - //gl.glPushMatrix(); - //gl.glLoadIdentity(); - //gl.glMatrixMode(GL.GL_MODELVIEW); - // gl.glPushMatrix(); - //gl.glLoadIdentity(); - // - // gl.glDepthRange(z, z); - // gl.glViewport((int) x - 1, (int) y - 1, 2, 2); - // - // // set the raster (window) position - // fx = x - (int) x; - // fy = y - (int) y; - // gl.glRasterPos4f(fx, fy, 0, w); - // gl.glR - - // - // // restore matrices, viewport and matrix mode - // gl.glPopMatrix(); - // gl.glMatrixMode(GL.GL_PROJECTION); - // gl.glPopMatrix(); - // - // gl.glPopAttrib(); - + // In A3D we can safely assume that the PImage has a valid associated texture. + PTexture tex = source.getTexture(); + if (tex != null) { + drawTexture(tex, 0, 0, source.width, source.height, x, y, source.width, source.height); + } else { + // throw warning here... + PGraphics.showWarning("A3D: The image doesn't have an associated texture to use."); + } } // Utility function to render texture. protected void drawTexture(PTexture tex, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { + int[] crop = {x1, y1, w1, h1}; + drawTexture(tex, crop, x2, y2, w2, h2); + } + + protected void drawTexture(PTexture tex, int[] crop, int x, int y, int w, int h) { gl.glEnable(tex.getGLTarget()); gl.glBindTexture(tex.getGLTarget(), tex.getGLTextureID()); gl.glDepthMask(false); gl.glDisable(GL10.GL_BLEND); + // The texels of the texture replace the color of wherever is in the screen. gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); - int[] crop = {x1, y1, w1, h1}; + // Setting texture crop. gl11.glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop, 0); - gl11x.glDrawTexiOES(0, x2, y2, w2, h2); + + // There is no need to setup orthographic projection or any related matrix set/restore + // operations here because glDrawTexiOES operates on window coordinates directly: + // "glDrawTexiOES takes window coordinates and bypasses the transform pipeline + // (except for mapping Z to the depth range), so there is no need for any + // matrix setup/restore code." + // (from https://www.khronos.org/message_boards/viewtopic.php?f=4&t=948&p=2553). + gl11x.glDrawTexiOES(0, x, y, w, h); + // Returning to the default texture environment mode, GL_MODULATE. This allows tinting a texture + // with the current fill color. gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE); gl.glDisable(tex.getGLTarget()); @@ -5003,6 +4877,14 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // Utility function to copy buffer to texture + protected void copyToTexture(PTexture tex, IntBuffer buffer, int x, int y, int w, int h) { + gl.glEnable(tex.getGLTarget()); + gl.glBindTexture(tex.getGLTarget(), tex.getGLTextureID()); + gl.glTexSubImage2D(tex.getGLTarget(), 0, x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer); + gl.glDisable(tex.getGLTarget()); + } + // //////////////////////////////////////////////////////////// // MASK