From b35c5e9820b047ca1dcaaac94de40edb73fad445 Mon Sep 17 00:00:00 2001 From: Kostyantyn Hushchyn Date: Mon, 27 Apr 2015 01:36:15 +0300 Subject: [PATCH] Remove redundand code. Fixed java/lang/IllegalStateException in com/jme3/asset/DesktopAssetManager.registerAndCloneSmartAsset. Added ogg loader --- jme3-ios/src/main/java/com/jme3/asset/IOS.cfg | 4 +- .../renderer/ios/IGLESShaderRenderer.java | 2573 ----------------- .../com/jme3/renderer/ios/TextureUtil.java | 576 ---- .../src/main/resources/com/jme3/asset/IOS.cfg | 4 +- 4 files changed, 6 insertions(+), 3151 deletions(-) delete mode 100644 jme3-ios/src/main/java/com/jme3/renderer/ios/IGLESShaderRenderer.java delete mode 100644 jme3-ios/src/main/java/com/jme3/renderer/ios/TextureUtil.java diff --git a/jme3-ios/src/main/java/com/jme3/asset/IOS.cfg b/jme3-ios/src/main/java/com/jme3/asset/IOS.cfg index 4e4052447..e9d79a459 100644 --- a/jme3-ios/src/main/java/com/jme3/asset/IOS.cfg +++ b/jme3-ios/src/main/java/com/jme3/asset/IOS.cfg @@ -2,7 +2,9 @@ INCLUDE com/jme3/asset/General.cfg # IOS specific loaders LOADER com.jme3.system.ios.IosImageLoader : jpg, bmp, gif, png, jpeg -LOADER com.jme3.material.plugins.J3MLoader : j3m, j3md +LOADER com.jme3.audio.plugins.OGGLoader : ogg +LOADER com.jme3.material.plugins.J3MLoader : j3m +LOADER com.jme3.material.plugins.J3MLoader : j3md LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib LOADER com.jme3.export.binary.BinaryImporter : j3o LOADER com.jme3.font.plugins.BitmapFontLoader : fnt diff --git a/jme3-ios/src/main/java/com/jme3/renderer/ios/IGLESShaderRenderer.java b/jme3-ios/src/main/java/com/jme3/renderer/ios/IGLESShaderRenderer.java deleted file mode 100644 index 8a59d0be8..000000000 --- a/jme3-ios/src/main/java/com/jme3/renderer/ios/IGLESShaderRenderer.java +++ /dev/null @@ -1,2573 +0,0 @@ -package com.jme3.renderer.ios; - -import com.jme3.light.LightList; -import com.jme3.material.RenderState; -import com.jme3.math.*; -import com.jme3.renderer.*; -import com.jme3.scene.Mesh; -import com.jme3.scene.Mesh.Mode; -import com.jme3.scene.VertexBuffer; -import com.jme3.scene.VertexBuffer.Format; -import com.jme3.scene.VertexBuffer.Type; -import com.jme3.scene.VertexBuffer.Usage; -import com.jme3.shader.Attribute; -import com.jme3.shader.Shader; -import com.jme3.shader.Shader.ShaderSource; -import com.jme3.shader.Shader.ShaderType; -import com.jme3.shader.Uniform; -import com.jme3.texture.FrameBuffer; -import com.jme3.texture.FrameBuffer.RenderBuffer; -import com.jme3.texture.Image; -import com.jme3.texture.Texture; -import com.jme3.texture.Texture.WrapAxis; -import com.jme3.util.BufferUtils; -import com.jme3.util.ListMap; -import com.jme3.util.NativeObjectManager; - -import java.nio.*; -import java.util.EnumSet; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import jme3tools.shader.ShaderDebug; - -/** - * The Renderer is responsible for taking rendering commands and - * executing them on the underlying video hardware. - * - * @author Kirill Vainer - */ -public class IGLESShaderRenderer implements Renderer { - - private static final Logger logger = Logger.getLogger(IGLESShaderRenderer.class.getName()); - private static final boolean VALIDATE_SHADER = false; - - private final NativeObjectManager objManager = new NativeObjectManager(); - private final EnumSet caps = EnumSet.noneOf(Caps.class); - private final Statistics statistics = new Statistics(); - private final StringBuilder stringBuf = new StringBuilder(250); - private final RenderContext context = new RenderContext(); - private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); - - 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 final int[] intBuf1 = new int[1]; - private final int[] intBuf16 = new int[16]; - - private int glslVer; - private int vertexTextureUnits; - private int fragTextureUnits; - private int vertexUniforms; - private int fragUniforms; - private int vertexAttribs; - private int maxRBSize; - private int maxTexSize; - private int maxCubeTexSize; - - private FrameBuffer lastFb = null; - private FrameBuffer mainFbOverride = null; - private boolean useVBO = true; - private boolean powerVr = false; - private boolean uintIndexSupport = false; - - private Shader boundShader; - - private int vpX, vpY, vpW, vpH; - private int clipX, clipY, clipW, clipH; - - public IGLESShaderRenderer() { - logger.log(Level.FINE, "IGLESShaderRenderer Constructor"); - } - - /** - * Get the capabilities of the renderer. - * @return The capabilities of the renderer. - */ - public EnumSet getCaps() { - logger.log(Level.FINE, "IGLESShaderRenderer getCaps"); - return caps; - } - - /** - * The statistics allow tracking of how data - * per frame, such as number of objects rendered, number of triangles, etc. - * These are updated when the Renderer's methods are used, make sure - * to call {@link Statistics#clearFrame() } at the appropriate time - * to get accurate info per frame. - */ - public Statistics getStatistics() { - logger.log(Level.FINE, "IGLESShaderRenderer getStatistics"); - return statistics; - } - - /** - * Invalidates the current rendering state. Should be called after - * the GL state was changed manually or through an external library. - */ - public void invalidateState() { - logger.log(Level.FINE, "IGLESShaderRenderer invalidateState"); - } - - /** - * Clears certain channels of the currently bound framebuffer. - * - * @param color True if to clear colors (RGBA) - * @param depth True if to clear depth/z - * @param stencil True if to clear stencil buffer (if available, otherwise - * ignored) - */ - public void clearBuffers(boolean color, boolean depth, boolean stencil) { - logger.log(Level.FINE, "IGLESShaderRenderer clearBuffers"); - int bits = 0; - if (color) { - //See explanations of the depth below, we must enable color write to be able to clear the color buffer - if (context.colorWriteEnabled == false) { - JmeIosGLES.glColorMask(true, true, true, true); - context.colorWriteEnabled = true; - } - bits = JmeIosGLES.GL_COLOR_BUFFER_BIT; - } - if (depth) { - //glClear(GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false - //here s some link on openl board - //http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223 - //if depth clear is requested, we enable the depthMask - if (context.depthWriteEnabled == false) { - JmeIosGLES.glDepthMask(true); - context.depthWriteEnabled = true; - } - bits |= JmeIosGLES.GL_DEPTH_BUFFER_BIT; - } - if (stencil) { - bits |= JmeIosGLES.GL_STENCIL_BUFFER_BIT; - } - if (bits != 0) { - JmeIosGLES.glClear(bits); - JmeIosGLES.checkGLError(); - } - } - - /** - * Sets the background (aka clear) color. - * - * @param color The background color to set - */ - public void setBackgroundColor(ColorRGBA color) { - logger.log(Level.FINE, "IGLESShaderRenderer setBackgroundColor"); - JmeIosGLES.glClearColor(color.r, color.g, color.b, color.a); - JmeIosGLES.checkGLError(); - } - - /** - * Applies the given {@link RenderState}, making the necessary - * GL calls so that the state is applied. - */ - public void applyRenderState(RenderState state) { - logger.log(Level.FINE, "IGLESShaderRenderer applyRenderState"); - /* - if (state.isWireframe() && !context.wireframe){ - GLES20.glPolygonMode(GLES20.GL_FRONT_AND_BACK, GLES20.GL_LINE); - context.wireframe = true; - }else if (!state.isWireframe() && context.wireframe){ - GLES20.glPolygonMode(GLES20.GL_FRONT_AND_BACK, GLES20.GL_FILL); - context.wireframe = false; - } - */ - if (state.isDepthTest() && !context.depthTestEnabled) { - JmeIosGLES.glEnable(JmeIosGLES.GL_DEPTH_TEST); - JmeIosGLES.glDepthFunc(convertTestFunction(context.depthFunc)); - JmeIosGLES.checkGLError(); - context.depthTestEnabled = true; - } else if (!state.isDepthTest() && context.depthTestEnabled) { - JmeIosGLES.glDisable(JmeIosGLES.GL_DEPTH_TEST); - JmeIosGLES.checkGLError(); - context.depthTestEnabled = false; - } - if (state.getDepthFunc() != context.depthFunc) { - JmeIosGLES.glDepthFunc(convertTestFunction(state.getDepthFunc())); - context.depthFunc = state.getDepthFunc(); - } - - if (state.isDepthWrite() && !context.depthWriteEnabled) { - JmeIosGLES.glDepthMask(true); - JmeIosGLES.checkGLError(); - context.depthWriteEnabled = true; - } else if (!state.isDepthWrite() && context.depthWriteEnabled) { - JmeIosGLES.glDepthMask(false); - JmeIosGLES.checkGLError(); - context.depthWriteEnabled = false; - } - if (state.isColorWrite() && !context.colorWriteEnabled) { - JmeIosGLES.glColorMask(true, true, true, true); - JmeIosGLES.checkGLError(); - context.colorWriteEnabled = true; - } else if (!state.isColorWrite() && context.colorWriteEnabled) { - JmeIosGLES.glColorMask(false, false, false, false); - JmeIosGLES.checkGLError(); - context.colorWriteEnabled = false; - } -// if (state.isPointSprite() && !context.pointSprite) { -//// GLES20.glEnable(GLES20.GL_POINT_SPRITE); -//// GLES20.glTexEnvi(GLES20.GL_POINT_SPRITE, GLES20.GL_COORD_REPLACE, GLES20.GL_TRUE); -//// GLES20.glEnable(GLES20.GL_VERTEX_PROGRAM_POINT_SIZE); -//// GLES20.glPointParameterf(GLES20.GL_POINT_SIZE_MIN, 1.0f); -// } else if (!state.isPointSprite() && context.pointSprite) { -//// GLES20.glDisable(GLES20.GL_POINT_SPRITE); -// } - - if (state.isPolyOffset()) { - if (!context.polyOffsetEnabled) { - JmeIosGLES.glEnable(JmeIosGLES.GL_POLYGON_OFFSET_FILL); - JmeIosGLES.glPolygonOffset(state.getPolyOffsetFactor(), - state.getPolyOffsetUnits()); - JmeIosGLES.checkGLError(); - - context.polyOffsetEnabled = true; - context.polyOffsetFactor = state.getPolyOffsetFactor(); - context.polyOffsetUnits = state.getPolyOffsetUnits(); - } else { - if (state.getPolyOffsetFactor() != context.polyOffsetFactor - || state.getPolyOffsetUnits() != context.polyOffsetUnits) { - JmeIosGLES.glPolygonOffset(state.getPolyOffsetFactor(), - state.getPolyOffsetUnits()); - JmeIosGLES.checkGLError(); - - context.polyOffsetFactor = state.getPolyOffsetFactor(); - context.polyOffsetUnits = state.getPolyOffsetUnits(); - } - } - } else { - if (context.polyOffsetEnabled) { - JmeIosGLES.glDisable(JmeIosGLES.GL_POLYGON_OFFSET_FILL); - JmeIosGLES.checkGLError(); - - context.polyOffsetEnabled = false; - context.polyOffsetFactor = 0; - context.polyOffsetUnits = 0; - } - } - if (state.getFaceCullMode() != context.cullMode) { - if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) { - JmeIosGLES.glDisable(JmeIosGLES.GL_CULL_FACE); - JmeIosGLES.checkGLError(); - } else { - JmeIosGLES.glEnable(JmeIosGLES.GL_CULL_FACE); - JmeIosGLES.checkGLError(); - } - - switch (state.getFaceCullMode()) { - case Off: - break; - case Back: - JmeIosGLES.glCullFace(JmeIosGLES.GL_BACK); - JmeIosGLES.checkGLError(); - break; - case Front: - JmeIosGLES.glCullFace(JmeIosGLES.GL_FRONT); - JmeIosGLES.checkGLError(); - break; - case FrontAndBack: - JmeIosGLES.glCullFace(JmeIosGLES.GL_FRONT_AND_BACK); - JmeIosGLES.checkGLError(); - break; - default: - throw new UnsupportedOperationException("Unrecognized face cull mode: " - + state.getFaceCullMode()); - } - - context.cullMode = state.getFaceCullMode(); - } - - if (state.getBlendMode() != context.blendMode) { - if (state.getBlendMode() == RenderState.BlendMode.Off) { - JmeIosGLES.glDisable(JmeIosGLES.GL_BLEND); - JmeIosGLES.checkGLError(); - } else { - JmeIosGLES.glEnable(JmeIosGLES.GL_BLEND); - switch (state.getBlendMode()) { - case Off: - break; - case Additive: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_ONE, JmeIosGLES.GL_ONE); - break; - case AlphaAdditive: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_SRC_ALPHA, JmeIosGLES.GL_ONE); - break; - case Color: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_ONE, JmeIosGLES.GL_ONE_MINUS_SRC_COLOR); - break; - case Alpha: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_SRC_ALPHA, JmeIosGLES.GL_ONE_MINUS_SRC_ALPHA); - break; - case PremultAlpha: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_ONE, JmeIosGLES.GL_ONE_MINUS_SRC_ALPHA); - break; - case Modulate: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_DST_COLOR, JmeIosGLES.GL_ZERO); - break; - case ModulateX2: - JmeIosGLES.glBlendFunc(JmeIosGLES.GL_DST_COLOR, JmeIosGLES.GL_SRC_COLOR); - break; - default: - throw new UnsupportedOperationException("Unrecognized blend mode: " - + state.getBlendMode()); - } - JmeIosGLES.checkGLError(); - } - context.blendMode = state.getBlendMode(); - } - } - - /** - * Set the range of the depth values for objects. All rendered - * objects will have their depth clamped to this range. - * - * @param start The range start - * @param end The range end - */ - public void setDepthRange(float start, float end) { - logger.log(Level.FINE, "IGLESShaderRenderer setDepthRange"); - JmeIosGLES.glDepthRangef(start, end); - JmeIosGLES.checkGLError(); - } - - /** - * Called when a new frame has been rendered. - */ - public void postFrame() { - logger.log(Level.FINE, "IGLESShaderRenderer onFrame"); - //JmeIosGLES.checkGLErrorForced(); - JmeIosGLES.checkGLError(); - - objManager.deleteUnused(this); - } - - /** - * Set the world matrix to use. Does nothing if the Renderer is - * shader based. - * - * @param worldMatrix World matrix to use. - */ - public void setWorldMatrix(Matrix4f worldMatrix) { - logger.log(Level.FINE, "IGLESShaderRenderer setWorldMatrix"); - } - - /** - * Sets the view and projection matrices to use. Does nothing if the Renderer - * is shader based. - * - * @param viewMatrix The view matrix to use. - * @param projMatrix The projection matrix to use. - */ - public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) { - logger.log(Level.FINE, "IGLESShaderRenderer setViewProjectionMatrices"); - } - - /** - * Set the viewport location and resolution on the screen. - * - * @param x The x coordinate of the viewport - * @param y The y coordinate of the viewport - * @param width Width of the viewport - * @param height Height of the viewport - */ - public void setViewPort(int x, int y, int width, int height) { - logger.log(Level.FINE, "IGLESShaderRenderer setViewPort"); - if (x != vpX || vpY != y || vpW != width || vpH != height) { - JmeIosGLES.glViewport(x, y, width, height); - JmeIosGLES.checkGLError(); - - vpX = x; - vpY = y; - vpW = width; - vpH = height; - } - } - - /** - * Specifies a clipping rectangle. - * For all future rendering commands, no pixels will be allowed - * to be rendered outside of the clip rectangle. - * - * @param x The x coordinate of the clip rect - * @param y The y coordinate of the clip rect - * @param width Width of the clip rect - * @param height Height of the clip rect - */ - public void setClipRect(int x, int y, int width, int height) { - logger.log(Level.FINE, "IGLESShaderRenderer setClipRect"); - if (!context.clipRectEnabled) { - JmeIosGLES.glEnable(JmeIosGLES.GL_SCISSOR_TEST); - JmeIosGLES.checkGLError(); - context.clipRectEnabled = true; - } - if (clipX != x || clipY != y || clipW != width || clipH != height) { - JmeIosGLES.glScissor(x, y, width, height); - JmeIosGLES.checkGLError(); - clipX = x; - clipY = y; - clipW = width; - clipH = height; - } - } - - /** - * Clears the clipping rectangle set with - * {@link #setClipRect(int, int, int, int) }. - */ - public void clearClipRect() { - logger.log(Level.FINE, "IGLESShaderRenderer clearClipRect"); - if (context.clipRectEnabled) { - JmeIosGLES.glDisable(JmeIosGLES.GL_SCISSOR_TEST); - JmeIosGLES.checkGLError(); - context.clipRectEnabled = false; - - clipX = 0; - clipY = 0; - clipW = 0; - clipH = 0; - } - } - - /** - * Set lighting state. - * Does nothing if the renderer is shader based. - * The lights should be provided in world space. - * Specify null to disable lighting. - * - * @param lights The light list to set. - */ - public void setLighting(LightList lights) { - logger.log(Level.FINE, "IGLESShaderRenderer setLighting"); - } - - /** - * Sets the shader to use for rendering. - * If the shader has not been uploaded yet, it is compiled - * and linked. If it has been uploaded, then the - * uniform data is updated and the shader is set. - * - * @param shader The shader to use for rendering. - */ - public void setShader(Shader shader) { - logger.log(Level.FINE, "IGLESShaderRenderer setShader"); - if (shader == null) { - throw new IllegalArgumentException("Shader cannot be null"); - } else { - if (shader.isUpdateNeeded()) { - updateShaderData(shader); - } - - // NOTE: might want to check if any of the - // sources need an update? - - assert shader.getId() > 0; - - updateShaderUniforms(shader); - bindProgram(shader); - } - } - - /** - * Deletes a shader. This method also deletes - * the attached shader sources. - * - * @param shader Shader to delete. - */ - public void deleteShader(Shader shader) { - logger.log(Level.FINE, "IGLESShaderRenderer deleteShader"); - if (shader.getId() == -1) { - logger.warning("Shader is not uploaded to GPU, cannot delete."); - return; - } - - for (ShaderSource source : shader.getSources()) { - if (source.getId() != -1) { - JmeIosGLES.glDetachShader(shader.getId(), source.getId()); - JmeIosGLES.checkGLError(); - - deleteShaderSource(source); - } - } - - JmeIosGLES.glDeleteProgram(shader.getId()); - JmeIosGLES.checkGLError(); - - statistics.onDeleteShader(); - shader.resetObject(); - } - - /** - * Deletes the provided shader source. - * - * @param source The ShaderSource to delete. - */ - public void deleteShaderSource(ShaderSource source) { - logger.log(Level.FINE, "IGLESShaderRenderer deleteShaderSource"); - if (source.getId() < 0) { - logger.warning("Shader source is not uploaded to GPU, cannot delete."); - return; - } - - source.clearUpdateNeeded(); - - JmeIosGLES.glDeleteShader(source.getId()); - JmeIosGLES.checkGLError(); - - source.resetObject(); - } - - /** - * Copies contents from src to dst, scaling if necessary. - */ - public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { - logger.log(Level.FINE, "IGLESShaderRenderer copyFrameBuffer"); - copyFrameBuffer(src, dst, true); - } - - /** - * Copies contents from src to dst, scaling if necessary. - * set copyDepth to false to only copy the color buffers. - */ - public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) { - logger.warning("IGLESShaderRenderer copyFrameBuffer with depth TODO"); - throw new RendererException("Copy framebuffer not implemented yet."); - } - - /** - * Sets the framebuffer that will be drawn to. - */ - public void setFrameBuffer(FrameBuffer fb) { - logger.log(Level.FINE, "IGLESShaderRenderer setFrameBuffer"); - if (fb == null && mainFbOverride != null) { - fb = mainFbOverride; - } - - if (lastFb == fb) { - if (fb == null || !fb.isUpdateNeeded()) { - return; - } - } - - // generate mipmaps for last FB if needed - if (lastFb != null) { - for (int i = 0; i < lastFb.getNumColorBuffers(); i++) { - RenderBuffer rb = lastFb.getColorBuffer(i); - Texture tex = rb.getTexture(); - if (tex != null - && tex.getMinFilter().usesMipMapLevels()) { - setTexture(0, rb.getTexture()); - -// int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace()); - int textureType = convertTextureType(tex.getType()); - JmeIosGLES.glGenerateMipmap(textureType); - JmeIosGLES.checkGLError(); - } - } - } - - if (fb == null) { - // unbind any fbos - if (context.boundFBO != 0) { - JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, 0); - JmeIosGLES.checkGLError(); - - statistics.onFrameBufferUse(null, true); - - context.boundFBO = 0; - } - - /* - // select back buffer - if (context.boundDrawBuf != -1) { - glDrawBuffer(initialDrawBuf); - context.boundDrawBuf = -1; - } - if (context.boundReadBuf != -1) { - glReadBuffer(initialReadBuf); - context.boundReadBuf = -1; - } - */ - - lastFb = null; - } else { - 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()) { - JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, fb.getId()); - JmeIosGLES.checkGLError(); - - statistics.onFrameBufferUse(fb, true); - - // update viewport to reflect framebuffer's resolution - setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - - context.boundFBO = fb.getId(); - } else { - statistics.onFrameBufferUse(fb, false); - } - if (fb.getNumColorBuffers() == 0) { -// // make sure to select NONE as draw buf -// // no color buffer attached. select NONE - if (context.boundDrawBuf != -2) { -// glDrawBuffer(GL_NONE); - context.boundDrawBuf = -2; - } - if (context.boundReadBuf != -2) { -// 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 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 < 16; i++) { - intBuf16[i] = i < fb.getNumColorBuffers() ? JmeIosGLES.GL_COLOR_ATTACHMENT0 + i : 0; - } - - //intBuf16.flip();// TODO: flip -// glDrawBuffers(intBuf16); - context.boundDrawBuf = 100 + fb.getNumColorBuffers(); - } - } else { - RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex()); - // select this draw buffer - if (context.boundDrawBuf != rb.getSlot()) { - JmeIosGLES.glActiveTexture(convertAttachmentSlot(rb.getSlot())); - JmeIosGLES.checkGLError(); - - context.boundDrawBuf = rb.getSlot(); - } - } - } - - assert fb.getId() >= 0; - assert context.boundFBO == fb.getId(); - - lastFb = fb; - - checkFrameBufferStatus(fb); - } - } - - /** - * Set the framebuffer that will be set instead of the main framebuffer - * when a call to setFrameBuffer(null) is made. - * - * @param fb - */ - public void setMainFrameBufferOverride(FrameBuffer fb) { - logger.log(Level.FINE, "IGLESShaderRenderer setMainFrameBufferOverride"); - mainFbOverride = fb; - } - - /** - * Reads the pixels currently stored in the specified framebuffer - * into the given ByteBuffer object. - * Only color pixels are transferred, the format is BGRA with 8 bits - * per component. The given byte buffer should have at least - * fb.getWidth() * fb.getHeight() * 4 bytes remaining. - * - * @param fb The framebuffer to read from - * @param byteBuf The bytebuffer to transfer color data to - */ - public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { - logger.log(Level.FINE, "IGLESShaderRenderer readFrameBuffer"); - if (fb != null) { - RenderBuffer rb = fb.getColorBuffer(); - if (rb == null) { - throw new IllegalArgumentException("Specified framebuffer" - + " does not have a colorbuffer"); - } - - setFrameBuffer(fb); - } else { - setFrameBuffer(null); - } - - //JmeIosGLES.glReadPixels2(vpX, vpY, vpW, vpH, JmeIosGLES.GL_RGBA, JmeIosGLES.GL_UNSIGNED_BYTE, byteBuf.array(), 0, vpW * vpH * 4); - JmeIosGLES.glReadPixels(vpX, vpY, vpW, vpH, JmeIosGLES.GL_RGBA, JmeIosGLES.GL_UNSIGNED_BYTE, byteBuf); - JmeIosGLES.checkGLError(); - } - - /** - * Deletes a framebuffer and all attached renderbuffers - */ - public void deleteFrameBuffer(FrameBuffer fb) { - logger.log(Level.FINE, "IGLESShaderRenderer deleteFrameBuffer"); - if (fb.getId() != -1) { - if (context.boundFBO == fb.getId()) { - JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, 0); - JmeIosGLES.checkGLError(); - - context.boundFBO = 0; - } - - if (fb.getDepthBuffer() != null) { - deleteRenderBuffer(fb, fb.getDepthBuffer()); - } - if (fb.getColorBuffer() != null) { - deleteRenderBuffer(fb, fb.getColorBuffer()); - } - - intBuf1[0] = fb.getId(); - JmeIosGLES.glDeleteFramebuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - fb.resetObject(); - - statistics.onDeleteFrameBuffer(); - } - } - - /** - * Sets the texture to use for the given texture unit. - */ - public void setTexture(int unit, Texture tex) { - logger.log(Level.FINE, "IGLESShaderRenderer setTexture"); - Image image = tex.getImage(); - if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated()) ) { - updateTexImageData(image, tex.getType()); - } - - int texId = image.getId(); - assert texId != -1; - - if (texId == -1) { - logger.warning("error: texture image has -1 id"); - } - - Image[] textures = context.boundTextures; - - int type = convertTextureType(tex.getType()); - if (textures[unit] != image) { - if (context.boundTextureUnit != unit) { - JmeIosGLES.glActiveTexture(JmeIosGLES.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; - } - - JmeIosGLES.glBindTexture(type, texId); - JmeIosGLES.checkGLError(); - - textures[unit] = image; - - statistics.onTextureUse(tex.getImage(), true); - } else { - statistics.onTextureUse(tex.getImage(), false); - } - - setupTextureParams(tex); - } - - /** - * Modify the given Texture tex with the given Image. The image will be put at x and y into the texture. - * - * @param tex the Texture that will be modified - * @param pixels the source Image data to copy data from - * @param x the x position to put the image into the texture - * @param y the y position to put the image into the texture - */ - public void modifyTexture(Texture tex, Image pixels, int x, int y) { - logger.log(Level.FINE, "IGLESShaderRenderer modifyTexture"); - setTexture(0, tex); - TextureUtil.uploadSubTexture(pixels, convertTextureType(tex.getType()), 0, x, y); - } - - /** - * Deletes a texture from the GPU. - */ - public void deleteImage(Image image) { - logger.log(Level.FINE, "IGLESShaderRenderer deleteImage"); - int texId = image.getId(); - if (texId != -1) { - intBuf1[0] = texId; - - JmeIosGLES.glDeleteTextures(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - image.resetObject(); - - statistics.onDeleteTexture(); - } - } - - /** - * Uploads a vertex buffer to the GPU. - * - * @param vb The vertex buffer to upload - */ - public void updateBufferData(VertexBuffer vb) { - logger.log(Level.FINE, "IGLESShaderRenderer updateBufferData"); - int bufId = vb.getId(); - boolean created = false; - if (bufId == -1) { - // create buffer - JmeIosGLES.glGenBuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - bufId = intBuf1[0]; - vb.setId(bufId); - objManager.registerObject(vb); - - created = true; - } - - // bind buffer - int target; - if (vb.getBufferType() == VertexBuffer.Type.Index) { - target = JmeIosGLES.GL_ELEMENT_ARRAY_BUFFER; - if (context.boundElementArrayVBO != bufId) { - JmeIosGLES.glBindBuffer(target, bufId); - JmeIosGLES.checkGLError(); - - context.boundElementArrayVBO = bufId; - } - } else { - target = JmeIosGLES.GL_ARRAY_BUFFER; - if (context.boundArrayVBO != bufId) { - JmeIosGLES.glBindBuffer(target, bufId); - JmeIosGLES.checkGLError(); - - context.boundArrayVBO = bufId; - } - } - - int usage = convertUsage(vb.getUsage()); - vb.getData().rewind(); - - if (created || vb.hasDataSizeChanged()) { - // upload data based on format - int size = vb.getData().limit() * vb.getFormat().getComponentSize(); - - switch (vb.getFormat()) { - case Byte: - case UnsignedByte: - JmeIosGLES.glBufferData(target, size, (ByteBuffer) vb.getData(), usage); - JmeIosGLES.checkGLError(); - break; - case Short: - case UnsignedShort: - JmeIosGLES.glBufferData(target, size, (ShortBuffer) vb.getData(), usage); - JmeIosGLES.checkGLError(); - break; - case Int: - case UnsignedInt: - JmeIosGLES.glBufferData(target, size, (IntBuffer) vb.getData(), usage); - JmeIosGLES.checkGLError(); - break; - case Float: - JmeIosGLES.glBufferData(target, size, (FloatBuffer) vb.getData(), usage); - JmeIosGLES.checkGLError(); - break; - default: - throw new RuntimeException("Unknown buffer format."); - } - } else { - int size = vb.getData().limit() * vb.getFormat().getComponentSize(); - - switch (vb.getFormat()) { - case Byte: - case UnsignedByte: - JmeIosGLES.glBufferSubData(target, 0, size, (ByteBuffer) vb.getData()); - JmeIosGLES.checkGLError(); - break; - case Short: - case UnsignedShort: - JmeIosGLES.glBufferSubData(target, 0, size, (ShortBuffer) vb.getData()); - JmeIosGLES.checkGLError(); - break; - case Int: - case UnsignedInt: - JmeIosGLES.glBufferSubData(target, 0, size, (IntBuffer) vb.getData()); - JmeIosGLES.checkGLError(); - break; - case Float: - JmeIosGLES.glBufferSubData(target, 0, size, (FloatBuffer) vb.getData()); - JmeIosGLES.checkGLError(); - break; - default: - throw new RuntimeException("Unknown buffer format."); - } - } - vb.clearUpdateNeeded(); - } - - /** - * Deletes a vertex buffer from the GPU. - * @param vb The vertex buffer to delete - */ - public void deleteBuffer(VertexBuffer vb) { - logger.log(Level.FINE, "IGLESShaderRenderer deleteBuffer"); - int bufId = vb.getId(); - if (bufId != -1) { - // delete buffer - intBuf1[0] = bufId; - - JmeIosGLES.glDeleteBuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - vb.resetObject(); - } - } - - /** - * Renders count meshes, with the geometry data supplied. - * The shader which is currently set with setShader is - * responsible for transforming the input verticies into clip space - * and shading it based on the given vertex attributes. - * The int variable gl_InstanceID can be used to access the current - * instance of the mesh being rendered inside the vertex shader. - * - * @param mesh The mesh to render - * @param lod The LOD level to use, see {@link Mesh#setLodLevels(com.jme3.scene.VertexBuffer[]) }. - * @param count Number of mesh instances to render - */ - public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - logger.log(Level.FINE, "IGLESShaderRenderer renderMesh"); - if (mesh.getVertexCount() == 0) { - return; - } - /* - * NOTE: not supported in OpenGL ES 2.0. - if (context.pointSize != mesh.getPointSize()) { - GLES10.glPointSize(mesh.getPointSize()); - context.pointSize = mesh.getPointSize(); - } - */ - if (context.lineWidth != mesh.getLineWidth()) { - JmeIosGLES.glLineWidth(mesh.getLineWidth()); - JmeIosGLES.checkGLError(); - context.lineWidth = mesh.getLineWidth(); - } - - statistics.onMeshDrawn(mesh, lod); -// if (GLContext.getCapabilities().GL_ARB_vertex_array_object){ -// renderMeshVertexArray(mesh, lod, count); -// }else{ - - if (useVBO) { - renderMeshDefault(mesh, lod, count); - } else { - renderMeshVertexArray(mesh, lod, count); - } - } - - /** - * Resets all previously used {@link NativeObject Native Objects} on this Renderer. - * The state of the native objects is reset in such way, that using - * them again will cause the renderer to reupload them. - * Call this method when you know the GL context is going to shutdown. - * - * @see NativeObject#resetObject() - */ - public void resetGLObjects() { - logger.log(Level.FINE, "IGLESShaderRenderer resetGLObjects"); - objManager.resetObjects(); - statistics.clearMemory(); - boundShader = null; - lastFb = null; - context.reset(); - } - - /** - * Deletes all previously used {@link NativeObject Native Objects} on this Renderer, and - * then resets the native objects. - * - * @see #resetGLObjects() - * @see NativeObject#deleteObject(java.lang.Object) - */ - public void cleanup() { - logger.log(Level.FINE, "IGLESShaderRenderer cleanup"); - objManager.deleteAllObjects(this); - statistics.clearMemory(); - } - - /** - * Sets the alpha to coverage state. - *

- * When alpha coverage and multi-sampling is enabled, - * each pixel will contain alpha coverage in all - * of its subsamples, which is then combined when - * other future alpha-blended objects are rendered. - *

- *

- * Alpha-to-coverage is useful for rendering transparent objects - * without having to worry about sorting them. - *

- */ - public void setAlphaToCoverage(boolean value) { - logger.log(Level.FINE, "IGLESShaderRenderer setAlphaToCoverage"); - if (value) { - JmeIosGLES.glEnable(JmeIosGLES.GL_SAMPLE_ALPHA_TO_COVERAGE); - JmeIosGLES.checkGLError(); - } else { - JmeIosGLES.glDisable(JmeIosGLES.GL_SAMPLE_ALPHA_TO_COVERAGE); - JmeIosGLES.checkGLError(); - } - } - - - /* ------------------------------------------------------------------------------ */ - - - public void initialize() { - Level store = logger.getLevel(); - logger.setLevel(Level.FINE); - - logger.log(Level.FINE, "Vendor: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_VENDOR)); - logger.log(Level.FINE, "Renderer: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_RENDERER)); - logger.log(Level.FINE, "Version: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_VERSION)); - logger.log(Level.FINE, "Shading Language Version: {0}", JmeIosGLES.glGetString(JmeIosGLES.GL_SHADING_LANGUAGE_VERSION)); - - /* - // Fix issue in TestRenderToMemory when GL_FRONT is the main - // buffer being used. - 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 ", JmeIosGLES.glGetString(JmeIosGLES.GL_VERSION)); - if (openGlVer == -1) { - glslVer = -1; - throw new UnsupportedOperationException("OpenGL ES 2.0+ is required for IGLESShaderRenderer!"); - } - - // Check shader language version - glslVer = extractVersion("OpenGL ES GLSL ES ", JmeIosGLES.glGetString(JmeIosGLES.GL_SHADING_LANGUAGE_VERSION)); - switch (glslVer) { - // TODO: When new versions of OpenGL ES shader language come out, - // update this. - default: - caps.add(Caps.GLSL100); - break; - } - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16, 0); - vertexTextureUnits = intBuf16[0]; - logger.log(Level.FINE, "VTF Units: {0}", vertexTextureUnits); - if (vertexTextureUnits > 0) { - caps.add(Caps.VertexTextureFetch); - } - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16, 0); - fragTextureUnits = intBuf16[0]; - logger.log(Level.FINE, "Texture Units: {0}", fragTextureUnits); - - // Multiply vector count by 4 to get float count. - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VERTEX_UNIFORM_VECTORS, intBuf16, 0); - vertexUniforms = intBuf16[0] * 4; - logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_FRAGMENT_UNIFORM_VECTORS, intBuf16, 0); - fragUniforms = intBuf16[0] * 4; - logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VARYING_VECTORS, intBuf16, 0); - int varyingFloats = intBuf16[0] * 4; - logger.log(Level.FINER, "Varying Floats: {0}", varyingFloats); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_VERTEX_ATTRIBS, intBuf16, 0); - vertexAttribs = intBuf16[0]; - logger.log(Level.FINE, "Vertex Attributes: {0}", vertexAttribs); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_SUBPIXEL_BITS, intBuf16, 0); - int subpixelBits = intBuf16[0]; - logger.log(Level.FINE, "Subpixel Bits: {0}", subpixelBits); - -// GLES10.glGetIntegerv(GLES10.GL_MAX_ELEMENTS_VERTICES, intBuf16); -// maxVertCount = intBuf16.get(0); -// logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount); -// -// GLES10.glGetIntegerv(GLES10.GL_MAX_ELEMENTS_INDICES, intBuf16); -// maxTriCount = intBuf16.get(0); -// logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_TEXTURE_SIZE, intBuf16, 0); - maxTexSize = intBuf16[0]; - logger.log(Level.FINE, "Maximum Texture Resolution: {0}", maxTexSize); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16, 0); - maxCubeTexSize = intBuf16[0]; - logger.log(Level.FINE, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); - - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_MAX_RENDERBUFFER_SIZE, intBuf16, 0); - maxRBSize = intBuf16[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. - if (ctxCaps.GL_ARB_half_float_pixel){ - caps.add(Caps.FloatColorBuffer); - } - } - - if (ctxCaps.GL_ARB_depth_buffer_float){ - caps.add(Caps.FloatDepthBuffer); - } - - if (ctxCaps.GL_ARB_draw_instanced) - caps.add(Caps.MeshInstancing); - - if (ctxCaps.GL_ARB_texture_buffer_object) - caps.add(Caps.TextureBuffer); - - if (ctxCaps.GL_ARB_texture_float){ - if (ctxCaps.GL_ARB_half_float_pixel){ - caps.add(Caps.FloatTexture); - } - } - - if (ctxCaps.GL_EXT_packed_float){ - caps.add(Caps.PackedFloatColorBuffer); - if (ctxCaps.GL_ARB_half_float_pixel){ - // because textures are usually uploaded as RGB16F - // need half-float pixel - caps.add(Caps.PackedFloatTexture); - } - } - - if (ctxCaps.GL_EXT_texture_array) - caps.add(Caps.TextureArray); - - if (ctxCaps.GL_EXT_texture_shared_exponent) - caps.add(Caps.SharedExponentTexture); - - if (ctxCaps.GL_EXT_framebuffer_object){ - caps.add(Caps.FrameBuffer); - - glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16); - maxRBSize = intBuf16.get(0); - logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize); - - glGetInteger(GL_MAX_COLOR_ATTACHMENTS_EXT, intBuf16); - maxFBOAttachs = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs); - - if (ctxCaps.GL_EXT_framebuffer_multisample){ - caps.add(Caps.FrameBufferMultisample); - - glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16); - maxFBOSamples = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples); - } - - if (ctxCaps.GL_ARB_draw_buffers){ - caps.add(Caps.FrameBufferMRT); - glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16); - maxMRTFBOAttachs = intBuf16.get(0); - logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs); - } - } - - if (ctxCaps.GL_ARB_multisample){ - glGetInteger(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, intBuf16); - boolean available = intBuf16.get(0) != 0; - glGetInteger(ARBMultisample.GL_SAMPLES_ARB, intBuf16); - int samples = intBuf16.get(0); - logger.log(Level.FINER, "Samples: {0}", samples); - boolean enabled = glIsEnabled(ARBMultisample.GL_MULTISAMPLE_ARB); - if (samples > 0 && available && !enabled){ - glEnable(ARBMultisample.GL_MULTISAMPLE_ARB); - } - } - */ - - String extensions = JmeIosGLES.glGetString(JmeIosGLES.GL_EXTENSIONS); - logger.log(Level.FINE, "GL_EXTENSIONS: {0}", extensions); - - // Get number of compressed formats available. - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_NUM_COMPRESSED_TEXTURE_FORMATS, intBuf16, 0); - int numCompressedFormats = intBuf16[0]; - - // Allocate buffer for compressed formats. - int[] compressedFormats = new int[numCompressedFormats]; - JmeIosGLES.glGetIntegerv(JmeIosGLES.GL_COMPRESSED_TEXTURE_FORMATS, compressedFormats, 0); - - // Check for errors after all glGet calls. - JmeIosGLES.checkGLError(); - - // Print compressed formats. - for (int i = 0; i < numCompressedFormats; i++) { - logger.log(Level.FINE, "Compressed Texture Formats: {0}", compressedFormats[i]); - } - - TextureUtil.loadTextureFeatures(extensions); - - applyRenderState(RenderState.DEFAULT); - JmeIosGLES.glDisable(JmeIosGLES.GL_DITHER); - JmeIosGLES.checkGLError(); - - logger.log(Level.FINE, "Caps: {0}", caps); - logger.setLevel(store); - - uintIndexSupport = extensions.contains("GL_OES_element_index_uint"); - logger.log(Level.FINE, "Support for UInt index: {0}", uintIndexSupport); - } - - - /* ------------------------------------------------------------------------------ */ - - - private int extractVersion(String prefixStr, String versionStr) { - if (versionStr != null) { - int spaceIdx = versionStr.indexOf(" ", prefixStr.length()); - if (spaceIdx >= 1) { - versionStr = versionStr.substring(prefixStr.length(), spaceIdx).trim(); - } else { - versionStr = versionStr.substring(prefixStr.length()).trim(); - } - float version = Float.parseFloat(versionStr); - return (int) (version * 100); - } else { - return -1; - } - } - - private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) { - intBuf1[0] = rb.getId(); - JmeIosGLES.glDeleteRenderbuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - } - - private int convertUsage(Usage usage) { - switch (usage) { - case Static: - return JmeIosGLES.GL_STATIC_DRAW; - case Dynamic: - return JmeIosGLES.GL_DYNAMIC_DRAW; - case Stream: - return JmeIosGLES.GL_STREAM_DRAW; - default: - throw new RuntimeException("Unknown usage type."); - } - } - - - protected void bindProgram(Shader shader) { - int shaderId = shader.getId(); - if (context.boundShaderProgram != shaderId) { - JmeIosGLES.glUseProgram(shaderId); - JmeIosGLES.checkGLError(); - - statistics.onShaderUse(shader, true); - boundShader = shader; - context.boundShaderProgram = shaderId; - } else { - statistics.onShaderUse(shader, false); - } - } - - protected void updateShaderUniforms(Shader shader) { - ListMap uniforms = shader.getUniformMap(); - for (int i = 0; i < uniforms.size(); i++) { - Uniform uniform = uniforms.getValue(i); - if (uniform.isUpdateNeeded()) { - updateUniform(shader, uniform); - } - } - } - - - protected void updateUniform(Shader shader, Uniform uniform) { - logger.log(Level.FINE, "IGLESShaderRenderer private updateUniform: " + uniform.getVarType()); - int shaderId = shader.getId(); - - assert uniform.getName() != null; - assert shader.getId() > 0; - - if (context.boundShaderProgram != shaderId) { - JmeIosGLES.glUseProgram(shaderId); - JmeIosGLES.checkGLError(); - - statistics.onShaderUse(shader, true); - boundShader = shader; - context.boundShaderProgram = shaderId; - } else { - statistics.onShaderUse(shader, false); - } - - int loc = uniform.getLocation(); - if (loc == -1) { - return; - } - - if (loc == -2) { - // get uniform location - updateUniformLocation(shader, uniform); - if (uniform.getLocation() == -1) { - // not declared, ignore - uniform.clearUpdateNeeded(); - return; - } - loc = uniform.getLocation(); - } - - if (uniform.getVarType() == null) { - // removed logging the warning to avoid flooding the log - // (LWJGL also doesn't post a warning) - //logger.log(Level.FINEST, "Uniform value is not set yet. Shader: {0}, Uniform: {1}", - // new Object[]{shader.toString(), uniform.toString()}); - return; // value not set yet.. - } - - statistics.onUniformSet(); - - uniform.clearUpdateNeeded(); - ByteBuffer bb;//GetPrimitiveArrayCritical - FloatBuffer fb; - IntBuffer ib; - switch (uniform.getVarType()) { - case Float: - Float f = (Float) uniform.getValue(); - JmeIosGLES.glUniform1f(loc, f.floatValue()); - break; - case Vector2: - Vector2f v2 = (Vector2f) uniform.getValue(); - JmeIosGLES.glUniform2f(loc, v2.getX(), v2.getY()); - break; - case Vector3: - Vector3f v3 = (Vector3f) uniform.getValue(); - JmeIosGLES.glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ()); - break; - case Vector4: - Object val = uniform.getValue(); - if (val instanceof ColorRGBA) { - ColorRGBA c = (ColorRGBA) val; - JmeIosGLES.glUniform4f(loc, c.r, c.g, c.b, c.a); - } else if (val instanceof Vector4f) { - Vector4f c = (Vector4f) val; - JmeIosGLES.glUniform4f(loc, c.x, c.y, c.z, c.w); - } else { - Quaternion c = (Quaternion) uniform.getValue(); - JmeIosGLES.glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW()); - } - break; - case Boolean: - Boolean b = (Boolean) uniform.getValue(); - JmeIosGLES.glUniform1i(loc, b.booleanValue() ? JmeIosGLES.GL_TRUE : JmeIosGLES.GL_FALSE); - break; - case Matrix3: - fb = (FloatBuffer) uniform.getValue(); - assert fb.remaining() == 9; - JmeIosGLES.glUniformMatrix3fv(loc, 1, false, fb); - break; - case Matrix4: - fb = (FloatBuffer) uniform.getValue(); - assert fb.remaining() == 16; - JmeIosGLES.glUniformMatrix4fv(loc, 1, false, fb); - break; - case IntArray: - ib = (IntBuffer) uniform.getValue(); - JmeIosGLES.glUniform1iv(loc, ib.limit(), ib); - break; - case FloatArray: - fb = (FloatBuffer) uniform.getValue(); - JmeIosGLES.glUniform1fv(loc, fb.limit(), fb); - break; - case Vector2Array: - fb = (FloatBuffer) uniform.getValue(); - JmeIosGLES.glUniform2fv(loc, fb.limit() / 2, fb); - break; - case Vector3Array: - fb = (FloatBuffer) uniform.getValue(); - JmeIosGLES.glUniform3fv(loc, fb.limit() / 3, fb); - break; - case Vector4Array: - fb = (FloatBuffer) uniform.getValue(); - JmeIosGLES.glUniform4fv(loc, fb.limit() / 4, fb); - break; - case Matrix4Array: - fb = (FloatBuffer) uniform.getValue(); - JmeIosGLES.glUniformMatrix4fv(loc, fb.limit() / 16, false, fb); - break; - case Int: - Integer i = (Integer) uniform.getValue(); - JmeIosGLES.glUniform1i(loc, i.intValue()); - break; - default: - throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType()); - } - JmeIosGLES.checkGLError(); - } - - protected void updateUniformLocation(Shader shader, Uniform uniform) { - stringBuf.setLength(0); - stringBuf.append(uniform.getName()).append('\0'); - updateNameBuffer(); - int loc = JmeIosGLES.glGetUniformLocation(shader.getId(), uniform.getName()); - JmeIosGLES.checkGLError(); - - if (loc < 0) { - uniform.setLocation(-1); - // uniform is not declared in shader - } else { - uniform.setLocation(loc); - } - } - - protected void updateNameBuffer() { - int len = stringBuf.length(); - - nameBuf.position(0); - nameBuf.limit(len); - for (int i = 0; i < len; i++) { - nameBuf.put((byte) stringBuf.charAt(i)); - } - - nameBuf.rewind(); - } - - - public void updateShaderData(Shader shader) { - int id = shader.getId(); - boolean needRegister = false; - if (id == -1) { - // create program - id = JmeIosGLES.glCreateProgram(); - JmeIosGLES.checkGLError(); - - if (id <= 0) { - throw new RendererException("Invalid ID received when trying to create shader program."); - } - - shader.setId(id); - needRegister = true; - } - - for (ShaderSource source : shader.getSources()) { - if (source.isUpdateNeeded()) { - updateShaderSourceData(source); - } - - JmeIosGLES.glAttachShader(id, source.getId()); - JmeIosGLES.checkGLError(); - } - - // link shaders to program - JmeIosGLES.glLinkProgram(id); - JmeIosGLES.checkGLError(); - - JmeIosGLES.glGetProgramiv(id, JmeIosGLES.GL_LINK_STATUS, intBuf1, 0); - JmeIosGLES.checkGLError(); - - boolean linkOK = intBuf1[0] == JmeIosGLES.GL_TRUE; - String infoLog = null; - - if (VALIDATE_SHADER || !linkOK) { - JmeIosGLES.glGetProgramiv(id, JmeIosGLES.GL_INFO_LOG_LENGTH, intBuf1, 0); - JmeIosGLES.checkGLError(); - - int length = intBuf1[0]; - if (length > 3) { - // get infos - infoLog = JmeIosGLES.glGetProgramInfoLog(id); - JmeIosGLES.checkGLError(); - } - } - - if (linkOK) { - if (infoLog != null) { - logger.log(Level.FINE, "shader link success. \n{0}", infoLog); - } else { - logger.fine("shader link success"); - } - shader.clearUpdateNeeded(); - if (needRegister) { - // Register shader for clean up if it was created in this method. - objManager.registerObject(shader); - statistics.onNewShader(); - } else { - // OpenGL spec: uniform locations may change after re-link - resetUniformLocations(shader); - } - } else { - if (infoLog != null) { - throw new RendererException("Shader link failure, shader:" + shader + "\n" + infoLog); - } else { - throw new RendererException("Shader link failure, shader:" + shader + "\ninfo: "); - } - } - } - - protected void resetUniformLocations(Shader shader) { - ListMap uniforms = shader.getUniformMap(); - for (int i = 0; i < uniforms.size(); i++) { - Uniform uniform = uniforms.getValue(i); - uniform.reset(); // e.g check location again - } - } - - public void updateTexImageData(Image img, Texture.Type type) { - int texId = img.getId(); - if (texId == -1) { - // create texture - JmeIosGLES.glGenTextures(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - texId = intBuf1[0]; - img.setId(texId); - objManager.registerObject(img); - - statistics.onNewTexture(); - } - - // bind texture - int target = convertTextureType(type); - if (context.boundTextures[0] != img) { - if (context.boundTextureUnit != 0) { - JmeIosGLES.glActiveTexture(JmeIosGLES.GL_TEXTURE0); - JmeIosGLES.checkGLError(); - - context.boundTextureUnit = 0; - } - - JmeIosGLES.glBindTexture(target, texId); - JmeIosGLES.checkGLError(); - - context.boundTextures[0] = img; - } - - boolean needMips = false; - if (img.isGeneratedMipmapsRequired()) { - needMips = true; - img.setMipmapsGenerated(true); - } - - if (target == JmeIosGLES.GL_TEXTURE_CUBE_MAP) { - // Check max texture size before upload - if (img.getWidth() > maxCubeTexSize || img.getHeight() > maxCubeTexSize) { - throw new RendererException("Cannot upload cubemap " + img + ". The maximum supported cubemap resolution is " + maxCubeTexSize); - } - } else { - if (img.getWidth() > maxTexSize || img.getHeight() > maxTexSize) { - throw new RendererException("Cannot upload texture " + img + ". The maximum supported texture resolution is " + maxTexSize); - } - } - - if (target == JmeIosGLES.GL_TEXTURE_CUBE_MAP) { - // Upload a cube map / sky box - /* - @SuppressWarnings("unchecked") - List bmps = (List) img.getEfficentData(); - if (bmps != null) { - // Native android bitmap - if (bmps.size() != 6) { - throw new UnsupportedOperationException("Invalid texture: " + img - + "Cubemap textures must contain 6 data units."); - } - for (int i = 0; i < 6; i++) { - TextureUtil.uploadTextureBitmap(JmeIosGLES.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, bmps.get(i).getBitmap(), needMips); - bmps.get(i).notifyBitmapUploaded(); - } - } else { - */ - // Standard jme3 image data - List data = img.getData(); - if (data.size() != 6) { - throw new UnsupportedOperationException("Invalid texture: " + img - + "Cubemap textures must contain 6 data units."); - } - for (int i = 0; i < 6; i++) { - TextureUtil.uploadTextureAny(img, JmeIosGLES.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, needMips); - } - //} - } else { - TextureUtil.uploadTextureAny(img, target, 0, needMips); - /* - if (img.getEfficentData() instanceof AndroidImageInfo) { - AndroidImageInfo info = (AndroidImageInfo) img.getEfficentData(); - info.notifyBitmapUploaded(); - } - */ - } - - img.clearUpdateNeeded(); - } - - private void setupTextureParams(Texture tex) { - int target = convertTextureType(tex.getType()); - - // filter things - int minFilter = convertMinFilter(tex.getMinFilter()); - int magFilter = convertMagFilter(tex.getMagFilter()); - - JmeIosGLES.glTexParameteri(target, JmeIosGLES.GL_TEXTURE_MIN_FILTER, minFilter); - JmeIosGLES.checkGLError(); - JmeIosGLES.glTexParameteri(target, JmeIosGLES.GL_TEXTURE_MAG_FILTER, magFilter); - JmeIosGLES.checkGLError(); - - /* - if (tex.getAnisotropicFilter() > 1){ - - if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic){ - glTexParameterf(target, - EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, - tex.getAnisotropicFilter()); - } - - } - */ - // repeat modes - - switch (tex.getType()) { - case ThreeDimensional: - case CubeMap: // cubemaps use 3D coords - // GL_TEXTURE_WRAP_R is not available in api 8 - //GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R))); - case TwoDimensional: - case TwoDimensionalArray: - JmeIosGLES.glTexParameteri(target, JmeIosGLES.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T))); - - // fall down here is intentional.. -// case OneDimensional: - JmeIosGLES.glTexParameteri(target, JmeIosGLES.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S))); - - JmeIosGLES.checkGLError(); - break; - default: - throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); - } - - // R to Texture compare mode -/* - if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off){ - GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_COMPARE_MODE, GLES20.GL_COMPARE_R_TO_TEXTURE); - GLES20.glTexParameteri(target, GLES20.GL_DEPTH_TEXTURE_MODE, GLES20.GL_INTENSITY); - if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual){ - GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_COMPARE_FUNC, GLES20.GL_GEQUAL); - }else{ - GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_COMPARE_FUNC, GLES20.GL_LEQUAL); - } - } - */ - } - - private int convertTextureType(Texture.Type type) { - switch (type) { - case TwoDimensional: - return JmeIosGLES.GL_TEXTURE_2D; - // case TwoDimensionalArray: - // return EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT; -// case ThreeDimensional: - // return GLES20.GL_TEXTURE_3D; - case CubeMap: - return JmeIosGLES.GL_TEXTURE_CUBE_MAP; - default: - throw new UnsupportedOperationException("Unknown texture type: " + type); - } - } - - private int convertMagFilter(Texture.MagFilter filter) { - switch (filter) { - case Bilinear: - return JmeIosGLES.GL_LINEAR; - case Nearest: - return JmeIosGLES.GL_NEAREST; - default: - throw new UnsupportedOperationException("Unknown mag filter: " + filter); - } - } - - private int convertMinFilter(Texture.MinFilter filter) { - switch (filter) { - case Trilinear: - return JmeIosGLES.GL_LINEAR_MIPMAP_LINEAR; - case BilinearNearestMipMap: - return JmeIosGLES.GL_LINEAR_MIPMAP_NEAREST; - case NearestLinearMipMap: - return JmeIosGLES.GL_NEAREST_MIPMAP_LINEAR; - case NearestNearestMipMap: - return JmeIosGLES.GL_NEAREST_MIPMAP_NEAREST; - case BilinearNoMipMaps: - return JmeIosGLES.GL_LINEAR; - case NearestNoMipMaps: - return JmeIosGLES.GL_NEAREST; - default: - throw new UnsupportedOperationException("Unknown min filter: " + filter); - } - } - - private int convertWrapMode(Texture.WrapMode mode) { - switch (mode) { - case BorderClamp: - case Clamp: - case EdgeClamp: - return JmeIosGLES.GL_CLAMP_TO_EDGE; - case Repeat: - return JmeIosGLES.GL_REPEAT; - case MirroredRepeat: - return JmeIosGLES.GL_MIRRORED_REPEAT; - default: - throw new UnsupportedOperationException("Unknown wrap mode: " + mode); - } - } - - private void renderMeshVertexArray(Mesh mesh, int lod, int count) { - for (VertexBuffer vb : mesh.getBufferList().getArray()) { - if (vb.getBufferType() == Type.InterleavedData - || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers - || vb.getBufferType() == Type.Index) { - continue; - } - - if (vb.getStride() == 0) { - // not interleaved - setVertexAttrib_Array(vb); - } else { - // interleaved - VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); - setVertexAttrib_Array(vb, interleavedData); - } - } - - VertexBuffer indices = null; - if (mesh.getNumLodLevels() > 0) { - indices = mesh.getLodLevel(lod); - } else { - indices = mesh.getBuffer(Type.Index);//buffers.get(Type.Index.ordinal()); - } - if (indices != null) { - drawTriangleList_Array(indices, mesh, count); - } else { - JmeIosGLES.glDrawArrays(convertElementMode(mesh.getMode()), 0, mesh.getVertexCount()); - JmeIosGLES.checkGLError(); - } - clearVertexAttribs(); - } - - private void renderMeshDefault(Mesh mesh, int lod, int count) { - VertexBuffer indices = null; - VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); - if (interleavedData != null && interleavedData.isUpdateNeeded()) { - updateBufferData(interleavedData); - } - - //IntMap buffers = mesh.getBuffers(); ; - if (mesh.getNumLodLevels() > 0) { - indices = mesh.getLodLevel(lod); - } else { - indices = mesh.getBuffer(Type.Index);// buffers.get(Type.Index.ordinal()); - } - for (VertexBuffer vb : mesh.getBufferList().getArray()){ - if (vb.getBufferType() == Type.InterleavedData - || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers - || vb.getBufferType() == Type.Index) { - continue; - } - - if (vb.getStride() == 0) { - // not interleaved - setVertexAttrib(vb); - } else { - // interleaved - setVertexAttrib(vb, interleavedData); - } - } - if (indices != null) { - drawTriangleList(indices, mesh, count); - } else { -// throw new UnsupportedOperationException("Cannot render without index buffer"); - JmeIosGLES.glDrawArrays(convertElementMode(mesh.getMode()), 0, mesh.getVertexCount()); - JmeIosGLES.checkGLError(); - } - clearVertexAttribs(); - } - - - public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { - if (vb.getBufferType() == VertexBuffer.Type.Index) { - throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib"); - } - - if (vb.isUpdateNeeded() && idb == null) { - updateBufferData(vb); - } - - int programId = context.boundShaderProgram; - if (programId > 0) { - Attribute attrib = boundShader.getAttribute(vb.getBufferType()); - int loc = attrib.getLocation(); - if (loc == -1) { - return; // not defined - } - - if (loc == -2) { -// stringBuf.setLength(0); -// stringBuf.append("in").append(vb.getBufferType().name()).append('\0'); -// updateNameBuffer(); - - String attributeName = "in" + vb.getBufferType().name(); - loc = JmeIosGLES.glGetAttribLocation(programId, attributeName); - JmeIosGLES.checkGLError(); - - // not really the name of it in the shader (inPosition\0) but - // the internal name of the enum (Position). - if (loc < 0) { - attrib.setLocation(-1); - return; // not available in shader. - } else { - attrib.setLocation(loc); - } - } - - VertexBuffer[] attribs = context.boundAttribs; - if (!context.attribIndexList.moveToNew(loc)) { - JmeIosGLES.glEnableVertexAttribArray(loc); - JmeIosGLES.checkGLError(); - //System.out.println("Enabled ATTRIB IDX: "+loc); - } - if (attribs[loc] != vb) { - // NOTE: Use id from interleaved buffer if specified - int bufId = idb != null ? idb.getId() : vb.getId(); - assert bufId != -1; - - if (bufId == -1) { - logger.warning("invalid buffer id"); - } - - if (context.boundArrayVBO != bufId) { - JmeIosGLES.glBindBuffer(JmeIosGLES.GL_ARRAY_BUFFER, bufId); - JmeIosGLES.checkGLError(); - - context.boundArrayVBO = bufId; - } - - vb.getData().rewind(); - /* - Android22Workaround.glVertexAttribPointer(loc, - vb.getNumComponents(), - convertVertexBufferFormat(vb.getFormat()), - vb.isNormalized(), - vb.getStride(), - 0); - */ - logger.warning("iTODO Android22Workaround"); - - JmeIosGLES.glVertexAttribPointer(loc, - vb.getNumComponents(), - convertVertexBufferFormat(vb.getFormat()), - vb.isNormalized(), - vb.getStride(), - null); - - JmeIosGLES.checkGLError(); - - attribs[loc] = vb; - } - } else { - throw new IllegalStateException("Cannot render mesh without shader bound"); - } - } - - public void setVertexAttrib(VertexBuffer vb) { - setVertexAttrib(vb, null); - } - - public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) { - /* if (count > 1){ - ARBDrawInstanced.glDrawArraysInstancedARB(convertElementMode(mode), 0, - vertCount, count); - }else{*/ - JmeIosGLES.glDrawArrays(convertElementMode(mode), 0, vertCount); - JmeIosGLES.checkGLError(); - /* - }*/ - } - - public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) { - if (indexBuf.getBufferType() != VertexBuffer.Type.Index) { - throw new IllegalArgumentException("Only index buffers are allowed as triangle lists."); - } - - if (indexBuf.isUpdateNeeded()) { - updateBufferData(indexBuf); - } - - int bufId = indexBuf.getId(); - assert bufId != -1; - - if (bufId == -1) { - throw new RendererException("Invalid buffer ID"); - } - - if (context.boundElementArrayVBO != bufId) { - JmeIosGLES.glBindBuffer(JmeIosGLES.GL_ELEMENT_ARRAY_BUFFER, bufId); - JmeIosGLES.checkGLError(); - - context.boundElementArrayVBO = bufId; - } - - int vertCount = mesh.getVertexCount(); - boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); - - Buffer indexData = indexBuf.getData(); - - if (!uintIndexSupport && (indexBuf.getFormat() == Format.UnsignedInt)) { - throw new RendererException("OpenGL ES does not support 32-bit index buffers." + - "Split your models to avoid going over 65536 vertices."); - } - - if (mesh.getMode() == Mode.Hybrid) { - int[] modeStart = mesh.getModeStart(); - int[] elementLengths = mesh.getElementLengths(); - - int elMode = convertElementMode(Mode.Triangles); - int fmt = convertVertexBufferFormat(indexBuf.getFormat()); - int elSize = indexBuf.getFormat().getComponentSize(); - int listStart = modeStart[0]; - int stripStart = modeStart[1]; - int fanStart = modeStart[2]; - int curOffset = 0; - for (int i = 0; i < elementLengths.length; i++) { - if (i == stripStart) { - elMode = convertElementMode(Mode.TriangleStrip); - } else if (i == fanStart) { - elMode = convertElementMode(Mode.TriangleStrip); - } - int elementLength = elementLengths[i]; - - if (useInstancing) { - //ARBDrawInstanced. - throw new IllegalArgumentException("instancing is not supported."); - /* - GLES20.glDrawElementsInstancedARB(elMode, - elementLength, - fmt, - curOffset, - count); - */ - } else { - indexBuf.getData().position(curOffset); - JmeIosGLES.glDrawElements(elMode, elementLength, fmt, indexBuf.getData()); - JmeIosGLES.checkGLError(); - /* - glDrawRangeElements(elMode, - 0, - vertCount, - elementLength, - fmt, - curOffset); - */ - } - - curOffset += elementLength * elSize; - } - } else { - if (useInstancing) { - throw new IllegalArgumentException("instancing is not supported."); - //ARBDrawInstanced. -/* - GLES20.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()), - indexBuf.getData().limit(), - convertVertexBufferFormat(indexBuf.getFormat()), - 0, - count); - */ - } else { - logger.log(Level.FINE, "IGLESShaderRenderer drawTriangleList TODO check"); - indexData.rewind(); - JmeIosGLES.glDrawElementsIndex( - convertElementMode(mesh.getMode()), - indexBuf.getData().limit(), - convertVertexBufferFormat(indexBuf.getFormat()), - 0); - /*TODO: - indexData.rewind(); - JmeIosGLES.glDrawElements( - convertElementMode(mesh.getMode()), - indexBuf.getData().limit(), - convertVertexBufferFormat(indexBuf.getFormat()), - 0); - */ - JmeIosGLES.checkGLError(); - } - } - } - - public int convertElementMode(Mesh.Mode mode) { - switch (mode) { - case Points: - return JmeIosGLES.GL_POINTS; - case Lines: - return JmeIosGLES.GL_LINES; - case LineLoop: - return JmeIosGLES.GL_LINE_LOOP; - case LineStrip: - return JmeIosGLES.GL_LINE_STRIP; - case Triangles: - return JmeIosGLES.GL_TRIANGLES; - case TriangleFan: - return JmeIosGLES.GL_TRIANGLE_FAN; - case TriangleStrip: - return JmeIosGLES.GL_TRIANGLE_STRIP; - default: - throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode); - } - } - - - private int convertVertexBufferFormat(Format format) { - switch (format) { - case Byte: - return JmeIosGLES.GL_BYTE; - case UnsignedByte: - return JmeIosGLES.GL_UNSIGNED_BYTE; - case Short: - return JmeIosGLES.GL_SHORT; - case UnsignedShort: - return JmeIosGLES.GL_UNSIGNED_SHORT; - case Int: - return JmeIosGLES.GL_INT; - case UnsignedInt: - return JmeIosGLES.GL_UNSIGNED_INT; - /* - case Half: - return NVHalfFloat.GL_HALF_FLOAT_NV; - // return ARBHalfFloatVertex.GL_HALF_FLOAT; - */ - case Float: - return JmeIosGLES.GL_FLOAT; -// case Double: -// return JmeIosGLES.GL_DOUBLE; - default: - throw new RuntimeException("Unknown buffer format."); - - } - } - - public void clearVertexAttribs() { - IDList attribList = context.attribIndexList; - for (int i = 0; i < attribList.oldLen; i++) { - int idx = attribList.oldList[i]; - - JmeIosGLES.glDisableVertexAttribArray(idx); - JmeIosGLES.checkGLError(); - - context.boundAttribs[idx] = null; - } - context.attribIndexList.copyNewToOld(); - } - - public void updateFrameBuffer(FrameBuffer fb) { - int id = fb.getId(); - if (id == -1) { - // create FBO - JmeIosGLES.glGenFramebuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - id = intBuf1[0]; - fb.setId(id); - objManager.registerObject(fb); - - statistics.onNewFrameBuffer(); - } - - if (context.boundFBO != id) { - JmeIosGLES.glBindFramebuffer(JmeIosGLES.GL_FRAMEBUFFER, id); - JmeIosGLES.checkGLError(); - - // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0 - context.boundDrawBuf = 0; - context.boundFBO = id; - } - - FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer(); - if (depthBuf != null) { - updateFrameBufferAttachment(fb, depthBuf); - } - - for (int i = 0; i < fb.getNumColorBuffers(); i++) { - FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i); - updateFrameBufferAttachment(fb, colorBuf); - } - - fb.clearUpdateNeeded(); - } - - - public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) { - boolean needAttach; - if (rb.getTexture() == null) { - // if it hasn't been created yet, then attach is required. - needAttach = rb.getId() == -1; - updateRenderBuffer(fb, rb); - } else { - needAttach = false; - updateRenderTexture(fb, rb); - } - if (needAttach) { - JmeIosGLES.glFramebufferRenderbuffer(JmeIosGLES.GL_FRAMEBUFFER, - convertAttachmentSlot(rb.getSlot()), - JmeIosGLES.GL_RENDERBUFFER, - rb.getId()); - - JmeIosGLES.checkGLError(); - } - } - - - public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) { - Texture tex = rb.getTexture(); - Image image = tex.getImage(); - if (image.isUpdateNeeded()) { - updateTexImageData(image, tex.getType()); - - // NOTE: For depth textures, sets nearest/no-mips mode - // Required to fix "framebuffer unsupported" - // for old NVIDIA drivers! - setupTextureParams(tex); - } - - JmeIosGLES.glFramebufferTexture2D(JmeIosGLES.GL_FRAMEBUFFER, - convertAttachmentSlot(rb.getSlot()), - convertTextureType(tex.getType()), - image.getId(), - 0); - - JmeIosGLES.checkGLError(); - } - - - private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) { - int id = rb.getId(); - if (id == -1) { - JmeIosGLES.glGenRenderbuffers(1, intBuf1, 0); - JmeIosGLES.checkGLError(); - - id = intBuf1[0]; - rb.setId(id); - } - - if (context.boundRB != id) { - JmeIosGLES.glBindRenderbuffer(JmeIosGLES.GL_RENDERBUFFER, id); - JmeIosGLES.checkGLError(); - - context.boundRB = id; - } - - if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) { - throw new RendererException("Resolution " + fb.getWidth() - + ":" + fb.getHeight() + " is not supported."); - } - - TextureUtil.IosGLImageFormat imageFormat = TextureUtil.getImageFormat(rb.getFormat()); - if (imageFormat.renderBufferStorageFormat == 0) { - throw new RendererException("The format '" + rb.getFormat() + "' cannot be used for renderbuffers."); - } - -// 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 { - JmeIosGLES.glRenderbufferStorage(JmeIosGLES.GL_RENDERBUFFER, - imageFormat.renderBufferStorageFormat, - fb.getWidth(), - fb.getHeight()); - - JmeIosGLES.checkGLError(); - } - } - - - private int convertAttachmentSlot(int attachmentSlot) { - // can also add support for stencil here - if (attachmentSlot == FrameBuffer.SLOT_DEPTH) { - return JmeIosGLES.GL_DEPTH_ATTACHMENT; - } else if (attachmentSlot == 0) { - return JmeIosGLES.GL_COLOR_ATTACHMENT0; - } else { - throw new UnsupportedOperationException("Android does not support multiple color attachments to an FBO"); - } - } - - - private void checkFrameBufferStatus(FrameBuffer fb) { - try { - checkFrameBufferError(); - } catch (IllegalStateException ex) { - logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb); - printRealFrameBufferInfo(fb); - throw ex; - } - } - - private void checkFrameBufferError() { - int status = JmeIosGLES.glCheckFramebufferStatus(JmeIosGLES.GL_FRAMEBUFFER); - switch (status) { - case JmeIosGLES.GL_FRAMEBUFFER_COMPLETE: - break; - case JmeIosGLES.GL_FRAMEBUFFER_UNSUPPORTED: - //Choose different formats - throw new IllegalStateException("Framebuffer object format is " - + "unsupported by the video hardware."); - case JmeIosGLES.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - throw new IllegalStateException("Framebuffer has erronous attachment."); - case JmeIosGLES.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached."); - case JmeIosGLES.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - throw new IllegalStateException("Framebuffer attachments must have same dimensions."); -// 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: " + status); - } - } - - 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? " + JmeIosGLES.glIsRenderbuffer(rb.getId())); - - int attachment = convertAttachmentSlot(rb.getSlot()); - - //intBuf16.clear(); - JmeIosGLES.glGetFramebufferAttachmentParameteriv(JmeIosGLES.GL_FRAMEBUFFER, - attachment, JmeIosGLES.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16, 0); - int type = intBuf16[0]; - - //intBuf16.clear(); - JmeIosGLES.glGetFramebufferAttachmentParameteriv(JmeIosGLES.GL_FRAMEBUFFER, - attachment, JmeIosGLES.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16, 0); - int rbName = intBuf16[0]; - - switch (type) { - case JmeIosGLES.GL_NONE: - System.out.println("Type: None"); - break; - case JmeIosGLES.GL_TEXTURE: - System.out.println("Type: Texture"); - break; - case JmeIosGLES.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? " + JmeIosGLES.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) { - JmeIosGLES.glBindFramebuffer(JmeIosGLES.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); - } - - - } - - public void drawTriangleList_Array(VertexBuffer indexBuf, Mesh mesh, int count) { - if (indexBuf.getBufferType() != VertexBuffer.Type.Index) { - throw new IllegalArgumentException("Only index buffers are allowed as triangle lists."); - } - - boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing); - if (useInstancing) { - throw new IllegalArgumentException("Caps.MeshInstancing is not supported."); - } - - int vertCount = mesh.getVertexCount(); - Buffer indexData = indexBuf.getData(); - indexData.rewind(); - - if (mesh.getMode() == Mode.Hybrid) { - int[] modeStart = mesh.getModeStart(); - int[] elementLengths = mesh.getElementLengths(); - - int elMode = convertElementMode(Mode.Triangles); - int fmt = convertVertexBufferFormat(indexBuf.getFormat()); - int elSize = indexBuf.getFormat().getComponentSize(); - int listStart = modeStart[0]; - int stripStart = modeStart[1]; - int fanStart = modeStart[2]; - int curOffset = 0; - for (int i = 0; i < elementLengths.length; i++) { - if (i == stripStart) { - elMode = convertElementMode(Mode.TriangleStrip); - } else if (i == fanStart) { - elMode = convertElementMode(Mode.TriangleFan); - } - int elementLength = elementLengths[i]; - - indexBuf.getData().position(curOffset); - JmeIosGLES.glDrawElements(elMode, elementLength, fmt, indexBuf.getData()); - JmeIosGLES.checkGLError(); - - curOffset += elementLength * elSize; - } - } else { - JmeIosGLES.glDrawElements( - convertElementMode(mesh.getMode()), - indexBuf.getData().limit(), - convertVertexBufferFormat(indexBuf.getFormat()), - indexBuf.getData()); - JmeIosGLES.checkGLError(); - } - } - - public void setVertexAttrib_Array(VertexBuffer vb, VertexBuffer idb) { - if (vb.getBufferType() == VertexBuffer.Type.Index) { - throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib"); - } - - // Get shader - int programId = context.boundShaderProgram; - if (programId > 0) { - VertexBuffer[] attribs = context.boundAttribs; - - Attribute attrib = boundShader.getAttribute(vb.getBufferType()); - int loc = attrib.getLocation(); - if (loc == -1) { - //throw new IllegalArgumentException("Location is invalid for attrib: [" + vb.getBufferType().name() + "]"); - return; - } else if (loc == -2) { - String attributeName = "in" + vb.getBufferType().name(); - - loc = JmeIosGLES.glGetAttribLocation(programId, attributeName); - JmeIosGLES.checkGLError(); - - if (loc < 0) { - attrib.setLocation(-1); - return; // not available in shader. - } else { - attrib.setLocation(loc); - } - - } // if (loc == -2) - - if ((attribs[loc] != vb) || vb.isUpdateNeeded()) { - // NOTE: Use data from interleaved buffer if specified - VertexBuffer avb = idb != null ? idb : vb; - avb.getData().rewind(); - avb.getData().position(vb.getOffset()); - - // Upload attribute data - JmeIosGLES.glVertexAttribPointer(loc, - vb.getNumComponents(), - convertVertexBufferFormat(vb.getFormat()), - vb.isNormalized(), - vb.getStride(), - avb.getData()); - - JmeIosGLES.checkGLError(); - - JmeIosGLES.glEnableVertexAttribArray(loc); - JmeIosGLES.checkGLError(); - - attribs[loc] = vb; - } // if (attribs[loc] != vb) - } else { - throw new IllegalStateException("Cannot render mesh without shader bound"); - } - } - - public void setVertexAttrib_Array(VertexBuffer vb) { - setVertexAttrib_Array(vb, null); - } - - - public void updateShaderSourceData(ShaderSource source) { - int id = source.getId(); - if (id == -1) { - // Create id - id = JmeIosGLES.glCreateShader(convertShaderType(source.getType())); - JmeIosGLES.checkGLError(); - - if (id <= 0) { - throw new RendererException("Invalid ID received when trying to create shader."); - } - source.setId(id); - } - - if (!source.getLanguage().equals("GLSL100")) { - throw new RendererException("This shader cannot run in OpenGL ES. " - + "Only GLSL 1.0 shaders are supported."); - } - - // upload shader source - // merge the defines and source code - byte[] definesCodeData = source.getDefines().getBytes(); - byte[] sourceCodeData = source.getSource().getBytes(); - ByteBuffer codeBuf = BufferUtils.createByteBuffer(definesCodeData.length - + sourceCodeData.length); - codeBuf.put(definesCodeData); - codeBuf.put(sourceCodeData); - codeBuf.flip(); - - if (powerVr && source.getType() == ShaderType.Vertex) { - // XXX: This is to fix a bug in old PowerVR, remove - // when no longer applicable. - JmeIosGLES.glShaderSource( - id, source.getDefines() - + source.getSource()); - } else { - String precision =""; - if (source.getType() == ShaderType.Fragment) { - precision = "precision mediump float;\n"; - } - JmeIosGLES.glShaderSource( - id, - precision - +source.getDefines() - + source.getSource()); - } -// int range[] = new int[2]; -// int precision[] = new int[1]; -// GLES20.glGetShaderPrecisionFormat(GLES20.GL_VERTEX_SHADER, GLES20.GL_HIGH_FLOAT, range, 0, precision, 0); -// System.out.println("PRECISION HIGH FLOAT VERTEX"); -// System.out.println("range "+range[0]+"," +range[1]); -// System.out.println("precision "+precision[0]); - - JmeIosGLES.glCompileShader(id); - JmeIosGLES.checkGLError(); - - JmeIosGLES.glGetShaderiv(id, JmeIosGLES.GL_COMPILE_STATUS, intBuf1, 0); - JmeIosGLES.checkGLError(); - - boolean compiledOK = intBuf1[0] == JmeIosGLES.GL_TRUE; - String infoLog = null; - - if (VALIDATE_SHADER || !compiledOK) { - // even if compile succeeded, check - // log for warnings - JmeIosGLES.glGetShaderiv(id, JmeIosGLES.GL_INFO_LOG_LENGTH, intBuf1, 0); - JmeIosGLES.checkGLError(); - infoLog = JmeIosGLES.glGetShaderInfoLog(id); - } - - if (compiledOK) { - if (infoLog != null) { - logger.log(Level.FINE, "compile success: {0}, {1}", new Object[]{source.getName(), infoLog}); - } else { - logger.log(Level.FINE, "compile success: {0}", source.getName()); - } - source.clearUpdateNeeded(); - } else { - logger.log(Level.WARNING, "Bad compile of:\n{0}", - new Object[]{ShaderDebug.formatShaderSource(stringBuf.toString() + source.getDefines() + source.getSource())}); - if (infoLog != null) { - throw new RendererException("compile error in: " + source + "\n" + infoLog); - } else { - throw new RendererException("compile error in: " + source + "\nerror: "); - } - } - } - - - public int convertShaderType(ShaderType type) { - switch (type) { - case Fragment: - return JmeIosGLES.GL_FRAGMENT_SHADER; - case Vertex: - return JmeIosGLES.GL_VERTEX_SHADER; -// case Geometry: -// return ARBGeometryShader4.GL_GEOMETRY_SHADER_ARB; - default: - throw new RuntimeException("Unrecognized shader type."); - } - } - - private int convertTestFunction(RenderState.TestFunction testFunc) { - switch (testFunc) { - case Never: - return JmeIosGLES.GL_NEVER; - case Less: - return JmeIosGLES.GL_LESS; - case LessOrEqual: - return JmeIosGLES.GL_LEQUAL; - case Greater: - return JmeIosGLES.GL_GREATER; - case GreaterOrEqual: - return JmeIosGLES.GL_GEQUAL; - case Equal: - return JmeIosGLES.GL_EQUAL; - case NotEqual: - return JmeIosGLES.GL_NOTEQUAL; - case Always: - return JmeIosGLES.GL_ALWAYS; - default: - throw new UnsupportedOperationException("Unrecognized test function: " + testFunc); - } - } - - public void setMainFrameBufferSrgb(boolean srgb) { - - } - - public void setLinearizeSrgbImages(boolean linearize) { - - } - - public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { - throw new UnsupportedOperationException("Not supported yet. URA will make that work seamlessly"); - } -} \ No newline at end of file diff --git a/jme3-ios/src/main/java/com/jme3/renderer/ios/TextureUtil.java b/jme3-ios/src/main/java/com/jme3/renderer/ios/TextureUtil.java deleted file mode 100644 index d11308c2a..000000000 --- a/jme3-ios/src/main/java/com/jme3/renderer/ios/TextureUtil.java +++ /dev/null @@ -1,576 +0,0 @@ -package com.jme3.renderer.ios; - -//import android.graphics.Bitmap; -//import android.opengl.ETC1; -//import android.opengl.ETC1Util.ETC1Texture; -//import android.opengl.JmeIosGLES; -//import android.opengl.GLUtils; -//import com.jme3.asset.AndroidImageInfo; -import com.jme3.renderer.ios.JmeIosGLES; -import com.jme3.math.FastMath; -import com.jme3.renderer.RendererException; -import com.jme3.texture.Image; -import com.jme3.texture.Image.Format; -import com.jme3.util.BufferUtils; -import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class TextureUtil { - - private static final Logger logger = Logger.getLogger(TextureUtil.class.getName()); - //TODO Make this configurable through appSettings - public static boolean ENABLE_COMPRESSION = true; - private static boolean NPOT = false; - private static boolean ETC1support = false; - private static boolean DXT1 = false; - private static boolean PVRTC = false; - private static boolean DEPTH24_STENCIL8 = false; - private static boolean DEPTH_TEXTURE = false; - private static boolean RGBA8 = false; - - // Same constant used by both GL_ARM_rgba8 and GL_OES_rgb8_rgba8. - private static final int GL_RGBA8 = 0x8058; - - private static final int GL_DXT1 = 0x83F0; - private static final int GL_DXT1A = 0x83F1; - - private static final int GL_DEPTH_STENCIL_OES = 0x84F9; - private static final int GL_UNSIGNED_INT_24_8_OES = 0x84FA; - private static final int GL_DEPTH24_STENCIL8_OES = 0x88F0; - - public static void loadTextureFeatures(String extensionString) { - ETC1support = extensionString.contains("GL_OES_compressed_ETC1_RGB8_texture"); - DEPTH24_STENCIL8 = extensionString.contains("GL_OES_packed_depth_stencil"); - NPOT = extensionString.contains("GL_IMG_texture_npot") - || extensionString.contains("GL_OES_texture_npot") - || extensionString.contains("GL_NV_texture_npot_2D_mipmap"); - - PVRTC = extensionString.contains("GL_IMG_texture_compression_pvrtc"); - - DXT1 = extensionString.contains("GL_EXT_texture_compression_dxt1"); - DEPTH_TEXTURE = extensionString.contains("GL_OES_depth_texture"); - - RGBA8 = extensionString.contains("GL_ARM_rgba8") || - extensionString.contains("GL_OES_rgb8_rgba8"); - - logger.log(Level.FINE, "Supports ETC1? {0}", ETC1support); - logger.log(Level.FINE, "Supports DEPTH24_STENCIL8? {0}", DEPTH24_STENCIL8); - logger.log(Level.FINE, "Supports NPOT? {0}", NPOT); - logger.log(Level.FINE, "Supports PVRTC? {0}", PVRTC); - logger.log(Level.FINE, "Supports DXT1? {0}", DXT1); - logger.log(Level.FINE, "Supports DEPTH_TEXTURE? {0}", DEPTH_TEXTURE); - logger.log(Level.FINE, "Supports RGBA8? {0}", RGBA8); - } - - /* - private static void buildMipmap(Bitmap bitmap, boolean compress) { - int level = 0; - int height = bitmap.getHeight(); - int width = bitmap.getWidth(); - - logger.log(Level.FINEST, " - Generating mipmaps for bitmap using SOFTWARE"); - - JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1); - - while (height >= 1 || width >= 1) { - //First of all, generate the texture from our bitmap and set it to the according level - if (compress) { - logger.log(Level.FINEST, " - Uploading LOD level {0} ({1}x{2}) with compression.", new Object[]{level, width, height}); - uploadBitmapAsCompressed(JmeIosGLES.GL_TEXTURE_2D, level, bitmap, false, 0, 0); - } else { - logger.log(Level.FINEST, " - Uploading LOD level {0} ({1}x{2}) directly.", new Object[]{level, width, height}); - GLUtils.texImage2D(JmeIosGLES.GL_TEXTURE_2D, level, bitmap, 0); - } - - if (height == 1 || width == 1) { - break; - } - - //Increase the mipmap level - height /= 2; - width /= 2; - Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true); - - // Recycle any bitmaps created as a result of scaling the bitmap. - // Do not recycle the original image (mipmap level 0) - if (level != 0) { - bitmap.recycle(); - } - - bitmap = bitmap2; - - level++; - } - } - - private static void uploadBitmapAsCompressed(int target, int level, Bitmap bitmap, boolean subTexture, int x, int y) { - if (bitmap.hasAlpha()) { - logger.log(Level.FINEST, " - Uploading bitmap directly. Cannot compress as alpha present."); - if (subTexture) { - GLUtils.texSubImage2D(target, level, x, y, bitmap); - JmeIosGLES.checkGLError(); - } else { - GLUtils.texImage2D(target, level, bitmap, 0); - JmeIosGLES.checkGLError(); - } - } else { - // Convert to RGB565 - int bytesPerPixel = 2; - Bitmap rgb565 = bitmap.copy(Bitmap.Config.RGB_565, true); - - // Put texture data into ByteBuffer - ByteBuffer inputImage = BufferUtils.createByteBuffer(bitmap.getRowBytes() * bitmap.getHeight()); - rgb565.copyPixelsToBuffer(inputImage); - inputImage.position(0); - - // Delete the copied RGB565 image - rgb565.recycle(); - - // Encode the image into the output bytebuffer - int encodedImageSize = ETC1.getEncodedDataSize(bitmap.getWidth(), bitmap.getHeight()); - ByteBuffer compressedImage = BufferUtils.createByteBuffer(encodedImageSize); - ETC1.encodeImage(inputImage, bitmap.getWidth(), - bitmap.getHeight(), - bytesPerPixel, - bytesPerPixel * bitmap.getWidth(), - compressedImage); - - // Delete the input image buffer - BufferUtils.destroyDirectBuffer(inputImage); - - // Create an ETC1Texture from the compressed image data - ETC1Texture etc1tex = new ETC1Texture(bitmap.getWidth(), bitmap.getHeight(), compressedImage); - - // Upload the ETC1Texture - if (bytesPerPixel == 2) { - int oldSize = (bitmap.getRowBytes() * bitmap.getHeight()); - int newSize = compressedImage.capacity(); - logger.log(Level.FINEST, " - Uploading compressed image to GL, oldSize = {0}, newSize = {1}, ratio = {2}", new Object[]{oldSize, newSize, (float) oldSize / newSize}); - if (subTexture) { - JmeIosGLES.glCompressedTexSubImage2D(target, - level, - x, y, - bitmap.getWidth(), - bitmap.getHeight(), - ETC1.ETC1_RGB8_OES, - etc1tex.getData().capacity(), - etc1tex.getData()); - - JmeIosGLES.checkGLError(); - } else { - JmeIosGLES.glCompressedTexImage2D(target, - level, - ETC1.ETC1_RGB8_OES, - bitmap.getWidth(), - bitmap.getHeight(), - 0, - etc1tex.getData().capacity(), - etc1tex.getData()); - - JmeIosGLES.checkGLError(); - } - -// ETC1Util.loadTexture(target, level, 0, JmeIosGLES.GL_RGB, -// JmeIosGLES.GL_UNSIGNED_SHORT_5_6_5, etc1Texture); -// } else if (bytesPerPixel == 3) { -// ETC1Util.loadTexture(target, level, 0, JmeIosGLES.GL_RGB, -// JmeIosGLES.GL_UNSIGNED_BYTE, etc1Texture); - } - - BufferUtils.destroyDirectBuffer(compressedImage); - } - } - - /** - * uploadTextureBitmap uploads a native android bitmap - */ - /* - public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips) { - uploadTextureBitmap(target, bitmap, needMips, false, 0, 0); - } - - /** - * uploadTextureBitmap uploads a native android bitmap - */ - /* - public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips, boolean subTexture, int x, int y) { - boolean recycleBitmap = false; - //TODO, maybe this should raise an exception when NPOT is not supported - - boolean willCompress = ENABLE_COMPRESSION && ETC1support && !bitmap.hasAlpha(); - if (needMips && willCompress) { - // Image is compressed and mipmaps are desired, generate them - // using software. - buildMipmap(bitmap, willCompress); - } else { - if (willCompress) { - // Image is compressed but mipmaps are not desired, upload directly. - logger.log(Level.FINEST, " - Uploading compressed bitmap. Mipmaps are not generated."); - uploadBitmapAsCompressed(target, 0, bitmap, subTexture, x, y); - - } else { - // Image is not compressed, mipmaps may or may not be desired. - logger.log(Level.FINEST, " - Uploading bitmap directly.{0}", - (needMips - ? " Mipmaps will be generated in HARDWARE" - : " Mipmaps are not generated.")); - if (subTexture) { - System.err.println("x : " + x + " y :" + y + " , " + bitmap.getWidth() + "/" + bitmap.getHeight()); - GLUtils.texSubImage2D(target, 0, x, y, bitmap); - JmeIosGLES.checkGLError(); - } else { - GLUtils.texImage2D(target, 0, bitmap, 0); - JmeIosGLES.checkGLError(); - } - - if (needMips) { - // No pregenerated mips available, - // generate from base level if required - JmeIosGLES.glGenerateMipmap(target); - JmeIosGLES.checkGLError(); - } - } - } - - if (recycleBitmap) { - bitmap.recycle(); - } - } - */ - - public static void uploadTextureAny(Image img, int target, int index, boolean needMips) { - /* - if (img.getEfficentData() instanceof AndroidImageInfo) { - logger.log(Level.FINEST, " === Uploading image {0}. Using BITMAP PATH === ", img); - // If image was loaded from asset manager, use fast path - AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData(); - uploadTextureBitmap(target, imageInfo.getBitmap(), needMips); - } else { - */ - logger.log(Level.FINEST, " === Uploading image {0}. Using BUFFER PATH === ", img); - boolean wantGeneratedMips = needMips && !img.hasMipmaps(); - if (wantGeneratedMips && img.getFormat().isCompressed()) { - logger.log(Level.WARNING, "Generating mipmaps is only" - + " supported for Bitmap based or non-compressed images!"); - } - - // Upload using slower path - logger.log(Level.FINEST, " - Uploading bitmap directly.{0}", - (wantGeneratedMips - ? " Mipmaps will be generated in HARDWARE" - : " Mipmaps are not generated.")); - - uploadTexture(img, target, index); - - // Image was uploaded using slower path, since it is not compressed, - // then compress it - if (wantGeneratedMips) { - // No pregenerated mips available, - // generate from base level if required - JmeIosGLES.glGenerateMipmap(target); - JmeIosGLES.checkGLError(); - } - //} - } - - private static void unsupportedFormat(Format fmt) { - throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware."); - } - - public static IosGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException { - IosGLImageFormat imageFormat = new IosGLImageFormat(); - switch (fmt) { - case Depth32: - case Depth32F: - throw new UnsupportedOperationException("The image format '" - + fmt + "' is not supported by OpenGL ES 2.0 specification."); - case Alpha8: - imageFormat.format = JmeIosGLES.GL_ALPHA; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - if (RGBA8) { - imageFormat.renderBufferStorageFormat = GL_RGBA8; - } else { - // Highest precision alpha supported by vanilla OGLES2 - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4; - } - break; - case Luminance8: - imageFormat.format = JmeIosGLES.GL_LUMINANCE; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - if (RGBA8) { - imageFormat.renderBufferStorageFormat = GL_RGBA8; - } else { - // Highest precision luminance supported by vanilla OGLES2 - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; - } - break; - case Luminance8Alpha8: - imageFormat.format = JmeIosGLES.GL_LUMINANCE_ALPHA; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - if (RGBA8) { - imageFormat.renderBufferStorageFormat = GL_RGBA8; - } else { - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4; - } - break; - case RGB565: - imageFormat.format = JmeIosGLES.GL_RGB; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT_5_6_5; - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; - break; - case RGB5A1: - imageFormat.format = JmeIosGLES.GL_RGBA; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT_5_5_5_1; - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB5_A1; - break; - case RGB8: - imageFormat.format = JmeIosGLES.GL_RGB; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - if (RGBA8) { - imageFormat.renderBufferStorageFormat = GL_RGBA8; - } else { - // Fallback: Use RGB565 if RGBA8 is not available. - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; - } - break; - case BGR8: - imageFormat.format = JmeIosGLES.GL_RGB; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - if (RGBA8) { - imageFormat.renderBufferStorageFormat = GL_RGBA8; - } else { - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; - } - break; - case RGBA8: - imageFormat.format = JmeIosGLES.GL_RGBA; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - if (RGBA8) { - imageFormat.renderBufferStorageFormat = GL_RGBA8; - } else { - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4; - } - break; - case Depth: - case Depth16: - if (!DEPTH_TEXTURE) { - unsupportedFormat(fmt); - } - imageFormat.format = JmeIosGLES.GL_DEPTH_COMPONENT; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT; - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_DEPTH_COMPONENT16; - break; - case Depth24: - case Depth24Stencil8: - if (!DEPTH_TEXTURE) { - unsupportedFormat(fmt); - } - if (DEPTH24_STENCIL8) { - // NEW: True Depth24 + Stencil8 format. - imageFormat.format = GL_DEPTH_STENCIL_OES; - imageFormat.dataType = GL_UNSIGNED_INT_24_8_OES; - imageFormat.renderBufferStorageFormat = GL_DEPTH24_STENCIL8_OES; - } else { - // Vanilla OGLES2, only Depth16 available. - imageFormat.format = JmeIosGLES.GL_DEPTH_COMPONENT; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT; - imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_DEPTH_COMPONENT16; - } - break; - case DXT1: - if (!DXT1) { - unsupportedFormat(fmt); - } - imageFormat.format = GL_DXT1; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - imageFormat.compress = true; - break; - case DXT1A: - if (!DXT1) { - unsupportedFormat(fmt); - } - imageFormat.format = GL_DXT1A; - imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; - imageFormat.compress = true; - break; - default: - throw new UnsupportedOperationException("Unrecognized format: " + fmt); - } - return imageFormat; - } - - public static class IosGLImageFormat { - - boolean compress = false; - int format = -1; - int renderBufferStorageFormat = -1; - int dataType = -1; - } - - private static void uploadTexture(Image img, - int target, - int index) { - - /* - if (img.getEfficentData() instanceof AndroidImageInfo) { - throw new RendererException("This image uses efficient data. " - + "Use uploadTextureBitmap instead."); - } - */ - - // Otherwise upload image directly. - // Prefer to only use power of 2 textures here to avoid errors. - Image.Format fmt = img.getFormat(); - ByteBuffer data; - if (index >= 0 || img.getData() != null && img.getData().size() > 0) { - data = img.getData(index); - } else { - data = null; - } - - int width = img.getWidth(); - int height = img.getHeight(); - - if (!NPOT && img.isNPOT()) { - // Check if texture is POT - throw new RendererException("Non-power-of-2 textures " - + "are not supported by the video hardware " - + "and no scaling path available for image: " + img); - } - IosGLImageFormat imageFormat = getImageFormat(fmt); - - if (data != null) { - JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1); - JmeIosGLES.checkGLError(); - } - - int[] mipSizes = img.getMipMapSizes(); - int pos = 0; - if (mipSizes == null) { - if (data != null) { - mipSizes = new int[]{data.capacity()}; - } else { - mipSizes = new int[]{width * height * fmt.getBitsPerPixel() / 8}; - } - } - - for (int i = 0; i < mipSizes.length; i++) { - int mipWidth = Math.max(1, width >> i); - int mipHeight = Math.max(1, height >> i); - - if (data != null) { - data.position(pos); - data.limit(pos + mipSizes[i]); - } - - if (imageFormat.compress && data != null) { - JmeIosGLES.glCompressedTexImage2D(target, - i, - imageFormat.format, - mipWidth, - mipHeight, - 0, - data.remaining(), - data); - } else { - JmeIosGLES.glTexImage2D(target, - i, - imageFormat.format, - mipWidth, - mipHeight, - 0, - imageFormat.format, - imageFormat.dataType, - data); - } - JmeIosGLES.checkGLError(); - - pos += mipSizes[i]; - } - } - - /** - * Update the texture currently bound to target at with data from the given - * Image at position x and y. The parameter index is used as the zoffset in - * case a 3d texture or texture 2d array is being updated. - * - * @param image Image with the source data (this data will be put into the - * texture) - * @param target the target texture - * @param index the mipmap level to update - * @param x the x position where to put the image in the texture - * @param y the y position where to put the image in the texture - */ - public static void uploadSubTexture( - Image img, - int target, - int index, - int x, - int y) { - //TODO: - /* - if (img.getEfficentData() instanceof AndroidImageInfo) { - AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData(); - uploadTextureBitmap(target, imageInfo.getBitmap(), true, true, x, y); - return; - } - */ - - // Otherwise upload image directly. - // Prefer to only use power of 2 textures here to avoid errors. - Image.Format fmt = img.getFormat(); - ByteBuffer data; - if (index >= 0 || img.getData() != null && img.getData().size() > 0) { - data = img.getData(index); - } else { - data = null; - } - - int width = img.getWidth(); - int height = img.getHeight(); - - if (!NPOT && img.isNPOT()) { - // Check if texture is POT - throw new RendererException("Non-power-of-2 textures " - + "are not supported by the video hardware " - + "and no scaling path available for image: " + img); - } - IosGLImageFormat imageFormat = getImageFormat(fmt); - - if (data != null) { - JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1); - JmeIosGLES.checkGLError(); - } - - int[] mipSizes = img.getMipMapSizes(); - int pos = 0; - if (mipSizes == null) { - if (data != null) { - mipSizes = new int[]{data.capacity()}; - } else { - mipSizes = new int[]{width * height * fmt.getBitsPerPixel() / 8}; - } - } - - for (int i = 0; i < mipSizes.length; i++) { - int mipWidth = Math.max(1, width >> i); - int mipHeight = Math.max(1, height >> i); - - if (data != null) { - data.position(pos); - data.limit(pos + mipSizes[i]); - } - - if (imageFormat.compress && data != null) { - JmeIosGLES.glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, data.remaining(), data); - JmeIosGLES.checkGLError(); - } else { - JmeIosGLES.glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, imageFormat.dataType, data); - JmeIosGLES.checkGLError(); - } - - pos += mipSizes[i]; - } - } -} diff --git a/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg b/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg index 4e4052447..e9d79a459 100644 --- a/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg +++ b/jme3-ios/src/main/resources/com/jme3/asset/IOS.cfg @@ -2,7 +2,9 @@ INCLUDE com/jme3/asset/General.cfg # IOS specific loaders LOADER com.jme3.system.ios.IosImageLoader : jpg, bmp, gif, png, jpeg -LOADER com.jme3.material.plugins.J3MLoader : j3m, j3md +LOADER com.jme3.audio.plugins.OGGLoader : ogg +LOADER com.jme3.material.plugins.J3MLoader : j3m +LOADER com.jme3.material.plugins.J3MLoader : j3md LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib LOADER com.jme3.export.binary.BinaryImporter : j3o LOADER com.jme3.font.plugins.BitmapFontLoader : fnt