From 9e71ae0f05a990e37cce8741a626fd8b1a283adb Mon Sep 17 00:00:00 2001 From: codeanticode Date: Tue, 20 Mar 2012 14:35:03 +0000 Subject: [PATCH] Sync P3D on Android --- android/core/src/processing/core/PApplet.java | 1 + .../src/processing/core/PFontTexture.java | 19 +- .../src/processing/core/PFramebuffer.java | 40 +- android/core/src/processing/core/PGL.java | 198 +++-- .../core/src/processing/core/PGraphics.java | 4 + .../processing/core/PGraphicsAndroid3D.java | 730 +++++++++++------- android/core/src/processing/core/PShader.java | 16 +- .../core/src/processing/core/PShape3D.java | 291 +++++-- .../core/src/processing/core/PTexture.java | 23 +- .../src/processing/opengl/PFramebuffer.java | 2 - .../opengl/src/processing/opengl/PGL.java | 15 +- .../processing/opengl/PGraphicsOpenGL.java | 5 +- 12 files changed, 899 insertions(+), 445 deletions(-) diff --git a/android/core/src/processing/core/PApplet.java b/android/core/src/processing/core/PApplet.java index 22229e086..e7bacae17 100644 --- a/android/core/src/processing/core/PApplet.java +++ b/android/core/src/processing/core/PApplet.java @@ -2558,6 +2558,7 @@ public class PApplet extends Activity implements PConstants, Runnable { public void frameRate(float newRateTarget) { frameRateTarget = newRateTarget; frameRatePeriod = (long) (1000000000.0 / frameRateTarget); + g.setFrameRate(newRateTarget); } diff --git a/android/core/src/processing/core/PFontTexture.java b/android/core/src/processing/core/PFontTexture.java index 0f2b1aedd..c874131d0 100644 --- a/android/core/src/processing/core/PFontTexture.java +++ b/android/core/src/processing/core/PFontTexture.java @@ -49,8 +49,7 @@ import processing.core.PFont; class PFontTexture implements PConstants { protected PApplet parent; protected PGraphicsAndroid3D pg; - protected PGL pgl; - protected PGL.Context context; + protected PGL pgl; protected PFont font; protected int maxTexWidth; @@ -70,7 +69,6 @@ class PFontTexture implements PConstants { this.font = font; pg = (PGraphicsAndroid3D)parent.g; pgl = pg.pgl; - context = pgl.getContext(); initTexture(maxw, maxh); } @@ -218,6 +216,21 @@ class PFontTexture implements PConstants { } + public boolean contextIsOutdated() { + boolean outdated = false; + for (int i = 0; i < textures.length; i++) { + if (textures[i].contextIsOutdated()) { + outdated = true; + } + } + if (outdated) { + for (int i = 0; i < textures.length; i++) { + textures[i].glID = 0; + } + } + return outdated; + } + // Adds this glyph to the opengl texture in PFont. protected void addToTexture(int idx, PFont.Glyph glyph) { // We add one pixel to avoid issues when sampling the font texture at fractional diff --git a/android/core/src/processing/core/PFramebuffer.java b/android/core/src/processing/core/PFramebuffer.java index 138a18720..43ab3b33c 100644 --- a/android/core/src/processing/core/PFramebuffer.java +++ b/android/core/src/processing/core/PFramebuffer.java @@ -37,6 +37,7 @@ public class PFramebuffer implements PConstants { protected PApplet parent; protected PGraphicsAndroid3D pg; protected PGL pgl; + protected PGL.Context context; // The context that created this framebuffer. public int glFboID; public int glDepthBufferID; @@ -129,7 +130,7 @@ public class PFramebuffer implements PConstants { } screenFb = screen; - + allocate(); noDepth = false; @@ -178,10 +179,15 @@ public class PFramebuffer implements PConstants { public void copy(PFramebuffer dest) { pgl.glBindFramebuffer(PGL.GL_READ_FRAMEBUFFER, this.glFboID); pgl.glBindFramebuffer(PGL.GL_DRAW_FRAMEBUFFER, dest.glFboID); - pgl.glBlitFramebuffer(0, 0,this.width, this.height, 0, 0, dest.width, dest.height, PGL.GL_COLOR_BUFFER_BIT, PGL.GL_NEAREST); + pgl.glBlitFramebuffer(0, 0, this.width, this.height, + 0, 0, dest.width, dest.height, + PGL.GL_COLOR_BUFFER_BIT, PGL.GL_NEAREST); } public void bind() { + // if context is outdated ?? + + if (screenFb) { if (PGraphicsAndroid3D.fboSupported) { pgl.glBindFramebuffer(PGL.GL_FRAMEBUFFER, 0); @@ -336,10 +342,11 @@ public class PFramebuffer implements PConstants { protected void allocate() { release(); // Just in the case this object is being re-allocated. + context = pgl.getContext(); + if (screenFb) { glFboID = 0; - } else if (fboMode) { - //glFboID = ogl.createGLResource(PGraphicsAndroid3D.GL_FRAME_BUFFER); + } else if (fboMode) { glFboID = pg.createFrameBufferObject(); } else { glFboID = 0; @@ -349,7 +356,7 @@ public class PFramebuffer implements PConstants { if (multisample) { createColorBufferMultisample(); } - + if (combinedDepthStencil) { createCombinedDepthStencilBuffer(); } else { @@ -359,7 +366,7 @@ public class PFramebuffer implements PConstants { if (0 < stencilBits) { createStencilBuffer(); } - } + } } @@ -387,6 +394,25 @@ public class PFramebuffer implements PConstants { } + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + glFboID = 0; + glDepthBufferID = 0; + glStencilBufferID = 0; + glDepthStencilBufferID = 0; + glColorBufferMultisampleID = 0; + + for (int i = 0; i < numColorBuffers; i++) { + colorBufferTex[i] = null; + } + + backupTexture = null; + } + return outdated; + } + + protected void createColorBufferMultisample() { if (screenFb) return; @@ -395,7 +421,7 @@ public class PFramebuffer implements PConstants { pg.setFramebuffer(this); glColorBufferMultisampleID = pg.createRenderBufferObject(); - pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); + pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, PGL.GL_RGBA8, width, height); pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0, PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); diff --git a/android/core/src/processing/core/PGL.java b/android/core/src/processing/core/PGL.java index 9a34238e2..c1e428bcc 100644 --- a/android/core/src/processing/core/PGL.java +++ b/android/core/src/processing/core/PGL.java @@ -26,10 +26,12 @@ package processing.core; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; +import java.util.Arrays; import processing.glu.PGLU; import processing.glu.PGLUtessellator; import processing.glu.PGLUtessellatorCallbackAdapter; + import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; @@ -70,7 +72,7 @@ public class PGL { public static final int DEFAULT_TESS_INDICES = 32; /** Initial sizes for vertex cache used in PShape3D. */ - public static final int DEFAULT_VERTEX_CACHE_SIZE = 512; + public static final int DEFAULT_VERTEX_CACHE_SIZE = 256; /** Maximum lights by default is 8, the minimum defined by OpenGL. */ public static final int MAX_LIGHTS = 8; @@ -128,7 +130,7 @@ public class PGL { public static final int GL_CLAMP_TO_EDGE = GLES20.GL_CLAMP_TO_EDGE; public static final int GL_REPEAT = GLES20.GL_REPEAT; - public static final int GL_RGBA8 = -1; + public static final int GL_RGBA8 = -1; public static final int GL_DEPTH24_STENCIL8 = -1; public static final int GL_DEPTH_COMPONENT16 = GLES20.GL_DEPTH_COMPONENT16; @@ -142,6 +144,8 @@ public class PGL { public static final int GL_ARRAY_BUFFER = GLES20.GL_ARRAY_BUFFER; public static final int GL_ELEMENT_ARRAY_BUFFER = GLES20.GL_ELEMENT_ARRAY_BUFFER; + public static final int GL_SAMPLES = GLES20.GL_SAMPLES; + public static final int GL_FRAMEBUFFER_COMPLETE = GLES20.GL_FRAMEBUFFER_COMPLETE; public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; @@ -169,9 +173,9 @@ public class PGL { public static final int GL_EXTENSIONS = GLES20.GL_EXTENSIONS; public static final int GL_MAX_TEXTURE_SIZE = GLES20.GL_MAX_TEXTURE_SIZE; + public static final int GL_MAX_SAMPLES = -1; public static final int GL_ALIASED_LINE_WIDTH_RANGE = GLES20.GL_ALIASED_LINE_WIDTH_RANGE; public static final int GL_ALIASED_POINT_SIZE_RANGE = GLES20.GL_ALIASED_POINT_SIZE_RANGE; - public static final int GL_SAMPLES = GLES20.GL_SAMPLES; public static final int GLU_TESS_WINDING_NONZERO = PGLU.GLU_TESS_WINDING_NONZERO; public static final int GLU_TESS_WINDING_ODD = PGLU.GLU_TESS_WINDING_ODD; @@ -196,16 +200,16 @@ public class PGL { public static final int GL_DST_COLOR = GLES20.GL_DST_COLOR; public static final int GL_SRC_COLOR = GLES20.GL_SRC_COLOR; - public static final int GL_FRAMEBUFFER = GLES20.GL_FRAMEBUFFER; - public static final int GL_COLOR_ATTACHMENT0 = GLES20.GL_COLOR_ATTACHMENT0; + public static final int GL_FRAMEBUFFER = GLES20.GL_FRAMEBUFFER; + public static final int GL_COLOR_ATTACHMENT0 = GLES20.GL_COLOR_ATTACHMENT0; + public static final int GL_COLOR_ATTACHMENT1 = -1; + public static final int GL_COLOR_ATTACHMENT2 = -1; + public static final int GL_COLOR_ATTACHMENT3 = -1; public static final int GL_RENDERBUFFER = GLES20.GL_RENDERBUFFER; public static final int GL_DEPTH_ATTACHMENT = GLES20.GL_DEPTH_ATTACHMENT; public static final int GL_STENCIL_ATTACHMENT = GLES20.GL_STENCIL_ATTACHMENT; - public static final int GL_READ_FRAMEBUFFER = -1; - public static final int GL_DRAW_FRAMEBUFFER = -1; - public static final int GL_COLOR_ATTACHMENT1 = -1; - public static final int GL_COLOR_ATTACHMENT2 = -1; - public static final int GL_COLOR_ATTACHMENT3 = -1; + public static final int GL_READ_FRAMEBUFFER = -1; + public static final int GL_DRAW_FRAMEBUFFER = -1; public static final int GL_VERTEX_SHADER = GLES20.GL_VERTEX_SHADER; public static final int GL_FRAGMENT_SHADER = GLES20.GL_FRAGMENT_SHADER; @@ -219,38 +223,45 @@ public class PGL { public static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; public static final int EGL_OPENGL_ES2_BIT = 0x0004; + /** Basic GLES 1.0 interface */ public GL10 gl; - public PGLU glu; - - public AndroidRenderer renderer; + /** GLU interface **/ + public PGLU glu; + + /** The PGraphics object using this interface */ public PGraphicsAndroid3D pg; + /** Whether OpenGL has been initialized or not */ public boolean initialized; - + + /** The renderer object driving the rendering loop, + * analogous to the GLEventListener in JOGL */ + protected AndroidRenderer renderer; + /////////////////////////////////////////////////////////////////////////////////// // Intialization, finalization // TODO: implement double buffering support in onscreen rendering, offscreen rendering. + public PGL(PGraphicsAndroid3D pg) { this.pg = pg; renderer = new AndroidRenderer(); glu = new PGLU(); initialized = false; } + - static public void startup(boolean beforeUI) { + public void setFramerate(float framerate) { } - static public void shutdown() { - } - public void updatePrimary() { - + public void updatePrimary() { } + public void updateOffscreen(PGL primary) { gl = primary.gl; } @@ -301,6 +312,7 @@ public class PGL { initialized = true; } + public void initOffscreenSurface(PGL primary) { /* @@ -345,25 +357,11 @@ public class PGL { initialized = true; } - public void updateOffscreenSurface(PGL primary) { - } - - protected void detainContext() { - } - - public void releaseContext() { - } - - public void destroyContext() { - } /////////////////////////////////////////////////////////////////////////////////// // Frame rendering - - public boolean initOnscreenDraw() { - return true; - } + public void beginOnscreenDraw(boolean clear, int frame) { GLES20.glClearColor(0, 0, 0, 0); @@ -411,6 +409,7 @@ public class PGL { */ } + public void endOnscreenDraw(boolean clear0) { /* if (!clear0) { @@ -458,14 +457,17 @@ public class PGL { */ } + public void endOffscreenDraw(boolean clear0) { //swapOffscreenIndex(); } + public boolean canDraw() { return true; } + public void requestDraw() { if (pg.parent.looping) { // This "if" is needed to avoid flickering when looping is disabled. ((GLSurfaceView) pg.parent.surfaceView).requestRender(); @@ -477,71 +479,91 @@ public class PGL { // Caps query + public String glGetString(int name) { return GLES20.glGetString(name); } + public void glGetIntegerv(int name, int[] values, int offset) { - GLES20.glGetIntegerv(name, values, offset); + if (-1 < name) { + GLES20.glGetIntegerv(name, values, offset); + } else { + Arrays.fill(values, 0); + } } + /////////////////////////////////////////////////////////////////////////////////// // Enable/disable caps + public void glEnable(int cap) { if (-1 < cap) { GLES20.glEnable(cap); } } + public void glDisable(int cap) { if (-1 < cap) { GLES20.glDisable(cap); } } + /////////////////////////////////////////////////////////////////////////////////// // Render control + public void glFlush() { GLES20.glFlush(); } + public void glFinish() { GLES20.glFinish(); } + ///////////////////////////////////////////////////////////////////////////////// // Error handling + public int glGetError() { return GLES20.glGetError(); } + public String glErrorString(int err) { return GLU.gluErrorString(err); } + public String gluErrorString(int err) { return PGLU.gluErrorString(err); } + ///////////////////////////////////////////////////////////////////////////////// // Rendering options - public void setFrontFace(int mode) { + + public void glFrontFace(int mode) { GLES20.glFrontFace(mode); } - + + public void glDepthMask(boolean flag) { GLES20.glDepthMask(flag); } - - public void setDepthFunc(int func) { + + + public void glDepthFunc(int func) { GLES20.glDepthFunc(func); } @@ -550,58 +572,72 @@ public class PGL { // Textures + public void glGenTextures(int n, int[] ids, int offset) { GLES20.glGenTextures(n, ids, offset); } + public void glDeleteTextures(int n, int[] ids, int offset) { GLES20.glDeleteTextures(n, ids, offset); } + public void glActiveTexture(int unit) { GLES20.glActiveTexture(unit); } + public void glBindTexture(int target, int id) { GLES20.glBindTexture(target, id); } - + + public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer data) { GLES20.glTexImage2D(target, level, internalFormat, width, height, border, format, type, data); } + public void glTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, Buffer data) { GLES20.glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, data); } + public void glTexParameterf(int target, int param, int value) { GLES20.glTexParameterf(target, param, value); } + public void glGenerateMipmap(int target) { GLES20.glGenerateMipmap(target); } + ///////////////////////////////////////////////////////////////////////////////// // Vertex Buffers + public void glGenBuffers(int n, int[] ids, int offset) { GLES20.glGenBuffers(n, ids, offset); } + public void glDeleteBuffers(int n, int[] ids, int offset) { GLES20.glDeleteBuffers(n, ids, offset); } + public void glBindBuffer(int target, int id) { GLES20.glBindBuffer(target, id); } + public void glBufferData(int target, int size, Buffer data, int usage) { GLES20.glBufferData(target, size, data, usage); } + public void glBufferSubData(int target, int offset, int size, Buffer data) { GLES20.glBufferSubData(target, offset, size, data); } @@ -616,10 +652,12 @@ public class PGL { GLES20.glEnableVertexAttribArray(loc); } + public void glDisableVertexAttribArray(int loc) { GLES20.glDisableVertexAttribArray(loc); } + public void glVertexAttribPointer(int loc, int size, int type, boolean normalized, int stride, int offset) { GLES20.glVertexAttribPointer(loc, size, type, normalized, stride, offset); } @@ -630,183 +668,228 @@ public class PGL { return null; } + public ByteBuffer glMapBufferRange(int target, int offset, int length, int access) { //return gl2x.glMapBufferRange(GL.GL_ARRAY_BUFFER, offset, length, GL2.GL_READ_WRITE); return null; } + public void glUnmapBuffer(int target) { //gl2f.glUnmapBuffer(GL.GL_ARRAY_BUFFER); } + ///////////////////////////////////////////////////////////////////////////////// // Framebuffers, renderbuffers + public void glGenFramebuffers(int n, int[] ids, int offset) { GLES20.glGenFramebuffers(n, ids, offset); } + public void glDeleteFramebuffers(int n, int[] ids, int offset) { GLES20.glDeleteFramebuffers(n, ids, offset); } + public void glGenRenderbuffers(int n, int[] ids, int offset) { GLES20.glGenRenderbuffers(n, ids, offset); } + public void glDeleteRenderbuffers(int n, int[] ids, int offset) { GLES20.glDeleteRenderbuffers(n, ids, offset); } + public void glBindFramebuffer(int target, int id) { GLES20.glBindFramebuffer(target, id); } + public void glBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { // GLES20.glBlitFramebuffer(0, 0, srcW, srcH, 0, 0, destW, destH, GLES20.GL_COLOR_BUFFER_BIT, GLES20.GL_NEAREST); } + public void glFramebufferTexture2D(int target, int attachment, int texTarget, int texId, int level) { GLES20.glFramebufferTexture2D(target, attachment, texTarget, texId, level); } + public void glBindRenderbuffer(int target, int id) { GLES20.glBindRenderbuffer(target, id); } - + + public void glRenderbufferStorageMultisample(int target, int samples, int format, int width, int height) { // GLES20.glRenderbufferStorageMultisample(GLES20.GL_RENDERBUFFER, samples, format, w, h); } + public void glRenderbufferStorage(int target, int format, int width, int height) { // GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, format, w, h); } + public void glFramebufferRenderbuffer(int target, int attachment, int rendbufTarget, int rendbufId) { GLES20.glFramebufferRenderbuffer(target, attachment, rendbufTarget, rendbufId); } + public int glCheckFramebufferStatus(int target) { return GLES20.glCheckFramebufferStatus(target); } + ///////////////////////////////////////////////////////////////////////////////// // Shaders + public int glCreateProgram() { return GLES20.glCreateProgram(); } + public void glDeleteProgram(int id) { GLES20.glDeleteProgram(id); } + public int glCreateShader(int type) { return GLES20.glCreateShader(type); } + public void glDeleteShader(int id) { GLES20.glDeleteShader(id); } - + + public void glLinkProgram(int prog) { GLES20.glLinkProgram(prog); } + public void glValidateProgram(int prog) { GLES20.glValidateProgram(prog); } + public void glUseProgram(int prog) { GLES20.glUseProgram(prog); } + public int glGetAttribLocation(int prog, String name) { return GLES20.glGetAttribLocation(prog, name); } + public int glGetUniformLocation(int prog, String name) { return GLES20.glGetUniformLocation(prog, name); } + public void glUniform1i(int loc, int value) { GLES20.glUniform1i(loc, value); } + public void glUniform1f(int loc, float value) { GLES20.glUniform1f(loc, value); } + public void glUniform2f(int loc, float value0, float value1) { GLES20.glUniform2f(loc, value0, value1); } + public void glUniform3f(int loc, float value0, float value1, float value2) { GLES20.glUniform3f(loc, value0, value1, value2); } + public void glUniform4f(int loc, float value0, float value1, float value2, float value3) { GLES20.glUniform4f(loc, value0, value1, value2, value3); } + public void glUniform1fv(int loc, int count, float[] v, int offset) { GLES20.glUniform1fv(loc, count, v, offset); } + public void glUniform2fv(int loc, int count, float[] v, int offset) { GLES20.glUniform2fv(loc, count, v, offset); } + public void glUniform3fv(int loc, int count, float[] v, int offset) { GLES20.glUniform3fv(loc, count, v, offset); } + public void glUniform4fv(int loc, int count, float[] v, int offset) { GLES20.glUniform4fv(loc, count, v, offset); } + public void glUniformMatrix2fv(int loc, int count, boolean transpose, float[] mat, int offset) { GLES20.glUniformMatrix2fv(loc, count, transpose, mat, offset); } + public void glUniformMatrix3fv(int loc, int count, boolean transpose, float[] mat, int offset) { GLES20.glUniformMatrix3fv(loc, count, transpose, mat, offset); } + public void glUniformMatrix4fv(int loc, int count, boolean transpose, float[] mat, int offset) { GLES20.glUniformMatrix4fv(loc, count, transpose, mat, offset); } + public void glVertexAttrib1f(int loc, float value) { GLES20.glVertexAttrib1f(loc, value); } + public void glVertexAttrib2f(int loc, float value0, float value1) { GLES20.glVertexAttrib2f(loc, value0, value1); } + public void glVertexAttrib3f(int loc, float value0, float value1, float value2) { GLES20.glVertexAttrib3f(loc, value0, value1, value2); } + public void glVertexAttrib4f(int loc, float value0, float value1, float value2, float value3) { GLES20.glVertexAttrib4f(loc, value0, value1, value2, value3); } + public void glShaderSource(int id, String source) { GLES20.glShaderSource(id, source); } + public void glCompileShader(int id) { GLES20.glCompileShader(id); } + public void glAttachShader(int prog, int shader) { GLES20.glAttachShader(prog, shader); } + ///////////////////////////////////////////////////////////////////////////////// // Viewport @@ -816,6 +899,7 @@ public class PGL { GLES20.glViewport(x, y, width, height); } + ///////////////////////////////////////////////////////////////////////////////// // Clipping (scissor test) @@ -845,22 +929,27 @@ public class PGL { // Pixels - public void setReadBuffer(int buf) { + + public void glReadBuffer(int buf) { // GLES20.glReadBuffer(buf); } + public void glReadPixels(int x, int y, int width, int height, int format, int type, Buffer buffer) { GLES20.glReadPixels(x, y, width, height, format, type, buffer); } - public void setDrawBuffer(int buf) { + + public void glDrawBuffer(int buf) { // GLES20.glDrawBuffer(GLES20.GL_COLOR_ATTACHMENT0 + buf); } + public void glClearColor(float r, float g, float b, float a) { GLES20.glClearColor(r, g, b, a); } + public void glClear(int mask) { GLES20.glClear(mask); } @@ -870,10 +959,12 @@ public class PGL { // Context interface + public Context getContext() { return new Context(/*context*/); } + public class Context { //protected GLContext context; @@ -890,11 +981,13 @@ public class PGL { ///////////////////////////////////////////////////////////////////////////////// // Tessellator interface - + + public Tessellator createTessellator(TessellatorCallback callback) { return new Tessellator(callback); } + public class Tessellator { protected PGLUtessellator tess; protected TessellatorCallback callback; @@ -960,6 +1053,7 @@ public class PGL { } } + public interface TessellatorCallback { public void begin(int type); public void end(); @@ -969,14 +1063,17 @@ public class PGL { public void error(int errnum); } + /////////////////////////////////////////////////////////////////////////////////// // Utility functions + public boolean contextIsCurrent(Context other) { return other.same(/*context*/); } + static public short makeIndex(int intIdx) { // When the index value is greater than 32767, subtracting 65536 // will make it (as a short) to wrap around to the negative range, which @@ -986,14 +1083,17 @@ public class PGL { return 32767 < intIdx ? (short)(intIdx - 65536) : (short)intIdx; } + public void enableTexturing(int target) { //gl.glEnable(target); } + public void disableTexturing(int target) { //gl.glDisable(target); } + public void initTexture(int target, int width, int height, int format, int type) { // Doing in patches of 16x16 pixels to avoid creating a (potentially) // very large transient array which in certain situations (memory- @@ -1008,6 +1108,7 @@ public class PGL { } } + public String getShaderLog(int id) { int[] compiled = new int[1]; GLES20.glGetShaderiv(id, GLES20.GL_COMPILE_STATUS, compiled, 0); @@ -1018,22 +1119,27 @@ public class PGL { } } + ///////////////////////////////////////////////////////////////////////////////// // Android specific stuff + public AndroidRenderer getRenderer() { return renderer; } + public AndroidContextFactory getContextFactory() { return new AndroidContextFactory(); } + public AndroidConfigChooser getConfigChooser(int r, int g, int b, int a, int d, int s) { return new AndroidConfigChooser(r, g, b, a, d, s); } + public class AndroidRenderer implements Renderer { public AndroidRenderer() { } @@ -1057,6 +1163,7 @@ public class PGL { } } + public class AndroidContextFactory implements GLSurfaceView.EGLContextFactory { public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { @@ -1071,6 +1178,7 @@ public class PGL { } } + public class AndroidConfigChooser implements EGLConfigChooser { // Desired size (in bits) for the rgba color, depth and stencil buffers. public int redTarget; diff --git a/android/core/src/processing/core/PGraphics.java b/android/core/src/processing/core/PGraphics.java index 3ee5a53e8..95e774b01 100644 --- a/android/core/src/processing/core/PGraphics.java +++ b/android/core/src/processing/core/PGraphics.java @@ -583,6 +583,10 @@ public class PGraphics extends PImage implements PConstants { this.path = path; } + + public void setFrameRate(float framerate) { // ignore + } + /** * The final step in setting up a renderer, set its size of this renderer. diff --git a/android/core/src/processing/core/PGraphicsAndroid3D.java b/android/core/src/processing/core/PGraphicsAndroid3D.java index ffb760985..eff1c7506 100644 --- a/android/core/src/processing/core/PGraphicsAndroid3D.java +++ b/android/core/src/processing/core/PGraphicsAndroid3D.java @@ -32,6 +32,7 @@ import java.util.Set; import java.util.HashSet; import java.util.Stack; + // drawPixels is missing...calls to glDrawPixels are commented out // setRasterPos() is also commented out @@ -89,9 +90,10 @@ public class PGraphicsAndroid3D extends PGraphics { /** Some hardware limits */ static public int maxTextureSize; + static public int maxSamples; static public float maxPointSize; static public float maxLineWidth; - + /** OpenGL information strings */ static public String OPENGL_VENDOR; static public String OPENGL_RENDERER; @@ -309,7 +311,7 @@ public class PGraphicsAndroid3D extends PGraphics { /** Used to register calls to glClear. */ protected boolean clearColorBuffer; - protected boolean clearColorBuffer0; + protected boolean clearColorBuffer0; protected boolean openContour = false; protected boolean breakShape = false; @@ -391,13 +393,15 @@ public class PGraphicsAndroid3D extends PGraphics { */ static public boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// // INIT/ALLOCATE/FINISH + public PGraphicsAndroid3D() { pgl = new PGL(this); + pg = null; tessellator = new Tessellator(); @@ -426,6 +430,7 @@ public class PGraphicsAndroid3D extends PGraphics { glPointIndexBufferID = 0; } + //public void setParent(PApplet parent) // PGraphics @@ -436,7 +441,16 @@ public class PGraphicsAndroid3D extends PGraphics { //public void setPath(String path) // PGraphics - + + + //public void setAntiAlias(int samples) // PGraphics + + + public void setFrameRate(float framerate) { + pgl.setFramerate(framerate); + } + + public void setSize(int iwidth, int iheight) { resized = (0 < width && width != iwidth) || (0 < height && height != iwidth); @@ -448,8 +462,6 @@ public class PGraphicsAndroid3D extends PGraphics { allocate(); reapplySettings(); - vertexCheck(); - // init perspective projection based on new dimensions cameraFOV = 60 * DEG_TO_RAD; // at least for now cameraX = width / 2.0f; @@ -461,7 +473,10 @@ public class PGraphicsAndroid3D extends PGraphics { cameraDepth = cameraZ; // eye is at (cameraX, cameraY, cameraZ), aiming at (cameraX, cameraY, 0) // set this flag so that beginDraw() will do an update to the camera. - sizeChanged = true; + sizeChanged = true; + + // Forces a restart of OpenGL so the canvas has the right size. + pgl.initialized = false; } @@ -496,41 +511,12 @@ public class PGraphicsAndroid3D extends PGraphics { currentLightSpecular = new float[3]; lightsAllocated = true; } - - if (primarySurface) { - // Allocation of the main renderer, which mainly involves initializing OpenGL. -// if (context == null) { -// initPrimary(); -// } else { -// reapplySettings(); -// } - if (pgl.initialized) { - reapplySettings(); - } - } else { - // Allocation of an offscreen renderer. -// if (context == null) { -// initOffscreen(); -// } else { -// // Updating OpenGL context associated to this offscreen -// // surface, to take into account a context recreation situation. -// updateOffscreenContext(); -// reapplySettings(); -// } - if (pgl.initialized) { - updateOffscreenContext(); - reapplySettings(); - } - } } public void dispose() { // PGraphics super.dispose(); - pgl.detainContext(); - deleteFinalizedGLResources(); - pgl.releaseContext(); - PGL.shutdown(); + deleteFinalizedGLResources(); } @@ -544,6 +530,7 @@ public class PGraphicsAndroid3D extends PGraphics { // RESOURCE HANDLING + // Texture Objects ------------------------------------------- protected int createTextureObject() { @@ -603,6 +590,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // Vertex Buffer Objects ---------------------------------------------- protected int createVertexBufferObject() { @@ -662,6 +650,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // FrameBuffer Objects ----------------------------------------- protected int createFrameBufferObject() { @@ -721,13 +710,14 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // RenderBuffer Objects ----------------------------------------------- protected int createRenderBufferObject() { deleteFinalizedRenderBufferObjects(); int[] temp = new int[1]; - pgl.glDeleteRenderbuffers(1, temp, 0); + pgl.glGenRenderbuffers(1, temp, 0); int id = temp[0]; if (glRenderBuffers.containsKey(id)) { @@ -741,8 +731,8 @@ public class PGraphicsAndroid3D extends PGraphics { protected void deleteRenderBufferObject(int id) { if (glRenderBuffers.containsKey(id)) { - int[] temp = { id }; - pgl.glGenRenderbuffers(1, temp, 0); + int[] temp = { id }; + pgl.glDeleteRenderbuffers(1, temp, 0); glRenderBuffers.remove(id); } } @@ -780,6 +770,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // GLSL Program Objects ----------------------------------------------- protected int createGLSLProgramObject() { @@ -834,6 +825,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // GLSL Vertex Shader Objects ----------------------------------------------- protected int createGLSLVertShaderObject() { @@ -888,8 +880,8 @@ public class PGraphicsAndroid3D extends PGraphics { } } - // GLSL Fragment Shader Objects ----------------------------------------------- - + + // GLSL Fragment Shader Objects ----------------------------------------------- protected int createGLSLFragShaderObject() { deleteFinalizedGLSLFragShaderObjects(); @@ -953,7 +945,8 @@ public class PGraphicsAndroid3D extends PGraphics { deleteFinalizedGLSLVertShaderObjects(); deleteFinalizedGLSLFragShaderObjects(); } - + + protected void deleteAllGLResources() { deleteAllTextureObjects(); deleteAllVertexBufferObjects(); @@ -964,10 +957,12 @@ public class PGraphicsAndroid3D extends PGraphics { deleteAllGLSLFragShaderObjects(); } + ////////////////////////////////////////////////////////////// // FRAMEBUFFERS + public void pushFramebuffer() { fbStack.push(currentFramebuffer); } @@ -989,25 +984,12 @@ public class PGraphicsAndroid3D extends PGraphics { } } + ////////////////////////////////////////////////////////////// // FRAME RENDERING + -// public GLContext getContext() { -// return context; -// } -// public GLCapabilities getCapabilities() { -// return capabilities; -// } -// public GLProfile getProfile() { -// return profile; -// } -// public GLDrawable getDrawable() { -// return drawable; -// } - - - protected void releaseResources() { // First, releasing the resources used by // the renderer itself. @@ -1044,6 +1026,36 @@ public class PGraphicsAndroid3D extends PGraphics { if (defPointShader != null) { defPointShader.release(); defPointShader = null; + } + + if (fillShaderSimple != null) { + fillShaderSimple.release(); + fillShaderSimple = null; + } + + if (fillShaderTex != null) { + fillShaderTex.release(); + fillShaderTex = null; + } + + if (fillShaderLit != null) { + fillShaderLit.release(); + fillShaderLit = null; + } + + if (fillShaderFull != null) { + fillShaderFull.release(); + fillShaderFull = null; + } + + if (lineShader != null) { + lineShader.release(); + lineShader = null; + } + + if (pointShader != null) { + pointShader.release(); + pointShader = null; } if (fillVBOsCreated) { @@ -1065,21 +1077,8 @@ public class PGraphicsAndroid3D extends PGraphics { // (from user's objects). deleteAllGLResources(); } - - /** - * Destroys current OpenGL context and creates a new one, making sure that all - * the current OpenGL objects remain valid afterward. - */ - public void restartContext() { - releaseResources(); - - pgl.releaseContext(); - pgl.destroyContext(); - restartSurface(); - pgl.detainContext(); - updatePGL(); - } + protected void createFillBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizei = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_INT; @@ -1126,6 +1125,7 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } + protected void updateFillBuffers(boolean lit, boolean tex) { int size = tessGeo.fillVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; @@ -1159,8 +1159,19 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillTexCoordBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.fillTexcoords, 0, 2 * size), vboMode); } + + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.fillIndexCount * PGL.SIZEOF_INDEX, + ShortBuffer.wrap(tessGeo.fillIndices, 0, tessGeo.fillIndexCount), vboMode); } + + protected void unbindFillBuffers() { + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + protected void releaseFillBuffers() { deleteVertexBufferObject(glFillVertexBufferID); glFillVertexBufferID = 0; @@ -1190,6 +1201,7 @@ public class PGraphicsAndroid3D extends PGraphics { glFillIndexBufferID = 0; } + protected void createLineBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; @@ -1217,6 +1229,7 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } + protected void updateLineBuffers() { int size = tessGeo.lineVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; @@ -1230,8 +1243,19 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineDirWidthBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 4 * sizef, FloatBuffer.wrap(tessGeo.lineDirWidths, 0, 4 * size), vboMode); + + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glLineIndexBufferID); + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.lineIndexCount * PGL.SIZEOF_INDEX, + ShortBuffer.wrap(tessGeo.lineIndices, 0, tessGeo.lineIndexCount), vboMode); } + + protected void unbindLineBuffers() { + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + protected void releaseLineBuffers() { deleteVertexBufferObject(glLineVertexBufferID); glLineVertexBufferID = 0; @@ -1246,6 +1270,7 @@ public class PGraphicsAndroid3D extends PGraphics { glLineIndexBufferID = 0; } + protected void createPointBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; @@ -1272,6 +1297,7 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } + protected void updatePointBuffers() { int size = tessGeo.pointVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; @@ -1284,9 +1310,20 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.pointColors, 0, size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.pointSizes, 0, 2 * size), vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.pointSizes, 0, 2 * size), vboMode); + + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glPointIndexBufferID); + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.pointIndexCount * PGL.SIZEOF_INDEX, + ShortBuffer.wrap(tessGeo.pointIndices, 0, tessGeo.pointIndexCount), vboMode); } + + protected void unbindPointBuffers() { + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + protected void releasePointBuffers() { deleteVertexBufferObject(glPointVertexBufferID); glPointVertexBufferID = 0; @@ -1312,8 +1349,14 @@ public class PGraphicsAndroid3D extends PGraphics { public void requestDraw() { - pgl.requestDraw(); - } + if (primarySurface) { + if (pgl.initialized) { + pgl.requestDraw(); + } else { + initPrimary(); + } + } + } public void beginDraw() { @@ -1323,29 +1366,29 @@ public class PGraphicsAndroid3D extends PGraphics { } if (primarySurface) { - if (!pgl.initialized) { - initPrimary(); - } - - if (!pgl.initOnscreenDraw()) { - return; - } - pgl.detainContext(); + pgl.updatePrimary(); } else { if (!pgl.initialized) { - initOffscreen(); - } + initOffscreen(); + } else { + boolean outdated = offscreenFramebuffer != null && offscreenFramebuffer.contextIsOutdated(); + boolean outdatedMulti = offscreenFramebufferMultisample != null && offscreenFramebufferMultisample.contextIsOutdated(); + if (outdated || outdatedMulti) { + pgl.initialized = false; + initOffscreen(); + } + } pushFramebuffer(); if (offscreenMultisample) { setFramebuffer(offscreenFramebufferMultisample); - pgl.setDrawBuffer(0); + pgl.glDrawBuffer(PGL.GL_COLOR_ATTACHMENT0); } else { setFramebuffer(offscreenFramebuffer); - } - } + } - updatePGL(); + pgl.updateOffscreen(pg.pgl); + } if (!glParamsRead) { getGLParameters(); @@ -1357,20 +1400,11 @@ public class PGraphicsAndroid3D extends PGraphics { // We are ready to go! - report("top beginDraw()"); + report("top beginDraw()"); - if (!primarySurface) { - pg.saveGLState(); - - // Disabling all lights, so the offscreen renderer can set completely - // new light configuration (otherwise some light configuration from the - // primary renderer might stay). - //pg.disableLights(); - } - - inGeo.reset(); - tessGeo.reset(); - texCache.reset(); + inGeo.clear(); + tessGeo.clear(); + texCache.clear(); // Each frame starts with textures disabled. super.noTexture(); @@ -1388,13 +1422,7 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glEnable(PGL.GL_DEPTH_TEST); } // use <= since that's what processing.core does - pgl.setDepthFunc(PGL.GL_LEQUAL); - - if (hints[DISABLE_DEPTH_MASK]) { - pgl.glDepthMask(false); - } else { - pgl.glDepthMask(true); - } + pgl.glDepthFunc(PGL.GL_LEQUAL); if (hints[ENABLE_ACCURATE_2D]) { flushMode = FLUSH_CONTINUOUSLY; @@ -1402,6 +1430,25 @@ public class PGraphicsAndroid3D extends PGraphics { flushMode = FLUSH_WHEN_FULL; } + if (primarySurface) { + int[] temp = { 0 }; + pgl.glGetIntegerv(PGL.GL_SAMPLES, temp, 0); + if (antialias != temp[0] && 1 < temp[0] && 1 < antialias) { + antialias = temp[0]; + } + } + if (antialias < 2) { + pgl.glDisable(PGL.GL_MULTISAMPLE); + pgl.glEnable(PGL.GL_POINT_SMOOTH); + pgl.glEnable(PGL.GL_LINE_SMOOTH); + pgl.glEnable(PGL.GL_POLYGON_SMOOTH); + } else { + pgl.glEnable(PGL.GL_MULTISAMPLE); + pgl.glDisable(PGL.GL_POINT_SMOOTH); + pgl.glDisable(PGL.GL_LINE_SMOOTH); + pgl.glDisable(PGL.GL_POLYGON_SMOOTH); + } + // setup opengl viewport. pgl.glGetIntegerv(PGL.GL_VIEWPORT, savedViewport, 0); viewport[0] = 0; viewport[1] = 0; viewport[2] = width; viewport[3] = height; @@ -1447,7 +1494,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightSpecular(0, 0, 0); // because y is flipped - pgl.setFrontFace(PGL.GL_CW); + pgl.glFrontFace(PGL.GL_CW); // Processing uses only one texture unit. pgl.glActiveTexture(PGL.GL_TEXTURE0); @@ -1456,9 +1503,16 @@ public class PGraphicsAndroid3D extends PGraphics { normalX = normalY = normalZ = 0; // Clear depth and stencil buffers. + pgl.glDepthMask(true); pgl.glClearColor(0, 0, 0, 0); pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT | PGL.GL_STENCIL_BUFFER_BIT); + if (hints[DISABLE_DEPTH_MASK]) { + pgl.glDepthMask(false); + } else { + pgl.glDepthMask(true); + } + if (primarySurface) { pgl.beginOnscreenDraw(clearColorBuffer, parent.frameCount); } else { @@ -1495,9 +1549,8 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]); if (primarySurface) { - pgl.glFlush(); + pgl.glFlush(); pgl.endOnscreenDraw(clearColorBuffer0); - pgl.releaseContext(); } else { if (offscreenMultisample) { offscreenFramebufferMultisample.copy(offscreenFramebuffer); @@ -1506,7 +1559,7 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.endOffscreenDraw(clearColorBuffer0); - pg.restoreGLState(); + pg.restoreGL(); } drawing = false; @@ -1516,73 +1569,68 @@ public class PGraphicsAndroid3D extends PGraphics { public PGL beginPGL() { - saveGLState(); return pgl; } public void endPGL() { - restoreGLState(); + restoreGL(); } - public void updatePGL() { - if (primarySurface) { - pgl.updatePrimary(); - } else { - pgl.updateOffscreen(pg.pgl); - } + public void restartPGL() { + pgl.initialized = false; } - protected void saveGLState() { - } - - - protected void restoreGLState() { - // Restoring viewport. - pgl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + protected void restoreGL() { + blendMode(blendMode); - // Restoring hints. if (hints[DISABLE_DEPTH_TEST]) { pgl.glDisable(PGL.GL_DEPTH_TEST); - pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); } else { pgl.glEnable(PGL.GL_DEPTH_TEST); } + pgl.glDepthFunc(PGL.GL_LEQUAL); + + if (antialias < 2) { + pgl.glDisable(PGL.GL_MULTISAMPLE); + pgl.glEnable(PGL.GL_POINT_SMOOTH); + pgl.glEnable(PGL.GL_LINE_SMOOTH); + pgl.glEnable(PGL.GL_POLYGON_SMOOTH); + } else { + pgl.glEnable(PGL.GL_MULTISAMPLE); + pgl.glDisable(PGL.GL_POINT_SMOOTH); + pgl.glDisable(PGL.GL_LINE_SMOOTH); + pgl.glDisable(PGL.GL_POLYGON_SMOOTH); + } + + pgl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + pgl.glFrontFace(PGL.GL_CW); + + pgl.glActiveTexture(PGL.GL_TEXTURE0); if (hints[DISABLE_DEPTH_MASK]) { pgl.glDepthMask(false); } else { pgl.glDepthMask(true); - } - - // Restoring blending. - blendMode(blendMode); - - // Some things the user might have changed from OpenGL, - // but we want to make sure they return to the Processing - // defaults (plus these cannot be changed through the API - // so they should remain constant anyways): - pgl.setFrontFace(PGL.GL_CW); - pgl.setDepthFunc(PGL.GL_LEQUAL); - } - + } + } + // Utility function to get ready OpenGL for a specific // operation, such as grabbing the contents of the color // buffer. protected void beginGLOp() { - pgl.detainContext(); - updatePGL(); + pgl.updateOffscreen(pg.pgl); } // Pairs-up with beginGLOp(). protected void endGLOp() { - pgl.releaseContext(); } + protected void updateGLProjection() { if (glProjection == null) { @@ -1610,6 +1658,7 @@ public class PGraphicsAndroid3D extends PGraphics { glProjection[15] = projection.m33; } + protected void updateGLModelview() { if (glModelview == null) { glModelview = new float[16]; @@ -1636,11 +1685,13 @@ public class PGraphicsAndroid3D extends PGraphics { glModelview[15] = modelview.m33; } + protected void calcProjmodelview() { projmodelview.set(projection); projmodelview.apply(modelview); } + protected void updateGLProjmodelview() { if (glProjmodelview == null) { glProjmodelview = new float[16]; @@ -1667,6 +1718,7 @@ public class PGraphicsAndroid3D extends PGraphics { glProjmodelview[15] = projmodelview.m33; } + protected void updateGLNormal() { if (glNormal == null) { glNormal = new float[9]; @@ -1689,6 +1741,7 @@ public class PGraphicsAndroid3D extends PGraphics { glNormal[8] = modelviewInv.m22; } + ////////////////////////////////////////////////////////////// // SETTINGS @@ -1725,15 +1778,17 @@ public class PGraphicsAndroid3D extends PGraphics { ambient(80); specular(125); emissive(0); - shininess(1); + shininess(1); } + // reapplySettings ////////////////////////////////////////////////////////////// // HINTS + public void hint(int which) { boolean oldValue = hints[PApplet.abs(which)]; super.hint(which); @@ -1746,46 +1801,35 @@ public class PGraphicsAndroid3D extends PGraphics { if (which == DISABLE_DEPTH_TEST) { flush(); pgl.glDisable(PGL.GL_DEPTH_TEST); - pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); - } else if (which == ENABLE_DEPTH_TEST) { flush(); pgl.glEnable(PGL.GL_DEPTH_TEST); - } else if (which == DISABLE_DEPTH_MASK) { flush(); pgl.glDepthMask(false); - } else if (which == ENABLE_DEPTH_MASK) { flush(); - pgl.glDepthMask(true); - + pgl.glDepthMask(true); } else if (which == DISABLE_ACCURATE_2D) { flush(); - setFlushMode(FLUSH_WHEN_FULL); - + setFlushMode(FLUSH_WHEN_FULL); } else if (which == ENABLE_ACCURATE_2D) { flush(); - setFlushMode(FLUSH_CONTINUOUSLY); - + setFlushMode(FLUSH_CONTINUOUSLY); } else if (which == DISABLE_TEXTURE_CACHE) { - flush(); - + flush(); } else if (which == DISABLE_PERSPECTIVE_CORRECTED_LINES) { if (0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount) { flush(); - } - + } } else if (which == ENABLE_PERSPECTIVE_CORRECTED_LINES) { if (0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount) { flush(); - } - + } } - } + ////////////////////////////////////////////////////////////// // SHAPE CREATORS @@ -1795,6 +1839,7 @@ public class PGraphicsAndroid3D extends PGraphics { return createShape(POLYGON); } + public PShape createShape(int type) { PShape3D shape = null; if (type == PShape.GROUP) { @@ -1827,6 +1872,7 @@ public class PGraphicsAndroid3D extends PGraphics { return shape; } + public PShape createShape(int kind, float... p) { PShape3D shape = null; int len = p.length; @@ -1903,14 +1949,16 @@ public class PGraphicsAndroid3D extends PGraphics { return shape; } + ////////////////////////////////////////////////////////////// // VERTEX SHAPES + public void beginShape(int kind) { shape = kind; - inGeo.reset(); + inGeo.clear(); breakShape = false; defaultEdges = true; @@ -2121,6 +2169,7 @@ public class PGraphicsAndroid3D extends PGraphics { // protected void sort() + protected void tessellate(int mode) { tessellator.setInGeometry(inGeo); tessellator.setTessGeometry(tessGeo); @@ -2164,10 +2213,12 @@ public class PGraphicsAndroid3D extends PGraphics { setLastTexIndex(tessGeo.lastFillIndex); } + protected void setFirstTexIndex(int first) { firstTexIndex = first; } + protected void setLastTexIndex(int last) { if (textureImage0 != textureImage || texCache.count == 0) { texCache.addTexture(textureImage, firstTexIndex, last); @@ -2176,6 +2227,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + public void flush() { boolean hasPoints = 0 < tessGeo.pointVertexCount && 0 < tessGeo.pointIndexCount; boolean hasLines = 0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount; @@ -2208,8 +2260,8 @@ public class PGraphicsAndroid3D extends PGraphics { } } - tessGeo.reset(); - texCache.reset(); + tessGeo.clear(); + texCache.clear(); } @@ -2225,17 +2277,14 @@ public class PGraphicsAndroid3D extends PGraphics { shader.setVertexAttribute(glPointVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setColorAttribute(glPointColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setSizeAttribute(glPointSizeBufferID, 2, PGL.GL_FLOAT, 0, 0); - - int size = tessGeo.pointIndexCount; - int sizex = size * PGL.SIZEOF_INDEX; - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glPointIndexBufferID); - pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, ShortBuffer.wrap(tessGeo.pointIndices, 0, size), vboMode); - pgl.glDrawElements(PGL.GL_TRIANGLES, size, PGL.INDEX_TYPE, 0); - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + + pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.pointIndexCount, PGL.INDEX_TYPE, 0); shader.stop(); + unbindPointBuffers(); } + protected void renderLines() { if (!lineVBOsCreated) { createLineBuffers(); @@ -2245,18 +2294,16 @@ public class PGraphicsAndroid3D extends PGraphics { LineShader shader = getLineShader(); shader.start(); + shader.setVertexAttribute(glLineVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setColorAttribute(glLineColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); - shader.setDirWidthAttribute(glLineDirWidthBufferID, 4, PGL.GL_FLOAT, 0, 0); + shader.setDirWidthAttribute(glLineDirWidthBufferID, 4, PGL.GL_FLOAT, 0, 0); + report("renderLines: attribs set"); - int size = tessGeo.lineIndexCount; - int sizex = size * PGL.SIZEOF_INDEX; - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glLineIndexBufferID); - pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, ShortBuffer.wrap(tessGeo.lineIndices, 0, size), vboMode); - pgl.glDrawElements(PGL.GL_TRIANGLES, size, PGL.INDEX_TYPE, 0); - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.lineIndexCount, PGL.INDEX_TYPE, 0); shader.stop(); + unbindLineBuffers(); } @@ -2266,15 +2313,11 @@ public class PGraphicsAndroid3D extends PGraphics { fillVBOsCreated = true; } updateFillBuffers(lights, texCache.hasTexture); - - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); - pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.fillIndexCount * PGL.SIZEOF_INDEX, - ShortBuffer.wrap(tessGeo.fillIndices, 0, tessGeo.fillIndexCount), vboMode); - texCache.beginRender(); - for (int i = 0; i < texCache.count; i++) { - PTexture tex = texCache.getTexture(i); - + texCache.beginRender(); + for (int i = 0; i < texCache.count; i++) { + PTexture tex = texCache.getTexture(i); + FillShader shader = getFillShader(lights, tex != null); shader.start(); @@ -2289,7 +2332,7 @@ public class PGraphicsAndroid3D extends PGraphics { shader.setShininessAttribute(glFillShininessBufferID, 1, PGL.GL_FLOAT, 0, 0); } - if (tex != null) { + if (tex != null) { shader.setTexCoordAttribute(glFillTexCoordBufferID, 2, PGL.GL_FLOAT, 0, 0); shader.setTexture(tex); } @@ -2300,8 +2343,8 @@ public class PGraphicsAndroid3D extends PGraphics { shader.stop(); } - texCache.endRender(); - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + texCache.endRender(); + unbindFillBuffers(); } @@ -2340,10 +2383,12 @@ public class PGraphicsAndroid3D extends PGraphics { shader.stop(); } + ////////////////////////////////////////////////////////////// // PSHAPE RENDERING IN 3D + public void shape(PShape shape, float x, float y, float z) { if (shape.isVisible()) { // don't do expensive matrix ops if invisible pushMatrix(); @@ -2361,6 +2406,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + public void shape(PShape shape, float x, float y, float z, float c, float d, float e) { if (shape.isVisible()) { // don't do expensive matrix ops if invisible @@ -2389,11 +2435,13 @@ public class PGraphicsAndroid3D extends PGraphics { popMatrix(); } } + ////////////////////////////////////////////////////////////// // BEZIER CURVE VERTICES + public void bezierDetail(int detail) { bezierDetail = detail; @@ -2409,6 +2457,7 @@ public class PGraphicsAndroid3D extends PGraphics { bezierDrawMatrix.apply(pg.bezierBasisMatrix); } + public void bezierVertex(float x2, float y2, float x3, float y3, float x4, float y4) { @@ -2417,6 +2466,7 @@ public class PGraphicsAndroid3D extends PGraphics { x4, y4, 0); } + public void bezierVertex(float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { @@ -2448,12 +2498,14 @@ public class PGraphicsAndroid3D extends PGraphics { } } + public void quadraticVertex(float cx, float cy, float x3, float y3) { quadraticVertex(cx, cy, 0, x3, y3, 0); } + public void quadraticVertex(float cx, float cy, float cz, float x3, float y3, float z3) { float x1 = inGeo.getLastVertexX(); @@ -2465,18 +2517,21 @@ public class PGraphicsAndroid3D extends PGraphics { x3, y3, z3); } + protected void bezierInitCheck() { if (!bezierInited) { bezierInit(); } } + protected void bezierInit() { // overkill to be broken out, but better parity with the curve stuff below bezierDetail(bezierDetail); bezierInited = true; } + protected void bezierVertexCheck() { if (shape != POLYGON) { throw new RuntimeException("beginShape() or beginShape(POLYGON) " + @@ -2488,24 +2543,29 @@ public class PGraphicsAndroid3D extends PGraphics { } } + ////////////////////////////////////////////////////////////// // CATMULL-ROM CURVE VERTICES + public void curveDetail(int detail) { curveDetail = detail; curveInit(); } + public void curveTightness(float tightness) { curveTightness = tightness; curveInit(); } + public void curveVertex(float x, float y) { curveVertex(x, y, 0); } + public void curveVertex(float x, float y, float z) { curveVertexCheck(); float[] vertex = curveVertices[curveVertexCount]; @@ -2553,12 +2613,14 @@ public class PGraphicsAndroid3D extends PGraphics { curveInitCheck(); } + protected void curveInitCheck() { if (!curveInited) { curveInit(); } } + protected void curveInit() { // allocate only if/when used to save startup time if (curveDrawMatrix == null) { @@ -2592,6 +2654,7 @@ public class PGraphicsAndroid3D extends PGraphics { curveDrawMatrix.apply(curveBasisMatrix); } + /** * Handle emitting a specific segment of Catmull-Rom curve. This can be * overridden by subclasses that need more efficient rendering options. @@ -2627,10 +2690,12 @@ public class PGraphicsAndroid3D extends PGraphics { } } + ////////////////////////////////////////////////////////////// // SPLINE UTILITY FUNCTIONS (used by both Bezier and Catmull-Rom) + /** * Setup forward-differencing matrix to be used for speedy * curve rendering. It's based on using a specific number @@ -2710,7 +2775,8 @@ public class PGraphicsAndroid3D extends PGraphics { ////////////////////////////////////////////////////////////// // ARC - + + protected void arcImpl(float x, float y, float w, float h, float start, float stop) { float hr = w / 2f; @@ -2772,6 +2838,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + ////////////////////////////////////////////////////////////// // BOX @@ -2859,6 +2926,8 @@ public class PGraphicsAndroid3D extends PGraphics { ////////////////////////////////////////////////////////////// // SMOOTH + + public void smooth() { smooth(2); } @@ -2867,29 +2936,20 @@ public class PGraphicsAndroid3D extends PGraphics { public void smooth(int level) { smooth = true; - if (antialias != level) { + if (maxSamples < level) { + PGraphics.showWarning("Smooth level " + level + " is not supported by the hardware. Using " + maxSamples + " instead."); + level = maxSamples; + } + + if (antialias != level) { antialias = level; - if (primarySurface) { - restartContext(); -// throw new PApplet.RendererChangeException(); - } else { - initOffscreen(); + if (antialias == 1) { + antialias = 0; } + // This will trigger a surface restart next time + // requestDraw() is called. + pgl.initialized = false; } - - int[] temp = { 0 }; - pgl.glGetIntegerv(PGL.GL_SAMPLES, temp, 0); - if (antialias != temp[0]) { - antialias = temp[0]; - PApplet.println("Effective multisampling level: " + antialias); - } - - if (antialias < 2) { - pgl.glEnable(PGL.GL_MULTISAMPLE); - pgl.glEnable(PGL.GL_POINT_SMOOTH); - pgl.glEnable(PGL.GL_LINE_SMOOTH); - pgl.glEnable(PGL.GL_POLYGON_SMOOTH); - } } @@ -2898,34 +2958,30 @@ public class PGraphicsAndroid3D extends PGraphics { if (1 < antialias) { antialias = 0; - if (primarySurface) { - restartContext(); - //throw new PApplet.RendererChangeException(); - } else { - initOffscreen(); - } + // This will trigger a surface restart next time + // requestDraw() is called. + pgl.initialized = false; } - - pgl.glDisable(PGL.GL_MULTISAMPLE); - pgl.glDisable(PGL.GL_POINT_SMOOTH); - pgl.glDisable(PGL.GL_LINE_SMOOTH); - pgl.glDisable(PGL.GL_POLYGON_SMOOTH); } + ////////////////////////////////////////////////////////////// // SHAPE // public void shapeMode(int mode) + public void shape(PShape3D shape) { shape.draw(this); } + public void shape(PShape3D shape, float x, float y) { shape(shape, x, y, 0); } + public void shape(PShape3D shape, float x, float y, float z) { pushMatrix(); translate(x, y, z); @@ -2933,6 +2989,7 @@ public class PGraphicsAndroid3D extends PGraphics { popMatrix(); } + // public void shape(PShape shape, float x, float y, float c, float d) ////////////////////////////////////////////////////////////// @@ -2972,6 +3029,7 @@ public class PGraphicsAndroid3D extends PGraphics { // TEXT IMPL + // protected void textLineAlignImpl(char buffer[], int start, int stop, // float x, float y) @@ -2984,11 +3042,7 @@ public class PGraphicsAndroid3D extends PGraphics { textTex = new PFontTexture(parent, textFont, maxTextureSize, maxTextureSize); textFont.setCache(this, textTex); } else { - if (!pgl.contextIsCurrent(textTex.context)) { - for (int i = 0; i < textTex.textures.length; i++) { - textTex.textures[i].glID = 0; // To avoid finalization (texture objects were already deleted when context changed). - textTex.textures[i] = null; - } + if (textTex.contextIsOutdated()) { textTex = new PFontTexture(parent, textFont, PApplet.min(PGL.MAX_FONT_TEX_SIZE, maxTextureSize), PApplet.min(PGL.MAX_FONT_TEX_SIZE, maxTextureSize)); textFont.setCache(this, textTex); @@ -3035,6 +3089,7 @@ public class PGraphicsAndroid3D extends PGraphics { blendMode(savedBlendMode); } + protected void textCharImpl(char ch, float x, float y) { PFont.Glyph glyph = textFont.getGlyph(ch); @@ -3064,7 +3119,7 @@ public class PGraphicsAndroid3D extends PGraphics { protected void textCharModelImpl(PFontTexture.TextureInfo info, float x0, float y0, - float x1, float y1) { + float x1, float y1) { if (textTex.currentTex != info.texIndex) { textTex.setTexture(info.texIndex); } @@ -3300,12 +3355,15 @@ public class PGraphicsAndroid3D extends PGraphics { // MATRIX GET/SET/PRINT + public PMatrix getMatrix() { return modelview.get(); } + // public PMatrix2D getMatrix(PMatrix2D target) + public PMatrix3D getMatrix(PMatrix3D target) { if (target == null) { target = new PMatrix3D(); @@ -3314,13 +3372,16 @@ public class PGraphicsAndroid3D extends PGraphics { return target; } + // public void setMatrix(PMatrix source) + public void setMatrix(PMatrix2D source) { resetMatrix(); applyMatrix(source); } + /** * Set the current transformation to the contents of the specified source. */ @@ -3329,6 +3390,7 @@ public class PGraphicsAndroid3D extends PGraphics { applyMatrix(source); } + /** * Print the current model (or "transformation") matrix. */ @@ -3336,6 +3398,7 @@ public class PGraphicsAndroid3D extends PGraphics { modelview.print(); } + ////////////////////////////////////////////////////////////// // PROJECTION @@ -3897,14 +3960,17 @@ public class PGraphicsAndroid3D extends PGraphics { // STROKE CAP/JOIN/WEIGHT + public void strokeWeight(float weight) { this.strokeWeight = weight; } + public void strokeJoin(int join) { this.strokeJoin = join; } + public void strokeCap(int cap) { this.strokeCap = cap; } @@ -4029,6 +4095,7 @@ public class PGraphicsAndroid3D extends PGraphics { colorMode = colorModeSaved; } + /** * Disables lighting. */ @@ -4037,6 +4104,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightCount = 0; } + /** * Add an ambient light based on the current color mode. */ @@ -4044,6 +4112,7 @@ public class PGraphicsAndroid3D extends PGraphics { ambientLight(r, g, b, 0, 0, 0); } + /** * Add an ambient light based on the current color mode. This version includes * an (x, y, z) position for situations where the falloff distance is used. @@ -4069,6 +4138,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightCount++; } + public void directionalLight(float r, float g, float b, float dx, float dy, float dz) { @@ -4093,6 +4163,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightCount++; } + public void pointLight(float r, float g, float b, float x, float y, float z) { enableLighting(); @@ -4118,6 +4189,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightCount++; } + public void spotLight(float r, float g, float b, float x, float y, float z, float dx, float dy, float dz, @@ -4145,6 +4217,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightCount++; } + /** * Set the light falloff rates for the last light that was created. Default is * lightFalloff(1, 0, 0). @@ -4155,6 +4228,7 @@ public class PGraphicsAndroid3D extends PGraphics { currentLightFalloffQuadratic = quadratic; } + /** * Set the specular color of the last light created. */ @@ -4165,12 +4239,14 @@ public class PGraphicsAndroid3D extends PGraphics { currentLightSpecular[2] = calcB; } + protected void enableLighting() { if (!lights) { flush(); // Flushing non-lit geometry. lights = true; } } + protected void disableLighting() { if (lights) { @@ -4179,6 +4255,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected void lightPosition(int num, float x, float y, float z, boolean dir) { lightPosition[4 * num + 0] = x * modelview.m00 + y * modelview.m01 + z * modelview.m02 + modelview.m03; lightPosition[4 * num + 1] = x * modelview.m10 + y * modelview.m11 + z * modelview.m12 + modelview.m13; @@ -4188,6 +4265,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightPosition[4 * num + 3] = dir ? 1: 0; } + protected void lightNormal(int num, float dx, float dy, float dz) { // Applying normal matrix to the light direction vector, which is the transpose of the inverse of the // modelview. @@ -4201,12 +4279,14 @@ public class PGraphicsAndroid3D extends PGraphics { lightNormal[3 * num + 2] = invn * nz; } + protected void lightAmbient(int num, float r, float g, float b) { colorCalc(r, g, b); lightAmbient[3 * num + 0] = calcR; lightAmbient[3 * num + 1] = calcG; lightAmbient[3 * num + 2] = calcB; } + protected void noLightAmbient(int num) { lightAmbient[3 * num + 0] = 0; @@ -4214,12 +4294,14 @@ public class PGraphicsAndroid3D extends PGraphics { lightAmbient[3 * num + 2] = 0; } + protected void lightDiffuse(int num, float r, float g, float b) { colorCalc(r, g, b); lightDiffuse[3 * num + 0] = calcR; lightDiffuse[3 * num + 1] = calcG; lightDiffuse[3 * num + 2] = calcB; } + protected void noLightDiffuse(int num) { lightDiffuse[3 * num + 0] = 0; @@ -4227,35 +4309,41 @@ public class PGraphicsAndroid3D extends PGraphics { lightDiffuse[3 * num + 2] = 0; } + protected void lightSpecular(int num, float r, float g, float b) { lightSpecular[3 * num + 0] = r; lightSpecular[3 * num + 1] = g; lightSpecular[3 * num + 2] = b; } + protected void noLightSpecular(int num) { lightSpecular[3 * num + 0] = 0; lightSpecular[3 * num + 1] = 0; lightSpecular[3 * num + 2] = 0; } + protected void lightFalloff(int num, float c0, float c1, float c2) { lightFalloffCoefficients[3 * num + 0] = c0; lightFalloffCoefficients[3 * num + 1] = c1; lightFalloffCoefficients[3 * num + 2] = c2; } + protected void noLightFalloff(int num) { lightFalloffCoefficients[3 * num + 0] = 1; lightFalloffCoefficients[3 * num + 1] = 0; lightFalloffCoefficients[3 * num + 2] = 0; } + protected void lightSpot(int num, float angle, float exponent) { lightSpotParameters[2 * num + 0] = Math.max(0, PApplet.cos(angle)); lightSpotParameters[2 * num + 1] = exponent; } + protected void noLightSpot(int num) { lightSpotParameters[2 * num + 0] = 0; lightSpotParameters[2 * num + 1] = 0; @@ -4266,24 +4354,33 @@ public class PGraphicsAndroid3D extends PGraphics { // BACKGROUND + protected void backgroundImpl(PImage image) { backgroundImpl(); set(0, 0, image); clearColorBuffer = true; } + protected void backgroundImpl() { - tessGeo.reset(); - texCache.reset(); + tessGeo.clear(); + texCache.clear(); + pgl.glDepthMask(true); pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); - + pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); + if (hints[DISABLE_DEPTH_MASK]) { + pgl.glDepthMask(false); + } else { + pgl.glDepthMask(true); + } + pgl.glClearColor(backgroundR, backgroundG, backgroundB, 1); pgl.glClear(PGL.GL_COLOR_BUFFER_BIT); clearColorBuffer = true; } + ////////////////////////////////////////////////////////////// // COLOR MODE @@ -4339,6 +4436,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + ////////////////////////////////////////////////////////////// // RENDERER SUPPORT QUERIES @@ -4381,6 +4479,7 @@ public class PGraphicsAndroid3D extends PGraphics { // LOAD/UPDATE PIXELS + public void loadPixels() { flush(); @@ -4403,7 +4502,7 @@ public class PGraphicsAndroid3D extends PGraphics { pixelBuffer.rewind(); if (primarySurface) { - pgl.setReadBuffer(PGL.GL_FRONT); + pgl.glReadBuffer(PGL.GL_FRONT); } pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer); @@ -4476,6 +4575,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + /** * Convert native OpenGL format into palatable ARGB format. This function * leaves alone (ignores) the alpha component. Also flips the image @@ -4515,6 +4615,7 @@ public class PGraphicsAndroid3D extends PGraphics { yindex -= image.width * 2; } } + /** * Convert native OpenGL format into palatable ARGB format. This function @@ -4558,6 +4659,7 @@ public class PGraphicsAndroid3D extends PGraphics { yindex -= image.width * 2; } } + /** * Convert ARGB (Java/Processing) data to native OpenGL format. This function @@ -4607,6 +4709,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + /** * Convert Java ARGB to native OpenGL format. Also flips the image vertically, * since images are upside-down in GL. @@ -4652,6 +4755,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + public void updatePixels() { // flip vertically (opengl stores images upside down), @@ -4721,11 +4825,13 @@ public class PGraphicsAndroid3D extends PGraphics { endGLOp(); } } + ////////////////////////////////////////////////////////////// // LOAD/UPDATE TEXTURE + public void loadTexture() { if (primarySurface) { if (!drawing) { @@ -4742,9 +4848,10 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected void loadTextureImpl(int sampling) { if (width == 0 || height == 0) return; - if (texture == null) { + if (texture == null || texture.contextIsOutdated()) { PTexture.Parameters params = PTexture.newParameters(ARGB, sampling); texture = new PTexture(parent, width, height, params); texture.setFlippedY(true); @@ -4759,6 +4866,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + // Draws wherever it is in the screen texture right now to the screen. public void updateTexture() { flush(); @@ -4785,14 +4893,17 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected void drawTexture() { drawTexture(texture, texCrop, 0, 0, width, height); } + protected void copyToTexture(IntBuffer buffer) { copyToTexture(texture, buffer, 0, 0, width, height); } + protected void copyFrameToTexture() { // Make sure that the execution off all the openGL commands is // finished before loading the texture. @@ -4800,26 +4911,32 @@ public class PGraphicsAndroid3D extends PGraphics { loadTexture(); } + protected void pixelsToTexture() { texture.set(pixels); } + protected void textureToPixels() { texture.get(pixels); } + ////////////////////////////////////////////////////////////// // RESIZE + public void resize(int wide, int high) { PGraphics.showMethodWarning("resize"); } + ////////////////////////////////////////////////////////////// // GET/SET + public int get(int x, int y) { flush(); @@ -4844,7 +4961,7 @@ public class PGraphicsAndroid3D extends PGraphics { getsetBuffer.rewind(); if (primarySurface) { - pgl.setReadBuffer(PGL.GL_FRONT); + pgl.glReadBuffer(PGL.GL_FRONT); } pgl.glReadPixels(x, height - y - 1, 1, 1, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, getsetBuffer); @@ -4866,9 +4983,11 @@ public class PGraphicsAndroid3D extends PGraphics { | ((getset >> 16) & 0xff); } } + // public PImage get(int x, int y, int w, int h) + protected PImage getImpl(int x, int y, int w, int h) { flush(); @@ -4884,7 +5003,7 @@ public class PGraphicsAndroid3D extends PGraphics { newbieBuffer.rewind(); if (primarySurface) { - pgl.setReadBuffer(PGL.GL_FRONT); + pgl.glReadBuffer(PGL.GL_FRONT); } pgl.glReadPixels(x, height - y - h, w, h, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, newbieBuffer); @@ -4899,10 +5018,12 @@ public class PGraphicsAndroid3D extends PGraphics { return newbie; } + public PImage get() { return get(0, 0, width, height); } + // TODO: doesn't appear to work public void set(int x, int y, int argb) { flush(); @@ -4954,6 +5075,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + /** * Set an image directly to the screen. * @@ -4990,11 +5112,13 @@ public class PGraphicsAndroid3D extends PGraphics { } } } - + + ////////////////////////////////////////////////////////////// // MASK + public void mask(int alpha[]) { PGraphics.showMethodWarning("mask"); } @@ -5004,10 +5128,12 @@ public class PGraphicsAndroid3D extends PGraphics { PGraphics.showMethodWarning("mask"); } + ////////////////////////////////////////////////////////////// // FILTER + /** * This is really inefficient and not a good idea in OpenGL. Use get() and * set() with a smaller image area, or call the filter on an image instead, @@ -5019,6 +5145,7 @@ public class PGraphicsAndroid3D extends PGraphics { set(0, 0, temp); } + /** * This is really inefficient and not a good idea in OpenGL. Use get() and * set() with a smaller image area, or call the filter on an image instead, @@ -5030,6 +5157,7 @@ public class PGraphicsAndroid3D extends PGraphics { set(0, 0, temp); } + ////////////////////////////////////////////////////////////// /** @@ -5048,6 +5176,7 @@ public class PGraphicsAndroid3D extends PGraphics { // int sx1, int sy1, int sx2, int sy2, // int dx1, int dy1, int dx2, int dy2) + ////////////////////////////////////////////////////////////// // BLEND @@ -5059,6 +5188,7 @@ public class PGraphicsAndroid3D extends PGraphics { // set(dx, dy, PImage.blendColor(src.get(sx, sy), get(dx, dy), mode)); // } + /** * Extremely slow and not optimized, should use GL methods instead. Currently * calls a beginPixels() on the whole canvas, then does the copy, then it @@ -5081,6 +5211,7 @@ public class PGraphicsAndroid3D extends PGraphics { // updatePixels(); // } + /** * Allows to set custom blend modes for the entire scene, using openGL. * Reference article about blending modes: @@ -5161,6 +5292,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected void setDefaultBlend() { blendMode = BLEND; pgl.glEnable(PGL.GL_BLEND); @@ -5177,10 +5309,12 @@ public class PGraphicsAndroid3D extends PGraphics { // public void save(String filename) // PImage calls loadPixels() + ////////////////////////////////////////////////////////////// // SHAPE I/O + protected String[] getSupportedShapeFormats() { return new String[] { "obj" }; } @@ -5202,6 +5336,7 @@ public class PGraphicsAndroid3D extends PGraphics { // TEXTURE UTILS + /** * This utility method returns the texture associated to the renderer's. * drawing surface, making sure is updated to reflect the current contents @@ -5212,6 +5347,7 @@ public class PGraphicsAndroid3D extends PGraphics { return texture; } + /** * This utility method returns the texture associated to the image. * creating and/or updating it if needed. @@ -5220,18 +5356,10 @@ public class PGraphicsAndroid3D extends PGraphics { public PTexture getTexture(PImage img) { PTexture tex = (PTexture)img.getCache(pg); if (tex == null) { - tex = addTexture(img); + tex = addTexture(img); } else { - if (!pgl.contextIsCurrent(tex.context)) { - // The texture was created with a different context. We need - // to recreate it. First, we make sure that the old GL id - // is not used to delete the texture object (it was already - // deleted when the context changed). - tex.glID = 0; + if (tex.contextIsOutdated()) { tex = addTexture(img); - // TODO: apply this mechanism to all the Processing objects using - // GL resources (PShape, PShader, PFramebuffer). They will probably - // need the cache thingy as well. } if (img.isModified()) { @@ -5270,14 +5398,15 @@ public class PGraphicsAndroid3D extends PGraphics { if (params == null) { params = PTexture.newParameters(); img.setParams(pg, params); - } - PTexture tex = new PTexture(img.parent, img.width, img.height, params); + } + PTexture tex = new PTexture(img.parent, img.width, img.height, params); img.loadPixels(); - if (img.pixels != null) tex.set(img.pixels); - img.setCache(pg, tex); + if (img.pixels != null) tex.set(img.pixels); + img.setCache(pg, tex); return tex; } + protected PImage wrapTexture(PTexture tex) { // We don't use the PImage(int width, int height, int mode) constructor to // avoid initializing the pixels array. @@ -5290,6 +5419,7 @@ public class PGraphicsAndroid3D extends PGraphics { return img; } + protected void updateTexture(PImage img, PTexture tex) { if (tex != null) { int x = img.getModifiedX1(); @@ -5345,11 +5475,13 @@ public class PGraphicsAndroid3D extends PGraphics { blendMode(savedBlendMode); } + protected void drawTexture(int w, int h, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { int[] crop = {x1, y1, w1, h1}; drawTexture(w, h, crop, x2, y2, w2, h2); } + /** * Utility function to render currently bound texture using current blend mode. * Equivalent to: @@ -5402,6 +5534,7 @@ public class PGraphicsAndroid3D extends PGraphics { drawTexQuad(0, 0, 1, 1); } + /** * Pushes a normalized (1x1) textured quad to the GPU. */ @@ -5436,51 +5569,39 @@ public class PGraphicsAndroid3D extends PGraphics { // INITIALIZATION ROUTINES - static public void init() { - PGL.startup(true); - } - - static public void init(boolean beforeUI) { - PGL.startup(beforeUI); - } - - protected void restartSurface() { - if (primarySurface) { - initPrimary(); - } else { - initOffscreen(); - } - } - protected void initPrimary() { + if (pg != null) { + releaseResources(); + } + pgl.initPrimarySurface(antialias); pg = this; } + protected void initOffscreen() { // Getting the context and capabilities from the main renderer. pg = (PGraphicsAndroid3D)parent.g; pgl.initOffscreenSurface(pg.pgl); - updatePGL(); + pgl.updateOffscreen(pg.pgl); loadTextureImpl(BILINEAR); // In case of reinitialization (for example, when the smooth level // is changed), we make sure that all the OpenGL resources associated // to the surface are released by calling delete(). if (offscreenFramebuffer != null) { - offscreenFramebuffer = null; + offscreenFramebuffer.release(); } if (offscreenFramebufferMultisample != null) { - offscreenFramebufferMultisample = null; + offscreenFramebufferMultisample.release(); } // We need the GL2GL3 profile to access the glRenderbufferStorageMultisample // function used in multisampled (antialiased) offscreen rendering. if (PGraphicsAndroid3D.fboMultisampleSupported && 1 < antialias) { - int nsamples = antialias; - offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, nsamples, 0, + offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, antialias, 0, offscreenDepthBits, offscreenStencilBits, offscreenDepthBits == 24 && offscreenStencilBits == 8, false); @@ -5492,23 +5613,19 @@ public class PGraphicsAndroid3D extends PGraphics { offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, 0, 0, false, false); - } else { + antialias = 0; offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, offscreenDepthBits, offscreenStencilBits, offscreenDepthBits == 24 && offscreenStencilBits == 8, false); offscreenMultisample = false; } - + offscreenFramebuffer.setColorBuffer(texture); offscreenFramebuffer.clear(); } - - protected void updateOffscreenContext() { - pgl.updateOffscreenSurface(pg.pgl); - updatePGL(); - } + protected void getGLParameters() { OPENGL_VENDOR = pgl.glGetString(PGL.GL_VENDOR); @@ -5533,6 +5650,9 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glGetIntegerv(PGL.GL_MAX_TEXTURE_SIZE, temp, 0); maxTextureSize = temp[0]; + + pgl.glGetIntegerv(PGL.GL_MAX_SAMPLES, temp, 0); + maxSamples = temp[0]; pgl.glGetIntegerv(PGL.GL_ALIASED_LINE_WIDTH_RANGE, temp, 0); maxLineWidth = temp[1]; @@ -5542,11 +5662,13 @@ public class PGraphicsAndroid3D extends PGraphics { glParamsRead = true; } + ////////////////////////////////////////////////////////////// // SHADER HANDLING + public PShader loadShader(String vertFilename, String fragFilename, int kind) { if (kind == FILL_SHADER_SIMPLE) { return new FillShaderSimple(parent, vertFilename, fragFilename); @@ -5566,6 +5688,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + public PShader loadShader(String fragFilename, int kind) { PShader shader; if (kind == FILL_SHADER_SIMPLE) { @@ -5593,6 +5716,7 @@ public class PGraphicsAndroid3D extends PGraphics { shader.setFragmentShader(fragFilename); return shader; } + public void setShader(PShader shader, int kind) { if (kind == FILL_SHADER_SIMPLE) { @@ -5612,6 +5736,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + public void resetShader(int kind) { if (kind == FILL_SHADER_SIMPLE) { if (defFillShaderSimple == null) { @@ -5648,6 +5773,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected FillShader getFillShader(boolean lit, boolean tex) { FillShader shader; if (lit) { @@ -5692,6 +5818,7 @@ public class PGraphicsAndroid3D extends PGraphics { return shader; } + protected LineShader getLineShader() { if (defLineShader == null) { defLineShader = new LineShader(parent, defLineShaderVertURL, defLineShaderFragURL); @@ -5704,6 +5831,7 @@ public class PGraphicsAndroid3D extends PGraphics { return lineShader; } + protected PointShader getPointShader() { if (defPointShader == null) { defPointShader = new PointShader(parent, defPointShaderVertURL, defPointShaderFragURL); @@ -5716,6 +5844,7 @@ public class PGraphicsAndroid3D extends PGraphics { return pointShader; } + protected class FillShader extends PShader { public FillShader(PApplet parent) { super(parent); @@ -5750,6 +5879,7 @@ public class PGraphicsAndroid3D extends PGraphics { public void setTexture(PTexture tex) { } } + protected class FillShaderSimple extends FillShader { protected int projmodelviewMatrixLoc; @@ -5805,6 +5935,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected class FillShaderLit extends FillShader { protected int projmodelviewMatrixLoc; protected int modelviewMatrixLoc; @@ -5941,6 +6072,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected class FillShaderTex extends FillShaderSimple { protected int inTexcoordLoc; @@ -6015,6 +6147,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected class FillShaderFull extends FillShaderLit { protected int inTexcoordLoc; @@ -6089,6 +6222,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected class LineShader extends PShader { protected int projectionMatrixLoc; protected int modelviewMatrixLoc; @@ -6176,6 +6310,7 @@ public class PGraphicsAndroid3D extends PGraphics { } } + protected class PointShader extends PShader { protected int projectionMatrixLoc; protected int modelviewMatrixLoc; @@ -6248,23 +6383,28 @@ public class PGraphicsAndroid3D extends PGraphics { super.stop(); } } + ////////////////////////////////////////////////////////////// // Input (raw) and Tessellated geometry, tessellator. + public InGeometry newInGeometry(int mode) { return new InGeometry(mode); } + protected TessGeometry newTessGeometry(int mode) { return new TessGeometry(mode); } + protected TexCache newTexCache() { return new TexCache(); } + // Holds an array of textures and the range of vertex // indices each texture applies to. public class TexCache { @@ -6287,7 +6427,7 @@ public class PGraphicsAndroid3D extends PGraphics { hasTexture = false; } - public void reset() { + public void clear() { java.util.Arrays.fill(textures, 0, count, null); count = 0; hasTexture = false; @@ -6307,8 +6447,8 @@ public class PGraphicsAndroid3D extends PGraphics { PImage img = textures[i]; PTexture tex = null; - if (img != null) { - tex = pg.getTexture(img); + if (img != null) { + tex = pg.getTexture(img); if (tex != null) { tex.bind(); tex0 = tex; @@ -6438,7 +6578,7 @@ public class PGraphicsAndroid3D extends PGraphics { allocate(); } - public void reset() { + public void clear() { vertexCount = firstVertex = lastVertex = 0; edgeCount = firstEdge = lastEdge = 0; } @@ -6456,7 +6596,7 @@ public class PGraphicsAndroid3D extends PGraphics { emissive = new int[PGL.DEFAULT_IN_VERTICES]; shininess = new float[PGL.DEFAULT_IN_VERTICES]; edges = new int[PGL.DEFAULT_IN_EDGES][3]; - reset(); + clear(); } public void trim() { @@ -7163,7 +7303,7 @@ public class PGraphicsAndroid3D extends PGraphics { allocate(); } - public void reset() { + public void clear() { firstFillVertex = lastFillVertex = fillVertexCount = 0; firstFillIndex = lastFillIndex = fillIndexCount = 0; @@ -7197,7 +7337,7 @@ public class PGraphicsAndroid3D extends PGraphics { pointSizes = new float[2 * PGL.DEFAULT_TESS_VERTICES]; pointIndices = new short[PGL.DEFAULT_TESS_VERTICES]; - reset(); + clear(); } public void trim() { @@ -7236,7 +7376,7 @@ public class PGraphicsAndroid3D extends PGraphics { trimPointIndices(); } } - + protected void trimFillVertices() { float temp[] = new float[3 * fillVertexCount]; PApplet.arrayCopy(fillVertices, 0, temp, 0, 3 * fillVertexCount); @@ -7468,7 +7608,7 @@ public class PGraphicsAndroid3D extends PGraphics { // shapes in the hierarchy, as the entire geometry will be stored // contiguously in a single VBO in the root node. for (int i = 0; i < lineIndexCount; i++) { - lineIndices[i] += firstLineVertex; + lineIndices[i] += voffset; } } @@ -7496,7 +7636,7 @@ public class PGraphicsAndroid3D extends PGraphics { // shapes in the hierarchy, as the entire geometry will be stored // contiguously in a single VBO in the root node. for (int i = 0; i < pointIndexCount; i++) { - pointIndices[i] += firstPointVertex; + pointIndices[i] += voffset; } } @@ -8704,7 +8844,7 @@ public class PGraphicsAndroid3D extends PGraphics { gluTess.endContour(); gluTess.beginContour(); } - + // Separting colors into individual rgba components for interpolation. int fa = (in.colors[i] >> 24) & 0xFF; int fr = (in.colors[i] >> 16) & 0xFF; @@ -8978,4 +9118,4 @@ public class PGraphicsAndroid3D extends PGraphics { } } } -} +} \ No newline at end of file diff --git a/android/core/src/processing/core/PShader.java b/android/core/src/processing/core/PShader.java index 22fa263fd..8f9b7373d 100644 --- a/android/core/src/processing/core/PShader.java +++ b/android/core/src/processing/core/PShader.java @@ -35,6 +35,7 @@ public class PShader { protected PApplet parent; protected PGraphicsAndroid3D pg; protected PGL pgl; + protected PGL.Context context; // The context that created this shader. protected URL vertexURL; protected URL fragmentURL; @@ -291,7 +292,9 @@ public class PShader { } protected void init() { - if (programObject == 0) { + if (programObject == 0 || contextIsOutdated()) { + + context = pgl.getContext(); programObject = pg.createGLSLProgramObject(); if (vertexFilename != null) { @@ -319,6 +322,17 @@ public class PShader { } + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + programObject = 0; + vertexShader = 0; + fragmentShader = 0; + } + return outdated; + } + + /** * Loads and compiles the vertex shader contained in file. * diff --git a/android/core/src/processing/core/PShape3D.java b/android/core/src/processing/core/PShape3D.java index a5eebb668..75fb26231 100644 --- a/android/core/src/processing/core/PShape3D.java +++ b/android/core/src/processing/core/PShape3D.java @@ -28,6 +28,7 @@ import processing.core.PGraphicsAndroid3D.LineShader; import processing.core.PGraphicsAndroid3D.PointShader; import processing.core.PGraphicsAndroid3D.TessGeometry; import processing.core.PGraphicsAndroid3D.Tessellator; + import java.nio.FloatBuffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -39,6 +40,16 @@ import java.util.Hashtable; import java.io.BufferedReader; +//Notes about geometry update in PShape3D. +//1) When applying a transformation on a group shape +// check if it is more efficient to apply as a gl +// transformation on all the childs, instead of +// propagating the transformation downwards in order +// to calculate the transformation matrices. +//2) Change the transformation logic, so the matrix is applied +// on the values stored in the vertex cache and not on the +// tessellated vertices. + /** * This class holds a 3D model composed of vertices, normals, colors (per vertex) and * texture coordinates (also per vertex). All this data is stored in Vertex Buffer Objects @@ -58,6 +69,7 @@ import java.io.BufferedReader; public class PShape3D extends PShape { protected PGraphicsAndroid3D pg; protected PGL pgl; + protected PGL.Context context; // The context that created this shape. protected PShape3D root; protected int glMode; @@ -2029,49 +2041,85 @@ public class PShape3D extends PShape { return tess.fillIndexCount; } - public float[] fillVertices() { + public float[] fillVertices(float[] vertices) { updateTesselation(); - return tess.fillVertices; + if (vertices == null || vertices.length != tess.fillVertices.length) { + vertices = new float[tess.fillVertices.length]; + } + PApplet.arrayCopy(tess.fillVertices, vertices); + return vertices; } - public int[] fillColors() { + public int[] fillColors(int[] colors) { updateTesselation(); - return tess.fillColors; + if (colors == null || colors.length != tess.fillColors.length) { + colors = new int[tess.fillColors.length]; + } + PApplet.arrayCopy(tess.fillColors, colors); + return colors; } - public float[] fillNormals() { + public float[] fillNormals(float[] normals) { updateTesselation(); - return tess.fillNormals; + if (normals == null || normals.length != tess.fillNormals.length) { + normals = new float[tess.fillNormals.length]; + } + PApplet.arrayCopy(tess.fillNormals, normals); + return normals; } - public float[] fillTexCoords() { + public float[] fillTexCoords(float[] texcoords) { updateTesselation(); - return tess.fillTexcoords; + if (texcoords == null || texcoords.length != tess.fillTexcoords.length) { + texcoords = new float[tess.fillTexcoords.length]; + } + PApplet.arrayCopy(tess.fillTexcoords, texcoords); + return texcoords; } - public int[] fillAmbient() { + public int[] fillAmbient(int[] ambient) { updateTesselation(); - return tess.fillAmbient; + if (ambient == null || ambient.length != tess.fillAmbient.length) { + ambient = new int[tess.fillAmbient.length]; + } + PApplet.arrayCopy(tess.fillAmbient, ambient); + return ambient; } - public int[] fillSpecular() { + public int[] fillSpecular(int[] specular) { updateTesselation(); - return tess.fillSpecular; + if (specular == null || specular.length != tess.fillSpecular.length) { + specular = new int[tess.fillSpecular.length]; + } + PApplet.arrayCopy(tess.fillSpecular, specular); + return specular; } - public int[] fillEmissive() { + public int[] fillEmissive(int[] emissive) { updateTesselation(); - return tess.fillEmissive; + if (emissive == null || emissive.length != tess.fillEmissive.length) { + emissive = new int[tess.fillEmissive.length]; + } + PApplet.arrayCopy(tess.fillEmissive, emissive); + return emissive; } - public float[] fillShininess() { + public float[] fillShininess(float[] shininess) { updateTesselation(); - return tess.fillShininess; + if (shininess == null || shininess.length != tess.fillShininess.length) { + shininess = new float[tess.fillShininess.length]; + } + PApplet.arrayCopy(tess.fillShininess, shininess); + return shininess; } - public short[] fillIndices() { + public int[] fillIndices(int[] indices) { updateTesselation(); - return tess.fillIndices; + if (indices == null || indices.length != tess.fillIndices.length) { + indices = new int[tess.fillIndices.length]; + } + PApplet.arrayCopy(tess.fillIndexCount, indices); + return indices; } public int firstLineVertex() { @@ -2104,24 +2152,40 @@ public class PShape3D extends PShape { return tess.lineIndexCount; } - public float[] lineVertices() { + public float[] lineVertices(float[] vertices) { updateTesselation(); - return tess.lineVertices; + if (vertices == null || vertices.length != tess.lineVertices.length) { + vertices = new float[tess.lineVertices.length]; + } + PApplet.arrayCopy(tess.lineVertices, vertices); + return vertices; } - public int[] lineColors() { + public int[] lineColors(int[] colors) { updateTesselation(); - return tess.lineColors; + if (colors == null || colors.length != tess.lineColors.length) { + colors = new int[tess.lineColors.length]; + } + PApplet.arrayCopy(tess.lineColors, colors); + return colors; } - public float[] lineAttributes() { + public float[] lineAttributes(float[] attribs) { updateTesselation(); - return tess.lineDirWidths; + if (attribs == null || attribs.length != tess.lineDirWidths.length) { + attribs = new float[tess.lineDirWidths.length]; + } + PApplet.arrayCopy(tess.lineDirWidths, attribs); + return attribs; } - public short[] lineIndices() { + public int[] lineIndices(int[] indices) { updateTesselation(); - return tess.lineIndices; + if (indices == null || indices.length != tess.lineIndices.length) { + indices = new int[tess.lineIndices.length]; + } + PApplet.arrayCopy(tess.lineIndices, indices); + return indices; } public int firstPointVertex() { @@ -2154,24 +2218,40 @@ public class PShape3D extends PShape { return tess.pointIndexCount; } - public float[] pointVertices() { + public float[] pointVertices(float[] vertices) { updateTesselation(); - return tess.pointVertices; + if (vertices == null || vertices.length != tess.pointVertices.length) { + vertices = new float[tess.pointVertices.length]; + } + PApplet.arrayCopy(tess.pointVertices, vertices); + return vertices; } - public int[] pointColors() { + public int[] pointColors(int[] colors) { updateTesselation(); - return tess.pointColors; + if (colors == null || colors.length != tess.pointColors.length) { + colors = new int[tess.pointColors.length]; + } + PApplet.arrayCopy(tess.pointColors, colors); + return colors; } - public float[] pointAttributes() { + public float[] pointAttributes(float[] attribs) { updateTesselation(); - return tess.pointSizes; + if (attribs == null || attribs.length != tess.pointSizes.length) { + attribs = new float[tess.pointSizes.length]; + } + PApplet.arrayCopy(tess.pointSizes, attribs); + return attribs; } - public short[] pointIndices() { + public int[] pointIndices(int[] indices) { updateTesselation(); - return tess.pointIndices; + if (indices == null || indices.length != tess.pointIndices.length) { + indices = new int[tess.pointIndices.length]; + } + PApplet.arrayCopy(tess.pointIndices, indices); + return indices; } public FloatBuffer mapFillVertices() { @@ -2361,7 +2441,7 @@ public class PShape3D extends PShape { protected void updateTesselation() { - if (!root.tessellated) { + if (!root.tessellated || root.contextIsOutdated()) { root.tessellate(); root.aggregate(); } @@ -2375,7 +2455,11 @@ public class PShape3D extends PShape { child.tessellate(); } } else { - if (!tessellated && shapeEnded) { + if (shapeEnded) { + if (tessellated) { + tess.clear(); + } + tessellator.setInGeometry(in); tessellator.setTessGeometry(tess); tessellator.setFill(fill || texture != null); @@ -2500,9 +2584,14 @@ public class PShape3D extends PShape { protected void tessellateBox() { // TODO: move to InGeometry - float w = params[0]; - float h = params[1]; - float d = params[2]; + float w, h, d; + if (params.length == 1) { + w = h = d = params[0]; + } else { + w = params[0]; + h = params[1]; + d = params[2]; + } float x1 = -w/2f; float x2 = w/2f; float y1 = -h/2f; float y2 = h/2f; @@ -2645,52 +2734,72 @@ public class PShape3D extends PShape { // Copying any data remaining in the caches if (root.fillVerticesCache != null && root.fillVerticesCache.hasData()) { root.copyFillVertices(root.fillVerticesCache.offset, root.fillVerticesCache.size, root.fillVerticesCache.floatData); - root.fillVerticesCache.reset(); + root.fillVerticesCache.clear(); } if (root.fillColorsCache != null && root.fillColorsCache.hasData()) { root.copyFillColors(root.fillColorsCache.offset, root.fillColorsCache.size, root.fillColorsCache.intData); - root.fillColorsCache.reset(); + root.fillColorsCache.clear(); } if (root.fillNormalsCache != null && root.fillNormalsCache.hasData()) { root.copyFillNormals(root.fillNormalsCache.offset, root.fillNormalsCache.size, root.fillNormalsCache.floatData); - root.fillNormalsCache.reset(); + root.fillNormalsCache.clear(); } if (root.fillTexCoordsCache != null && root.fillTexCoordsCache.hasData()) { root.copyFillTexCoords(root.fillTexCoordsCache.offset, root.fillTexCoordsCache.size, root.fillTexCoordsCache.floatData); - root.fillTexCoordsCache.reset(); + root.fillTexCoordsCache.clear(); } + if (root.fillAmbientCache != null && root.fillAmbientCache.hasData()) { + root.copyFillAmbient(root.fillAmbientCache.offset, root.fillAmbientCache.size, root.fillAmbientCache.intData); + root.fillAmbientCache.clear(); + } + + if (root.fillSpecularCache != null && root.fillSpecularCache.hasData()) { + root.copyFillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); + root.fillSpecularCache.clear(); + } + + if (root.fillEmissiveCache != null && root.fillEmissiveCache.hasData()) { + root.copyFillEmissive(root.fillEmissiveCache.offset, root.fillEmissiveCache.size, root.fillEmissiveCache.intData); + root.fillEmissiveCache.clear(); + } + + if (root.fillShininessCache != null && root.fillShininessCache.hasData()) { + root.copyFillShininess(root.fillShininessCache.offset, root.fillShininessCache.size, root.fillShininessCache.floatData); + root.fillShininessCache.clear(); + } + if (root.lineVerticesCache != null && root.lineVerticesCache.hasData()) { root.copyLineVertices(root.lineVerticesCache.offset, root.lineVerticesCache.size, root.lineVerticesCache.floatData); - root.lineVerticesCache.reset(); + root.lineVerticesCache.clear(); } if (root.lineColorsCache != null && root.lineColorsCache.hasData()) { root.copyLineColors(root.lineColorsCache.offset, root.lineColorsCache.size, root.lineColorsCache.intData); - root.lineColorsCache.reset(); + root.lineColorsCache.clear(); } if (root.lineAttributesCache != null && root.lineAttributesCache.hasData()) { root.copyLineAttributes(root.lineAttributesCache.offset, root.lineAttributesCache.size, root.lineAttributesCache.floatData); - root.lineAttributesCache.reset(); + root.lineAttributesCache.clear(); } if (root.pointVerticesCache != null && root.pointVerticesCache.hasData()) { root.copyPointVertices(root.pointVerticesCache.offset, root.pointVerticesCache.size, root.pointVerticesCache.floatData); - root.pointVerticesCache.reset(); + root.pointVerticesCache.clear(); } if (root.pointColorsCache != null && root.pointColorsCache.hasData()) { root.copyPointColors(root.pointColorsCache.offset, root.pointColorsCache.size, root.pointColorsCache.intData); - root.pointColorsCache.reset(); + root.pointColorsCache.clear(); } if (root.pointAttributesCache != null && root.pointAttributesCache.hasData()) { root.copyPointAttributes(root.pointAttributesCache.offset, root.pointAttributesCache.size, root.pointAttributesCache.floatData); - root.pointAttributesCache.reset(); + root.pointAttributesCache.clear(); } } } @@ -2746,7 +2855,7 @@ public class PShape3D extends PShape { // level of the shape hierarchy. protected void aggregateImpl() { if (family == GROUP) { - tess.reset(); + tess.clear(); boolean firstGeom = true; boolean firstStroke = true; @@ -2804,6 +2913,7 @@ public class PShape3D extends PShape { } root.lastLineVertexOffset = tess.setLineVertex(root.lastLineVertexOffset); root.lastLineIndexOffset = tess.setLineIndex(root.firstLineVertexRel, root.lastLineIndexOffset); + root.firstLineVertexRel += tess.lineVertexCount; addLineIndexData(root.firstLineVertexAbs, tess.firstLineIndex, tess.lastLineIndex - tess.firstLineIndex + 1); } @@ -2814,6 +2924,7 @@ public class PShape3D extends PShape { } root.lastPointVertexOffset = tess.setPointVertex(root.lastPointVertexOffset); root.lastPointIndexOffset = tess.setPointIndex(root.firstPointVertexRel, root.lastPointIndexOffset); + root.firstPointVertexRel += tess.pointVertexCount; addPointIndexData(root.firstPointVertexAbs, tess.firstPointIndex, tess.lastPointIndex - tess.firstPointIndex + 1); } } @@ -2925,11 +3036,45 @@ public class PShape3D extends PShape { } } + + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + // The OpenGL resources have been already deleted + // when the context changed. We only need to zero + // them to avoid deleting them again when the GC + // runs the finalizers of the disposed object. + glFillVertexBufferID = 0; + glFillColorBufferID = 0; + glFillNormalBufferID = 0; + glFillTexCoordBufferID = 0; + glFillAmbientBufferID = 0; + glFillSpecularBufferID = 0; + glFillEmissiveBufferID = 0; + glFillShininessBufferID = 0; + glFillIndexBufferID = 0; + + glLineVertexBufferID = 0; + glLineColorBufferID = 0; + glLineDirWidthBufferID = 0; + glLineIndexBufferID = 0; + + glPointVertexBufferID = 0; + glPointColorBufferID = 0; + glPointSizeBufferID = 0; + glPointIndexBufferID = 0; + } + return outdated; + } + + protected void initFillBuffers(int nvert, int nind) { int sizef = nvert * PGL.SIZEOF_FLOAT; int sizei = nvert * PGL.SIZEOF_INT; int sizex = nind * PGL.SIZEOF_INDEX; + context = pgl.getContext(); + glFillVertexBufferID = pg.createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, glMode); @@ -3010,7 +3155,7 @@ public class PShape3D extends PShape { modifiedFillVertices = false; } else if (root.fillVerticesCache != null && root.fillVerticesCache.hasData()) { root.copyFillVertices(root.fillVerticesCache.offset, root.fillVerticesCache.size, root.fillVerticesCache.floatData); - root.fillVerticesCache.reset(); + root.fillVerticesCache.clear(); } if (modifiedFillColors) { @@ -3021,7 +3166,7 @@ public class PShape3D extends PShape { modifiedFillColors = false; } else if (root.fillColorsCache != null && root.fillColorsCache.hasData()) { root.copyFillColors(root.fillColorsCache.offset, root.fillColorsCache.size, root.fillColorsCache.intData); - root.fillColorsCache.reset(); + root.fillColorsCache.clear(); } if (modifiedFillNormals) { @@ -3032,7 +3177,7 @@ public class PShape3D extends PShape { modifiedFillNormals = false; } else if (root.fillNormalsCache != null && root.fillNormalsCache.hasData()) { root.copyFillNormals(root.fillNormalsCache.offset, root.fillNormalsCache.size, root.fillNormalsCache.floatData); - root.fillNormalsCache.reset(); + root.fillNormalsCache.clear(); } if (modifiedFillTexCoords) { @@ -3043,7 +3188,7 @@ public class PShape3D extends PShape { modifiedFillTexCoords = false; } else if (root.fillTexCoordsCache != null && root.fillTexCoordsCache.hasData()) { root.copyFillTexCoords(root.fillTexCoordsCache.offset, root.fillTexCoordsCache.size, root.fillTexCoordsCache.floatData); - root.fillTexCoordsCache.reset(); + root.fillTexCoordsCache.clear(); } if (modifiedFillAmbient) { @@ -3053,8 +3198,8 @@ public class PShape3D extends PShape { root.fillAmbientCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillAmbient); modifiedFillAmbient = false; } else if (root.fillAmbientCache != null && root.fillAmbientCache.hasData()) { - root.copyfillAmbient(root.fillAmbientCache.offset, root.fillAmbientCache.size, root.fillAmbientCache.intData); - root.fillAmbientCache.reset(); + root.copyFillAmbient(root.fillAmbientCache.offset, root.fillAmbientCache.size, root.fillAmbientCache.intData); + root.fillAmbientCache.clear(); } if (modifiedFillSpecular) { @@ -3064,8 +3209,8 @@ public class PShape3D extends PShape { root.fillSpecularCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillSpecular); modifiedFillSpecular = false; } else if (root.fillSpecularCache != null && root.fillSpecularCache.hasData()) { - root.copyfillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); - root.fillSpecularCache.reset(); + root.copyFillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); + root.fillSpecularCache.clear(); } if (modifiedFillEmissive) { @@ -3075,8 +3220,8 @@ public class PShape3D extends PShape { root.fillEmissiveCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillEmissive); modifiedFillEmissive = false; } else if (root.fillEmissiveCache != null && root.fillEmissiveCache.hasData()) { - root.copyfillEmissive(root.fillEmissiveCache.offset, root.fillEmissiveCache.size, root.fillEmissiveCache.intData); - root.fillEmissiveCache.reset(); + root.copyFillEmissive(root.fillEmissiveCache.offset, root.fillEmissiveCache.size, root.fillEmissiveCache.intData); + root.fillEmissiveCache.clear(); } if (modifiedFillShininess) { @@ -3086,8 +3231,8 @@ public class PShape3D extends PShape { root.fillShininessCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillShininess); modifiedFillShininess = false; } else if (root.fillShininessCache != null && root.fillShininessCache.hasData()) { - root.copyfillShininess(root.fillShininessCache.offset, root.fillShininessCache.size, root.fillShininessCache.floatData); - root.fillShininessCache.reset(); + root.copyFillShininess(root.fillShininessCache.offset, root.fillShininessCache.size, root.fillShininessCache.floatData); + root.fillShininessCache.clear(); } } @@ -3100,7 +3245,7 @@ public class PShape3D extends PShape { modifiedLineVertices = false; } else if (root.lineVerticesCache != null && root.lineVerticesCache.hasData()) { root.copyLineVertices(root.lineVerticesCache.offset, root.lineVerticesCache.size, root.lineVerticesCache.floatData); - root.lineVerticesCache.reset(); + root.lineVerticesCache.clear(); } if (modifiedLineColors) { @@ -3111,7 +3256,7 @@ public class PShape3D extends PShape { modifiedLineColors = false; } else if (root.lineColorsCache != null && root.lineColorsCache.hasData()) { root.copyLineColors(root.lineColorsCache.offset, root.lineColorsCache.size, root.lineColorsCache.intData); - root.lineColorsCache.reset(); + root.lineColorsCache.clear(); } if (modifiedLineAttributes) { @@ -3122,7 +3267,7 @@ public class PShape3D extends PShape { modifiedLineAttributes = false; } else if (root.lineAttributesCache != null && root.lineAttributesCache.hasData()) { root.copyLineAttributes(root.lineAttributesCache.offset, root.lineAttributesCache.size, root.lineAttributesCache.floatData); - root.lineAttributesCache.reset(); + root.lineAttributesCache.clear(); } } @@ -3135,7 +3280,7 @@ public class PShape3D extends PShape { modifiedPointVertices = false; } else if (root.pointVerticesCache != null && root.pointVerticesCache.hasData()) { root.copyPointVertices(root.pointVerticesCache.offset, root.pointVerticesCache.size, root.pointVerticesCache.floatData); - root.pointVerticesCache.reset(); + root.pointVerticesCache.clear(); } if (modifiedPointColors) { @@ -3146,7 +3291,7 @@ public class PShape3D extends PShape { modifiedPointColors = false; } else if (root.pointColorsCache != null && root.pointColorsCache.hasData()) { root.copyPointColors(root.pointColorsCache.offset, root.pointColorsCache.size, root.pointColorsCache.intData); - root.pointColorsCache.reset(); + root.pointColorsCache.clear(); } if (modifiedPointAttributes) { @@ -3157,7 +3302,7 @@ public class PShape3D extends PShape { modifiedPointAttributes = false; } else if (root.pointAttributesCache != null && root.pointAttributesCache.hasData()) { root.copyPointAttributes(root.pointAttributesCache.offset, root.pointAttributesCache.size, root.pointAttributesCache.floatData); - root.pointAttributesCache.reset(); + root.pointAttributesCache.clear(); } } @@ -3235,28 +3380,28 @@ public class PShape3D extends PShape { } - protected void copyfillAmbient(int offset, int size, int[] ambient) { + protected void copyFillAmbient(int offset, int size, int[] ambient) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillAmbientBufferID); pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(ambient, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyfillSpecular(int offset, int size, int[] specular) { + protected void copyFillSpecular(int offset, int size, int[] specular) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillSpecularBufferID); pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(specular, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyfillEmissive(int offset, int size, int[] emissive) { + protected void copyFillEmissive(int offset, int size, int[] emissive) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillEmissiveBufferID); pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(emissive, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyfillShininess(int offset, int size, float[] shininess) { + protected void copyFillShininess(int offset, int size, float[] shininess) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillShininessBufferID); pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_FLOAT, size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(shininess, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); @@ -3785,7 +3930,7 @@ public class PShape3D extends PShape { this.size = 0; } - void reset() { + void clear() { offset = 0; size = 0; } diff --git a/android/core/src/processing/core/PTexture.java b/android/core/src/processing/core/PTexture.java index 6974de362..a835abc70 100644 --- a/android/core/src/processing/core/PTexture.java +++ b/android/core/src/processing/core/PTexture.java @@ -97,8 +97,7 @@ public class PTexture implements PConstants { this.parent = parent; pg = (PGraphicsAndroid3D)parent.g; - pgl = pg.pgl; - context = pgl.getContext(); + pgl = pg.pgl; glID = 0; @@ -114,8 +113,7 @@ public class PTexture implements PConstants { } finally { super.finalize(); } - } - + } //////////////////////////////////////////////////////////// @@ -771,23 +769,24 @@ public class PTexture implements PConstants { pgl.enableTexturing(glTarget); + context = pgl.getContext(); glID = pg.createTextureObject(); pgl.glBindTexture(glTarget, glID); pgl.glTexParameterf(glTarget, PGL.GL_TEXTURE_MIN_FILTER, glMinFilter); - pgl.glTexParameterf(glTarget, PGL.GL_TEXTURE_MAG_FILTER, glMagFilter); + pgl.glTexParameterf(glTarget, PGL.GL_TEXTURE_MAG_FILTER, glMagFilter); pgl.glTexParameterf(glTarget, PGL.GL_TEXTURE_WRAP_S, glWrapS); - pgl.glTexParameterf(glTarget, PGL.GL_TEXTURE_WRAP_T, glWrapT); + pgl.glTexParameterf(glTarget, PGL.GL_TEXTURE_WRAP_T, glWrapT); // First, we use glTexImage2D to set the full size of the texture (glW/glH might be diff // from w/h in the case that the GPU doesn't support NPOT textures) pgl.glTexImage2D(glTarget, 0, glFormat, glWidth, glHeight, 0, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, null); // Makes sure that the texture buffer in video memory doesn't contain any garbage. - pgl.initTexture(glTarget, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE); + pgl.initTexture(glTarget, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE); pgl.glBindTexture(glTarget, 0); - pgl.disableTexturing(glTarget); + pgl.disableTexturing(glTarget); } @@ -802,6 +801,14 @@ public class PTexture implements PConstants { } + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + glID = 0; + } + return outdated; + } + /////////////////////////////////////////////////////////// // Utilities. diff --git a/java/libraries/opengl/src/processing/opengl/PFramebuffer.java b/java/libraries/opengl/src/processing/opengl/PFramebuffer.java index cff5aefe6..2da4ff88a 100644 --- a/java/libraries/opengl/src/processing/opengl/PFramebuffer.java +++ b/java/libraries/opengl/src/processing/opengl/PFramebuffer.java @@ -39,8 +39,6 @@ import java.nio.IntBuffer; * By Andres Colubri. */ -// TODO: restart framebuffer when context changes - public class PFramebuffer implements PConstants { protected PApplet parent; protected PGraphicsOpenGL pg; diff --git a/java/libraries/opengl/src/processing/opengl/PGL.java b/java/libraries/opengl/src/processing/opengl/PGL.java index ee439664b..05677a718 100644 --- a/java/libraries/opengl/src/processing/opengl/PGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGL.java @@ -34,7 +34,6 @@ import java.util.TimerTask; import javax.media.opengl.GL; import javax.media.opengl.GL2; -import javax.media.opengl.GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; @@ -210,16 +209,16 @@ public class PGL { public static final int GL_DST_COLOR = GL.GL_DST_COLOR; public static final int GL_SRC_COLOR = GL.GL_SRC_COLOR; - public static final int GL_FRAMEBUFFER = GL.GL_FRAMEBUFFER; - public static final int GL_COLOR_ATTACHMENT0 = GL.GL_COLOR_ATTACHMENT0; + public static final int GL_FRAMEBUFFER = GL.GL_FRAMEBUFFER; + public static final int GL_COLOR_ATTACHMENT0 = GL.GL_COLOR_ATTACHMENT0; + public static final int GL_COLOR_ATTACHMENT1 = GL2.GL_COLOR_ATTACHMENT1; + public static final int GL_COLOR_ATTACHMENT2 = GL2.GL_COLOR_ATTACHMENT2; + public static final int GL_COLOR_ATTACHMENT3 = GL2.GL_COLOR_ATTACHMENT3; public static final int GL_RENDERBUFFER = GL.GL_RENDERBUFFER; public static final int GL_DEPTH_ATTACHMENT = GL.GL_DEPTH_ATTACHMENT; public static final int GL_STENCIL_ATTACHMENT = GL.GL_STENCIL_ATTACHMENT; - public static final int GL_READ_FRAMEBUFFER = GL2.GL_READ_FRAMEBUFFER; - public static final int GL_DRAW_FRAMEBUFFER = GL2.GL_DRAW_FRAMEBUFFER ; - public static final int GL_COLOR_ATTACHMENT1 = GL2.GL_COLOR_ATTACHMENT1; - public static final int GL_COLOR_ATTACHMENT2 = GL2.GL_COLOR_ATTACHMENT2; - public static final int GL_COLOR_ATTACHMENT3 = GL2.GL_COLOR_ATTACHMENT3; + public static final int GL_READ_FRAMEBUFFER = GL2.GL_READ_FRAMEBUFFER; + public static final int GL_DRAW_FRAMEBUFFER = GL2.GL_DRAW_FRAMEBUFFER; public static final int GL_VERTEX_SHADER = GL2.GL_VERTEX_SHADER; public static final int GL_FRAGMENT_SHADER = GL2.GL_FRAGMENT_SHADER; diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index db6ecdea4..4eab6e213 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -1439,8 +1439,7 @@ public class PGraphicsOpenGL extends PGraphics { if (primarySurface) { int[] temp = { 0 }; pgl.glGetIntegerv(PGL.GL_SAMPLES, temp, 0); - if (antialias != temp[0]) { - PGraphics.showWarning("Smooth level " + antialias + " not supported. Using " + temp[0] + " instead."); + if (antialias != temp[0] && 1 < temp[0] && 1 < antialias) { antialias = temp[0]; } } @@ -2944,7 +2943,7 @@ public class PGraphicsOpenGL extends PGraphics { smooth = true; if (maxSamples < level) { - PGraphics.showWarning("Smooth level not supported by the video card. Using " + maxSamples + " instead."); + PGraphics.showWarning("Smooth level " + level + " is not supported by the hardware. Using " + maxSamples + " instead."); level = maxSamples; }