• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Main repository of MikuMikuStudio


Commit MetaInfo

Revision941bac4835e96b2c45228d8b4ae3d91111335963 (tree)
Time2013-04-06 13:18:43
Authoriwgeric@gmail.com <iwgeric@gmai...>
Commiteriwgeric@gmail.com

Log Message

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: http://jmonkeyengine.googlecode.com/svn/trunk@10513 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

Change Summary

Incremental Difference

--- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
+++ b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
@@ -78,7 +78,9 @@ public class OGLESShaderRenderer implements Renderer {
7878 private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
7979 // current state
8080 private Shader boundShader;
81-// private int initialDrawBuf, initialReadBuf;
81+ // initalDrawBuf and initialReadBuf are not used on ES,
82+ // http://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindFramebuffer.xml
83+ //private int initialDrawBuf, initialReadBuf;
8284 private int glslVer;
8385 private int vertexTextureUnits;
8486 private int fragTextureUnits;
@@ -86,15 +88,16 @@ public class OGLESShaderRenderer implements Renderer {
8688 private int fragUniforms;
8789 private int vertexAttribs;
8890 // private int maxFBOSamples;
89-// private int maxFBOAttachs;
90-// private int maxMRTFBOAttachs;
91-// private int maxRBSize;
91+ private final int maxFBOAttachs = 1; // Only 1 color attachment on ES
92+ private final int maxMRTFBOAttachs = 1; // FIXME for now, not sure if > 1 is needed for ES
93+ private int maxRBSize;
9294 private int maxTexSize;
9395 private int maxCubeTexSize;
9496 private int maxVertCount;
9597 private int maxTriCount;
9698 private boolean tdc;
97-// private FrameBuffer lastFb = null;
99+ private FrameBuffer lastFb = null;
100+ private FrameBuffer mainFbOverride = null;
98101 private final Statistics statistics = new Statistics();
99102 private int vpX, vpY, vpW, vpH;
100103 private int clipX, clipY, clipW, clipH;
@@ -155,11 +158,18 @@ public class OGLESShaderRenderer implements Renderer {
155158
156159 powerVr = GLES20.glGetString(GLES20.GL_RENDERER).contains("PowerVR");
157160
161+ /*
158162 // Fix issue in TestRenderToMemory when GL_FRONT is the main
159163 // buffer being used.
160-
161-// initialDrawBuf = GLES20.glGetIntegeri(GLES20.GL_DRAW_BUFFER);
162-// initialReadBuf = GLES20.glGetIntegeri(GLES20.GL_READ_BUFFER);
164+ initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
165+ initialReadBuf = glGetInteger(GL_READ_BUFFER);
166+
167+ // XXX: This has to be GL_BACK for canvas on Mac
168+ // Since initialDrawBuf is GL_FRONT for pbuffer, gotta
169+ // change this value later on ...
170+// initialDrawBuf = GL_BACK;
171+// initialReadBuf = GL_BACK;
172+ */
163173
164174 // Check OpenGL version
165175 int openGlVer = extractVersion("OpenGL ES ", GLES20.glGetString(GLES20.GL_VERSION));
@@ -226,6 +236,10 @@ public class OGLESShaderRenderer implements Renderer {
226236 maxCubeTexSize = intBuf16.get(0);
227237 logger.log(Level.FINE, "Maximum CubeMap Resolution: {0}", maxCubeTexSize);
228238
239+ GLES20.glGetIntegerv(GLES20.GL_MAX_RENDERBUFFER_SIZE, intBuf16);
240+ maxRBSize = intBuf16.get(0);
241+ logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
242+
229243 /*
230244 if (ctxCaps.GL_ARB_color_buffer_float){
231245 // XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
@@ -311,11 +325,11 @@ public class OGLESShaderRenderer implements Renderer {
311325 // Get number of compressed formats available.
312326 GLES20.glGetIntegerv(GLES20.GL_NUM_COMPRESSED_TEXTURE_FORMATS, intBuf16);
313327 int numCompressedFormats = intBuf16.get(0);
314-
328+
315329 // Allocate buffer for compressed formats.
316330 IntBuffer compressedFormats = BufferUtils.createIntBuffer(numCompressedFormats);
317331 GLES20.glGetIntegerv(GLES20.GL_COMPRESSED_TEXTURE_FORMATS, compressedFormats);
318-
332+
319333 // Print compressed formats.
320334 for (int i = 0; i < numCompressedFormats; i++) {
321335 logger.log(Level.FINE, "Compressed Texture Formats: {0}", compressedFormats.get(i));
@@ -793,14 +807,14 @@ public class OGLESShaderRenderer implements Renderer {
793807 precision = "precision mediump float;\n";
794808 }
795809 GLES20.glShaderSource(
796- id,
810+ id,
797811 precision
798812 +source.getDefines()
799813 + source.getSource());
800814 }
801815 // int range[] = new int[2];
802-// int precision[] = new int[1];
803-// GLES20.glGetShaderPrecisionFormat(GLES20.GL_VERTEX_SHADER, GLES20.GL_HIGH_FLOAT, range, 0, precision, 0);
816+// int precision[] = new int[1];
817+// GLES20.glGetShaderPrecisionFormat(GLES20.GL_VERTEX_SHADER, GLES20.GL_HIGH_FLOAT, range, 0, precision, 0);
804818 // System.out.println("PRECISION HIGH FLOAT VERTEX");
805819 // System.out.println("range "+range[0]+"," +range[1]);
806820 // System.out.println("precision "+precision[0]);
@@ -951,418 +965,499 @@ public class OGLESShaderRenderer implements Renderer {
951965 |* Framebuffers *|
952966 \*********************************************************************/
953967 public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
954- logger.warning("copyFrameBuffer is not supported.");
968+ copyFrameBuffer(src, dst, true);
955969 }
956970
957971 public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
958- logger.warning("copyFrameBuffer is not supported.");
959- }
960- /*
961- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
962- if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){
963- int srcW = 0;
964- int srcH = 0;
965- int dstW = 0;
966- int dstH = 0;
967- int prevFBO = context.boundFBO;
968-
969- if (src != null && src.isUpdateNeeded())
970- updateFrameBuffer(src);
971-
972- if (dst != null && dst.isUpdateNeeded())
973- updateFrameBuffer(dst);
974-
975- if (src == null){
976- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
977- // srcW = viewWidth;
978- // srcH = viewHeight;
979- }else{
980- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
981- srcW = src.getWidth();
982- srcH = src.getHeight();
983- }
984- if (dst == null){
985- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
986- // dstW = viewWidth;
987- // dstH = viewHeight;
988- }else{
989- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
990- dstW = dst.getWidth();
991- dstH = dst.getHeight();
992- }
993- glBlitFramebufferEXT(0, 0, srcW, srcH,
994- 0, 0, dstW, dstH,
995- GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
996- GL_NEAREST);
997-
998- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
999- try {
1000- checkFrameBufferError();
1001- } catch (IllegalStateException ex){
1002- logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
1003- logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
1004- throw ex;
1005- }
1006- }else{
1007- throw new UnsupportedOperationException("EXT_framebuffer_blit required.");
1008- // TODO: support non-blit copies?
972+ throw new RendererException("Copy framebuffer not implemented yet.");
973+
974+// if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
975+// int srcX0 = 0;
976+// int srcY0 = 0;
977+// int srcX1 = 0;
978+// int srcY1 = 0;
979+//
980+// int dstX0 = 0;
981+// int dstY0 = 0;
982+// int dstX1 = 0;
983+// int dstY1 = 0;
984+//
985+// int prevFBO = context.boundFBO;
986+//
987+// if (mainFbOverride != null) {
988+// if (src == null) {
989+// src = mainFbOverride;
990+// }
991+// if (dst == null) {
992+// dst = mainFbOverride;
993+// }
994+// }
995+//
996+// if (src != null && src.isUpdateNeeded()) {
997+// updateFrameBuffer(src);
998+// }
999+//
1000+// if (dst != null && dst.isUpdateNeeded()) {
1001+// updateFrameBuffer(dst);
1002+// }
1003+//
1004+// if (src == null) {
1005+// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
1006+// srcX0 = vpX;
1007+// srcY0 = vpY;
1008+// srcX1 = vpX + vpW;
1009+// srcY1 = vpY + vpH;
1010+// } else {
1011+// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, src.getId());
1012+// srcX1 = src.getWidth();
1013+// srcY1 = src.getHeight();
1014+// }
1015+// if (dst == null) {
1016+// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
1017+// dstX0 = vpX;
1018+// dstY0 = vpY;
1019+// dstX1 = vpX + vpW;
1020+// dstY1 = vpY + vpH;
1021+// } else {
1022+// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, dst.getId());
1023+// dstX1 = dst.getWidth();
1024+// dstY1 = dst.getHeight();
1025+// }
1026+//
1027+//
1028+// int mask = GL_COLOR_BUFFER_BIT;
1029+// if (copyDepth) {
1030+// mask |= GL_DEPTH_BUFFER_BIT;
1031+// }
1032+// GLES20.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1,
1033+// dstX0, dstY0, dstX1, dstY1, mask,
1034+// GL_NEAREST);
1035+//
1036+//
1037+// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevFBO);
1038+// try {
1039+// checkFrameBufferError();
1040+// } catch (IllegalStateException ex) {
1041+// logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
1042+// logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
1043+// throw ex;
1044+// }
1045+// } else {
1046+// throw new RendererException("EXT_framebuffer_blit required.");
1047+// // TODO: support non-blit copies?
1048+// }
10091049 }
1050+
1051+ private void checkFrameBufferStatus(FrameBuffer fb) {
1052+ try {
1053+ checkFrameBufferError();
1054+ } catch (IllegalStateException ex) {
1055+ logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
1056+ printRealFrameBufferInfo(fb);
1057+ throw ex;
1058+ }
10101059 }
1011- */
10121060
10131061 private void checkFrameBufferError() {
1014- logger.warning("checkFrameBufferError is not supported.");
1062+ int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
1063+ switch (status) {
1064+ case GLES20.GL_FRAMEBUFFER_COMPLETE:
1065+ break;
1066+ case GLES20.GL_FRAMEBUFFER_UNSUPPORTED:
1067+ //Choose different formats
1068+ throw new IllegalStateException("Framebuffer object format is "
1069+ + "unsupported by the video hardware.");
1070+ case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1071+ throw new IllegalStateException("Framebuffer has erronous attachment.");
1072+ case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1073+ throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached.");
1074+ case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1075+ throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
1076+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
1077+// throw new IllegalStateException("Framebuffer attachments must have same formats.");
1078+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
1079+// throw new IllegalStateException("Incomplete draw buffer.");
1080+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1081+// throw new IllegalStateException("Incomplete read buffer.");
1082+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
1083+// throw new IllegalStateException("Incomplete multisample buffer.");
1084+ default:
1085+ //Programming error; will fail on all hardware
1086+ throw new IllegalStateException("Some video driver error "
1087+ + "or programming error occured. "
1088+ + "Framebuffer object status is invalid: " + status);
1089+ }
10151090 }
1016- /*
1017- private void checkFrameBufferError() {
1018- int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1019- switch (status) {
1020- case GL_FRAMEBUFFER_COMPLETE_EXT:
1021- break;
1022- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
1023- //Choose different formats
1024- throw new IllegalStateException("Framebuffer object format is " +
1025- "unsupported by the video hardware.");
1026- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
1027- throw new IllegalStateException("Framebuffer has erronous attachment.");
1028- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
1029- throw new IllegalStateException("Framebuffer is missing required attachment.");
1030- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
1031- throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
1032- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
1033- throw new IllegalStateException("Framebuffer attachments must have same formats.");
1034- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
1035- throw new IllegalStateException("Incomplete draw buffer.");
1036- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1037- throw new IllegalStateException("Incomplete read buffer.");
1038- case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
1039- throw new IllegalStateException("Incomplete multisample buffer.");
1040- default:
1041- //Programming error; will fail on all hardware
1042- throw new IllegalStateException("Some video driver error " +
1043- "or programming error occured. " +
1044- "Framebuffer object status is invalid. ");
1091+
1092+ private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) {
1093+ System.out.println("== Renderbuffer " + name + " ==");
1094+ System.out.println("RB ID: " + rb.getId());
1095+ System.out.println("Is proper? " + GLES20.glIsRenderbuffer(rb.getId()));
1096+
1097+ int attachment = convertAttachmentSlot(rb.getSlot());
1098+
1099+ intBuf16.clear();
1100+ GLES20.glGetFramebufferAttachmentParameteriv(GLES20.GL_FRAMEBUFFER,
1101+ attachment, GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16);
1102+ int type = intBuf16.get(0);
1103+
1104+ intBuf16.clear();
1105+ GLES20.glGetFramebufferAttachmentParameteriv(GLES20.GL_FRAMEBUFFER,
1106+ attachment, GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16);
1107+ int rbName = intBuf16.get(0);
1108+
1109+ switch (type) {
1110+ case GLES20.GL_NONE:
1111+ System.out.println("Type: None");
1112+ break;
1113+ case GLES20.GL_TEXTURE:
1114+ System.out.println("Type: Texture");
1115+ break;
1116+ case GLES20.GL_RENDERBUFFER:
1117+ System.out.println("Type: Buffer");
1118+ System.out.println("RB ID: " + rbName);
1119+ break;
1120+ }
1121+
1122+
1123+
10451124 }
1125+
1126+ private void printRealFrameBufferInfo(FrameBuffer fb) {
1127+// boolean doubleBuffer = GLES20.glGetBooleanv(GLES20.GL_DOUBLEBUFFER);
1128+ boolean doubleBuffer = false; // FIXME
1129+// String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER));
1130+// String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
1131+
1132+ int fbId = fb.getId();
1133+ intBuf16.clear();
1134+// int curDrawBinding = GLES20.glGetIntegerv(GLES20.GL_DRAW_FRAMEBUFFER_BINDING);
1135+// int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING);
1136+
1137+ System.out.println("=== OpenGL FBO State ===");
1138+ System.out.println("Context doublebuffered? " + doubleBuffer);
1139+ System.out.println("FBO ID: " + fbId);
1140+ System.out.println("Is proper? " + GLES20.glIsFramebuffer(fbId));
1141+// System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
1142+// System.out.println("Is bound to read? " + (fbId == curReadBinding));
1143+// System.out.println("Draw buffer: " + drawBuf);
1144+// System.out.println("Read buffer: " + readBuf);
1145+
1146+ if (context.boundFBO != fbId) {
1147+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbId);
1148+ context.boundFBO = fbId;
1149+ }
1150+
1151+ if (fb.getDepthBuffer() != null) {
1152+ printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
1153+ }
1154+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1155+ printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
1156+ }
10461157 }
1047- */
10481158
10491159 private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
1050- logger.warning("updateRenderBuffer is not supported.");
1051- }
1052- /*
1053- private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb){
1054- int id = rb.getId();
1055- if (id == -1){
1056- glGenRenderbuffersEXT(intBuf1);
1057- id = intBuf1.get(0);
1058- rb.setId(id);
1059- }
1160+ int id = rb.getId();
1161+ if (id == -1) {
1162+ GLES20.glGenRenderbuffers(1, intBuf1);
1163+ id = intBuf1.get(0);
1164+ rb.setId(id);
1165+ }
10601166
1061- if (context.boundRB != id){
1062- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id);
1063- context.boundRB = id;
1064- }
1167+ if (context.boundRB != id) {
1168+ GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, id);
1169+ context.boundRB = id;
1170+ }
10651171
1066- if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize)
1067- throw new UnsupportedOperationException("Resolution "+fb.getWidth()+
1068- ":"+fb.getHeight()+" is not supported.");
1172+ if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) {
1173+ throw new RendererException("Resolution " + fb.getWidth()
1174+ + ":" + fb.getHeight() + " is not supported.");
1175+ }
10691176
1070- if (fb.getSamples() > 0 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample){
1071- int samples = fb.getSamples();
1072- if (maxFBOSamples < samples){
1073- samples = maxFBOSamples;
1074- }
1075- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
1076- samples,
1077- TextureUtil.convertTextureFormat(rb.getFormat()),
1078- fb.getWidth(),
1079- fb.getHeight());
1080- }else{
1081- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
1082- TextureUtil.convertTextureFormat(rb.getFormat()),
1083- fb.getWidth(),
1084- fb.getHeight());
1085- }
1177+ int glRenderBufferStorageFormat = TextureUtil.getImageFormat(rb.getFormat()).renderBufferStorageFormat;
1178+
1179+// if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
1180+ if (fb.getSamples() > 1) {
1181+// // FIXME
1182+ throw new RendererException("Multisample FrameBuffer is not supported yet.");
1183+// int samples = fb.getSamples();
1184+// if (maxFBOSamples < samples) {
1185+// samples = maxFBOSamples;
1186+// }
1187+// glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
1188+// samples,
1189+// glFmt.internalFormat,
1190+// fb.getWidth(),
1191+// fb.getHeight());
1192+ } else {
1193+ GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
1194+ glRenderBufferStorageFormat,
1195+ fb.getWidth(),
1196+ fb.getHeight());
1197+ }
10861198 }
1087- */
10881199
10891200 private int convertAttachmentSlot(int attachmentSlot) {
1090- logger.warning("convertAttachmentSlot is not supported.");
1091- return -1;
1092- }
1093- /*
1094- private int convertAttachmentSlot(int attachmentSlot){
1095- // can also add support for stencil here
1096- if (attachmentSlot == -100){
1097- return GL_DEPTH_ATTACHMENT_EXT;
1098- }else if (attachmentSlot < 0 || attachmentSlot >= 16){
1099- throw new UnsupportedOperationException("Invalid FBO attachment slot: "+attachmentSlot);
1100- }
1201+ // can also add support for stencil here
1202+ if (attachmentSlot == -100) {
1203+ return GLES20.GL_DEPTH_ATTACHMENT;
1204+ } else if (attachmentSlot < 0 || attachmentSlot >= 16) {
1205+ throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot);
1206+ }
11011207
1102- return GL_COLOR_ATTACHMENT0_EXT + attachmentSlot;
1208+ return GLES20.GL_COLOR_ATTACHMENT0 + attachmentSlot;
11031209 }
1104- */
11051210
11061211 public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
1107- logger.warning("updateRenderTexture is not supported.");
1108- }
1109- /*
1110- public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb){
1111- Texture tex = rb.getTexture();
1112- Image image = tex.getImage();
1113- if (image.isUpdateNeeded())
1114- updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels());
1115-
1116- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
1117- convertAttachmentSlot(rb.getSlot()),
1118- convertTextureType(tex.getType()),
1119- image.getId(),
1120- 0);
1212+ Texture tex = rb.getTexture();
1213+ Image image = tex.getImage();
1214+ if (image.isUpdateNeeded()) {
1215+ updateTexImageData(image, tex.getType());
1216+
1217+ // NOTE: For depth textures, sets nearest/no-mips mode
1218+ // Required to fix "framebuffer unsupported"
1219+ // for old NVIDIA drivers!
1220+ setupTextureParams(tex);
1221+ }
1222+
1223+ GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
1224+ convertAttachmentSlot(rb.getSlot()),
1225+ convertTextureType(tex.getType()),
1226+ image.getId(),
1227+ 0);
11211228 }
1122- */
11231229
11241230 public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
1125- logger.warning("updateFrameBufferAttachment is not supported.");
1126- }
1127- /*
1128- public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb){
1129- boolean needAttach;
1130- if (rb.getTexture() == null){
1131- // if it hasn't been created yet, then attach is required.
1132- needAttach = rb.getId() == -1;
1133- updateRenderBuffer(fb, rb);
1134- }else{
1135- needAttach = false;
1136- updateRenderTexture(fb, rb);
1137- }
1138- if (needAttach){
1139- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
1140- convertAttachmentSlot(rb.getSlot()),
1141- GL_RENDERBUFFER_EXT,
1142- rb.getId());
1143- }
1231+ boolean needAttach;
1232+ if (rb.getTexture() == null) {
1233+ // if it hasn't been created yet, then attach is required.
1234+ needAttach = rb.getId() == -1;
1235+ updateRenderBuffer(fb, rb);
1236+ } else {
1237+ needAttach = false;
1238+ updateRenderTexture(fb, rb);
1239+ }
1240+ if (needAttach) {
1241+ GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
1242+ convertAttachmentSlot(rb.getSlot()),
1243+ GLES20.GL_RENDERBUFFER,
1244+ rb.getId());
1245+ }
11441246 }
1145- */
11461247
11471248 public void updateFrameBuffer(FrameBuffer fb) {
1148- logger.warning("updateFrameBuffer is not supported.");
1149- }
1150- /*
1151- public void updateFrameBuffer(FrameBuffer fb) {
1152- int id = fb.getId();
1153- if (id == -1){
1154- // create FBO
1155- glGenFramebuffersEXT(intBuf1);
1156- id = intBuf1.get(0);
1157- fb.setId(id);
1158- objManager.registerForCleanup(fb);
1249+ int id = fb.getId();
1250+ if (id == -1) {
1251+ intBuf1.clear();
1252+ // create FBO
1253+ GLES20.glGenFramebuffers(1, intBuf1);
1254+ id = intBuf1.get(0);
1255+ fb.setId(id);
1256+ objManager.registerForCleanup(fb);
11591257
1160- statistics.onNewFrameBuffer();
1161- }
1258+ statistics.onNewFrameBuffer();
1259+ }
11621260
1163- if (context.boundFBO != id){
1164- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
1165- // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
1166- context.boundDrawBuf = 0;
1167- context.boundFBO = id;
1168- }
1261+ if (context.boundFBO != id) {
1262+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, id);
1263+ // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
1264+ context.boundDrawBuf = 0;
1265+ context.boundFBO = id;
1266+ }
11691267
1170- FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
1171- if (depthBuf != null){
1172- updateFrameBufferAttachment(fb, depthBuf);
1173- }
1268+ FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
1269+ if (depthBuf != null) {
1270+ updateFrameBufferAttachment(fb, depthBuf);
1271+ }
11741272
1175- for (int i = 0; i < fb.getNumColorBuffers(); i++){
1176- FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
1177- updateFrameBufferAttachment(fb, colorBuf);
1178- }
1273+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1274+ FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
1275+ updateFrameBufferAttachment(fb, colorBuf);
1276+ }
11791277
1180- fb.clearUpdateNeeded();
1278+ fb.clearUpdateNeeded();
11811279 }
1182- */
11831280
11841281 public void setMainFrameBufferOverride(FrameBuffer fb){
1282+ mainFbOverride = fb;
11851283 }
11861284
11871285 public void setFrameBuffer(FrameBuffer fb) {
1188- }
1189- /*
1190- public void setFrameBuffer(FrameBuffer fb) {
1191- if (lastFb == fb)
1192- return;
1286+ if (fb == null && mainFbOverride != null) {
1287+ fb = mainFbOverride;
1288+ }
11931289
1194- // generate mipmaps for last FB if needed
1195- if (lastFb != null){
1196- for (int i = 0; i < lastFb.getNumColorBuffers(); i++){
1197- RenderBuffer rb = lastFb.getColorBuffer(i);
1198- Texture tex = rb.getTexture();
1199- if (tex != null
1200- && tex.getMinFilter().usesMipMapLevels()){
1201- setTexture(0, rb.getTexture());
1202- glGenerateMipmapEXT(convertTextureType(tex.getType()));
1203- }
1204- }
1205- }
1290+ if (lastFb == fb) {
1291+ if (fb == null || !fb.isUpdateNeeded()) {
1292+ return;
1293+ }
1294+ }
12061295
1296+ // generate mipmaps for last FB if needed
1297+ if (lastFb != null) {
1298+ for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
1299+ RenderBuffer rb = lastFb.getColorBuffer(i);
1300+ Texture tex = rb.getTexture();
1301+ if (tex != null
1302+ && tex.getMinFilter().usesMipMapLevels()) {
1303+ setTexture(0, rb.getTexture());
12071304
1208- if (fb == null){
1209- // unbind any fbos
1210- if (context.boundFBO != 0){
1211- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1212- statistics.onFrameBufferUse(null, true);
1305+// int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
1306+ int textureType = convertTextureType(tex.getType());
1307+ GLES20.glGenerateMipmap(textureType);
1308+ }
1309+ }
1310+ }
12131311
1214- context.boundFBO = 0;
1215- }
1216- // select back buffer
1217- if (context.boundDrawBuf != -1){
1218- glDrawBuffer(initialDrawBuf);
1219- context.boundDrawBuf = -1;
1220- }
1221- if (context.boundReadBuf != -1){
1222- glReadBuffer(initialReadBuf);
1223- context.boundReadBuf = -1;
1224- }
1312+ if (fb == null) {
1313+ // unbind any fbos
1314+ if (context.boundFBO != 0) {
1315+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
1316+ statistics.onFrameBufferUse(null, true);
12251317
1226- lastFb = null;
1227- }else{
1228- if (fb.isUpdateNeeded())
1229- updateFrameBuffer(fb);
1318+ context.boundFBO = 0;
1319+ }
12301320
1231- if (context.boundFBO != fb.getId()){
1232- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb.getId());
1233- statistics.onFrameBufferUse(fb, true);
1321+ /*
1322+ // select back buffer
1323+ if (context.boundDrawBuf != -1) {
1324+ glDrawBuffer(initialDrawBuf);
1325+ context.boundDrawBuf = -1;
1326+ }
1327+ if (context.boundReadBuf != -1) {
1328+ glReadBuffer(initialReadBuf);
1329+ context.boundReadBuf = -1;
1330+ }
1331+ */
12341332
1235- // update viewport to reflect framebuffer's resolution
1236- setViewPort(0, 0, fb.getWidth(), fb.getHeight());
1333+ lastFb = null;
1334+ } else {
1335+ if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
1336+ throw new IllegalArgumentException("The framebuffer: " + fb
1337+ + "\nDoesn't have any color/depth buffers");
1338+ }
12371339
1238- context.boundFBO = fb.getId();
1239- }else{
1240- statistics.onFrameBufferUse(fb, false);
1241- }
1242- if (fb.getNumColorBuffers() == 0){
1243- // make sure to select NONE as draw buf
1244- // no color buffer attached. select NONE
1245- if (context.boundDrawBuf != -2){
1246- glDrawBuffer(GL_NONE);
1247- context.boundDrawBuf = -2;
1248- }
1249- if (context.boundReadBuf != -2){
1250- glReadBuffer(GL_NONE);
1251- context.boundReadBuf = -2;
1252- }
1253- }else{
1254- if (fb.isMultiTarget()){
1255- if (fb.getNumColorBuffers() > maxMRTFBOAttachs)
1256- throw new UnsupportedOperationException("Framebuffer has more"
1257- + " targets than are supported"
1258- + " on the system!");
1340+ if (fb.isUpdateNeeded()) {
1341+ updateFrameBuffer(fb);
1342+ }
12591343
1260- if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()){
1261- intBuf16.clear();
1262- for (int i = 0; i < fb.getNumColorBuffers(); i++)
1263- intBuf16.put( GL_COLOR_ATTACHMENT0_EXT + i );
1344+ if (context.boundFBO != fb.getId()) {
1345+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb.getId());
1346+ statistics.onFrameBufferUse(fb, true);
12641347
1265- intBuf16.flip();
1266- glDrawBuffers(intBuf16);
1267- context.boundDrawBuf = 100 + fb.getNumColorBuffers();
1268- }
1269- }else{
1270- RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
1271- // select this draw buffer
1272- if (context.boundDrawBuf != rb.getSlot()){
1273- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
1274- context.boundDrawBuf = rb.getSlot();
1275- }
1276- }
1277- }
1348+ // update viewport to reflect framebuffer's resolution
1349+ setViewPort(0, 0, fb.getWidth(), fb.getHeight());
12781350
1279- assert fb.getId() >= 0;
1280- assert context.boundFBO == fb.getId();
1281- lastFb = fb;
1282- }
1351+ context.boundFBO = fb.getId();
1352+ } else {
1353+ statistics.onFrameBufferUse(fb, false);
1354+ }
1355+ if (fb.getNumColorBuffers() == 0) {
1356+// // make sure to select NONE as draw buf
1357+// // no color buffer attached. select NONE
1358+ if (context.boundDrawBuf != -2) {
1359+// glDrawBuffer(GL_NONE);
1360+ context.boundDrawBuf = -2;
1361+ }
1362+ if (context.boundReadBuf != -2) {
1363+// glReadBuffer(GL_NONE);
1364+ context.boundReadBuf = -2;
1365+ }
1366+ } else {
1367+ if (fb.getNumColorBuffers() > maxFBOAttachs) {
1368+ throw new RendererException("Framebuffer has more color "
1369+ + "attachments than are supported"
1370+ + " by the video hardware!");
1371+ }
1372+ if (fb.isMultiTarget()) {
1373+ if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
1374+ throw new RendererException("Framebuffer has more"
1375+ + " multi targets than are supported"
1376+ + " by the video hardware!");
1377+ }
1378+
1379+ if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
1380+ intBuf16.clear();
1381+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1382+ intBuf16.put(GLES20.GL_COLOR_ATTACHMENT0 + i);
1383+ }
1384+
1385+ intBuf16.flip();
1386+// glDrawBuffers(intBuf16);
1387+ context.boundDrawBuf = 100 + fb.getNumColorBuffers();
1388+ }
1389+ } else {
1390+ RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
1391+ // select this draw buffer
1392+ if (context.boundDrawBuf != rb.getSlot()) {
1393+ GLES20.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
1394+ context.boundDrawBuf = rb.getSlot();
1395+ }
1396+ }
1397+ }
12831398
1284- try {
1285- checkFrameBufferError();
1286- } catch (IllegalStateException ex){
1287- logger.log(Level.SEVERE, "Problem FBO:\n{0}", fb);
1288- throw ex;
1289- }
1399+ assert fb.getId() >= 0;
1400+ assert context.boundFBO == fb.getId();
1401+
1402+ lastFb = fb;
1403+
1404+ checkFrameBufferStatus(fb);
1405+ }
12901406 }
1291- */
12921407
12931408 /**
12941409 * Reads the Color Buffer from OpenGL and stores into the ByteBuffer.
1295- * Since jME for Android does not support Frame Buffers yet, make sure the FrameBuffer
1296- * passed in is NULL (default) or an exception will be thrown.
1297- * Also, make sure to call setViewPort with the appropriate viewport size before
1410+ * Make sure to call setViewPort with the appropriate viewport size before
12981411 * calling readFrameBuffer.
1299- * @param fb FrameBuffer (must be NULL)
1412+ * @param fb FrameBuffer
13001413 * @param byteBuf ByteBuffer to store the Color Buffer from OpenGL
13011414 */
13021415 public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
13031416 if (fb != null) {
1304- throw new IllegalArgumentException("FrameBuffer is not supported yet.");
1305- }
1306-
1307- GLES20.glReadPixels(vpX, vpY, vpW, vpH, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);
1308- }
1309- /*
1310- public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf){
1311- if (fb != null){
1312- RenderBuffer rb = fb.getColorBuffer();
1313- if (rb == null)
1314- throw new IllegalArgumentException("Specified framebuffer" +
1315- " does not have a colorbuffer");
1417+ RenderBuffer rb = fb.getColorBuffer();
1418+ if (rb == null) {
1419+ throw new IllegalArgumentException("Specified framebuffer"
1420+ + " does not have a colorbuffer");
1421+ }
13161422
1317- setFrameBuffer(fb);
1318- if (context.boundReadBuf != rb.getSlot()){
1319- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
1320- context.boundReadBuf = rb.getSlot();
1321- }
1322- }else{
1323- setFrameBuffer(null);
1324- }
1423+ setFrameBuffer(fb);
1424+ if (context.boundReadBuf != rb.getSlot()) {
1425+ GLES20.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
1426+ context.boundReadBuf = rb.getSlot();
1427+ }
1428+ } else {
1429+ setFrameBuffer(null);
1430+ }
13251431
1326- glReadPixels(vpX, vpY, vpW, vpH, GL_RGBA GL_BGRA, GL_UNSIGNED_BYTE, byteBuf);
1432+ GLES20.glReadPixels(vpX, vpY, vpW, vpH, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);
13271433 }
1328- */
13291434
13301435 private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
1331- logger.warning("deleteRenderBuffer is not supported.");
1436+ intBuf1.put(0, rb.getId());
1437+ GLES20.glDeleteRenderbuffers(1, intBuf1);
13321438 }
1333- /*
1334- private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb){
1335- intBuf1.put(0, rb.getId());
1336- glDeleteRenderbuffersEXT(intBuf1);
1337- }
1338- */
13391439
13401440 public void deleteFrameBuffer(FrameBuffer fb) {
1341- logger.warning("deleteFrameBuffer is not supported.");
1342- }
1343- /*
1344- public void deleteFrameBuffer(FrameBuffer fb) {
1345- if (fb.getId() != -1){
1346- if (context.boundFBO == fb.getId()){
1347- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1348- context.boundFBO = 0;
1349- }
1441+ if (fb.getId() != -1) {
1442+ if (context.boundFBO == fb.getId()) {
1443+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
1444+ context.boundFBO = 0;
1445+ }
13501446
1351- if (fb.getDepthBuffer() != null){
1352- deleteRenderBuffer(fb, fb.getDepthBuffer());
1353- }
1354- if (fb.getColorBuffer() != null){
1355- deleteRenderBuffer(fb, fb.getColorBuffer());
1356- }
1447+ if (fb.getDepthBuffer() != null) {
1448+ deleteRenderBuffer(fb, fb.getDepthBuffer());
1449+ }
1450+ if (fb.getColorBuffer() != null) {
1451+ deleteRenderBuffer(fb, fb.getColorBuffer());
1452+ }
13571453
1358- intBuf1.put(0, fb.getId());
1359- glDeleteFramebuffersEXT(intBuf1);
1360- fb.resetObject();
1454+ intBuf1.put(0, fb.getId());
1455+ GLES20.glDeleteFramebuffers(1, intBuf1);
1456+ fb.resetObject();
13611457
1362- statistics.onDeleteFrameBuffer();
1363- }
1458+ statistics.onDeleteFrameBuffer();
1459+ }
13641460 }
1365- */
13661461
13671462 /*********************************************************************\
13681463 |* Textures *|
@@ -1657,7 +1752,7 @@ public class OGLESShaderRenderer implements Renderer {
16571752 }
16581753 }
16591754
1660- private int convertFormat(Format format) {
1755+ private int convertVertexBufferFormat(Format format) {
16611756 switch (format) {
16621757 case Byte:
16631758 return GLES20.GL_BYTE;
@@ -1856,7 +1951,7 @@ public class OGLESShaderRenderer implements Renderer {
18561951
18571952 Android22Workaround.glVertexAttribPointer(loc,
18581953 vb.getNumComponents(),
1859- convertFormat(vb.getFormat()),
1954+ convertVertexBufferFormat(vb.getFormat()),
18601955 vb.isNormalized(),
18611956 vb.getStride(),
18621957 0);
@@ -1907,18 +2002,18 @@ public class OGLESShaderRenderer implements Renderer {
19072002 boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
19082003
19092004 Buffer indexData = indexBuf.getData();
1910-
2005+
19112006 if (indexBuf.getFormat() == Format.UnsignedInt) {
1912- throw new RendererException("OpenGL ES does not support 32-bit index buffers." +
2007+ throw new RendererException("OpenGL ES does not support 32-bit index buffers." +
19132008 "Split your models to avoid going over 65536 vertices.");
19142009 }
1915-
2010+
19162011 if (mesh.getMode() == Mode.Hybrid) {
19172012 int[] modeStart = mesh.getModeStart();
19182013 int[] elementLengths = mesh.getElementLengths();
19192014
19202015 int elMode = convertElementMode(Mode.Triangles);
1921- int fmt = convertFormat(indexBuf.getFormat());
2016+ int fmt = convertVertexBufferFormat(indexBuf.getFormat());
19222017 int elSize = indexBuf.getFormat().getComponentSize();
19232018 int listStart = modeStart[0];
19242019 int stripStart = modeStart[1];
@@ -1964,7 +2059,7 @@ public class OGLESShaderRenderer implements Renderer {
19642059 /*
19652060 GLES20.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()),
19662061 indexBuf.getData().limit(),
1967- convertFormat(indexBuf.getFormat()),
2062+ convertVertexBufferFormat(indexBuf.getFormat()),
19682063 0,
19692064 count);
19702065 */
@@ -1973,7 +2068,7 @@ public class OGLESShaderRenderer implements Renderer {
19732068 GLES20.glDrawElements(
19742069 convertElementMode(mesh.getMode()),
19752070 indexBuf.getData().limit(),
1976- convertFormat(indexBuf.getFormat()),
2071+ convertVertexBufferFormat(indexBuf.getFormat()),
19772072 0);
19782073 }
19792074 }
@@ -2172,7 +2267,7 @@ public class OGLESShaderRenderer implements Renderer {
21722267 int[] elementLengths = mesh.getElementLengths();
21732268
21742269 int elMode = convertElementMode(Mode.Triangles);
2175- int fmt = convertFormat(indexBuf.getFormat());
2270+ int fmt = convertVertexBufferFormat(indexBuf.getFormat());
21762271 int elSize = indexBuf.getFormat().getComponentSize();
21772272 int listStart = modeStart[0];
21782273 int stripStart = modeStart[1];
@@ -2195,7 +2290,7 @@ public class OGLESShaderRenderer implements Renderer {
21952290 GLES20.glDrawElements(
21962291 convertElementMode(mesh.getMode()),
21972292 indexBuf.getData().limit(),
2198- convertFormat(indexBuf.getFormat()),
2293+ convertVertexBufferFormat(indexBuf.getFormat()),
21992294 indexBuf.getData());
22002295 }
22012296 }
@@ -2242,7 +2337,7 @@ public class OGLESShaderRenderer implements Renderer {
22422337 // Upload attribute data
22432338 GLES20.glVertexAttribPointer(loc,
22442339 vb.getNumComponents(),
2245- convertFormat(vb.getFormat()),
2340+ convertVertexBufferFormat(vb.getFormat()),
22462341 vb.isNormalized(),
22472342 vb.getStride(),
22482343 avb.getData());
--- a/engine/src/android/com/jme3/renderer/android/TextureUtil.java
+++ b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
@@ -24,16 +24,19 @@ public class TextureUtil {
2424 private static boolean ETC1support = false;
2525 private static boolean DXT1 = false;
2626 private static boolean DEPTH24 = false;
27+ private static boolean DEPTH_TEXTURE = false;
2728
2829 public static void loadTextureFeatures(String extensionString) {
2930 ETC1support = extensionString.contains("GL_OES_compressed_ETC1_RGB8_texture");
3031 DEPTH24 = extensionString.contains("GL_OES_depth24");
3132 NPOT = extensionString.contains("GL_OES_texture_npot") || extensionString.contains("GL_NV_texture_npot_2D_mipmap");
3233 DXT1 = extensionString.contains("GL_EXT_texture_compression_dxt1");
34+ DEPTH_TEXTURE = extensionString.contains("GL_OES_depth_texture");
3335 logger.log(Level.FINE, "Supports ETC1? {0}", ETC1support);
3436 logger.log(Level.FINE, "Supports DEPTH24? {0}", DEPTH24);
3537 logger.log(Level.FINE, "Supports NPOT? {0}", NPOT);
3638 logger.log(Level.FINE, "Supports DXT1? {0}", DXT1);
39+ logger.log(Level.FINE, "Supports DEPTH_TEXTURE? {0}", DEPTH_TEXTURE);
3740 }
3841
3942 private static void buildMipmap(Bitmap bitmap, boolean compress) {
@@ -241,7 +244,7 @@ public class TextureUtil {
241244 throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware.");
242245 }
243246
244- private static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
247+ public static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
245248 AndroidGLImageFormat imageFormat = new AndroidGLImageFormat();
246249 switch (fmt) {
247250 case RGBA16:
@@ -269,14 +272,17 @@ public class TextureUtil {
269272 case RGB565:
270273 imageFormat.format = GLES20.GL_RGB;
271274 imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_6_5;
275+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
272276 break;
273277 case ARGB4444:
274278 imageFormat.format = GLES20.GL_RGBA4;
275279 imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_4_4_4_4;
280+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
276281 break;
277282 case RGB5A1:
278283 imageFormat.format = GLES20.GL_RGBA;
279284 imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_5_5_1;
285+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB5_A1;
280286 break;
281287 case RGB8:
282288 imageFormat.format = GLES20.GL_RGB;
@@ -293,8 +299,12 @@ public class TextureUtil {
293299 case Depth:
294300 case Depth16:
295301 case Depth24:
302+ if (!DEPTH_TEXTURE) {
303+ unsupportedFormat(fmt);
304+ }
296305 imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
297- imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
306+ imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
307+ imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
298308 break;
299309 case DXT1:
300310 if (!DXT1) {
@@ -318,10 +328,11 @@ public class TextureUtil {
318328 return imageFormat;
319329 }
320330
321- private static class AndroidGLImageFormat {
331+ public static class AndroidGLImageFormat {
322332
323333 boolean compress = false;
324334 int format = -1;
335+ int renderBufferStorageFormat = -1;
325336 int dataType = -1;
326337 }
327338
@@ -334,7 +345,7 @@ public class TextureUtil {
334345 + "Use uploadTextureBitmap instead.");
335346 }
336347
337- // Otherwise upload image directly.
348+ // Otherwise upload image directly.
338349 // Prefer to only use power of 2 textures here to avoid errors.
339350 Image.Format fmt = img.getFormat();
340351 ByteBuffer data;
@@ -436,7 +447,7 @@ public class TextureUtil {
436447 return;
437448 }
438449
439- // Otherwise upload image directly.
450+ // Otherwise upload image directly.
440451 // Prefer to only use power of 2 textures here to avoid errors.
441452 Image.Format fmt = img.getFormat();
442453 ByteBuffer data;