Android: Initial commit to support FrameBuffers. This is still a work in progress. FilterPostProcessors currently don't work on Android devices that do not support NPOT.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10513 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
iwg..om 12 years ago
parent a1fd0272d4
commit e26c86c794
  1. 487
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  2. 17
      engine/src/android/com/jme3/renderer/android/TextureUtil.java

@ -78,6 +78,8 @@ public class OGLESShaderRenderer implements Renderer {
private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
// current state
private Shader boundShader;
// initalDrawBuf and initialReadBuf are not used on ES,
// http://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindFramebuffer.xml
//private int initialDrawBuf, initialReadBuf;
private int glslVer;
private int vertexTextureUnits;
@ -86,15 +88,16 @@ public class OGLESShaderRenderer implements Renderer {
private int fragUniforms;
private int vertexAttribs;
// private int maxFBOSamples;
// private int maxFBOAttachs;
// private int maxMRTFBOAttachs;
// private int maxRBSize;
private final int maxFBOAttachs = 1; // Only 1 color attachment on ES
private final int maxMRTFBOAttachs = 1; // FIXME for now, not sure if > 1 is needed for ES
private int maxRBSize;
private int maxTexSize;
private int maxCubeTexSize;
private int maxVertCount;
private int maxTriCount;
private boolean tdc;
// private FrameBuffer lastFb = null;
private FrameBuffer lastFb = null;
private FrameBuffer mainFbOverride = null;
private final Statistics statistics = new Statistics();
private int vpX, vpY, vpW, vpH;
private int clipX, clipY, clipW, clipH;
@ -155,11 +158,18 @@ public class OGLESShaderRenderer implements Renderer {
powerVr = GLES20.glGetString(GLES20.GL_RENDERER).contains("PowerVR");
/*
// Fix issue in TestRenderToMemory when GL_FRONT is the main
// buffer being used.
// initialDrawBuf = GLES20.glGetIntegeri(GLES20.GL_DRAW_BUFFER);
// initialReadBuf = GLES20.glGetIntegeri(GLES20.GL_READ_BUFFER);
initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
initialReadBuf = glGetInteger(GL_READ_BUFFER);
// XXX: This has to be GL_BACK for canvas on Mac
// Since initialDrawBuf is GL_FRONT for pbuffer, gotta
// change this value later on ...
// initialDrawBuf = GL_BACK;
// initialReadBuf = GL_BACK;
*/
// Check OpenGL version
int openGlVer = extractVersion("OpenGL ES ", GLES20.glGetString(GLES20.GL_VERSION));
@ -226,6 +236,10 @@ public class OGLESShaderRenderer implements Renderer {
maxCubeTexSize = intBuf16.get(0);
logger.log(Level.FINE, "Maximum CubeMap Resolution: {0}", maxCubeTexSize);
GLES20.glGetIntegerv(GLES20.GL_MAX_RENDERBUFFER_SIZE, intBuf16);
maxRBSize = intBuf16.get(0);
logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
/*
if (ctxCaps.GL_ARB_color_buffer_float){
// XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
@ -951,180 +965,268 @@ public class OGLESShaderRenderer implements Renderer {
|* Framebuffers *|
\*********************************************************************/
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
logger.warning("copyFrameBuffer is not supported.");
copyFrameBuffer(src, dst, true);
}
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
logger.warning("copyFrameBuffer is not supported.");
}
/*
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){
int srcW = 0;
int srcH = 0;
int dstW = 0;
int dstH = 0;
int prevFBO = context.boundFBO;
if (src != null && src.isUpdateNeeded())
updateFrameBuffer(src);
if (dst != null && dst.isUpdateNeeded())
updateFrameBuffer(dst);
if (src == null){
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
// srcW = viewWidth;
// srcH = viewHeight;
}else{
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
srcW = src.getWidth();
srcH = src.getHeight();
}
if (dst == null){
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
// dstW = viewWidth;
// dstH = viewHeight;
}else{
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
dstW = dst.getWidth();
dstH = dst.getHeight();
throw new RendererException("Copy framebuffer not implemented yet.");
// if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
// int srcX0 = 0;
// int srcY0 = 0;
// int srcX1 = 0;
// int srcY1 = 0;
//
// int dstX0 = 0;
// int dstY0 = 0;
// int dstX1 = 0;
// int dstY1 = 0;
//
// int prevFBO = context.boundFBO;
//
// if (mainFbOverride != null) {
// if (src == null) {
// src = mainFbOverride;
// }
// if (dst == null) {
// dst = mainFbOverride;
// }
// }
//
// if (src != null && src.isUpdateNeeded()) {
// updateFrameBuffer(src);
// }
//
// if (dst != null && dst.isUpdateNeeded()) {
// updateFrameBuffer(dst);
// }
//
// if (src == null) {
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// srcX0 = vpX;
// srcY0 = vpY;
// srcX1 = vpX + vpW;
// srcY1 = vpY + vpH;
// } else {
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, src.getId());
// srcX1 = src.getWidth();
// srcY1 = src.getHeight();
// }
// if (dst == null) {
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// dstX0 = vpX;
// dstY0 = vpY;
// dstX1 = vpX + vpW;
// dstY1 = vpY + vpH;
// } else {
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, dst.getId());
// dstX1 = dst.getWidth();
// dstY1 = dst.getHeight();
// }
//
//
// int mask = GL_COLOR_BUFFER_BIT;
// if (copyDepth) {
// mask |= GL_DEPTH_BUFFER_BIT;
// }
// GLES20.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1,
// dstX0, dstY0, dstX1, dstY1, mask,
// GL_NEAREST);
//
//
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevFBO);
// try {
// checkFrameBufferError();
// } catch (IllegalStateException ex) {
// logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
// logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
// throw ex;
// }
// } else {
// throw new RendererException("EXT_framebuffer_blit required.");
// // TODO: support non-blit copies?
// }
}
glBlitFramebufferEXT(0, 0, srcW, srcH,
0, 0, dstW, dstH,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
private void checkFrameBufferStatus(FrameBuffer fb) {
try {
checkFrameBufferError();
} catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
printRealFrameBufferInfo(fb);
throw ex;
}
}else{
throw new UnsupportedOperationException("EXT_framebuffer_blit required.");
// TODO: support non-blit copies?
}
}
*/
private void checkFrameBufferError() {
logger.warning("checkFrameBufferError is not supported.");
}
/*
private void checkFrameBufferError() {
int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
switch (status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
case GLES20.GL_FRAMEBUFFER_COMPLETE:
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
case GLES20.GL_FRAMEBUFFER_UNSUPPORTED:
//Choose different formats
throw new IllegalStateException("Framebuffer object format is " +
"unsupported by the video hardware.");
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
throw new IllegalStateException("Framebuffer object format is "
+ "unsupported by the video hardware.");
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new IllegalStateException("Framebuffer has erronous attachment.");
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
throw new IllegalStateException("Framebuffer is missing required attachment.");
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached.");
case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
throw new IllegalStateException("Framebuffer attachments must have same formats.");
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
throw new IllegalStateException("Incomplete draw buffer.");
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
throw new IllegalStateException("Incomplete read buffer.");
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
throw new IllegalStateException("Incomplete multisample buffer.");
// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
// throw new IllegalStateException("Framebuffer attachments must have same formats.");
// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
// throw new IllegalStateException("Incomplete draw buffer.");
// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
// throw new IllegalStateException("Incomplete read buffer.");
// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
// throw new IllegalStateException("Incomplete multisample buffer.");
default:
//Programming error; will fail on all hardware
throw new IllegalStateException("Some video driver error " +
"or programming error occured. " +
"Framebuffer object status is invalid. ");
throw new IllegalStateException("Some video driver error "
+ "or programming error occured. "
+ "Framebuffer object status is invalid: " + status);
}
}
*/
private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
logger.warning("updateRenderBuffer is not supported.");
private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) {
System.out.println("== Renderbuffer " + name + " ==");
System.out.println("RB ID: " + rb.getId());
System.out.println("Is proper? " + GLES20.glIsRenderbuffer(rb.getId()));
int attachment = convertAttachmentSlot(rb.getSlot());
intBuf16.clear();
GLES20.glGetFramebufferAttachmentParameteriv(GLES20.GL_FRAMEBUFFER,
attachment, GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16);
int type = intBuf16.get(0);
intBuf16.clear();
GLES20.glGetFramebufferAttachmentParameteriv(GLES20.GL_FRAMEBUFFER,
attachment, GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16);
int rbName = intBuf16.get(0);
switch (type) {
case GLES20.GL_NONE:
System.out.println("Type: None");
break;
case GLES20.GL_TEXTURE:
System.out.println("Type: Texture");
break;
case GLES20.GL_RENDERBUFFER:
System.out.println("Type: Buffer");
System.out.println("RB ID: " + rbName);
break;
}
/*
}
private void printRealFrameBufferInfo(FrameBuffer fb) {
// boolean doubleBuffer = GLES20.glGetBooleanv(GLES20.GL_DOUBLEBUFFER);
boolean doubleBuffer = false; // FIXME
// String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER));
// String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
int fbId = fb.getId();
intBuf16.clear();
// int curDrawBinding = GLES20.glGetIntegerv(GLES20.GL_DRAW_FRAMEBUFFER_BINDING);
// int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING);
System.out.println("=== OpenGL FBO State ===");
System.out.println("Context doublebuffered? " + doubleBuffer);
System.out.println("FBO ID: " + fbId);
System.out.println("Is proper? " + GLES20.glIsFramebuffer(fbId));
// System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
// System.out.println("Is bound to read? " + (fbId == curReadBinding));
// System.out.println("Draw buffer: " + drawBuf);
// System.out.println("Read buffer: " + readBuf);
if (context.boundFBO != fbId) {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbId);
context.boundFBO = fbId;
}
if (fb.getDepthBuffer() != null) {
printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
}
for (int i = 0; i < fb.getNumColorBuffers(); i++) {
printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
}
}
private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
int id = rb.getId();
if (id == -1) {
glGenRenderbuffersEXT(intBuf1);
GLES20.glGenRenderbuffers(1, intBuf1);
id = intBuf1.get(0);
rb.setId(id);
}
if (context.boundRB != id) {
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, id);
context.boundRB = id;
}
if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize)
throw new UnsupportedOperationException("Resolution "+fb.getWidth()+
":"+fb.getHeight()+" is not supported.");
if (fb.getSamples() > 0 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample){
int samples = fb.getSamples();
if (maxFBOSamples < samples){
samples = maxFBOSamples;
if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) {
throw new RendererException("Resolution " + fb.getWidth()
+ ":" + fb.getHeight() + " is not supported.");
}
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
samples,
TextureUtil.convertTextureFormat(rb.getFormat()),
fb.getWidth(),
fb.getHeight());
int glRenderBufferStorageFormat = TextureUtil.getImageFormat(rb.getFormat()).renderBufferStorageFormat;
// if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
if (fb.getSamples() > 1) {
// // FIXME
throw new RendererException("Multisample FrameBuffer is not supported yet.");
// int samples = fb.getSamples();
// if (maxFBOSamples < samples) {
// samples = maxFBOSamples;
// }
// glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
// samples,
// glFmt.internalFormat,
// fb.getWidth(),
// fb.getHeight());
} else {
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
TextureUtil.convertTextureFormat(rb.getFormat()),
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
glRenderBufferStorageFormat,
fb.getWidth(),
fb.getHeight());
}
}
*/
private int convertAttachmentSlot(int attachmentSlot) {
logger.warning("convertAttachmentSlot is not supported.");
return -1;
}
/*
private int convertAttachmentSlot(int attachmentSlot) {
// can also add support for stencil here
if (attachmentSlot == -100) {
return GL_DEPTH_ATTACHMENT_EXT;
return GLES20.GL_DEPTH_ATTACHMENT;
} else if (attachmentSlot < 0 || attachmentSlot >= 16) {
throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot);
}
return GL_COLOR_ATTACHMENT0_EXT + attachmentSlot;
return GLES20.GL_COLOR_ATTACHMENT0 + attachmentSlot;
}
*/
public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
logger.warning("updateRenderTexture is not supported.");
}
/*
public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
Texture tex = rb.getTexture();
Image image = tex.getImage();
if (image.isUpdateNeeded())
updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels());
if (image.isUpdateNeeded()) {
updateTexImageData(image, tex.getType());
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
// NOTE: For depth textures, sets nearest/no-mips mode
// Required to fix "framebuffer unsupported"
// for old NVIDIA drivers!
setupTextureParams(tex);
}
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
convertAttachmentSlot(rb.getSlot()),
convertTextureType(tex.getType()),
image.getId(),
0);
}
*/
public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
logger.warning("updateFrameBufferAttachment is not supported.");
}
/*
public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
boolean needAttach;
if (rb.getTexture() == null) {
@ -1136,23 +1238,19 @@ public class OGLESShaderRenderer implements Renderer {
updateRenderTexture(fb, rb);
}
if (needAttach) {
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
convertAttachmentSlot(rb.getSlot()),
GL_RENDERBUFFER_EXT,
GLES20.GL_RENDERBUFFER,
rb.getId());
}
}
*/
public void updateFrameBuffer(FrameBuffer fb) {
logger.warning("updateFrameBuffer is not supported.");
}
/*
public void updateFrameBuffer(FrameBuffer fb) {
int id = fb.getId();
if (id == -1) {
intBuf1.clear();
// create FBO
glGenFramebuffersEXT(intBuf1);
GLES20.glGenFramebuffers(1, intBuf1);
id = intBuf1.get(0);
fb.setId(id);
objManager.registerForCleanup(fb);
@ -1161,7 +1259,7 @@ public class OGLESShaderRenderer implements Renderer {
}
if (context.boundFBO != id) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, id);
// binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
context.boundDrawBuf = 0;
context.boundFBO = id;
@ -1179,17 +1277,21 @@ public class OGLESShaderRenderer implements Renderer {
fb.clearUpdateNeeded();
}
*/
public void setMainFrameBufferOverride(FrameBuffer fb){
mainFbOverride = fb;
}
public void setFrameBuffer(FrameBuffer fb) {
if (fb == null && mainFbOverride != null) {
fb = mainFbOverride;
}
/*
public void setFrameBuffer(FrameBuffer fb) {
if (lastFb == fb)
if (lastFb == fb) {
if (fb == null || !fb.isUpdateNeeded()) {
return;
}
}
// generate mipmaps for last FB if needed
if (lastFb != null) {
@ -1199,20 +1301,24 @@ public class OGLESShaderRenderer implements Renderer {
if (tex != null
&& tex.getMinFilter().usesMipMapLevels()) {
setTexture(0, rb.getTexture());
glGenerateMipmapEXT(convertTextureType(tex.getType()));
// int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
int textureType = convertTextureType(tex.getType());
GLES20.glGenerateMipmap(textureType);
}
}
}
if (fb == null) {
// unbind any fbos
if (context.boundFBO != 0) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
statistics.onFrameBufferUse(null, true);
context.boundFBO = 0;
}
/*
// select back buffer
if (context.boundDrawBuf != -1) {
glDrawBuffer(initialDrawBuf);
@ -1222,14 +1328,21 @@ public class OGLESShaderRenderer implements Renderer {
glReadBuffer(initialReadBuf);
context.boundReadBuf = -1;
}
*/
lastFb = null;
} else {
if (fb.isUpdateNeeded())
if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
throw new IllegalArgumentException("The framebuffer: " + fb
+ "\nDoesn't have any color/depth buffers");
}
if (fb.isUpdateNeeded()) {
updateFrameBuffer(fb);
}
if (context.boundFBO != fb.getId()) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb.getId());
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb.getId());
statistics.onFrameBufferUse(fb, true);
// update viewport to reflect framebuffer's resolution
@ -1240,37 +1353,44 @@ public class OGLESShaderRenderer implements Renderer {
statistics.onFrameBufferUse(fb, false);
}
if (fb.getNumColorBuffers() == 0) {
// make sure to select NONE as draw buf
// no color buffer attached. select NONE
// // make sure to select NONE as draw buf
// // no color buffer attached. select NONE
if (context.boundDrawBuf != -2) {
glDrawBuffer(GL_NONE);
// glDrawBuffer(GL_NONE);
context.boundDrawBuf = -2;
}
if (context.boundReadBuf != -2) {
glReadBuffer(GL_NONE);
// glReadBuffer(GL_NONE);
context.boundReadBuf = -2;
}
} else {
if (fb.getNumColorBuffers() > maxFBOAttachs) {
throw new RendererException("Framebuffer has more color "
+ "attachments than are supported"
+ " by the video hardware!");
}
if (fb.isMultiTarget()) {
if (fb.getNumColorBuffers() > maxMRTFBOAttachs)
throw new UnsupportedOperationException("Framebuffer has more"
+ " targets than are supported"
+ " on the system!");
if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
throw new RendererException("Framebuffer has more"
+ " multi targets than are supported"
+ " by the video hardware!");
}
if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
intBuf16.clear();
for (int i = 0; i < fb.getNumColorBuffers(); i++)
intBuf16.put( GL_COLOR_ATTACHMENT0_EXT + i );
for (int i = 0; i < fb.getNumColorBuffers(); i++) {
intBuf16.put(GLES20.GL_COLOR_ATTACHMENT0 + i);
}
intBuf16.flip();
glDrawBuffers(intBuf16);
// glDrawBuffers(intBuf16);
context.boundDrawBuf = 100 + fb.getNumColorBuffers();
}
} else {
RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
// select this draw buffer
if (context.boundDrawBuf != rb.getSlot()) {
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
GLES20.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
context.boundDrawBuf = rb.getSlot();
}
}
@ -1278,73 +1398,49 @@ public class OGLESShaderRenderer implements Renderer {
assert fb.getId() >= 0;
assert context.boundFBO == fb.getId();
lastFb = fb;
}
try {
checkFrameBufferError();
} catch (IllegalStateException ex){
logger.log(Level.SEVERE, "Problem FBO:\n{0}", fb);
throw ex;
checkFrameBufferStatus(fb);
}
}
*/
/**
* Reads the Color Buffer from OpenGL and stores into the ByteBuffer.
* Since jME for Android does not support Frame Buffers yet, make sure the FrameBuffer
* passed in is NULL (default) or an exception will be thrown.
* Also, make sure to call setViewPort with the appropriate viewport size before
* Make sure to call setViewPort with the appropriate viewport size before
* calling readFrameBuffer.
* @param fb FrameBuffer (must be NULL)
* @param fb FrameBuffer
* @param byteBuf ByteBuffer to store the Color Buffer from OpenGL
*/
public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
if (fb != null) {
throw new IllegalArgumentException("FrameBuffer is not supported yet.");
}
GLES20.glReadPixels(vpX, vpY, vpW, vpH, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);
}
/*
public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
if (fb != null) {
RenderBuffer rb = fb.getColorBuffer();
if (rb == null)
throw new IllegalArgumentException("Specified framebuffer" +
" does not have a colorbuffer");
if (rb == null) {
throw new IllegalArgumentException("Specified framebuffer"
+ " does not have a colorbuffer");
}
setFrameBuffer(fb);
if (context.boundReadBuf != rb.getSlot()) {
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
GLES20.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
context.boundReadBuf = rb.getSlot();
}
} else {
setFrameBuffer(null);
}
glReadPixels(vpX, vpY, vpW, vpH, GL_RGBA GL_BGRA, GL_UNSIGNED_BYTE, byteBuf);
GLES20.glReadPixels(vpX, vpY, vpW, vpH, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);
}
*/
private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
logger.warning("deleteRenderBuffer is not supported.");
}
/*
private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
intBuf1.put(0, rb.getId());
glDeleteRenderbuffersEXT(intBuf1);
GLES20.glDeleteRenderbuffers(1, intBuf1);
}
*/
public void deleteFrameBuffer(FrameBuffer fb) {
logger.warning("deleteFrameBuffer is not supported.");
}
/*
public void deleteFrameBuffer(FrameBuffer fb) {
if (fb.getId() != -1) {
if (context.boundFBO == fb.getId()) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
context.boundFBO = 0;
}
@ -1356,13 +1452,12 @@ public class OGLESShaderRenderer implements Renderer {
}
intBuf1.put(0, fb.getId());
glDeleteFramebuffersEXT(intBuf1);
GLES20.glDeleteFramebuffers(1, intBuf1);
fb.resetObject();
statistics.onDeleteFrameBuffer();
}
}
*/
/*********************************************************************\
|* Textures *|
@ -1657,7 +1752,7 @@ public class OGLESShaderRenderer implements Renderer {
}
}
private int convertFormat(Format format) {
private int convertVertexBufferFormat(Format format) {
switch (format) {
case Byte:
return GLES20.GL_BYTE;
@ -1856,7 +1951,7 @@ public class OGLESShaderRenderer implements Renderer {
Android22Workaround.glVertexAttribPointer(loc,
vb.getNumComponents(),
convertFormat(vb.getFormat()),
convertVertexBufferFormat(vb.getFormat()),
vb.isNormalized(),
vb.getStride(),
0);
@ -1918,7 +2013,7 @@ public class OGLESShaderRenderer implements Renderer {
int[] elementLengths = mesh.getElementLengths();
int elMode = convertElementMode(Mode.Triangles);
int fmt = convertFormat(indexBuf.getFormat());
int fmt = convertVertexBufferFormat(indexBuf.getFormat());
int elSize = indexBuf.getFormat().getComponentSize();
int listStart = modeStart[0];
int stripStart = modeStart[1];
@ -1964,7 +2059,7 @@ public class OGLESShaderRenderer implements Renderer {
/*
GLES20.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()),
indexBuf.getData().limit(),
convertFormat(indexBuf.getFormat()),
convertVertexBufferFormat(indexBuf.getFormat()),
0,
count);
*/
@ -1973,7 +2068,7 @@ public class OGLESShaderRenderer implements Renderer {
GLES20.glDrawElements(
convertElementMode(mesh.getMode()),
indexBuf.getData().limit(),
convertFormat(indexBuf.getFormat()),
convertVertexBufferFormat(indexBuf.getFormat()),
0);
}
}
@ -2172,7 +2267,7 @@ public class OGLESShaderRenderer implements Renderer {
int[] elementLengths = mesh.getElementLengths();
int elMode = convertElementMode(Mode.Triangles);
int fmt = convertFormat(indexBuf.getFormat());
int fmt = convertVertexBufferFormat(indexBuf.getFormat());
int elSize = indexBuf.getFormat().getComponentSize();
int listStart = modeStart[0];
int stripStart = modeStart[1];
@ -2195,7 +2290,7 @@ public class OGLESShaderRenderer implements Renderer {
GLES20.glDrawElements(
convertElementMode(mesh.getMode()),
indexBuf.getData().limit(),
convertFormat(indexBuf.getFormat()),
convertVertexBufferFormat(indexBuf.getFormat()),
indexBuf.getData());
}
}
@ -2242,7 +2337,7 @@ public class OGLESShaderRenderer implements Renderer {
// Upload attribute data
GLES20.glVertexAttribPointer(loc,
vb.getNumComponents(),
convertFormat(vb.getFormat()),
convertVertexBufferFormat(vb.getFormat()),
vb.isNormalized(),
vb.getStride(),
avb.getData());

@ -24,16 +24,19 @@ public class TextureUtil {
private static boolean ETC1support = false;
private static boolean DXT1 = false;
private static boolean DEPTH24 = false;
private static boolean DEPTH_TEXTURE = false;
public static void loadTextureFeatures(String extensionString) {
ETC1support = extensionString.contains("GL_OES_compressed_ETC1_RGB8_texture");
DEPTH24 = extensionString.contains("GL_OES_depth24");
NPOT = extensionString.contains("GL_OES_texture_npot") || extensionString.contains("GL_NV_texture_npot_2D_mipmap");
DXT1 = extensionString.contains("GL_EXT_texture_compression_dxt1");
DEPTH_TEXTURE = extensionString.contains("GL_OES_depth_texture");
logger.log(Level.FINE, "Supports ETC1? {0}", ETC1support);
logger.log(Level.FINE, "Supports DEPTH24? {0}", DEPTH24);
logger.log(Level.FINE, "Supports NPOT? {0}", NPOT);
logger.log(Level.FINE, "Supports DXT1? {0}", DXT1);
logger.log(Level.FINE, "Supports DEPTH_TEXTURE? {0}", DEPTH_TEXTURE);
}
private static void buildMipmap(Bitmap bitmap, boolean compress) {
@ -241,7 +244,7 @@ public class TextureUtil {
throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware.");
}
private static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
public static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
AndroidGLImageFormat imageFormat = new AndroidGLImageFormat();
switch (fmt) {
case RGBA16:
@ -269,14 +272,17 @@ public class TextureUtil {
case RGB565:
imageFormat.format = GLES20.GL_RGB;
imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_6_5;
imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
break;
case ARGB4444:
imageFormat.format = GLES20.GL_RGBA4;
imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_4_4_4_4;
imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
break;
case RGB5A1:
imageFormat.format = GLES20.GL_RGBA;
imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_5_5_1;
imageFormat.renderBufferStorageFormat = GLES20.GL_RGB5_A1;
break;
case RGB8:
imageFormat.format = GLES20.GL_RGB;
@ -293,8 +299,12 @@ public class TextureUtil {
case Depth:
case Depth16:
case Depth24:
if (!DEPTH_TEXTURE) {
unsupportedFormat(fmt);
}
imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
break;
case DXT1:
if (!DXT1) {
@ -318,10 +328,11 @@ public class TextureUtil {
return imageFormat;
}
private static class AndroidGLImageFormat {
public static class AndroidGLImageFormat {
boolean compress = false;
int format = -1;
int renderBufferStorageFormat = -1;
int dataType = -1;
}

Loading…
Cancel
Save