mirror of
https://github.com/processing/processing4.git
synced 2026-06-08 16:40:46 +02:00
flush before changing projection matrix, fixed load pixels in GL
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user