159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.renderer.lwjgl;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.light.LightList;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState.StencilOperation;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState.TestFunction;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.*;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.*;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh.Mode;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Format;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Usage;
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Attribute;
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Shader;
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Shader.ShaderSource;
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Shader.ShaderType;
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.Uniform;
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.FrameBuffer;
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.FrameBuffer.RenderBuffer;
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Image;
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture;
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture.WrapAxis;
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils;
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.IntMap;
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.IntMap.Entry;
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.ListMap;
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.NativeObjectManager;
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.SafeArrayList;
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.*;
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.EnumSet;
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List;
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level;
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger;
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport jme3tools.converters.MipMapGenerator;
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.ARBTextureMultisample.*;
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.EXTFramebufferBlit.*;
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.EXTFramebufferMultisample.*;
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.EXTFramebufferObject.*;
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL11.*;
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL12.*;
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL13.*;
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL14.*;
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL15.*;
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.opengl.GL20.*;
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport org.lwjgl.opengl.*;
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//import static org.lwjgl.opengl.ARBDrawInstanced.*;
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class LwjglRenderer implements Renderer {
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final Logger logger = Logger.getLogger(LwjglRenderer.class.getName());
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final boolean VALIDATE_SHADER = false;
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final StringBuilder stringBuf = new StringBuilder(250);
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1);
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16);
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final RenderContext context = new RenderContext();
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final NativeObjectManager objManager = new NativeObjectManager();
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // current state
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Shader boundShader;
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int initialDrawBuf, initialReadBuf;
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int glslVer;
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int vertexTextureUnits;
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int fragTextureUnits;
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int vertexUniforms;
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int fragUniforms;
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int vertexAttribs;
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxFBOSamples;
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxFBOAttachs;
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxMRTFBOAttachs;
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxRBSize;
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxTexSize;
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxCubeTexSize;
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxVertCount;
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxTriCount;
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxColorTexSamples;
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int maxDepthTexSamples;
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean tdc;
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private FrameBuffer lastFb = null;
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private FrameBuffer mainFbOverride = null;
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private final Statistics statistics = new Statistics();
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int vpX, vpY, vpW, vpH;
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int clipX, clipY, clipW, clipH;
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public LwjglRenderer() {
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void updateNameBuffer() {
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int len = stringBuf.length();
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        nameBuf.position(0);
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        nameBuf.limit(len);
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < len; i++) {
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            nameBuf.put((byte) stringBuf.charAt(i));
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        nameBuf.rewind();
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Statistics getStatistics() {
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return statistics;
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public EnumSet<Caps> getCaps() {
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return caps;
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @SuppressWarnings("fallthrough")
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void initialize() {
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ContextCapabilities ctxCaps = GLContext.getCapabilities();
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.OpenGL20) {
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.OpenGL20);
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.OpenGL21) {
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.OpenGL21);
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (ctxCaps.OpenGL30) {
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    caps.add(Caps.OpenGL30);
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (ctxCaps.OpenGL31) {
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        caps.add(Caps.OpenGL31);
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        if (ctxCaps.OpenGL32) {
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            caps.add(Caps.OpenGL32);
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String versionStr = null;
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.OpenGL20) {
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            versionStr = glGetString(GL_SHADING_LANGUAGE_VERSION);
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (versionStr == null || versionStr.equals("")) {
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glslVer = -1;
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new UnsupportedOperationException("GLSL and OpenGL2 is "
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    + "required for the LWJGL "
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    + "renderer!");
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Fix issue in TestRenderToMemory when GL_FRONT is the main
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // buffer being used.
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialReadBuf = glGetInteger(GL_READ_BUFFER);
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // XXX: This has to be GL_BACK for canvas on Mac
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Since initialDrawBuf is GL_FRONT for pbuffer, gotta
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // change this value later on ...
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        initialDrawBuf = GL_BACK;
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        initialReadBuf = GL_BACK;
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int spaceIdx = versionStr.indexOf(" ");
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spaceIdx >= 1) {
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            versionStr = versionStr.substring(0, spaceIdx);
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float version = Float.parseFloat(versionStr);
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glslVer = (int) (version * 100);
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (glslVer) {
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (glslVer < 400) {
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // so that future OpenGL revisions wont break jme3
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // fall through intentional
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 400:
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 330:
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 150:
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.GLSL150);
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 140:
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.GLSL140);
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 130:
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.GLSL130);
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 120:
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.GLSL120);
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 110:
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.GLSL110);
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case 100:
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.GLSL100);
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!caps.contains(Caps.GLSL100)) {
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.WARNING, "Force-adding GLSL100 support, since OpenGL2 is supported.");
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.GLSL100);
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16);
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vertexTextureUnits = intBuf16.get(0);
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits);
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vertexTextureUnits > 0) {
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.VertexTextureFetch);
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16);
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fragTextureUnits = intBuf16.get(0);
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Texture Units: {0}", fragTextureUnits);
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16);
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vertexUniforms = intBuf16.get(0);
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms);
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16);
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fragUniforms = intBuf16.get(0);
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms);
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_VERTEX_ATTRIBS, intBuf16);
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vertexAttribs = intBuf16.get(0);
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Vertex Attributes: {0}", vertexAttribs);
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_SUBPIXEL_BITS, intBuf16);
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int subpixelBits = intBuf16.get(0);
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Subpixel Bits: {0}", subpixelBits);
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_ELEMENTS_VERTICES, intBuf16);
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        maxVertCount = intBuf16.get(0);
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount);
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_ELEMENTS_INDICES, intBuf16);
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        maxTriCount = intBuf16.get(0);
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount);
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_TEXTURE_SIZE, intBuf16);
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        maxTexSize = intBuf16.get(0);
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Maximum Texture Resolution: {0}", maxTexSize);
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetInteger(GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16);
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        maxCubeTexSize = intBuf16.get(0);
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize);
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_color_buffer_float) {
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.GL_ARB_half_float_pixel) {
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.FloatColorBuffer);
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_depth_buffer_float) {
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.FloatDepthBuffer);
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_draw_instanced) {
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.MeshInstancing);
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_fragment_program) {
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.ARBprogram);
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_texture_buffer_object) {
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.TextureBuffer);
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_texture_float) {
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.GL_ARB_half_float_pixel) {
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.FloatTexture);
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_vertex_array_object) {
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.VertexBufferArray);
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_texture_non_power_of_two) {
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.NonPowerOfTwoTextures);
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.WARNING, "Your graphics card does not "
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    + "support non-power-of-2 textures. "
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    + "Some features might not work.");
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean latc = ctxCaps.GL_EXT_texture_compression_latc;
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean atdc = ctxCaps.GL_ATI_texture_compression_3dc;
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (latc || atdc) {
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.TextureCompressionLATC);
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (atdc && !latc) {
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tdc = true;
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_EXT_packed_float) {
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.PackedFloatColorBuffer);
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.GL_ARB_half_float_pixel) {
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // because textures are usually uploaded as RGB16F
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // need half-float pixel
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.PackedFloatTexture);
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_EXT_texture_array) {
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.TextureArray);
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_EXT_texture_shared_exponent) {
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.SharedExponentTexture);
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_EXT_framebuffer_object) {
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            caps.add(Caps.FrameBuffer);
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16);
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            maxRBSize = intBuf16.get(0);
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetInteger(GL_MAX_COLOR_ATTACHMENTS_EXT, intBuf16);
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            maxFBOAttachs = intBuf16.get(0);
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs);
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.GL_EXT_framebuffer_multisample) {
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.FrameBufferMultisample);
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16);
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxFBOSamples = intBuf16.get(0);
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples);
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.GL_ARB_texture_multisample) {
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.TextureMultisample);
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGetInteger(GL_MAX_COLOR_TEXTURE_SAMPLES, intBuf16);
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxColorTexSamples = intBuf16.get(0);
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.FINER, "Texture Multisample Color Samples: {0}", maxColorTexSamples);
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGetInteger(GL_MAX_DEPTH_TEXTURE_SAMPLES, intBuf16);
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxDepthTexSamples = intBuf16.get(0);
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples);
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (ctxCaps.GL_ARB_draw_buffers) {
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                caps.add(Caps.FrameBufferMRT);
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16);
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                maxMRTFBOAttachs = intBuf16.get(0);
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (ctxCaps.GL_ARB_multisample) {
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetInteger(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, intBuf16);
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            boolean available = intBuf16.get(0) != 0;
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetInteger(ARBMultisample.GL_SAMPLES_ARB, intBuf16);
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int samples = intBuf16.get(0);
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.FINER, "Samples: {0}", samples);
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            boolean enabled = glIsEnabled(ARBMultisample.GL_MULTISAMPLE_ARB);
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (samples > 0 && available && !enabled) {
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(ARBMultisample.GL_MULTISAMPLE_ARB);
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.INFO, "Caps: {0}", caps);
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void invalidateState() {
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        context.reset();
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boundShader = null;
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        lastFb = null;
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        initialReadBuf = glGetInteger(GL_READ_BUFFER);
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void resetGLObjects() {
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.INFO, "Reseting objects and invalidating state");
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        objManager.resetObjects();
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        statistics.clearMemory();
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        invalidateState();
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void cleanup() {
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.INFO, "Deleting objects and invalidating state");
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        objManager.deleteAllObjects(this);
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        statistics.clearMemory();
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        invalidateState();
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void checkCap(Caps cap) {
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!caps.contains(cap)) {
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new UnsupportedOperationException("Required capability missing: " + cap.name());
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Render State                                                      *|
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setDepthRange(float start, float end) {
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glDepthRange(start, end);
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void clearBuffers(boolean color, boolean depth, boolean stencil) {
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int bits = 0;
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (color) {
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //See explanations of the depth below, we must enable color write to be able to clear the color buffer
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.colorWriteEnabled == false) {
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glColorMask(true, true, true, true);
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.colorWriteEnabled = true;
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            bits = GL_COLOR_BUFFER_BIT;
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (depth) {
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //glClear(GL_DEPTH_BUFFER_BIT) seems to not work when glDepthMask is false
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //here s some link on openl board
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=257223
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //if depth clear is requested, we enable the depthMask
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.depthWriteEnabled == false) {
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDepthMask(true);
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.depthWriteEnabled = true;
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            bits |= GL_DEPTH_BUFFER_BIT;
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (stencil) {
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            bits |= GL_STENCIL_BUFFER_BIT;
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (bits != 0) {
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glClear(bits);
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setBackgroundColor(ColorRGBA color) {
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glClearColor(color.r, color.g, color.b, color.a);
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setAlphaToCoverage(boolean value) {
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (value) {
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glEnable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDisable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void applyRenderState(RenderState state) {
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isWireframe() && !context.wireframe) {
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.wireframe = true;
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (!state.isWireframe() && context.wireframe) {
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.wireframe = false;
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isDepthTest() && !context.depthTestEnabled) {
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glEnable(GL_DEPTH_TEST);
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDepthFunc(GL_LEQUAL);
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.depthTestEnabled = true;
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (!state.isDepthTest() && context.depthTestEnabled) {
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDisable(GL_DEPTH_TEST);
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.depthTestEnabled = false;
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isAlphaTest() && !context.alphaTestEnabled) {
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glEnable(GL_ALPHA_TEST);
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glAlphaFunc(GL_GREATER, state.getAlphaFallOff());
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.alphaTestEnabled = true;
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (!state.isAlphaTest() && context.alphaTestEnabled) {
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDisable(GL_ALPHA_TEST);
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.alphaTestEnabled = false;
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isDepthWrite() && !context.depthWriteEnabled) {
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDepthMask(true);
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.depthWriteEnabled = true;
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (!state.isDepthWrite() && context.depthWriteEnabled) {
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDepthMask(false);
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.depthWriteEnabled = false;
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isColorWrite() && !context.colorWriteEnabled) {
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glColorMask(true, true, true, true);
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.colorWriteEnabled = true;
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (!state.isColorWrite() && context.colorWriteEnabled) {
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glColorMask(false, false, false, false);
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.colorWriteEnabled = false;
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isPointSprite() && !context.pointSprite) {
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // Only enable/disable sprite
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundTextures[0] != null){
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (context.boundTextureUnit != 0){
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glActiveTexture(GL_TEXTURE0);
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.boundTextureUnit = 0;
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(GL_POINT_SPRITE);
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.pointSprite = true;
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (!state.isPointSprite() && context.pointSprite) {
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundTextures[0] != null){
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (context.boundTextureUnit != 0){
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glActiveTexture(GL_TEXTURE0);
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.boundTextureUnit = 0;
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_POINT_SPRITE);
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.pointSprite = false;
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.isPolyOffset()) {
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!context.polyOffsetEnabled) {
53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(GL_POLYGON_OFFSET_FILL);
53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glPolygonOffset(state.getPolyOffsetFactor(),
53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        state.getPolyOffsetUnits());
53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.polyOffsetEnabled = true;
53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.polyOffsetFactor = state.getPolyOffsetFactor();
53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.polyOffsetUnits = state.getPolyOffsetUnits();
53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (state.getPolyOffsetFactor() != context.polyOffsetFactor
53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        || state.getPolyOffsetUnits() != context.polyOffsetUnits) {
54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glPolygonOffset(state.getPolyOffsetFactor(),
54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            state.getPolyOffsetUnits());
54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.polyOffsetFactor = state.getPolyOffsetFactor();
54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.polyOffsetUnits = state.getPolyOffsetUnits();
54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.polyOffsetEnabled) {
54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_POLYGON_OFFSET_FILL);
54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.polyOffsetEnabled = false;
55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.polyOffsetFactor = 0;
55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.polyOffsetUnits = 0;
55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.getFaceCullMode() != context.cullMode) {
55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) {
55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_CULL_FACE);
55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(GL_CULL_FACE);
56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            switch (state.getFaceCullMode()) {
56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Off:
56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Back:
56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glCullFace(GL_BACK);
56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Front:
56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glCullFace(GL_FRONT);
57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case FrontAndBack:
57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glCullFace(GL_FRONT_AND_BACK);
57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                default:
57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    throw new UnsupportedOperationException("Unrecognized face cull mode: "
57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            + state.getFaceCullMode());
57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.cullMode = state.getFaceCullMode();
58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (state.getBlendMode() != context.blendMode) {
58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (state.getBlendMode() == RenderState.BlendMode.Off) {
58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_BLEND);
58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(GL_BLEND);
58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                switch (state.getBlendMode()) {
58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case Off:
58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case Additive:
59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_ONE, GL_ONE);
59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case AlphaAdditive:
59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case Color:
59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case Alpha:
60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case PremultAlpha:
60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case Modulate:
60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_DST_COLOR, GL_ZERO);
60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    case ModulateX2:
60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        break;
61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    default:
61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new UnsupportedOperationException("Unrecognized blend mode: "
61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                + state.getBlendMode());
61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.blendMode = state.getBlendMode();
61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.stencilTest != state.isStencilTest()
62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation()
62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation()
62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation()
62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation()
62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation()
62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation()
62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.frontStencilFunction != state.getFrontStencilFunction()
62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                || context.backStencilFunction != state.getBackStencilFunction()) {
62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation();   //terrible looking, I know
63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation();
63259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation();
63359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation();
63459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation();
63559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation();
63659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.frontStencilFunction = state.getFrontStencilFunction();
63759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.backStencilFunction = state.getBackStencilFunction();
63859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
63959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (state.isStencilTest()) {
64059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(GL_STENCIL_TEST);
64159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glStencilOpSeparate(GL_FRONT,
64259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertStencilOperation(state.getFrontStencilStencilFailOperation()),
64359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertStencilOperation(state.getFrontStencilDepthFailOperation()),
64459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertStencilOperation(state.getFrontStencilDepthPassOperation()));
64559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glStencilOpSeparate(GL_BACK,
64659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertStencilOperation(state.getBackStencilStencilFailOperation()),
64759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertStencilOperation(state.getBackStencilDepthFailOperation()),
64859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertStencilOperation(state.getBackStencilDepthPassOperation()));
64959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glStencilFuncSeparate(GL_FRONT,
65059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertTestFunction(state.getFrontStencilFunction()),
65159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0, Integer.MAX_VALUE);
65259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glStencilFuncSeparate(GL_BACK,
65359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertTestFunction(state.getBackStencilFunction()),
65459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0, Integer.MAX_VALUE);
65559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
65659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_STENCIL_TEST);
65759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
65859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
65959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
66059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
66159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertStencilOperation(StencilOperation stencilOp) {
66259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (stencilOp) {
66359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Keep:
66459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_KEEP;
66559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Zero:
66659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_ZERO;
66759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Replace:
66859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_REPLACE;
66959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Increment:
67059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_INCR;
67159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case IncrementWrap:
67259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_INCR_WRAP;
67359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Decrement:
67459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_DECR;
67559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case DecrementWrap:
67659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_DECR_WRAP;
67759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Invert:
67859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_INVERT;
67959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
68059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unrecognized stencil operation: " + stencilOp);
68159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
68259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
68359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
68459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertTestFunction(TestFunction testFunc) {
68559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (testFunc) {
68659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Never:
68759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_NEVER;
68859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Less:
68959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LESS;
69059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case LessOrEqual:
69159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LEQUAL;
69259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Greater:
69359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_GREATER;
69459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GreaterOrEqual:
69559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_GEQUAL;
69659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Equal:
69759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_EQUAL;
69859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case NotEqual:
69959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_NOTEQUAL;
70059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Always:
70159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_ALWAYS;
70259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
70359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unrecognized test function: " + testFunc);
70459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
70559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
70659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
70759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
70859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Camera and World transforms                                       *|
70959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
71059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewPort(int x, int y, int w, int h) {
71159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (x != vpX || vpY != y || vpW != w || vpH != h) {
71259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glViewport(x, y, w, h);
71359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vpX = x;
71459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vpY = y;
71559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vpW = w;
71659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vpH = h;
71759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
71859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
71959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
72059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setClipRect(int x, int y, int width, int height) {
72159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!context.clipRectEnabled) {
72259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glEnable(GL_SCISSOR_TEST);
72359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.clipRectEnabled = true;
72459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
72559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (clipX != x || clipY != y || clipW != width || clipH != height) {
72659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glScissor(x, y, width, height);
72759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipX = x;
72859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipY = y;
72959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipW = width;
73059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipH = height;
73159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
73259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
73359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
73459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void clearClipRect() {
73559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.clipRectEnabled) {
73659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDisable(GL_SCISSOR_TEST);
73759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.clipRectEnabled = false;
73859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
73959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipX = 0;
74059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipY = 0;
74159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipW = 0;
74259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            clipH = 0;
74359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
74459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
74559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
74659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void onFrame() {
74759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        objManager.deleteUnused(this);
74859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        statistics.clearFrame();
74959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
75059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
75159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setWorldMatrix(Matrix4f worldMatrix) {
75259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
75359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
75459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
75559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
75659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
75759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
75859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Shaders                                                           *|
75959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
76059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void updateUniformLocation(Shader shader, Uniform uniform) {
76159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        stringBuf.setLength(0);
76259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        stringBuf.append(uniform.getName()).append('\0');
76359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        updateNameBuffer();
76459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int loc = glGetUniformLocation(shader.getId(), nameBuf);
76559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (loc < 0) {
76659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            uniform.setLocation(-1);
76759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // uniform is not declared in shader
76859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.INFO, "Uniform {0} is not declared in shader {1}.", new Object[]{uniform.getName(), shader.getSources()});
76959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
77059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            uniform.setLocation(loc);
77159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
77259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
77359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
77459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void bindProgram(Shader shader){
77559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int shaderId = shader.getId();
77659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundShaderProgram != shaderId) {
77759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glUseProgram(shaderId);
77859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onShaderUse(shader, true);
77959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            boundShader = shader;
78059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundShaderProgram = shaderId;
78159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
78259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onShaderUse(shader, false);
78359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
78459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
78559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
78659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void updateUniform(Shader shader, Uniform uniform) {
78759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int shaderId = shader.getId();
78859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
78959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert uniform.getName() != null;
79059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert shader.getId() > 0;
79159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        bindProgram(shader);
79359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int loc = uniform.getLocation();
79559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (loc == -1) {
79659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
79759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
79859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (loc == -2) {
80059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // get uniform location
80159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateUniformLocation(shader, uniform);
80259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (uniform.getLocation() == -1) {
80359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // not declared, ignore
80459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                uniform.clearUpdateNeeded();
80559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return;
80659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
80759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            loc = uniform.getLocation();
80859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
80959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
81059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (uniform.getVarType() == null) {
81159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return; // value not set yet..
81259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
81359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        statistics.onUniformSet();
81459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
81559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        uniform.clearUpdateNeeded();
81659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer fb;
81759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (uniform.getVarType()) {
81859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Float:
81959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Float f = (Float) uniform.getValue();
82059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform1f(loc, f.floatValue());
82159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
82259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vector2:
82359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector2f v2 = (Vector2f) uniform.getValue();
82459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform2f(loc, v2.getX(), v2.getY());
82559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
82659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vector3:
82759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f v3 = (Vector3f) uniform.getValue();
82859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ());
82959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
83059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vector4:
83159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Object val = uniform.getValue();
83259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (val instanceof ColorRGBA) {
83359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ColorRGBA c = (ColorRGBA) val;
83459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glUniform4f(loc, c.r, c.g, c.b, c.a);
83559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (val instanceof Vector4f) {
83659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    Vector4f c = (Vector4f) val;
83759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glUniform4f(loc, c.x, c.y, c.z, c.w);
83859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
83959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    Quaternion c = (Quaternion) uniform.getValue();
84059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW());
84159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
84259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
84359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Boolean:
84459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Boolean b = (Boolean) uniform.getValue();
84559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform1i(loc, b.booleanValue() ? GL_TRUE : GL_FALSE);
84659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
84759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Matrix3:
84859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
84959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                assert fb.remaining() == 9;
85059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniformMatrix3(loc, false, fb);
85159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
85259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Matrix4:
85359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
85459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                assert fb.remaining() == 16;
85559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniformMatrix4(loc, false, fb);
85659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
85759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case FloatArray:
85859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
85959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform1(loc, fb);
86059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
86159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vector2Array:
86259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
86359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform2(loc, fb);
86459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
86559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vector3Array:
86659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
86759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform3(loc, fb);
86859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
86959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vector4Array:
87059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
87159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform4(loc, fb);
87259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
87359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Matrix4Array:
87459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                fb = (FloatBuffer) uniform.getValue();
87559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniformMatrix4(loc, false, fb);
87659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
87759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Int:
87859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Integer i = (Integer) uniform.getValue();
87959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glUniform1i(loc, i.intValue());
88059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
88159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
88259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType());
88359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
88459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
88559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
88659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void updateShaderUniforms(Shader shader) {
88759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ListMap<String, Uniform> uniforms = shader.getUniformMap();
88859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        for (Uniform uniform : shader.getUniforms()){
88959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < uniforms.size(); i++) {
89059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Uniform uniform = uniforms.getValue(i);
89159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (uniform.isUpdateNeeded()) {
89259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateUniform(shader, uniform);
89359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
89459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
89559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
89659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
89759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void resetUniformLocations(Shader shader) {
89859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ListMap<String, Uniform> uniforms = shader.getUniformMap();
89959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        for (Uniform uniform : shader.getUniforms()){
90059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < uniforms.size(); i++) {
90159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Uniform uniform = uniforms.getValue(i);
90259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            uniform.reset(); // e.g check location again
90359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
90459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
90559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
90659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*
90759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * (Non-javadoc)
90859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Only used for fixed-function. Ignored.
90959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
91059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setLighting(LightList list) {
91159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
91259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
91359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int convertShaderType(ShaderType type) {
91459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (type) {
91559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Fragment:
91659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_FRAGMENT_SHADER;
91759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Vertex:
91859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_VERTEX_SHADER;
91959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case Geometry:
92059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return ARBGeometryShader4.GL_GEOMETRY_SHADER_ARB;
92159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
92259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unrecognized shader type.");
92359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
92459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
92559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
92659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateShaderSourceData(ShaderSource source, String language) {
92759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int id = source.getId();
92859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (id == -1) {
92959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // create id
93059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            id = glCreateShader(convertShaderType(source.getType()));
93159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (id <= 0) {
93259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("Invalid ID received when trying to create shader.");
93359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
93459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
93559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            source.setId(id);
93659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
93759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new RendererException("Cannot recompile shader source");
93859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
93959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
94059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // upload shader source
94159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // merge the defines and source code
94259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
94359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        stringBuf.setLength(0);
94459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (language.startsWith("GLSL")) {
94559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int version = Integer.parseInt(language.substring(4));
94659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (version > 100) {
94759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                stringBuf.append("#version ");
94859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                stringBuf.append(language.substring(4));
94959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (version >= 150) {
95059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    stringBuf.append(" core");
95159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
95259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                stringBuf.append("\n");
95359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
95459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
95559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        updateNameBuffer();
95659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
95759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        byte[] definesCodeData = source.getDefines().getBytes();
95859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        byte[] sourceCodeData = source.getSource().getBytes();
95959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ByteBuffer codeBuf = BufferUtils.createByteBuffer(nameBuf.limit()
96059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + definesCodeData.length
96159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + sourceCodeData.length);
96259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        codeBuf.put(nameBuf);
96359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        codeBuf.put(definesCodeData);
96459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        codeBuf.put(sourceCodeData);
96559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        codeBuf.flip();
96659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
96759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glShaderSource(id, codeBuf);
96859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glCompileShader(id);
96959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
97059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetShader(id, GL_COMPILE_STATUS, intBuf1);
97159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
97259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean compiledOK = intBuf1.get(0) == GL_TRUE;
97359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String infoLog = null;
97459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
97559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (VALIDATE_SHADER || !compiledOK) {
97659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // even if compile succeeded, check
97759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // log for warnings
97859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetShader(id, GL_INFO_LOG_LENGTH, intBuf1);
97959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int length = intBuf1.get(0);
98059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (length > 3) {
98159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // get infos
98259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                ByteBuffer logBuf = BufferUtils.createByteBuffer(length);
98359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGetShaderInfoLog(id, null, logBuf);
98459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                byte[] logBytes = new byte[length];
98559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logBuf.get(logBytes, 0, length);
98659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // convert to string, etc
98759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                infoLog = new String(logBytes);
98859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
98959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
99059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
99159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (compiledOK) {
99259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (infoLog != null) {
99359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.INFO, "{0} compile success\n{1}",
99459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        new Object[]{source.getName(), infoLog});
99559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
99659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.FINE, "{0} compile success", source.getName());
99759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
99859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
99959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.WARNING, "Bad compile of:\n{0}{1}",
100059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    new Object[]{source.getDefines(), source.getSource()});
100159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (infoLog != null) {
100259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("compile error in:" + source + " error:" + infoLog);
100359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
100459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("compile error in:" + source + " error: <not provided>");
100559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
100659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
100759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
100859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        source.clearUpdateNeeded();
100959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // only usable if compiled
101059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        source.setUsable(compiledOK);
101159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!compiledOK) {
101259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // make sure to dispose id cause all program's
101359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // shaders will be cleared later.
101459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDeleteShader(id);
101559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
101659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // register for cleanup since the ID is usable
101759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // NOTE: From now on cleanup is handled
101859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // by the parent shader object so no need
101959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // to register.
102059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //objManager.registerForCleanup(source);
102159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
102259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
102359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
102459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateShaderData(Shader shader) {
102559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int id = shader.getId();
102659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean needRegister = false;
102759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (id == -1) {
102859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // create program
102959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            id = glCreateProgram();
103059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (id == 0) {
103159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("Invalid ID (" + id + ") received when trying to create shader program.");
103259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
103359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
103459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            shader.setId(id);
103559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            needRegister = true;
103659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
103759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
103859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (ShaderSource source : shader.getSources()) {
103959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (source.isUpdateNeeded()) {
104059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateShaderSourceData(source, shader.getLanguage());
104159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // shader has been compiled here
104259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
104359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
104459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!source.isUsable()) {
104559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // it's useless.. just forget about everything..
104659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                shader.setUsable(false);
104759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                shader.clearUpdateNeeded();
104859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return;
104959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
105059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glAttachShader(id, source.getId());
105159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
105259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
105359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (caps.contains(Caps.OpenGL30)) {
105459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // Check if GLSL version is 1.5 for shader
105559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            GL30.glBindFragDataLocation(id, 0, "outFragColor");
105659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
105759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
105859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // link shaders to program
105959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glLinkProgram(id);
106059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glGetProgram(id, GL_LINK_STATUS, intBuf1);
106159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean linkOK = intBuf1.get(0) == GL_TRUE;
106259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String infoLog = null;
106359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
106459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (VALIDATE_SHADER || !linkOK) {
106559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetProgram(id, GL_INFO_LOG_LENGTH, intBuf1);
106659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int length = intBuf1.get(0);
106759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (length > 3) {
106859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // get infos
106959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                ByteBuffer logBuf = BufferUtils.createByteBuffer(length);
107059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGetProgramInfoLog(id, null, logBuf);
107159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
107259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // convert to string, etc
107359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                byte[] logBytes = new byte[length];
107459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logBuf.get(logBytes, 0, length);
107559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                infoLog = new String(logBytes);
107659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
107759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
107859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
107959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (linkOK) {
108059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (infoLog != null) {
108159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.INFO, "shader link success. \n{0}", infoLog);
108259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
108359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.fine("shader link success");
108459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
108559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
108659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (infoLog != null) {
108759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
108859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
108959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
109059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
109159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
109259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
109359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        shader.clearUpdateNeeded();
109459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!linkOK) {
109559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // failure.. forget about everything
109659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            shader.resetSources();
109759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            shader.setUsable(false);
109859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            deleteShader(shader);
109959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
110059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            shader.setUsable(true);
110159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (needRegister) {
110259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                objManager.registerForCleanup(shader);
110359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                statistics.onNewShader();
110459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
110559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // OpenGL spec: uniform locations may change after re-link
110659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                resetUniformLocations(shader);
110759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
110859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
110959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
111059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
111159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setShader(Shader shader) {
111259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (shader == null) {
111359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException("shader cannot be null");
111459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (context.boundShaderProgram > 0) {
111559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                glUseProgram(0);
111659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                statistics.onShaderUse(null, true);
111759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                context.boundShaderProgram = 0;
111859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                boundShader = null;
111959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
112059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
112159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (shader.isUpdateNeeded()) {
112259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateShaderData(shader);
112359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
112459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
112559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // NOTE: might want to check if any of the
112659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // sources need an update?
112759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
112859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!shader.isUsable()) {
112959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return;
113059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
113159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
113259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            assert shader.getId() > 0;
113359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
113459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateShaderUniforms(shader);
113559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            bindProgram(shader);
113659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
113759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
113859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
113959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void deleteShaderSource(ShaderSource source) {
114059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (source.getId() < 0) {
114159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.warning("Shader source is not uploaded to GPU, cannot delete.");
114259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
114359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
114459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        source.setUsable(false);
114559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        source.clearUpdateNeeded();
114659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glDeleteShader(source.getId());
114759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        source.resetObject();
114859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
114959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
115059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void deleteShader(Shader shader) {
115159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (shader.getId() == -1) {
115259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.warning("Shader is not uploaded to GPU, cannot delete.");
115359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
115459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
115559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
115659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (ShaderSource source : shader.getSources()) {
115759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (source.getId() != -1) {
115859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDetachShader(shader.getId(), source.getId());
115959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                deleteShaderSource(source);
116059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
116159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
116259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
116359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // kill all references so sources can be collected
116459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // if needed.
116559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        shader.resetSources();
116659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glDeleteProgram(shader.getId());
116759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
116859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        statistics.onDeleteShader();
116959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
117059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
117159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
117259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Framebuffers                                                      *|
117359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
117459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
117559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        copyFrameBuffer(src, dst, true);
117659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
117759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
117859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
117959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
118059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int srcW = 0;
118159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int srcH = 0;
118259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int dstW = 0;
118359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int dstH = 0;
118459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int prevFBO = context.boundFBO;
118559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
118659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (src != null && src.isUpdateNeeded()) {
118759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateFrameBuffer(src);
118859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
118959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
119059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (dst != null && dst.isUpdateNeeded()) {
119159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateFrameBuffer(dst);
119259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
119359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
119459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (src == null) {
119559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
119659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                srcW = viewWidth;
119759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                srcH = viewHeight;
119859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
119959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
120059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                srcW = src.getWidth();
120159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                srcH = src.getHeight();
120259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
120359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (dst == null) {
120459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
120559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                dstW = viewWidth;
120659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                dstH = viewHeight;
120759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
120859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
120959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                dstW = dst.getWidth();
121059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                dstH = dst.getHeight();
121159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
121259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int mask = GL_COLOR_BUFFER_BIT;
121359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (copyDepth) {
121459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                mask |= GL_DEPTH_BUFFER_BIT;
121559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
121659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBlitFramebufferEXT(0, 0, srcW, srcH,
121759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    0, 0, dstW, dstH, mask,
121859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    GL_NEAREST);
121959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
122059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
122159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
122259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            try {
122359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                checkFrameBufferError();
122459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } catch (IllegalStateException ex) {
122559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
122659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
122759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw ex;
122859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
122959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
123059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new RendererException("EXT_framebuffer_blit required.");
123159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // TODO: support non-blit copies?
123259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
123359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
123459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
123559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private String getTargetBufferName(int buffer){
123659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (buffer){
123759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_NONE: return "NONE";
123859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRONT: return "GL_FRONT";
123959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_BACK: return "GL_BACK";
124059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
124159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if ( buffer >= GL_COLOR_ATTACHMENT0_EXT
124259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                  && buffer <= GL_COLOR_ATTACHMENT15_EXT){
124359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return "GL_COLOR_ATTACHMENT" +
124459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                (buffer - GL_COLOR_ATTACHMENT0_EXT);
124559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }else{
124659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return "UNKNOWN? " + buffer;
124759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
124859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
124959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
125059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
125159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name){
125259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("== Renderbuffer " + name + " ==");
125359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("RB ID: " + rb.getId());
125459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Is proper? " + glIsRenderbufferEXT(rb.getId()));
125559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
125659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int attachment = convertAttachmentSlot(rb.getSlot());
125759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
125859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int type = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT,
125959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                          attachment,
126059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                          GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT);
126159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
126259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int rbName = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT,
126359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                            attachment,
126459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                            GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT);
126559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
126659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (type){
126759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_NONE:
126859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                System.out.println("Type: None");
126959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return; // note: return from method as other queries will be invalid
127059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_TEXTURE:
127159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                System.out.println("Type: Texture");
127259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
127359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_RENDERBUFFER_EXT:
127459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                System.out.println("Type: Buffer");
127559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                System.out.println("RB ID: " + rbName);
127659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
127759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
127859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
127959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
128059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
128159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
128259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
128359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void printRealFrameBufferInfo(FrameBuffer fb) {
128459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean doubleBuffer = glGetBoolean(GL_DOUBLEBUFFER);
128559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER));
128659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
128759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
128859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int fbId = fb.getId();
128959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int curDrawBinding = glGetInteger(ARBFramebufferObject.GL_DRAW_FRAMEBUFFER_BINDING);
129059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING);
129159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
129259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("=== OpenGL FBO State ===");
129359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Context doublebuffered? " + doubleBuffer);
129459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("FBO ID: " + fbId);
129559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Is proper? " + glIsFramebufferEXT(fbId));
129659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
129759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Is bound to read? " + (fbId == curReadBinding));
129859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Draw buffer: " + drawBuf);
129959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        System.out.println("Read buffer: " + readBuf);
130059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
130159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundFBO != fbId){
130259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbId);
130359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundFBO = fbId;
130459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
130559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
130659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb.getDepthBuffer() != null){
130759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
130859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
130959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < fb.getNumColorBuffers(); i++){
131059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
131159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
131259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
131359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
131459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void checkFrameBufferError() {
131559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
131659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (status) {
131759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_COMPLETE_EXT:
131859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
131959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
132059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //Choose different formats
132159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Framebuffer object format is "
132259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        + "unsupported by the video hardware.");
132359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
132459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Framebuffer has erronous attachment.");
132559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
132659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached.");
132759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
132859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
132959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
133059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Framebuffer attachments must have same formats.");
133159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
133259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Incomplete draw buffer.");
133359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
133459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Incomplete read buffer.");
133559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
133659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Incomplete multisample buffer.");
133759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
133859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //Programming error; will fail on all hardware
133959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalStateException("Some video driver error "
134059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        + "or programming error occured. "
134159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        + "Framebuffer object status is invalid. ");
134259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
134359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
134459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
134559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
134659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int id = rb.getId();
134759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (id == -1) {
134859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGenRenderbuffersEXT(intBuf1);
134959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            id = intBuf1.get(0);
135059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rb.setId(id);
135159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
135259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
135359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundRB != id) {
135459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id);
135559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundRB = id;
135659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
135759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
135859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) {
135959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new RendererException("Resolution " + fb.getWidth()
136059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    + ":" + fb.getHeight() + " is not supported.");
136159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
136259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
136359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TextureUtil.checkFormatSupported(rb.getFormat());
136459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
136559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
136659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int samples = fb.getSamples();
136759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (maxFBOSamples < samples) {
136859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                samples = maxFBOSamples;
136959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
137059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
137159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    samples,
137259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    TextureUtil.convertTextureFormat(rb.getFormat()),
137359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fb.getWidth(),
137459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fb.getHeight());
137559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
137659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
137759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    TextureUtil.convertTextureFormat(rb.getFormat()),
137859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fb.getWidth(),
137959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    fb.getHeight());
138059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
138159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
138259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
138359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertAttachmentSlot(int attachmentSlot) {
138459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // can also add support for stencil here
138559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (attachmentSlot == -100) {
138659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return GL_DEPTH_ATTACHMENT_EXT;
138759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (attachmentSlot < 0 || attachmentSlot >= 16) {
138859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot);
138959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
139059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
139159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return GL_COLOR_ATTACHMENT0_EXT + attachmentSlot;
139259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
139359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
139459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
139559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Texture tex = rb.getTexture();
139659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Image image = tex.getImage();
139759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (image.isUpdateNeeded()) {
139859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels(), 0);
139959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
140059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // NOTE: For depth textures, sets nearest/no-mips mode
140159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // Required to fix "framebuffer unsupported"
140259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // for old NVIDIA drivers!
140359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setupTextureParams(tex);
140459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
140559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
140659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
140759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                convertAttachmentSlot(rb.getSlot()),
140859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                convertTextureType(tex.getType(), image.getMultiSamples()),
140959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                image.getId(),
141059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                0);
141159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
141259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
141359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
141459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean needAttach;
141559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (rb.getTexture() == null) {
141659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // if it hasn't been created yet, then attach is required.
141759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            needAttach = rb.getId() == -1;
141859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateRenderBuffer(fb, rb);
141959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
142059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            needAttach = false;
142159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateRenderTexture(fb, rb);
142259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
142359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (needAttach) {
142459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
142559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    convertAttachmentSlot(rb.getSlot()),
142659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    GL_RENDERBUFFER_EXT,
142759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    rb.getId());
142859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
142959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
143059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
143159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateFrameBuffer(FrameBuffer fb) {
143259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int id = fb.getId();
143359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (id == -1) {
143459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // create FBO
143559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGenFramebuffersEXT(intBuf1);
143659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            id = intBuf1.get(0);
143759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fb.setId(id);
143859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            objManager.registerForCleanup(fb);
143959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
144059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onNewFrameBuffer();
144159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
144259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
144359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundFBO != id) {
144459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
144559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
144659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundDrawBuf = 0;
144759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundFBO = id;
144859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
144959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
145059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
145159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (depthBuf != null) {
145259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateFrameBufferAttachment(fb, depthBuf);
145359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
145459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
145559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < fb.getNumColorBuffers(); i++) {
145659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
145759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateFrameBufferAttachment(fb, colorBuf);
145859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
145959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
146059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fb.clearUpdateNeeded();
146159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
146259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
146359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector2f[] getFrameBufferSamplePositions(FrameBuffer fb) {
146459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb.getSamples() <= 1) {
146559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException("Framebuffer must be multisampled");
146659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
146759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
146859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setFrameBuffer(fb);
146959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
147059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector2f[] samplePositions = new Vector2f[fb.getSamples()];
147159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FloatBuffer samplePos = BufferUtils.createFloatBuffer(2);
147259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < samplePositions.length; i++) {
147359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGetMultisample(GL_SAMPLE_POSITION, i, samplePos);
147459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            samplePos.clear();
147559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            samplePositions[i] = new Vector2f(samplePos.get(0) - 0.5f,
147659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    samplePos.get(1) - 0.5f);
147759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
147859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return samplePositions;
147959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
148059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
148159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setMainFrameBufferOverride(FrameBuffer fb){
148259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        mainFbOverride = fb;
148359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
148459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
148559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrameBuffer(FrameBuffer fb) {
148659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb == null && mainFbOverride != null){
148759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fb = mainFbOverride;
148859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
148959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
149059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (lastFb == fb) {
149159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fb == null || !fb.isUpdateNeeded()){
149259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return;
149359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
149459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
149559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
149659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // generate mipmaps for last FB if needed
149759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (lastFb != null) {
149859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
149959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                RenderBuffer rb = lastFb.getColorBuffer(i);
150059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Texture tex = rb.getTexture();
150159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (tex != null
150259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        && tex.getMinFilter().usesMipMapLevels()) {
150359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    setTexture(0, rb.getTexture());
150459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
150559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples());
150659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glEnable(textureType);
150759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glGenerateMipmapEXT(textureType);
150859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glDisable(textureType);
150959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
151059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
151159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
151259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
151359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb == null) {
151459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // unbind any fbos
151559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundFBO != 0) {
151659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
151759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                statistics.onFrameBufferUse(null, true);
151859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
151959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundFBO = 0;
152059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
152159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // select back buffer
152259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundDrawBuf != -1) {
152359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDrawBuffer(initialDrawBuf);
152459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundDrawBuf = -1;
152559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
152659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundReadBuf != -1) {
152759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glReadBuffer(initialReadBuf);
152859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundReadBuf = -1;
152959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
153059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
153159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            lastFb = null;
153259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
153359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null){
153459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalArgumentException("The framebuffer: " + fb +
153559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                   "\nDoesn't have any color/depth buffers");
153659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
153759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
153859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fb.isUpdateNeeded()) {
153959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateFrameBuffer(fb);
154059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
154159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
154259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundFBO != fb.getId()) {
154359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb.getId());
154459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                statistics.onFrameBufferUse(fb, true);
154559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
154659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // update viewport to reflect framebuffer's resolution
154759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setViewPort(0, 0, fb.getWidth(), fb.getHeight());
154859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
154959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundFBO = fb.getId();
155059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
155159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                statistics.onFrameBufferUse(fb, false);
155259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
155359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fb.getNumColorBuffers() == 0) {
155459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // make sure to select NONE as draw buf
155559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // no color buffer attached. select NONE
155659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (context.boundDrawBuf != -2) {
155759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glDrawBuffer(GL_NONE);
155859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.boundDrawBuf = -2;
155959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
156059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (context.boundReadBuf != -2) {
156159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glReadBuffer(GL_NONE);
156259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.boundReadBuf = -2;
156359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
156459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
156559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (fb.isMultiTarget()) {
156659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
156759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new RendererException("Framebuffer has more"
156859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                + " targets than are supported"
156959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                + " on the system!");
157059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
157159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
157259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
157359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        intBuf16.clear();
157459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        for (int i = 0; i < fb.getNumColorBuffers(); i++) {
157559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            intBuf16.put(GL_COLOR_ATTACHMENT0_EXT + i);
157659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        }
157759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
157859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        intBuf16.flip();
157959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glDrawBuffers(intBuf16);
158059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        context.boundDrawBuf = 100 + fb.getNumColorBuffers();
158159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
158259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
158359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
158459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    // select this draw buffer
158559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (context.boundDrawBuf != rb.getSlot()) {
158659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
158759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        context.boundDrawBuf = rb.getSlot();
158859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
158959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
159059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
159159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
159259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            assert fb.getId() >= 0;
159359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            assert context.boundFBO == fb.getId();
159459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
159559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            lastFb = fb;
159659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
159759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            try {
159859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                checkFrameBufferError();
159959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } catch (IllegalStateException ex) {
160059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
160159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                printRealFrameBufferInfo(fb);
160259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw ex;
160359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
160459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
160559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
160659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
160759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
160859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb != null) {
160959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            RenderBuffer rb = fb.getColorBuffer();
161059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (rb == null) {
161159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IllegalArgumentException("Specified framebuffer"
161259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        + " does not have a colorbuffer");
161359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
161459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
161559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setFrameBuffer(fb);
161659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundReadBuf != rb.getSlot()) {
161759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
161859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundReadBuf = rb.getSlot();
161959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
162059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
162159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setFrameBuffer(null);
162259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
162359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
162459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glReadPixels(vpX, vpY, vpW, vpH, /*GL_RGBA*/ GL_BGRA, GL_UNSIGNED_BYTE, byteBuf);
162559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
162659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
162759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
162859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        intBuf1.put(0, rb.getId());
162959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glDeleteRenderbuffersEXT(intBuf1);
163059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
163159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
163259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void deleteFrameBuffer(FrameBuffer fb) {
163359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fb.getId() != -1) {
163459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundFBO == fb.getId()) {
163559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
163659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundFBO = 0;
163759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
163859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
163959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fb.getDepthBuffer() != null) {
164059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                deleteRenderBuffer(fb, fb.getDepthBuffer());
164159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
164259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (fb.getColorBuffer() != null) {
164359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                deleteRenderBuffer(fb, fb.getColorBuffer());
164459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
164559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
164659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            intBuf1.put(0, fb.getId());
164759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDeleteFramebuffersEXT(intBuf1);
164859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fb.resetObject();
164959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
165059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onDeleteFrameBuffer();
165159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
165259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
165359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
165459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
165559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Textures                                                          *|
165659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
165759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertTextureType(Texture.Type type, int samples) {
165859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (type) {
165959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case TwoDimensional:
166059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (samples > 1) {
166159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return ARBTextureMultisample.GL_TEXTURE_2D_MULTISAMPLE;
166259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
166359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return GL_TEXTURE_2D;
166459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
166559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case TwoDimensionalArray:
166659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (samples > 1) {
166759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return ARBTextureMultisample.GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
166859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
166959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT;
167059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
167159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case ThreeDimensional:
167259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_TEXTURE_3D;
167359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case CubeMap:
167459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_TEXTURE_CUBE_MAP;
167559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
167659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown texture type: " + type);
167759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
167859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
167959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
168059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertMagFilter(Texture.MagFilter filter) {
168159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (filter) {
168259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Bilinear:
168359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINEAR;
168459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Nearest:
168559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_NEAREST;
168659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
168759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown mag filter: " + filter);
168859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
168959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
169059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
169159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertMinFilter(Texture.MinFilter filter) {
169259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (filter) {
169359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Trilinear:
169459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINEAR_MIPMAP_LINEAR;
169559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case BilinearNearestMipMap:
169659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINEAR_MIPMAP_NEAREST;
169759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case NearestLinearMipMap:
169859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_NEAREST_MIPMAP_LINEAR;
169959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case NearestNearestMipMap:
170059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_NEAREST_MIPMAP_NEAREST;
170159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case BilinearNoMipMaps:
170259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINEAR;
170359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case NearestNoMipMaps:
170459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_NEAREST;
170559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
170659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown min filter: " + filter);
170759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
170859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
170959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
171059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertWrapMode(Texture.WrapMode mode) {
171159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (mode) {
171259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case BorderClamp:
171359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_CLAMP_TO_BORDER;
171459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Clamp:
171559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_CLAMP;
171659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case EdgeClamp:
171759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_CLAMP_TO_EDGE;
171859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Repeat:
171959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_REPEAT;
172059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case MirroredRepeat:
172159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_MIRRORED_REPEAT;
172259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
172359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown wrap mode: " + mode);
172459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
172559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
172659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
172759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @SuppressWarnings("fallthrough")
172859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void setupTextureParams(Texture tex) {
172959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Image image = tex.getImage();
173059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1);
173159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
173259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // filter things
173359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int minFilter = convertMinFilter(tex.getMinFilter());
173459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int magFilter = convertMagFilter(tex.getMagFilter());
173559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter);
173659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter);
173759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
173859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (tex.getAnisotropicFilter() > 1) {
173959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic) {
174059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameterf(target,
174159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT,
174259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        tex.getAnisotropicFilter());
174359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
174459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
174559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
174659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.pointSprite) {
174759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return; // Attempt to fix glTexParameter crash for some ATI GPUs
174859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
174959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // repeat modes
175059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (tex.getType()) {
175159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case ThreeDimensional:
175259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case CubeMap: // cubemaps use 3D coords
175359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
175459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case TwoDimensional:
175559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case TwoDimensionalArray:
175659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
175759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // fall down here is intentional..
175859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            case OneDimensional:
175959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
176059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                break;
176159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
176259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
176359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
176459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
176559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // R to Texture compare mode
176659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) {
176759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
176859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glTexParameteri(target, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
176959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) {
177059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_GEQUAL);
177159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
177259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
177359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
177459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
177559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
177659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
177759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateTexImageData(Image img, Texture.Type type, boolean mips, int unit) {
177859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int texId = img.getId();
177959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (texId == -1) {
178059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // create texture
178159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGenTextures(intBuf1);
178259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texId = intBuf1.get(0);
178359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            img.setId(texId);
178459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            objManager.registerForCleanup(img);
178559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
178659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onNewTexture();
178759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
178859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
178959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // bind texture
179059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int target = convertTextureType(type, img.getMultiSamples());
179159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundTextureUnit != unit) {
179259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glActiveTexture(GL_TEXTURE0 + unit);
179359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundTextureUnit = unit;
179459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
179559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundTextures[unit] != img) {
179659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindTexture(target, texId);
179759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundTextures[unit] = img;
179859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
179959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onTextureUse(img, true);
180059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
180159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
180259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!img.hasMipmaps() && mips) {
180359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // No pregenerated mips available,
180459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // generate from base level if required
180559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!GLContext.getCapabilities().OpenGL30) {
180659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
180759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
180859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
180959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//          glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0 );
181059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (img.getMipMapSizes() != null) {
181159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, img.getMipMapSizes().length);
181259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
181359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
181459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
181559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int imageSamples = img.getMultiSamples();
181659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (imageSamples > 1) {
181759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (img.getFormat().isDepthFormat()) {
181859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                img.setMultiSamples(Math.min(maxDepthTexSamples, imageSamples));
181959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
182059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                img.setMultiSamples(Math.min(maxColorTexSamples, imageSamples));
182159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
182259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
182359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
182459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT.
182559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
182659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (img.getWidth() != 0 && img.getHeight() != 0) {
182759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (!FastMath.isPowerOfTwo(img.getWidth())
182859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        || !FastMath.isPowerOfTwo(img.getHeight())) {
182959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (img.getData(0) == null) {
183059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware");
183159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    } else {
183259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        MipMapGenerator.resizeToPowerOf2(img);
183359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
183459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
183559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
183659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
183759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
183859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Check if graphics card doesn't support multisample textures
183959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!GLContext.getCapabilities().GL_ARB_texture_multisample) {
184059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (img.getMultiSamples() > 1) {
184159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new RendererException("Multisample textures not supported by graphics hardware");
184259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
184359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
184459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
184559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (target == GL_TEXTURE_CUBE_MAP) {
184659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            List<ByteBuffer> data = img.getData();
184759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (data.size() != 6) {
184859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.WARNING, "Invalid texture: {0}\n"
184959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        + "Cubemap textures must contain 6 data units.", img);
185059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return;
185159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
185259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int i = 0; i < 6; i++) {
185359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc);
185459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
185559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) {
185659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            List<ByteBuffer> data = img.getData();
185759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // -1 index specifies prepare data for 2D Array
185859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            TextureUtil.uploadTexture(img, target, -1, 0, tdc);
185959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int i = 0; i < data.size(); i++) {
186059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // upload each slice of 2D array in turn
186159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // this time with the appropriate index
186259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                TextureUtil.uploadTexture(img, target, i, 0, tdc);
186359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
186459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
186559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            TextureUtil.uploadTexture(img, target, 0, 0, tdc);
186659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
186759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
186859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (img.getMultiSamples() != imageSamples) {
186959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            img.setMultiSamples(imageSamples);
187059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
187159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
187259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (GLContext.getCapabilities().OpenGL30) {
187359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!img.hasMipmaps() && mips && img.getData() != null) {
187459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // XXX: Required for ATI
187559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnable(target);
187659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glGenerateMipmapEXT(target);
187759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(target);
187859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
187959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
188059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
188159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        img.clearUpdateNeeded();
188259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
188359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
188459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setTexture(int unit, Texture tex) {
188559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Image image = tex.getImage();
188659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (image.isUpdateNeeded()) {
188759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels(), unit);
188859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
188959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
189059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int texId = image.getId();
189159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert texId != -1;
189259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
189359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Image[] textures = context.boundTextures;
189459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
189559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int type = convertTextureType(tex.getType(), image.getMultiSamples());
189659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        if (!context.textureIndexList.moveToNew(unit)) {
189759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//             if (context.boundTextureUnit != unit){
189859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                glActiveTexture(GL_TEXTURE0 + unit);
189959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                context.boundTextureUnit = unit;
190059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//             }
190159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//             glEnable(type);
190259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
190359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
190459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundTextureUnit != unit) {
190559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glActiveTexture(GL_TEXTURE0 + unit);
190659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundTextureUnit = unit;
190759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
190859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (textures[unit] != image) {
190959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindTexture(type, texId);
191059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            textures[unit] = image;
191159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
191259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onTextureUse(image, true);
191359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
191459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onTextureUse(image, false);
191559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
191659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
191759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setupTextureParams(tex);
191859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
191959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
192059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void clearTextureUnits() {
192159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        IDList textureList = context.textureIndexList;
192259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        Image[] textures = context.boundTextures;
192359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        for (int i = 0; i < textureList.oldLen; i++) {
192459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            int idx = textureList.oldList[i];
192559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (context.boundTextureUnit != idx){
192659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                glActiveTexture(GL_TEXTURE0 + idx);
192759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                context.boundTextureUnit = idx;
192859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
192959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            glDisable(convertTextureType(textures[idx].getType()));
193059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            textures[idx] = null;
193159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
193259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        context.textureIndexList.copyNewToOld();
193359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
193459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
193559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void deleteImage(Image image) {
193659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int texId = image.getId();
193759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (texId != -1) {
193859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            intBuf1.put(0, texId);
193959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            intBuf1.position(0).limit(1);
194059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDeleteTextures(intBuf1);
194159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            image.resetObject();
194259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
194359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statistics.onDeleteTexture();
194459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
194559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
194659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
194759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
194859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Vertex Buffers and Attributes                                     *|
194959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
195059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertUsage(Usage usage) {
195159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (usage) {
195259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Static:
195359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_STATIC_DRAW;
195459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Dynamic:
195559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_DYNAMIC_DRAW;
195659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Stream:
195759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_STREAM_DRAW;
195859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
195959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown usage type.");
196059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
196159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
196259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
196359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int convertFormat(Format format) {
196459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (format) {
196559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Byte:
196659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_BYTE;
196759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case UnsignedByte:
196859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_UNSIGNED_BYTE;
196959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Short:
197059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_SHORT;
197159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case UnsignedShort:
197259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_UNSIGNED_SHORT;
197359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Int:
197459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_INT;
197559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case UnsignedInt:
197659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_UNSIGNED_INT;
197759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Half:
197859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return NVHalfFloat.GL_HALF_FLOAT_NV;
197959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                return ARBHalfFloatVertex.GL_HALF_FLOAT;
198059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Float:
198159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_FLOAT;
198259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Double:
198359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_DOUBLE;
198459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
198559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unknown buffer format.");
198659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
198759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
198859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
198959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
199059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateBufferData(VertexBuffer vb) {
199159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int bufId = vb.getId();
199259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean created = false;
199359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (bufId == -1) {
199459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // create buffer
199559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glGenBuffers(intBuf1);
199659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            bufId = intBuf1.get(0);
199759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vb.setId(bufId);
199859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            objManager.registerForCleanup(vb);
199959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
200059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //statistics.onNewVertexBuffer();
200159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
200259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            created = true;
200359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
200459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
200559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // bind buffer
200659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int target;
200759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vb.getBufferType() == VertexBuffer.Type.Index) {
200859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            target = GL_ELEMENT_ARRAY_BUFFER;
200959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundElementArrayVBO != bufId) {
201059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindBuffer(target, bufId);
201159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundElementArrayVBO = bufId;
201259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //statistics.onVertexBufferUse(vb, true);
201359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else{
201459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //statistics.onVertexBufferUse(vb, false);
201559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
201659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
201759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            target = GL_ARRAY_BUFFER;
201859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundArrayVBO != bufId) {
201959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glBindBuffer(target, bufId);
202059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.boundArrayVBO = bufId;
202159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //statistics.onVertexBufferUse(vb, true);
202259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else{
202359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //statistics.onVertexBufferUse(vb, false);
202459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
202559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
202659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
202759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int usage = convertUsage(vb.getUsage());
202859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vb.getData().rewind();
202959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
203059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (created || vb.hasDataSizeChanged()) {
203159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // upload data based on format
203259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            switch (vb.getFormat()) {
203359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Byte:
203459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case UnsignedByte:
203559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferData(target, (ByteBuffer) vb.getData(), usage);
203659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
203759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //            case Half:
203859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Short:
203959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case UnsignedShort:
204059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferData(target, (ShortBuffer) vb.getData(), usage);
204159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
204259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Int:
204359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case UnsignedInt:
204459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferData(target, (IntBuffer) vb.getData(), usage);
204559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
204659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Float:
204759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferData(target, (FloatBuffer) vb.getData(), usage);
204859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
204959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Double:
205059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferData(target, (DoubleBuffer) vb.getData(), usage);
205159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
205259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                default:
205359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    throw new UnsupportedOperationException("Unknown buffer format.");
205459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
205559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
205659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            switch (vb.getFormat()) {
205759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Byte:
205859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case UnsignedByte:
205959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferSubData(target, 0, (ByteBuffer) vb.getData());
206059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
206159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Short:
206259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case UnsignedShort:
206359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferSubData(target, 0, (ShortBuffer) vb.getData());
206459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
206559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Int:
206659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case UnsignedInt:
206759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferSubData(target, 0, (IntBuffer) vb.getData());
206859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
206959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Float:
207059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferSubData(target, 0, (FloatBuffer) vb.getData());
207159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
207259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Double:
207359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBufferSubData(target, 0, (DoubleBuffer) vb.getData());
207459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    break;
207559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                default:
207659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    throw new UnsupportedOperationException("Unknown buffer format.");
207759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
207859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
207959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }else{
208059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (created || vb.hasDataSizeChanged()){
208159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                glBufferData(target, vb.getData().capacity() * vb.getFormat().getComponentSize(), usage);
208259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
208359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
208459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            ByteBuffer buf = glMapBuffer(target,
208559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                                         GL_WRITE_ONLY,
208659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                                         vb.getMappedData());
208759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
208859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            if (buf != vb.getMappedData()){
208959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                buf = buf.order(ByteOrder.nativeOrder());
209059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                vb.setMappedData(buf);
209159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
209259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
209359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            buf.clear();
209459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
209559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            switch (vb.getFormat()){
209659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case Byte:
209759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case UnsignedByte:
209859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    buf.put( (ByteBuffer) vb.getData() );
209959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    break;
210059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case Short:
210159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case UnsignedShort:
210259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    buf.asShortBuffer().put( (ShortBuffer) vb.getData() );
210359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    break;
210459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case Int:
210559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case UnsignedInt:
210659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    buf.asIntBuffer().put( (IntBuffer) vb.getData() );
210759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    break;
210859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case Float:
210959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    buf.asFloatBuffer().put( (FloatBuffer) vb.getData() );
211059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    break;
211159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                case Double:
211259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    break;
211359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                default:
211459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//                    throw new RuntimeException("Unknown buffer format.");
211559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            }
211659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//
211759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            glUnmapBuffer(target);
211859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
211959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
212059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vb.clearUpdateNeeded();
212159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
212259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
212359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void deleteBuffer(VertexBuffer vb) {
212459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int bufId = vb.getId();
212559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (bufId != -1) {
212659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // delete buffer
212759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            intBuf1.put(0, bufId);
212859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            intBuf1.position(0).limit(1);
212959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDeleteBuffers(intBuf1);
213059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vb.resetObject();
213159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
213259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //statistics.onDeleteVertexBuffer();
213359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
213459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
213559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
213659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void clearVertexAttribs() {
213759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        IDList attribList = context.attribIndexList;
213859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < attribList.oldLen; i++) {
213959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int idx = attribList.oldList[i];
214059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDisableVertexAttribArray(idx);
214159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundAttribs[idx] = null;
214259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
214359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        context.attribIndexList.copyNewToOld();
214459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
214559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
214659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) {
214759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vb.getBufferType() == VertexBuffer.Type.Index) {
214859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib");
214959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
215059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
215159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int programId = context.boundShaderProgram;
215259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (programId > 0) {
215359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Attribute attrib = boundShader.getAttribute(vb.getBufferType());
215459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int loc = attrib.getLocation();
215559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (loc == -1) {
215659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return; // not defined
215759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
215859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (loc == -2) {
215959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                stringBuf.setLength(0);
216059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                stringBuf.append("in").append(vb.getBufferType().name()).append('\0');
216159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateNameBuffer();
216259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                loc = glGetAttribLocation(programId, nameBuf);
216359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
216459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // not really the name of it in the shader (inPosition\0) but
216559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // the internal name of the enum (Position).
216659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (loc < 0) {
216759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    attrib.setLocation(-1);
216859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return; // not available in shader.
216959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
217059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    attrib.setLocation(loc);
217159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
217259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
217359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
217459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vb.isUpdateNeeded() && idb == null) {
217559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                updateBufferData(vb);
217659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
217759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
217859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            VertexBuffer[] attribs = context.boundAttribs;
217959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!context.attribIndexList.moveToNew(loc)) {
218059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glEnableVertexAttribArray(loc);
218159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                //System.out.println("Enabled ATTRIB IDX: "+loc);
218259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
218359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (attribs[loc] != vb) {
218459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // NOTE: Use id from interleaved buffer if specified
218559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                int bufId = idb != null ? idb.getId() : vb.getId();
218659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                assert bufId != -1;
218759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (context.boundArrayVBO != bufId) {
218859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glBindBuffer(GL_ARRAY_BUFFER, bufId);
218959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.boundArrayVBO = bufId;
219059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    //statistics.onVertexBufferUse(vb, true);
219159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }else{
219259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    //statistics.onVertexBufferUse(vb, false);
219359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
219459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
219559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glVertexAttribPointer(loc,
219659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vb.getNumComponents(),
219759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertFormat(vb.getFormat()),
219859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vb.isNormalized(),
219959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vb.getStride(),
220059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vb.getOffset());
220159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
220259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                attribs[loc] = vb;
220359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
220459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
220559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalStateException("Cannot render mesh without shader bound");
220659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
220759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
220859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
220959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setVertexAttrib(VertexBuffer vb) {
221059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setVertexAttrib(vb, null);
221159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
221259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
221359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) {
221459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (count > 1) {
221559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ARBDrawInstanced.glDrawArraysInstancedARB(convertElementMode(mode), 0,
221659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    vertCount, count);
221759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
221859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glDrawArrays(convertElementMode(mode), 0, vertCount);
221959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
222059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
222159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
222259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) {
222359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (indexBuf.getBufferType() != VertexBuffer.Type.Index) {
222459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IllegalArgumentException("Only index buffers are allowed as triangle lists.");
222559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
222659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
222759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (indexBuf.isUpdateNeeded()) {
222859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateBufferData(indexBuf);
222959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
223059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
223159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int bufId = indexBuf.getId();
223259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        assert bufId != -1;
223359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
223459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundElementArrayVBO != bufId) {
223559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufId);
223659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundElementArrayVBO = bufId;
223759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //statistics.onVertexBufferUse(indexBuf, true);
223859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
223959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //statistics.onVertexBufferUse(indexBuf, true);
224059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
224159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
224259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int vertCount = mesh.getVertexCount();
224359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
224459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
224559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (mesh.getMode() == Mode.Hybrid) {
224659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int[] modeStart = mesh.getModeStart();
224759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int[] elementLengths = mesh.getElementLengths();
224859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
224959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int elMode = convertElementMode(Mode.Triangles);
225059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int fmt = convertFormat(indexBuf.getFormat());
225159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int elSize = indexBuf.getFormat().getComponentSize();
225259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int listStart = modeStart[0];
225359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int stripStart = modeStart[1];
225459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int fanStart = modeStart[2];
225559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int curOffset = 0;
225659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int i = 0; i < elementLengths.length; i++) {
225759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (i == stripStart) {
225859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    elMode = convertElementMode(Mode.TriangleStrip);
225959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (i == fanStart) {
226059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    elMode = convertElementMode(Mode.TriangleStrip);
226159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
226259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                int elementLength = elementLengths[i];
226359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
226459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (useInstancing) {
226559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    ARBDrawInstanced.glDrawElementsInstancedARB(elMode,
226659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            elementLength,
226759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fmt,
226859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            curOffset,
226959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            count);
227059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
227159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glDrawRangeElements(elMode,
227259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            0,
227359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            vertCount,
227459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            elementLength,
227559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            fmt,
227659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                            curOffset);
227759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
227859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
227959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                curOffset += elementLength * elSize;
228059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
228159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
228259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (useInstancing) {
228359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                ARBDrawInstanced.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()),
228459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        indexBuf.getData().limit(),
228559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertFormat(indexBuf.getFormat()),
228659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0,
228759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        count);
228859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
228959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDrawRangeElements(convertElementMode(mesh.getMode()),
229059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0,
229159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        vertCount,
229259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        indexBuf.getData().limit(),
229359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        convertFormat(indexBuf.getFormat()),
229459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        0);
229559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
229659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
229759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
229859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
229959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /*********************************************************************\
230059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    |* Render Calls                                                      *|
230159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    \*********************************************************************/
230259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int convertElementMode(Mesh.Mode mode) {
230359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        switch (mode) {
230459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Points:
230559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_POINTS;
230659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Lines:
230759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINES;
230859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case LineLoop:
230959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINE_LOOP;
231059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case LineStrip:
231159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_LINE_STRIP;
231259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case Triangles:
231359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_TRIANGLES;
231459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case TriangleFan:
231559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_TRIANGLE_FAN;
231659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            case TriangleStrip:
231759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return GL_TRIANGLE_STRIP;
231859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            default:
231959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode);
232059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
232159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
232259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
232359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateVertexArray(Mesh mesh) {
232459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int id = mesh.getId();
232559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (id == -1) {
232659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            IntBuffer temp = intBuf1;
232759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ARBVertexArrayObject.glGenVertexArrays(temp);
232859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            id = temp.get(0);
232959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            mesh.setId(id);
233059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
233159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
233259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundVertexArray != id) {
233359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ARBVertexArrayObject.glBindVertexArray(id);
233459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundVertexArray = id;
233559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
233659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
233759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
233859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (interleavedData != null && interleavedData.isUpdateNeeded()) {
233959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateBufferData(interleavedData);
234059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
234159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
234259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        IntMap<VertexBuffer> buffers = mesh.getBuffers();
234359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Entry<VertexBuffer> entry : buffers) {
234459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            VertexBuffer vb = entry.getValue();
234559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
234659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vb.getBufferType() == Type.InterleavedData
234759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
234859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    || vb.getBufferType() == Type.Index) {
234959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                continue;
235059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
235159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
235259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vb.getStride() == 0) {
235359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // not interleaved
235459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setVertexAttrib(vb);
235559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
235659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // interleaved
235759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setVertexAttrib(vb, interleavedData);
235859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
235959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
236059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
236159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
236259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void renderMeshVertexArray(Mesh mesh, int lod, int count) {
236359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (mesh.getId() == -1){
236459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateVertexArray(mesh);
236559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
236659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // TODO: Check if it was updated
236759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
236859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
236959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.boundVertexArray != mesh.getId()) {
237059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ARBVertexArrayObject.glBindVertexArray(mesh.getId());
237159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.boundVertexArray = mesh.getId();
237259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
237359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
237459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        IntMap<VertexBuffer> buffers = mesh.getBuffers();
237559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer indices = null;
237659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (mesh.getNumLodLevels() > 0) {
237759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            indices = mesh.getLodLevel(lod);
237859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
237959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            indices = mesh.getBuffer(Type.Index);
238059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
238159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (indices != null) {
238259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            drawTriangleList(indices, mesh, count);
238359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
238459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
238559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
238659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        clearVertexAttribs();
238759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        clearTextureUnits();
238859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
238959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
239059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void renderMeshDefault(Mesh mesh, int lod, int count) {
239159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer indices = null;
239259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
239359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
239459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (interleavedData != null && interleavedData.isUpdateNeeded()) {
239559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            updateBufferData(interleavedData);
239659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
239759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
239859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        IntMap<VertexBuffer> buffers = mesh.getBuffers();
239959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        SafeArrayList<VertexBuffer> buffersList = mesh.getBufferList();
240059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
240159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (mesh.getNumLodLevels() > 0) {
240259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            indices = mesh.getLodLevel(lod);
240359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
240459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            indices = mesh.getBuffer(Type.Index);
240559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
240659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
240759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        for (Entry<VertexBuffer> entry : buffers) {
240859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//             VertexBuffer vb = entry.getValue();
240959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (VertexBuffer vb : mesh.getBufferList().getArray()){
241059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vb.getBufferType() == Type.InterleavedData
241159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
241259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    || vb.getBufferType() == Type.Index) {
241359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                continue;
241459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
241559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
241659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (vb.getStride() == 0) {
241759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // not interleaved
241859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setVertexAttrib(vb);
241959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
242059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                // interleaved
242159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setVertexAttrib(vb, interleavedData);
242259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
242359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
242459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
242559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (indices != null) {
242659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            drawTriangleList(indices, mesh, count);
242759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
242859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
242959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
243059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        clearVertexAttribs();
243159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        clearTextureUnits();
243259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
243359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
243459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void renderMesh(Mesh mesh, int lod, int count) {
243559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (mesh.getVertexCount() == 0) {
243659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
243759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
243859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
243959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.pointSprite && mesh.getMode() != Mode.Points){
244059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // XXX: Hack, disable point sprite mode if mesh not in point mode
244159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (context.boundTextures[0] != null){
244259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (context.boundTextureUnit != 0){
244359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    glActiveTexture(GL_TEXTURE0);
244459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    context.boundTextureUnit = 0;
244559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
244659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_POINT_SPRITE);
244759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
244859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                context.pointSprite = false;
244959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
245059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
245159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
245259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.pointSize != mesh.getPointSize()) {
245359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glPointSize(mesh.getPointSize());
245459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.pointSize = mesh.getPointSize();
245559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
245659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (context.lineWidth != mesh.getLineWidth()) {
245759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            glLineWidth(mesh.getLineWidth());
245859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            context.lineWidth = mesh.getLineWidth();
245959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
246059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
246159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        statistics.onMeshDrawn(mesh, lod);
246259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        if (GLContext.getCapabilities().GL_ARB_vertex_array_object){
246359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            renderMeshVertexArray(mesh, lod, count);
246459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }else{
246559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderMeshDefault(mesh, lod, count);
246659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        }
246759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
246859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
2469