From b110bae80a88280b9f41ea385d58e2d560842ab9 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Sun, 25 Nov 2012 20:26:27 +0000 Subject: [PATCH] better resize handling --- core/src/processing/opengl/PGL.java | 127 +++++++++++------- .../processing/opengl/PGraphicsOpenGL.java | 68 ++++++---- 2 files changed, 116 insertions(+), 79 deletions(-) diff --git a/core/src/processing/opengl/PGL.java b/core/src/processing/opengl/PGL.java index 02d493784..4450f4b4c 100644 --- a/core/src/processing/opengl/PGL.java +++ b/core/src/processing/opengl/PGL.java @@ -374,6 +374,9 @@ public class PGL { /** Windowing toolkit */ protected static int toolkit = NEWT; + /** Enables/disables use of animator */ + protected static boolean useAnimator = false; + protected static boolean enable_screen_FBO_macosx = true; protected static boolean enable_screen_FBO_windows = true; protected static boolean enable_screen_FBO_linux = true; @@ -398,7 +401,7 @@ public class PGL { protected static PGLListener listener; /** Animator to drive the rendering thread in NEWT */ - protected static NEWTAnimator animator; + protected static PGLAnimator animator; /** Desired target framerate */ protected float targetFramerate = 60; @@ -532,12 +535,18 @@ public class PGL { } else { // Restarting... if (canvasAWT != null) { + if (useAnimator) { + animator.stop(); + animator.remove(canvasAWT); + } canvasAWT.removeGLEventListener(listener); pg.parent.removeListeners(canvasAWT); pg.parent.remove(canvasAWT); } else if (canvasNEWT != null) { - animator.stop(); - animator.remove(window); + if (useAnimator) { + animator.stop(); + animator.remove(window); + } window.removeGLEventListener(listener); pg.parent.remove(canvasNEWT); } @@ -585,6 +594,10 @@ public class PGL { listener = new PGLListener(); canvasAWT.addGLEventListener(listener); + if (useAnimator) { + animator = new PGLAnimator(canvasAWT); + animator.start(); + } } else if (toolkit == NEWT) { window = GLWindow.create(caps); canvasNEWT = new NewtCanvasAWT(window); @@ -605,8 +618,10 @@ public class PGL { listener = new PGLListener(); window.addGLEventListener(listener); - animator = new NEWTAnimator(window); - animator.start(); + if (useAnimator) { + animator = new PGLAnimator(window); + animator.start(); + } } firstFrame = true; @@ -782,10 +797,14 @@ public class PGL { protected void requestDraw() { if (initialized) { try { - if (toolkit == AWT) { - canvasAWT.display(); - } else if (toolkit == NEWT) { + if (useAnimator) { animator.requestDisplay(); + } else { + if (toolkit == AWT) { + canvasAWT.display(); + } else if (toolkit == NEWT) { + window.display(); + } } } catch (GLException e) { // Unwrap GLException so that only the causing exception is shown. @@ -2474,14 +2493,6 @@ public class PGL { public void reshape(GLAutoDrawable adrawable, int x, int y, int w, int h) { drawable = adrawable; context = adrawable.getContext(); - - /* - if (glColorFbo[0] != 0) { - // The screen FBO hack needs the FBO to be recreated when starting - // and after resizing. - glColorFbo[0] = 0; - } - */ } } @@ -2581,28 +2592,29 @@ public class PGL { } // Animator to drive render loop when using NEWT. - protected static class NEWTAnimator extends AnimatorBase { + protected static class PGLAnimator extends AnimatorBase { private static int count = 0; private Timer timer = null; - private TimerTask task = null; - private volatile boolean shouldRun; + private Task task = null; @Override protected String getBaseName(String prefix) { - return prefix + "NEWTAnimator"; + return prefix + "PGLAnimator"; } /** Creates an CustomAnimator with an initial drawable to * animate. */ - public NEWTAnimator(GLAutoDrawable drawable) { + public PGLAnimator(GLAutoDrawable drawable) { if (drawable != null) { add(drawable); } } - public synchronized void requestDisplay() { - shouldRun = true; + public void requestDisplay() { + if (task != null) { + task.shouldRun(); + } } public final boolean isStarted() { @@ -2624,34 +2636,12 @@ public class PGL { } private void startTask() { - if(null != task) { + if (null != task) { return; } - task = new TimerTask() { - private boolean firstRun = true; - @Override - public void run() { - if (firstRun) { - Thread.currentThread().setName("PGL-RenderQueue-" + count); - firstRun = false; - count++; - } - if (NEWTAnimator.this.shouldRun) { - NEWTAnimator.this.animThread = Thread.currentThread(); - // display impl. uses synchronized block on the animator instance - display(); - synchronized (this) { - // done with current frame. - shouldRun = false; - } - } - } - }; - + task = new Task(); fpsCounter.resetFPSCounter(); - shouldRun = false; - timer.schedule(task, 0, 1); } @@ -2676,12 +2666,11 @@ public class PGL { } stateSync.lock(); try { - shouldRun = false; - if(null != task) { + if (null != task) { task.cancel(); task = null; } - if(null != timer) { + if (null != timer) { timer.cancel(); timer = null; } @@ -2698,5 +2687,43 @@ public class PGL { public final boolean isPaused() { return false; } public synchronized boolean resume() { return false; } public synchronized boolean pause() { return false; } + + private class Task extends TimerTask { + private boolean firstRun = true; + private boolean shouldRun = false; + + public void shouldRun() { + synchronized (this) { + shouldRun = true; + } + } + + @Override + public void run() { + if (firstRun) { + Thread.currentThread().setName("PGL-RenderQueue-" + count); + firstRun = false; + count++; + } + if (shouldRun) { + PGLAnimator.this.animThread = Thread.currentThread(); + // display impl. uses synchronized block on the animator instance + display(); + synchronized (this) { + // done with current frame. + shouldRun = false; + } + } + } + + @Override + public boolean cancel() { + synchronized (this) { + // done with current frame. + shouldRun = false; + } + return super.cancel(); + } + } } } diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 037b4dfdf..ed346227d 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -432,9 +432,6 @@ public class PGraphicsOpenGL extends PGraphics { static protected final int OP_WRITE = 2; protected int pixelsOp = OP_NONE; - /** Used to detect the occurrence of a frame resize event. */ - protected boolean resized = false; - /** Viewport dimensions. */ protected int[] viewport = {0, 0, 0, 0}; @@ -537,17 +534,9 @@ public class PGraphicsOpenGL extends PGraphics { @Override public void setSize(int iwidth, int iheight) { - resized = (0 < width && width != iwidth) || - (0 < height && height != iwidth); - width = iwidth; height = iheight; - if (pixels != null) { - // The user is using the pixels array, so we need to resize accordingly - allocatePixels(); - } - allocate(); reapplySettings(); @@ -560,11 +549,12 @@ public class PGraphicsOpenGL extends PGraphics { cameraFar = cameraZ * 10.0f; cameraAspect = (float) width / (float) height; + // Forces a restart of OpenGL so the canvas has the right size. + //pgl.initialized = false; + restartPGL(); + // set this flag so that beginDraw() will do an update to the camera. sized = true; - - // Forces a restart of OpenGL so the canvas has the right size. - pgl.initialized = false; } @@ -1595,7 +1585,8 @@ public class PGraphicsOpenGL extends PGraphics { boolean outdatedMulti = multisampleFramebuffer != null && multisampleFramebuffer.contextIsOutdated(); if (outdated || outdatedMulti) { - pgl.initialized = false; +// pgl.initialized = false; + restartPGL(); initOffscreen(); } } @@ -1665,21 +1656,12 @@ public class PGraphicsOpenGL extends PGraphics { // setup opengl viewport. viewport[0] = 0; viewport[1] = 0; viewport[2] = width; viewport[3] = height; pgl.viewport(viewport[0], viewport[1], viewport[2], viewport[3]); - if (resized) { + + if (sized) { // To avoid having garbage in the screen after a resize, // in the case background is not called in draw(). background(backgroundColor); - if (texture != null) { - // The screen texture should be deleted because it - // corresponds to the old window size. - pgPrimary.removeCache(this); - texture = null; - loadTexture(); - } - resized = false; - } - if (sized) { // Sets the default projection and camera (initializes modelview). // If the user has setup up their own projection, they'll need // to fix it after resize anyway. This helps the people who haven't @@ -1687,6 +1669,11 @@ public class PGraphicsOpenGL extends PGraphics { defaultPerspective(); defaultCamera(); + if (pixels != null) { + // The pixels array is being used, so we need to resize accordingly + loadPixels(); + } + // clear the flag sized = false; } else { @@ -1821,6 +1808,14 @@ public class PGraphicsOpenGL extends PGraphics { protected void restartPGL() { pgl.initialized = false; + /* + if (texture != null) { + PApplet.println("restart: " + Thread.currentThread()); + // The screen texture should be deleted because it + // corresponds to the old window size. + removeCache(this); + texture = ptexture = null; + }*/ } @@ -3234,9 +3229,11 @@ public class PGraphicsOpenGL extends PGraphics { if (quality == 1) { quality = 0; } + // This will trigger a surface restart next time // requestDraw() is called. - pgl.initialized = false; +// pgl.initialized = false; + restartPGL(); } } @@ -3262,7 +3259,8 @@ public class PGraphicsOpenGL extends PGraphics { quality = 0; // This will trigger a surface restart next time // requestDraw() is called. - pgl.initialized = false; +// pgl.initialized = false; + restartPGL(); } } @@ -5191,10 +5189,17 @@ public class PGraphicsOpenGL extends PGraphics { protected void drawPixels(int x, int y, int w, int h) { + if (sized || texture == null) { + // This shouldn't happen... some threading problem because sized is turned + // to false in beginDraw() + // http://code.google.com/p/processing/issues/detail?id=1119 + return; + } + int i0 = y * width + x; int len = w * h; - if (nativePixels == null || nativePixels.length < len) { + if (nativePixels == null || nativePixels.length != len) { nativePixels = new int[len]; nativePixelBuffer = IntBuffer.wrap(nativePixels); } @@ -5208,6 +5213,7 @@ public class PGraphicsOpenGL extends PGraphics { // of non-FBO-backed primary surface we might need to create the texture. loadTextureImpl(POINT, false); } + pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glName, x, y, w, h, IntBuffer.wrap(nativePixels)); @@ -5859,6 +5865,10 @@ public class PGraphicsOpenGL extends PGraphics { if (pgPrimary == null) { pgPrimary = this; } + if (texture != null) { + pgPrimary.removeCache(this); + texture = ptexture = null; + } }