Main repository of MikuMikuStudio
Revision | 941bac4835e96b2c45228d8b4ae3d91111335963 (tree) |
---|---|
Time | 2013-04-06 13:18:43 |
Author | iwgeric@gmail.com <iwgeric@gmai...> |
Commiter | iwgeric@gmail.com |
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
@@ -78,7 +78,9 @@ public class OGLESShaderRenderer implements Renderer { | ||
78 | 78 | private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class); |
79 | 79 | // current state |
80 | 80 | 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; | |
82 | 84 | private int glslVer; |
83 | 85 | private int vertexTextureUnits; |
84 | 86 | private int fragTextureUnits; |
@@ -86,15 +88,16 @@ public class OGLESShaderRenderer implements Renderer { | ||
86 | 88 | private int fragUniforms; |
87 | 89 | private int vertexAttribs; |
88 | 90 | // 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; | |
92 | 94 | private int maxTexSize; |
93 | 95 | private int maxCubeTexSize; |
94 | 96 | private int maxVertCount; |
95 | 97 | private int maxTriCount; |
96 | 98 | private boolean tdc; |
97 | -// private FrameBuffer lastFb = null; | |
99 | + private FrameBuffer lastFb = null; | |
100 | + private FrameBuffer mainFbOverride = null; | |
98 | 101 | private final Statistics statistics = new Statistics(); |
99 | 102 | private int vpX, vpY, vpW, vpH; |
100 | 103 | private int clipX, clipY, clipW, clipH; |
@@ -155,11 +158,18 @@ public class OGLESShaderRenderer implements Renderer { | ||
155 | 158 | |
156 | 159 | powerVr = GLES20.glGetString(GLES20.GL_RENDERER).contains("PowerVR"); |
157 | 160 | |
161 | + /* | |
158 | 162 | // Fix issue in TestRenderToMemory when GL_FRONT is the main |
159 | 163 | // 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 | + */ | |
163 | 173 | |
164 | 174 | // Check OpenGL version |
165 | 175 | int openGlVer = extractVersion("OpenGL ES ", GLES20.glGetString(GLES20.GL_VERSION)); |
@@ -226,6 +236,10 @@ public class OGLESShaderRenderer implements Renderer { | ||
226 | 236 | maxCubeTexSize = intBuf16.get(0); |
227 | 237 | logger.log(Level.FINE, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); |
228 | 238 | |
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 | + | |
229 | 243 | /* |
230 | 244 | if (ctxCaps.GL_ARB_color_buffer_float){ |
231 | 245 | // XXX: Require both 16 and 32 bit float support for FloatColorBuffer. |
@@ -311,11 +325,11 @@ public class OGLESShaderRenderer implements Renderer { | ||
311 | 325 | // Get number of compressed formats available. |
312 | 326 | GLES20.glGetIntegerv(GLES20.GL_NUM_COMPRESSED_TEXTURE_FORMATS, intBuf16); |
313 | 327 | int numCompressedFormats = intBuf16.get(0); |
314 | - | |
328 | + | |
315 | 329 | // Allocate buffer for compressed formats. |
316 | 330 | IntBuffer compressedFormats = BufferUtils.createIntBuffer(numCompressedFormats); |
317 | 331 | GLES20.glGetIntegerv(GLES20.GL_COMPRESSED_TEXTURE_FORMATS, compressedFormats); |
318 | - | |
332 | + | |
319 | 333 | // Print compressed formats. |
320 | 334 | for (int i = 0; i < numCompressedFormats; i++) { |
321 | 335 | logger.log(Level.FINE, "Compressed Texture Formats: {0}", compressedFormats.get(i)); |
@@ -793,14 +807,14 @@ public class OGLESShaderRenderer implements Renderer { | ||
793 | 807 | precision = "precision mediump float;\n"; |
794 | 808 | } |
795 | 809 | GLES20.glShaderSource( |
796 | - id, | |
810 | + id, | |
797 | 811 | precision |
798 | 812 | +source.getDefines() |
799 | 813 | + source.getSource()); |
800 | 814 | } |
801 | 815 | // 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); | |
804 | 818 | // System.out.println("PRECISION HIGH FLOAT VERTEX"); |
805 | 819 | // System.out.println("range "+range[0]+"," +range[1]); |
806 | 820 | // System.out.println("precision "+precision[0]); |
@@ -951,418 +965,499 @@ public class OGLESShaderRenderer implements Renderer { | ||
951 | 965 | |* Framebuffers *| |
952 | 966 | \*********************************************************************/ |
953 | 967 | public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { |
954 | - logger.warning("copyFrameBuffer is not supported."); | |
968 | + copyFrameBuffer(src, dst, true); | |
955 | 969 | } |
956 | 970 | |
957 | 971 | 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 | +// } | |
1009 | 1049 | } |
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 | + } | |
1010 | 1059 | } |
1011 | - */ | |
1012 | 1060 | |
1013 | 1061 | 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 | + } | |
1015 | 1090 | } |
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 | + | |
1045 | 1124 | } |
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 | + } | |
1046 | 1157 | } |
1047 | - */ | |
1048 | 1158 | |
1049 | 1159 | 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 | + } | |
1060 | 1166 | |
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 | + } | |
1065 | 1171 | |
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 | + } | |
1069 | 1176 | |
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 | + } | |
1086 | 1198 | } |
1087 | - */ | |
1088 | 1199 | |
1089 | 1200 | 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 | + } | |
1101 | 1207 | |
1102 | - return GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; | |
1208 | + return GLES20.GL_COLOR_ATTACHMENT0 + attachmentSlot; | |
1103 | 1209 | } |
1104 | - */ | |
1105 | 1210 | |
1106 | 1211 | 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); | |
1121 | 1228 | } |
1122 | - */ | |
1123 | 1229 | |
1124 | 1230 | 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 | + } | |
1144 | 1246 | } |
1145 | - */ | |
1146 | 1247 | |
1147 | 1248 | 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); | |
1159 | 1257 | |
1160 | - statistics.onNewFrameBuffer(); | |
1161 | - } | |
1258 | + statistics.onNewFrameBuffer(); | |
1259 | + } | |
1162 | 1260 | |
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 | + } | |
1169 | 1267 | |
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 | + } | |
1174 | 1272 | |
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 | + } | |
1179 | 1277 | |
1180 | - fb.clearUpdateNeeded(); | |
1278 | + fb.clearUpdateNeeded(); | |
1181 | 1279 | } |
1182 | - */ | |
1183 | 1280 | |
1184 | 1281 | public void setMainFrameBufferOverride(FrameBuffer fb){ |
1282 | + mainFbOverride = fb; | |
1185 | 1283 | } |
1186 | 1284 | |
1187 | 1285 | 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 | + } | |
1193 | 1289 | |
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 | + } | |
1206 | 1295 | |
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()); | |
1207 | 1304 | |
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 | + } | |
1213 | 1311 | |
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); | |
1225 | 1317 | |
1226 | - lastFb = null; | |
1227 | - }else{ | |
1228 | - if (fb.isUpdateNeeded()) | |
1229 | - updateFrameBuffer(fb); | |
1318 | + context.boundFBO = 0; | |
1319 | + } | |
1230 | 1320 | |
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 | + */ | |
1234 | 1332 | |
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 | + } | |
1237 | 1339 | |
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 | + } | |
1259 | 1343 | |
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); | |
1264 | 1347 | |
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()); | |
1278 | 1350 | |
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 | + } | |
1283 | 1398 | |
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 | + } | |
1290 | 1406 | } |
1291 | - */ | |
1292 | 1407 | |
1293 | 1408 | /** |
1294 | 1409 | * 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 | |
1298 | 1411 | * calling readFrameBuffer. |
1299 | - * @param fb FrameBuffer (must be NULL) | |
1412 | + * @param fb FrameBuffer | |
1300 | 1413 | * @param byteBuf ByteBuffer to store the Color Buffer from OpenGL |
1301 | 1414 | */ |
1302 | 1415 | public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { |
1303 | 1416 | 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 | + } | |
1316 | 1422 | |
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 | + } | |
1325 | 1431 | |
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); | |
1327 | 1433 | } |
1328 | - */ | |
1329 | 1434 | |
1330 | 1435 | 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); | |
1332 | 1438 | } |
1333 | - /* | |
1334 | - private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb){ | |
1335 | - intBuf1.put(0, rb.getId()); | |
1336 | - glDeleteRenderbuffersEXT(intBuf1); | |
1337 | - } | |
1338 | - */ | |
1339 | 1439 | |
1340 | 1440 | 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 | + } | |
1350 | 1446 | |
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 | + } | |
1357 | 1453 | |
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(); | |
1361 | 1457 | |
1362 | - statistics.onDeleteFrameBuffer(); | |
1363 | - } | |
1458 | + statistics.onDeleteFrameBuffer(); | |
1459 | + } | |
1364 | 1460 | } |
1365 | - */ | |
1366 | 1461 | |
1367 | 1462 | /*********************************************************************\ |
1368 | 1463 | |* Textures *| |
@@ -1657,7 +1752,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
1657 | 1752 | } |
1658 | 1753 | } |
1659 | 1754 | |
1660 | - private int convertFormat(Format format) { | |
1755 | + private int convertVertexBufferFormat(Format format) { | |
1661 | 1756 | switch (format) { |
1662 | 1757 | case Byte: |
1663 | 1758 | return GLES20.GL_BYTE; |
@@ -1856,7 +1951,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
1856 | 1951 | |
1857 | 1952 | Android22Workaround.glVertexAttribPointer(loc, |
1858 | 1953 | vb.getNumComponents(), |
1859 | - convertFormat(vb.getFormat()), | |
1954 | + convertVertexBufferFormat(vb.getFormat()), | |
1860 | 1955 | vb.isNormalized(), |
1861 | 1956 | vb.getStride(), |
1862 | 1957 | 0); |
@@ -1907,18 +2002,18 @@ public class OGLESShaderRenderer implements Renderer { | ||
1907 | 2002 | boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); |
1908 | 2003 | |
1909 | 2004 | Buffer indexData = indexBuf.getData(); |
1910 | - | |
2005 | + | |
1911 | 2006 | 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." + | |
1913 | 2008 | "Split your models to avoid going over 65536 vertices."); |
1914 | 2009 | } |
1915 | - | |
2010 | + | |
1916 | 2011 | if (mesh.getMode() == Mode.Hybrid) { |
1917 | 2012 | int[] modeStart = mesh.getModeStart(); |
1918 | 2013 | int[] elementLengths = mesh.getElementLengths(); |
1919 | 2014 | |
1920 | 2015 | int elMode = convertElementMode(Mode.Triangles); |
1921 | - int fmt = convertFormat(indexBuf.getFormat()); | |
2016 | + int fmt = convertVertexBufferFormat(indexBuf.getFormat()); | |
1922 | 2017 | int elSize = indexBuf.getFormat().getComponentSize(); |
1923 | 2018 | int listStart = modeStart[0]; |
1924 | 2019 | int stripStart = modeStart[1]; |
@@ -1964,7 +2059,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
1964 | 2059 | /* |
1965 | 2060 | GLES20.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()), |
1966 | 2061 | indexBuf.getData().limit(), |
1967 | - convertFormat(indexBuf.getFormat()), | |
2062 | + convertVertexBufferFormat(indexBuf.getFormat()), | |
1968 | 2063 | 0, |
1969 | 2064 | count); |
1970 | 2065 | */ |
@@ -1973,7 +2068,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
1973 | 2068 | GLES20.glDrawElements( |
1974 | 2069 | convertElementMode(mesh.getMode()), |
1975 | 2070 | indexBuf.getData().limit(), |
1976 | - convertFormat(indexBuf.getFormat()), | |
2071 | + convertVertexBufferFormat(indexBuf.getFormat()), | |
1977 | 2072 | 0); |
1978 | 2073 | } |
1979 | 2074 | } |
@@ -2172,7 +2267,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
2172 | 2267 | int[] elementLengths = mesh.getElementLengths(); |
2173 | 2268 | |
2174 | 2269 | int elMode = convertElementMode(Mode.Triangles); |
2175 | - int fmt = convertFormat(indexBuf.getFormat()); | |
2270 | + int fmt = convertVertexBufferFormat(indexBuf.getFormat()); | |
2176 | 2271 | int elSize = indexBuf.getFormat().getComponentSize(); |
2177 | 2272 | int listStart = modeStart[0]; |
2178 | 2273 | int stripStart = modeStart[1]; |
@@ -2195,7 +2290,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
2195 | 2290 | GLES20.glDrawElements( |
2196 | 2291 | convertElementMode(mesh.getMode()), |
2197 | 2292 | indexBuf.getData().limit(), |
2198 | - convertFormat(indexBuf.getFormat()), | |
2293 | + convertVertexBufferFormat(indexBuf.getFormat()), | |
2199 | 2294 | indexBuf.getData()); |
2200 | 2295 | } |
2201 | 2296 | } |
@@ -2242,7 +2337,7 @@ public class OGLESShaderRenderer implements Renderer { | ||
2242 | 2337 | // Upload attribute data |
2243 | 2338 | GLES20.glVertexAttribPointer(loc, |
2244 | 2339 | vb.getNumComponents(), |
2245 | - convertFormat(vb.getFormat()), | |
2340 | + convertVertexBufferFormat(vb.getFormat()), | |
2246 | 2341 | vb.isNormalized(), |
2247 | 2342 | vb.getStride(), |
2248 | 2343 | avb.getData()); |
@@ -24,16 +24,19 @@ public class TextureUtil { | ||
24 | 24 | private static boolean ETC1support = false; |
25 | 25 | private static boolean DXT1 = false; |
26 | 26 | private static boolean DEPTH24 = false; |
27 | + private static boolean DEPTH_TEXTURE = false; | |
27 | 28 | |
28 | 29 | public static void loadTextureFeatures(String extensionString) { |
29 | 30 | ETC1support = extensionString.contains("GL_OES_compressed_ETC1_RGB8_texture"); |
30 | 31 | DEPTH24 = extensionString.contains("GL_OES_depth24"); |
31 | 32 | NPOT = extensionString.contains("GL_OES_texture_npot") || extensionString.contains("GL_NV_texture_npot_2D_mipmap"); |
32 | 33 | DXT1 = extensionString.contains("GL_EXT_texture_compression_dxt1"); |
34 | + DEPTH_TEXTURE = extensionString.contains("GL_OES_depth_texture"); | |
33 | 35 | logger.log(Level.FINE, "Supports ETC1? {0}", ETC1support); |
34 | 36 | logger.log(Level.FINE, "Supports DEPTH24? {0}", DEPTH24); |
35 | 37 | logger.log(Level.FINE, "Supports NPOT? {0}", NPOT); |
36 | 38 | logger.log(Level.FINE, "Supports DXT1? {0}", DXT1); |
39 | + logger.log(Level.FINE, "Supports DEPTH_TEXTURE? {0}", DEPTH_TEXTURE); | |
37 | 40 | } |
38 | 41 | |
39 | 42 | private static void buildMipmap(Bitmap bitmap, boolean compress) { |
@@ -241,7 +244,7 @@ public class TextureUtil { | ||
241 | 244 | throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware."); |
242 | 245 | } |
243 | 246 | |
244 | - private static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException { | |
247 | + public static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException { | |
245 | 248 | AndroidGLImageFormat imageFormat = new AndroidGLImageFormat(); |
246 | 249 | switch (fmt) { |
247 | 250 | case RGBA16: |
@@ -269,14 +272,17 @@ public class TextureUtil { | ||
269 | 272 | case RGB565: |
270 | 273 | imageFormat.format = GLES20.GL_RGB; |
271 | 274 | imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_6_5; |
275 | + imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565; | |
272 | 276 | break; |
273 | 277 | case ARGB4444: |
274 | 278 | imageFormat.format = GLES20.GL_RGBA4; |
275 | 279 | imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_4_4_4_4; |
280 | + imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4; | |
276 | 281 | break; |
277 | 282 | case RGB5A1: |
278 | 283 | imageFormat.format = GLES20.GL_RGBA; |
279 | 284 | imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_5_5_1; |
285 | + imageFormat.renderBufferStorageFormat = GLES20.GL_RGB5_A1; | |
280 | 286 | break; |
281 | 287 | case RGB8: |
282 | 288 | imageFormat.format = GLES20.GL_RGB; |
@@ -293,8 +299,12 @@ public class TextureUtil { | ||
293 | 299 | case Depth: |
294 | 300 | case Depth16: |
295 | 301 | case Depth24: |
302 | + if (!DEPTH_TEXTURE) { | |
303 | + unsupportedFormat(fmt); | |
304 | + } | |
296 | 305 | 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; | |
298 | 308 | break; |
299 | 309 | case DXT1: |
300 | 310 | if (!DXT1) { |
@@ -318,10 +328,11 @@ public class TextureUtil { | ||
318 | 328 | return imageFormat; |
319 | 329 | } |
320 | 330 | |
321 | - private static class AndroidGLImageFormat { | |
331 | + public static class AndroidGLImageFormat { | |
322 | 332 | |
323 | 333 | boolean compress = false; |
324 | 334 | int format = -1; |
335 | + int renderBufferStorageFormat = -1; | |
325 | 336 | int dataType = -1; |
326 | 337 | } |
327 | 338 |
@@ -334,7 +345,7 @@ public class TextureUtil { | ||
334 | 345 | + "Use uploadTextureBitmap instead."); |
335 | 346 | } |
336 | 347 | |
337 | - // Otherwise upload image directly. | |
348 | + // Otherwise upload image directly. | |
338 | 349 | // Prefer to only use power of 2 textures here to avoid errors. |
339 | 350 | Image.Format fmt = img.getFormat(); |
340 | 351 | ByteBuffer data; |
@@ -436,7 +447,7 @@ public class TextureUtil { | ||
436 | 447 | return; |
437 | 448 | } |
438 | 449 | |
439 | - // Otherwise upload image directly. | |
450 | + // Otherwise upload image directly. | |
440 | 451 | // Prefer to only use power of 2 textures here to avoid errors. |
441 | 452 | Image.Format fmt = img.getFormat(); |
442 | 453 | ByteBuffer data; |