@Override
void readOffScreenBuffer(Canvas3D cv, Context ctx, int format, int dataType, Object data, int width, int height) {
if (VERBOSE) System.err.println("JoglPipeline.readOffScreenBuffer()");
GLDrawable glDrawable = ((JoglDrawable)cv.drawable).getGLDrawable();
GLCapabilitiesImmutable chosenCaps = glDrawable.getChosenGLCapabilities();
GLFBODrawable fboDrawable = null;
GL2 gl = context(ctx).getGL().getGL2();
// If FBO
if (chosenCaps.isFBO()) {
fboDrawable = (GLFBODrawable)glDrawable;
if (chosenCaps.getDoubleBuffered()) {
// swap = resolve multisampling or flip back/front FBO
fboDrawable.swapBuffers();
// unbind texture render target, we read from FBO
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
}
// bind FBO for reading pixel data
// GL_FRONT = SamplingSinkFBO if double buffered and multisampled
// GL_FRONT if double buffered ( = GL_BAck before swap was called)
// GL_FRONT = GL_BACK if single buffered (single FBO)
fboDrawable.getFBObject( GL.GL_FRONT ).bind(gl);
}
// else pbuffer
gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, width);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
int type = 0;
if((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY) ||
(dataType == ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_BUFFER)) {
switch (format) {
// GL_BGR
case ImageComponentRetained.TYPE_BYTE_BGR:
type = GL2.GL_BGR;
break;
case ImageComponentRetained.TYPE_BYTE_RGB:
type = GL.GL_RGB;
break;
// GL_ABGR_EXT
case ImageComponentRetained.TYPE_BYTE_ABGR:
if (gl.isExtensionAvailable("GL_EXT_abgr")) { // If false, should never come here!
type = GL2.GL_ABGR_EXT;
} else {
assert false;
return;
}
break;
case ImageComponentRetained.TYPE_BYTE_RGBA:
type = GL.GL_RGBA;
break;
/* This method only supports 3 and 4 components formats and BYTE types. */
case ImageComponentRetained.TYPE_BYTE_LA:
case ImageComponentRetained.TYPE_BYTE_GRAY:
case ImageComponentRetained.TYPE_USHORT_GRAY:
case ImageComponentRetained.TYPE_INT_BGR:
case ImageComponentRetained.TYPE_INT_RGB:
case ImageComponentRetained.TYPE_INT_ARGB:
default:
throw new AssertionError("illegal format " + format);
}
gl.glReadPixels(0, 0, width, height, type, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap((byte[]) data));
}
else if ((dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_ARRAY) ||
(dataType == ImageComponentRetained.IMAGE_DATA_TYPE_INT_BUFFER)) {
int intType = GL2.GL_UNSIGNED_INT_8_8_8_8;
boolean forceAlphaToOne = false;
switch (format) {
/* GL_BGR */
case ImageComponentRetained.TYPE_INT_BGR: /* Assume XBGR format */
type = GL.GL_RGBA;
intType = GL2.GL_UNSIGNED_INT_8_8_8_8_REV;
forceAlphaToOne = true;
break;
case ImageComponentRetained.TYPE_INT_RGB: /* Assume XRGB format */
forceAlphaToOne = true;
/* Fall through to next case */
case ImageComponentRetained.TYPE_INT_ARGB:
type = GL2.GL_BGRA;
intType = GL2.GL_UNSIGNED_INT_8_8_8_8_REV;
break;
/* This method only supports 3 and 4 components formats and BYTE types. */
case ImageComponentRetained.TYPE_BYTE_LA:
case ImageComponentRetained.TYPE_BYTE_GRAY:
case ImageComponentRetained.TYPE_USHORT_GRAY:
case ImageComponentRetained.TYPE_BYTE_BGR:
case ImageComponentRetained.TYPE_BYTE_RGB:
case ImageComponentRetained.TYPE_BYTE_RGBA:
case ImageComponentRetained.TYPE_BYTE_ABGR:
default:
throw new AssertionError("illegal format " + format);
}
/* Force Alpha to 1.0 if needed */
if(forceAlphaToOne) {
gl.glPixelTransferf(GL2.GL_ALPHA_SCALE, 0.0f);
gl.glPixelTransferf(GL2.GL_ALPHA_BIAS, 1.0f);
}
gl.glReadPixels(0, 0, width, height, type, intType, IntBuffer.wrap((int[]) data));
/* Restore Alpha scale and bias */
if(forceAlphaToOne) {
gl.glPixelTransferf(GL2.GL_ALPHA_SCALE, 1.0f);
gl.glPixelTransferf(GL2.GL_ALPHA_BIAS, 0.0f);
}
}
else {
throw new AssertionError("illegal image data type " + dataType);
}
// If FBO
if (chosenCaps.isFBO()) {
// bind FBO for drawing
fboDrawable.getFBObject( GL.GL_BACK ).bind(gl);
}
}