flush before changing projection matrix, fixed load pixels in GL

This commit is contained in:
codeanticode
2012-07-16 06:30:06 +00:00
parent b48f7d6429
commit 0562ca3420
12 changed files with 415 additions and 156 deletions
@@ -63,8 +63,6 @@ public class PGL {
public static final int AWT = 0; // http://jogamp.org/wiki/index.php/Using_JOGL_in_AWT_SWT_and_Swing
public static final int NEWT = 1; // http://jogamp.org/jogl/doc/NEWT-Overview.html
public static int toolkit = AWT;
/** Size of a short (in bytes). */
public static final int SIZEOF_SHORT = Short.SIZE / 8;
@@ -321,6 +319,9 @@ public class PGL {
/** Whether OpenGL has been initialized or not */
public boolean initialized;
/** Windowing toolkit */
public static int toolkit = AWT;
/** Selected GL profile */
public GLProfile profile;
@@ -349,7 +350,7 @@ public class PGL {
protected PGLListener listener;
/** Animator to drive the rendering thread in NEWT */
protected GLAnimator animator;
protected PGLAnimator animator;
/** Desired target framerate */
protected float targetFramerate = 60;
@@ -500,6 +501,14 @@ public class PGL {
}
public void setToolkit(int toolkit) {
if (PGL.toolkit != toolkit) {
PGL.toolkit = toolkit;
this.initialized = false;
}
}
public void initPrimarySurface(int antialias) {
if (ENABLE_OSX_SCREEN_FBO) {
needScreenFBO = false;
@@ -527,11 +536,15 @@ public class PGL {
profile = GLProfile.getDefault();
} else {
// Restarting...
if (toolkit == AWT) {
if (canvasAWT != null) {
// TODO: Even if the GLCanvas is put inside an animator, the rendering runs
// inside the EDT, ask the JOGL guys about this.
// animator.stop();
// animator.remove(canvasAWT);
canvasAWT.removeGLEventListener(listener);
pg.parent.removeListeners(canvasAWT);
pg.parent.remove(canvasAWT);
} else if (toolkit == NEWT) {
} else if (canvasNEWT != null) {
animator.stop();
animator.remove(window);
window.removeGLEventListener(listener);
@@ -565,9 +578,12 @@ public class PGL {
listener = new PGLListener();
canvasAWT.addGLEventListener(listener);
// animator = new PGLAnimator(canvasAWT);
// animator.start();
capabilities = canvasAWT.getChosenGLCapabilities();
canvas = canvasAWT;
canvasNEWT = null;
} else if (toolkit == NEWT) {
window = GLWindow.create(caps);
canvasNEWT = new NewtCanvasAWT(window);
@@ -579,11 +595,12 @@ public class PGL {
listener = new PGLListener();
window.addGLEventListener(listener);
animator = new GLAnimator(window);
animator = new PGLAnimator(window);
animator.start();
capabilities = window.getChosenGLCapabilities();
canvas = canvasNEWT;
canvasAWT = null;
}
initialized = true;
@@ -829,11 +846,14 @@ public class PGL {
public void requestDraw() {
if (initialized) {
//animator.requestDisplay();
if (toolkit == AWT) {
canvasAWT.display();
} else if (toolkit == NEWT) {
animator.requestDisplay();
}
}
}
@@ -2350,20 +2370,20 @@ public class PGL {
/** Animator subclass to drive render loop when using NEWT.
**/
protected static class GLAnimator extends AnimatorBase {
// private static int count = 0;
protected static class PGLAnimator extends AnimatorBase {
private static int count = 0;
private Timer timer = null;
private TimerTask task = null;
private volatile boolean shouldRun;
protected String getBaseName(String prefix) {
return prefix + "PGLAnimator" ;
return prefix + "PGLAnimator";
}
/** Creates an CustomAnimator with an initial drawable to
* animate.
*/
public GLAnimator(GLAutoDrawable drawable) {
public PGLAnimator(GLAutoDrawable drawable) {
if (drawable != null) {
add(drawable);
}
@@ -2397,15 +2417,15 @@ public class PGL {
}
task = new TimerTask() {
// private boolean firstRun = true;
private boolean firstRun = true;
public void run() {
// if (firstRun) {
// Thread.currentThread().setName("NEWT-RenderQueue-" + count);
// firstRun = false;
// count++;
// }
if (GLAnimator.this.shouldRun) {
GLAnimator.this.animThread = Thread.currentThread();
if (firstRun) {
Thread.currentThread().setName("PGL-RenderQueue-" + count);
firstRun = false;
count++;
}
if (PGLAnimator.this.shouldRun) {
PGLAnimator.this.animThread = Thread.currentThread();
// display impl. uses synchronized block on the animator instance
display();
synchronized (this) {
@@ -489,7 +489,12 @@ public class PGraphicsOpenGL extends PGraphics {
pgl.setFramerate(framerate);
}
public void setToolkit(int toolkit) {
pgl.setToolkit(toolkit);
}
public void setSize(int iwidth, int iheight) {
resized = (0 < width && width != iwidth) || (0 < height && height != iwidth);
@@ -1693,7 +1698,9 @@ public class PGraphicsOpenGL extends PGraphics {
}
popFramebuffer();
texture.updateTexels(); // Mark all texels in screen texture as modified.
pgl.endOffscreenDraw(pgPrimary.clearColorBuffer0);
pgPrimary.restoreGL();
@@ -3743,6 +3750,8 @@ public class PGraphicsOpenGL extends PGraphics {
public void popProjection() {
flush(); // The geometry with the old projection matrix needs to be drawn now
if (projectionStackDepth == 0) {
throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW);
}
@@ -3752,11 +3761,13 @@ public class PGraphicsOpenGL extends PGraphics {
public void applyProjection(PMatrix3D mat) {
flush();
projection.apply(mat);
}
public void setProjection(PMatrix3D mat) {
flush();
projection.set(mat);
}
@@ -4947,7 +4958,7 @@ public class PGraphicsOpenGL extends PGraphics {
pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer);
endPixelsOp();
PGL.nativeToJavaARGB(pixels, width, height);
PGL.nativeToJavaARGB(pixels, width, height);
}
@@ -5026,22 +5037,52 @@ public class PGraphicsOpenGL extends PGraphics {
// array, and then the pixels array into the screen texture.
public void loadTexture() {
if (primarySurface) {
loadTextureImpl(POINT, false);
loadTextureImpl(Texture.POINT, false);
loadPixels();
pixelsToTexture();
}
}
// Draws wherever it is in the screen texture right now to the screen.
public void updateTexture() {
// Draws wherever it is in the screen texture right now to the display.
public void updateDisplay() {
flush();
beginPixelsOp(OP_WRITE);
drawTexture();
endPixelsOp();
}
// Uses the texture in img as the color buffer for this surface.
public void setTexture(PImage img) {
if (width != img.width || height != img.height) {
PGraphics.showWarning("Resolution of image is different from PGraphics object");
return;
}
if (texture == null || texture != img.getCache(pgPrimary)) {
Texture.Parameters params;
if (primarySurface) {
params = new Texture.Parameters(ARGB, Texture.POINT, false);
} else {
params = new Texture.Parameters(ARGB, Texture.BILINEAR, false);
}
texture = addTexture(img, params);
texture.setFlippedY(true);
this.setCache(pgPrimary, texture);
this.setParams(pgPrimary, params);
if (!primarySurface && offscreenFramebuffer != null) {
// Attach as the color buffer for this offscreen surface
offscreenFramebuffer.setColorBuffer(texture);
offscreenFramebuffer.clear();
}
}
}
protected void loadTextureImpl(int sampling, boolean mipmap) {
if (width == 0 || height == 0) return;
if (texture == null || texture.contextIsOutdated()) {
@@ -5052,8 +5093,8 @@ public class PGraphicsOpenGL extends PGraphics {
this.setParams(pgPrimary, params);
}
}
protected void drawTexture() {
pgl.drawTexture(texture.glTarget, texture.glID,
texture.glWidth, texture.glHeight,
@@ -5348,41 +5389,6 @@ public class PGraphicsOpenGL extends PGraphics {
return tex;
}
/**
* Copies the contents of the texture bound to img to its pixels array.
* @param img the image to have a texture metadata associated to it
*/
/*
public void loadPixels(PImage img) {
if (img.pixels == null) {
img.pixels = new int[img.width * img.height];
}
Texture tex = (Texture)img.getCache(pgPrimary);
if (tex == null) {
tex = addTexture(img);
} else {
if (tex.contextIsOutdated()) {
tex = addTexture(img);
}
if (tex.hasBuffers()) {
// Updates the texture AND the pixels
// array of the image at the same time,
// getting the pixels directly from the
// buffer data (avoiding expenive transfer
// beteeen video and main memory).
tex.bufferUpdate(img.pixels);
}
if (tex.isModified()) {
// Regular pixel copy from texture.
tex.get(img.pixels);
}
}
}
*/
/**
* This utility method creates a texture for the provided image, and adds it
@@ -5419,7 +5425,18 @@ public class PGraphicsOpenGL extends PGraphics {
return tex;
}
protected Texture addTexture(PImage img, Texture.Parameters params) {
Texture tex = new Texture(img.parent, img.width, img.height, params);
if (img.pixels == null) {
img.loadPixels();
}
if (img.pixels != null) tex.set(img.pixels);
img.setCache(pgPrimary, tex);
return tex;
}
protected PImage wrapTexture(Texture tex) {
// We don't use the PImage(int width, int height, int mode) constructor to
// avoid initializing the pixels array.
@@ -96,8 +96,9 @@ public class Texture implements PConstants {
protected FrameBuffer tempFbo = null;
/** modified portion of the texture */
/** Modified portion of the texture */
protected boolean modified;
protected int mx1, my1, mx2, my2;
protected Object bufferSource;
protected LinkedList<BufferData> bufferCache = null;
@@ -355,7 +356,9 @@ public class Texture implements PConstants {
}
pgl.glBindTexture(glTarget, 0);
pgl.disableTexturing(glTarget);
pgl.disableTexturing(glTarget);
updateTexels(x, y, w, h);
}
@@ -395,6 +398,27 @@ public class Texture implements PConstants {
}
/**
* Copies the contents of the texture to the pixels array.
* @param pixels
*/
public void loadPixels(int[] pixels) {
if (hasBuffers()) {
// Updates the texture AND the pixels array of the image at the same time,
// getting the pixels directly from the buffer data (and thus avoiding expensive
// transfer between video and main memory).
bufferUpdate(pixels);
}
if (isModified()) {
// Regular pixel copy from texture.
get(pixels);
}
setModified(false);
}
////////////////////////////////////////////////////////////
// Put methods (the source texture is not resized to cover the entire
@@ -481,16 +505,19 @@ public class Texture implements PConstants {
// Bind/unbind
public void bind() {
pgl.enableTexturing(glTarget);
pgl.glBindTexture(glTarget, glID);
}
public void unbind() {
pgl.enableTexturing(glTarget);
pgl.glBindTexture(glTarget, 0);
}
//////////////////////////////////////////////////////////////
// Modified flag
@@ -509,7 +536,62 @@ public class Texture implements PConstants {
public void setModified(boolean m) {
modified = m;
}
public int getModifiedX1() {
return mx1;
}
public int getModifiedX2() {
return mx2;
}
public int getModifiedY1() {
return my1;
}
public int getModifiedY2() {
return my2;
}
public void updateTexels() {
updateTexelsImpl(0, 0, width, height);
}
public void updateTexels(int x, int y, int w, int h) {
updateTexelsImpl(x, y, w, h);
}
protected void updateTexelsImpl(int x, int y, int w, int h) {
int x2 = x + w;
int y2 = y + h;
if (!modified) {
mx1 = PApplet.max(0, x);
mx2 = PApplet.min(width - 1, x2);
my1 = PApplet.max(0, y);
my2 = PApplet.min(height - 1, y2);
modified = true;
} else {
if (x < mx1) mx1 = PApplet.max(0, x);
if (x > mx2) mx2 = PApplet.min(width - 1, x);
if (y < my1) my1 = PApplet.max(0, y);
if (y > my2) my2 = y;
if (x2 < mx1) mx1 = PApplet.max(0, x2);
if (x2 > mx2) mx2 = PApplet.min(width - 1, x2);
if (y2 < my1) my1 = PApplet.max(0, y2);
if (y2 > my2) my2 = PApplet.min(height - 1, y2);
}
}
////////////////////////////////////////////////////////////
@@ -538,11 +620,13 @@ public class Texture implements PConstants {
}
}
}
public boolean hasBufferSource() {
return bufferSource != null;
}
public boolean hasBuffers() {
return bufferSource != null && bufferCache != null && 0 < bufferCache.size();
}
@@ -571,10 +655,9 @@ public class Texture implements PConstants {
return false;
}
}
protected boolean bufferUpdate(int[] pixels) {
//PApplet.println("buffer update with pix");
BufferData data = null;
try {
data = bufferCache.remove(0);
@@ -600,6 +683,7 @@ public class Texture implements PConstants {
return false;
}
}
protected void getSourceMethods() {
try {
@@ -609,6 +693,7 @@ public class Texture implements PConstants {
}
}
////////////////////////////////////////////////////////////
// Utilities
@@ -933,6 +1018,7 @@ public class Texture implements PConstants {
return outdated;
}
///////////////////////////////////////////////////////////
// Utilities.
@@ -969,24 +1055,32 @@ public class Texture implements PConstants {
x, y, w, h, x, y, w, h);
}
pg.popFramebuffer();
updateTexels(x, y, w, h);
}
protected void setTexels(int[] pix, int x, int y, int w, int h) {
setTexels(pix, 0, x, y, w, h);
}
protected void setTexels(int[] pix, int level, int x, int y, int w, int h) {
pgl.glTexSubImage2D(glTarget, level, x, y, w, h, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, IntBuffer.wrap(pix));
updateTexels(x, y, w, h);
}
protected void setTexels(IntBuffer buffer, int x, int y, int w, int h) {
setTexels(buffer, 0, x, y, w, h);
}
protected void setTexels(IntBuffer buffer, int level, int x, int y, int w, int h) {
pgl.glTexSubImage2D(glTarget, level, x, y, w, h, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, buffer);
updateTexels(x, y, w, h);
}
protected void copyObject(Texture src) {
// The OpenGL texture of this object is replaced with the one from the source object,
// so we delete the former to avoid resource wasting.
@@ -1014,7 +1108,8 @@ public class Texture implements PConstants {
flippedX = src.flippedX;
flippedY = src.flippedY;
}
///////////////////////////////////////////////////////////
// Parameter handling
@@ -338,10 +338,6 @@ public class Capture extends PImage implements PConstants {
* @usage web_application
*/
public synchronized void read() {
// if (pixels == null) {
// pixels = new int[width * height];
// }
if (useBufferSink) { // The native buffer from gstreamer is copied to the buffer sink.
if (natBuffer == null) {
return;
@@ -349,7 +345,6 @@ public class Capture extends PImage implements PConstants {
if (firstFrame) {
super.init(bufWidth, bufHeight, ARGB);
//loadPixels();
firstFrame = false;
}
@@ -365,6 +360,7 @@ public class Capture extends PImage implements PConstants {
ByteBuffer byteBuffer = natBuffer.getByteBuffer();
try {
PApplet.println("copy buffer to sink...");
sinkCopyMethod.invoke(bufferSink, new Object[] { natBuffer, byteBuffer, bufWidth, bufHeight });
} catch (Exception e) {
e.printStackTrace();
@@ -536,7 +536,6 @@ public class Movie extends PImage implements PConstants {
if (firstFrame) {
super.init(bufWidth, bufHeight, ARGB);
//loadPixels();
firstFrame = false;
}
@@ -564,7 +563,6 @@ public class Movie extends PImage implements PConstants {
}
if (firstFrame) {
//resize(bufWidth, bufHeight);
super.init(bufWidth, bufHeight, RGB);
firstFrame = false;
}
@@ -73,7 +73,7 @@ public class Video implements PConstants {
// can improve performance significantly, since the video frames are automatically
// copied into the texture without passing through the pixels arrays, as well as
// having the color conversion into RGBA handled natively by gstreamer.
public static boolean useGLBufferSink = false;
public static boolean useGLBufferSink = true;
// Path that the video library will use to load the gstreamer native libs from.
// It is buit either from the system or local paths.