ar.com.quark.backend.lwjgl.opengl.DesktopGLES20.java Source code

Java tutorial

Introduction

Here is the source code for ar.com.quark.backend.lwjgl.opengl.DesktopGLES20.java

Source

/*
 * This file is part of Quark Framework, licensed under the APACHE License.
 *
 * Copyright (c) 2014-2016 Agustin L. Alvarez <wolftein1@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ar.com.quark.backend.lwjgl.opengl;

import ar.com.quark.system.utility.array.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.MemoryUtil;
import ar.com.quark.backend.lwjgl.utility.array.DesktopArrayFactory;
import ar.com.quark.render.Render;
import ar.com.quark.render.RenderCapabilities;
import ar.com.quark.system.utility.Manageable;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

import static ar.com.quark.render.Render.GLES3.GL_HALF_FLOAT;
import static ar.com.quark.render.Render.GLES3.GL_INT;
import static ar.com.quark.render.Render.GLES3.GL_UNSIGNED_INT;

/**
 * Implementation for {@link Render.GLES2}.
 */
public class DesktopGLES20 implements Render.GLES2 {
    protected final GLCapabilities mCapabilities;

    /**
     * Hold {@link EXT_Frame_Buffer_Object} extension.
     */
    protected final EXT_Frame_Buffer_Object mFrameBufferObjectExtension;

    /**
     * <p>Constructor</p>
     */
    public DesktopGLES20() {
        //!
        //! Read the capabilities.
        //!
        mCapabilities = GL.getCapabilities();

        //!
        //! Attach the extension(s).
        //!
        if (mCapabilities.OpenGL30) {
            mFrameBufferObjectExtension = EXT_Frame_Buffer_Object.CORE;
        } else if (mCapabilities.GL_ARB_framebuffer_object) {
            mFrameBufferObjectExtension = EXT_Frame_Buffer_Object.ARB;
        } else if (mCapabilities.GL_EXT_framebuffer_object) {
            mFrameBufferObjectExtension = EXT_Frame_Buffer_Object.EXT;
        } else {
            mFrameBufferObjectExtension = EXT_Frame_Buffer_Object.NONE;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RenderCapabilities glCapabilities() {
        //!
        //! Retrieves the capabilities from the context.
        //!
        final GLCapabilities capabilities = GL.getCapabilities();

        final RenderCapabilities.LanguageVersion version;
        if (capabilities.OpenGL33) {
            version = RenderCapabilities.LanguageVersion.GL33;
        } else if (capabilities.OpenGL32) {
            version = RenderCapabilities.LanguageVersion.GL32;
        } else if (capabilities.OpenGL31) {
            version = RenderCapabilities.LanguageVersion.GL31;
        } else if (capabilities.OpenGL30) {
            version = RenderCapabilities.LanguageVersion.GL30;
        } else if (capabilities.OpenGL21) {
            version = RenderCapabilities.LanguageVersion.GL21;
        } else {
            throw new RuntimeException("Cannot find a suitable context, OpenGL 2.1 is at-least required.");
        }

        //!
        //! Retrieves the limitation from the context.
        //!
        final Map<RenderCapabilities.Limit, Float> limit = new HashMap<>();

        limit.put(RenderCapabilities.Limit.FRAME_ATTACHMENT, GL11.glGetFloat(GL30.GL_MAX_COLOR_ATTACHMENTS));

        limit.put(RenderCapabilities.Limit.FRAME_MULTIPLE_RENDER_ATTACHMENT,
                GL11.glGetFloat(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB));

        limit.put(RenderCapabilities.Limit.FRAME_SAMPLE, GL11.glGetFloat(GL30.GL_MAX_SAMPLES));

        limit.put(RenderCapabilities.Limit.TEXTURE_ANISOTROPIC,
                GL11.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));

        limit.put(RenderCapabilities.Limit.TEXTURE_SIZE, GL11.glGetFloat(GL11.GL_MAX_TEXTURE_SIZE));

        limit.put(RenderCapabilities.Limit.TEXTURE_STAGE, GL11.glGetFloat(GL20.GL_MAX_TEXTURE_IMAGE_UNITS));

        limit.put(RenderCapabilities.Limit.GLSL_MAX_VERTEX_ATTRIBUTES, GL11.glGetFloat(GL20.GL_MAX_VERTEX_ATTRIBS));

        //!
        //! Retrieves the extension from the context.
        //!
        final Map<RenderCapabilities.Extension, Boolean> extension = new HashMap<>();

        extension.put(RenderCapabilities.Extension.FRAME_BUFFER, capabilities.GL_ARB_framebuffer_object);
        extension.put(RenderCapabilities.Extension.FRAME_BUFFER_MULTIPLE_RENDER_TARGET,
                capabilities.GL_ARB_draw_buffers);
        extension.put(RenderCapabilities.Extension.FRAME_BUFFER_MULTIPLE_SAMPLE, capabilities.GL_ARB_multisample);

        extension.put(RenderCapabilities.Extension.VERTEX_ARRAY_OBJECT, capabilities.GL_ARB_vertex_array_object);

        extension.put(RenderCapabilities.Extension.TEXTURE_3D, true);
        extension.put(RenderCapabilities.Extension.TEXTURE_COMPRESSION_S3TC,
                capabilities.GL_EXT_texture_compression_s3tc);
        extension.put(RenderCapabilities.Extension.TEXTURE_FILTER_ANISOTROPIC,
                capabilities.GL_EXT_texture_filter_anisotropic);

        extension.put(RenderCapabilities.Extension.GLSL_PRECISION, capabilities.GL_ARB_shader_precision);
        extension.put(RenderCapabilities.Extension.GLSL_EXPLICIT_ATTRIBUTE,
                capabilities.GL_ARB_explicit_attrib_location);
        extension.put(RenderCapabilities.Extension.GLSL_EXPLICIT_UNIFORM,
                capabilities.GL_ARB_explicit_uniform_location);
        extension.put(RenderCapabilities.Extension.GLSL_GEOMETRY, capabilities.GL_ARB_geometry_shader4);
        return new RenderCapabilities(version, extension, limit);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glEnable(int value) {
        GL11.glEnable(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDisable(int value) {
        GL11.glDisable(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBlendFunc(int source, int destination) {
        GL11.glBlendFunc(source, destination);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBlendEquationSeparate(int rgb, int alpha) {
        GL20.glBlendEquationSeparate(rgb, alpha);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glCullFace(int mode) {
        GL11.glCullFace(mode);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDepthMask(boolean activate) {
        GL11.glDepthMask(activate);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDepthRange(float near, float far) {
        GL11.glDepthRange(near, far);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDepthFunc(int mode) {
        GL11.glDepthFunc(mode);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glColorMask(boolean red, boolean green, boolean blue, boolean alpha) {
        GL11.glColorMask(red, green, blue, alpha);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glScissor(int x1, int y1, int x2, int y2) {
        GL11.glScissor(x1, y1, x2, y2);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glStencilOpSeparate(int face, int stencilFail, int depthFail, int depthPass) {
        GL20.glStencilOpSeparate(face, stencilFail, depthFail, depthPass);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glStencilFuncSeparate(int face, int func, int ref, int mask) {
        GL20.glStencilFuncSeparate(face, func, ref, mask);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glClear(int value) {
        GL11.glClear(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glClearColor(float red, float green, float blue, float alpha) {
        GL11.glClearColor(red, green, blue, alpha);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glViewport(int x, int y, int width, int height) {
        GL11.glViewport(x, y, width, height);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glGenTextures() {
        return GL11.glGenTextures();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glGenBuffers() {
        return GL15.glGenBuffers();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glCreateProgram() {
        return GL20.glCreateProgram();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glGenFramebuffers() {
        return mFrameBufferObjectExtension.glGenFramebuffers();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glGenRenderbuffers() {
        return mFrameBufferObjectExtension.glGenRenderbuffers();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDeleteTextures(int name) {
        GL11.glDeleteTextures(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDeleteBuffers(int name) {
        GL15.glDeleteBuffers(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDeleteProgram(int name) {
        GL20.glDeleteProgram(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDeleteFramebuffers(int name) {
        mFrameBufferObjectExtension.glDeleteFramebuffers(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDeleteRenderbuffers(int name) {
        mFrameBufferObjectExtension.glDeleteRenderbuffers(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glActiveTexture(int stage) {
        GL13.glActiveTexture(stage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBindTexture(int target, int name) {
        GL11.glBindTexture(target, name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBindBuffer(int target, int name) {
        GL15.glBindBuffer(target, name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUseProgram(int name) {
        GL20.glUseProgram(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBindFramebuffer(int type, int name) {
        mFrameBufferObjectExtension.glBindFramebuffer(type, name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBindRenderbuffer(int type, int name) {
        mFrameBufferObjectExtension.glBindRenderbuffer(type, name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, int capacity, int usage) {
        GL15.glBufferData(target, capacity, usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, Int8Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, Int16Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, Int32Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, UInt8Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, UInt16Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, UInt32Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, Float16Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferData(int target, Float32Array data, int usage) {
        GL15.nglBufferData(target, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()), usage);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, Int8Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, Int16Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, Int32Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, UInt8Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, UInt16Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, UInt32Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, Float16Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBufferSubData(int target, int offset, Float32Array data) {
        GL15.nglBufferSubData(target, offset, data.remaining(), MemoryUtil.memAddress(data.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDrawArrays(int primitive, int offset, int count) {
        GL11.glDrawArrays(primitive, offset, count);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDrawElements(int primitive, int count, int format, int offset) {
        GL11.glDrawElements(primitive, count, format, offset);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUnmapBuffer(int target) {
        GL15.glUnmapBuffer(target);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T extends Array<?>> T glMapBuffer(int target, int access, int format) {
        switch (format) {
        case GL_UNSIGNED_BYTE:
            return (T) new DesktopArrayFactory.DesktopUInt8Array(GL15.glMapBuffer(target, access));
        case GL_UNSIGNED_SHORT:
            return (T) new DesktopArrayFactory.DesktopUInt16Array(GL15.glMapBuffer(target, access));
        case GL_UNSIGNED_INT:
            return (T) new DesktopArrayFactory.DesktopUInt32Array(GL15.glMapBuffer(target, access));
        case GL_BYTE:
            return (T) new DesktopArrayFactory.DesktopInt8Array(GL15.glMapBuffer(target, access));
        case GL_SHORT:
            return (T) new DesktopArrayFactory.DesktopInt16Array(GL15.glMapBuffer(target, access));
        case GL_INT:
            return (T) new DesktopArrayFactory.DesktopInt32Array(GL15.glMapBuffer(target, access));
        case GL_HALF_FLOAT:
            return (T) new DesktopArrayFactory.DesktopFloat16Array(GL15.glMapBuffer(target, access));
        case GL_FLOAT:
            return (T) new DesktopArrayFactory.DesktopFloat32Array(GL15.glMapBuffer(target, access));
        }
        throw new IllegalArgumentException("Format unsupported");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glTexParameter(int target, int type, int value) {
        GL11.glTexParameteri(target, type, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glTexParameter(int target, int type, float value) {
        GL11.glTexParameterf(target, type, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glTexImage2D(int target, int level, int internal, int width, int height, int border, int format,
            int type, Int8Array data) {
        GL11.glTexImage2D(target, level, internal, width, height, border, format, type, data.<ByteBuffer>data());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glCompressedTexImage2D(int target, int level, int internal, int width, int height, int border,
            Int8Array data) {
        GL13.glCompressedTexImage2D(target, level, internal, width, height, border, data.data());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glGenerateMipmap(int target) {
        GL30.glGenerateMipmap(target);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glFramebufferTexture2D(int target, int attachment, int texture, int name, int level) {
        mFrameBufferObjectExtension.glFramebufferTexture2D(target, attachment, texture, name, level);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glEnableVertexAttribArray(int name) {
        GL20.glEnableVertexAttribArray(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDisableVertexAttribArray(int name) {
        GL20.glDisableVertexAttribArray(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glVertexAttribPointer(int name, int component, int type, boolean normalised, int stride,
            int offset) {
        GL20.glVertexAttribPointer(name, component, type, normalised, stride, offset);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glLinkProgram(int name) {
        GL20.glLinkProgram(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glGetProgram(int name, int property) {
        return GL20.glGetProgrami(name, property);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glDeleteShader(int name) {
        GL20.glDeleteShader(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glCreateShader(int type) {
        return GL20.glCreateShader(type);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glShaderSource(int name, String source) {
        GL20.glShaderSource(name, source);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glCompileShader(int name) {
        GL20.glCompileShader(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glAttachShader(int name, int shader) {
        GL20.glAttachShader(name, shader);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBindAttribLocation(int name, int id, String attribute) {
        GL20.glBindAttribLocation(name, id, attribute);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int glGetUniformLocation(int name, String uniform) {
        return GL20.glGetUniformLocation(name, uniform);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String glGetProgramInfoLog(int name) {
        return GL20.glGetProgramInfoLog(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glRenderbufferStorage(int target, int format, int width, int height) {
        mFrameBufferObjectExtension.glRenderbufferStorage(target, format, width, height);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform1f(int name, float i1) {
        GL20.glUniform1f(name, i1);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform2f(int name, float i1, float i2) {
        GL20.glUniform2f(name, i1, i2);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform3f(int name, float i1, float i2, float i3) {
        GL20.glUniform3f(name, i1, i2, i3);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform4f(int name, float i1, float i2, float i3, float i4) {
        GL20.glUniform4f(name, i1, i2, i3, i4);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform1fv(int name, Float32Array buffer) {
        GL20.nglUniform1fv(name, buffer.remaining(), MemoryUtil.memAddress(buffer.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform1i(int name, int i1) {
        GL20.glUniform1i(name, i1);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform2i(int name, int i1, int i2) {
        GL20.glUniform2i(name, i1, i2);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform3i(int name, int i1, int i2, int i3) {
        GL20.glUniform3i(name, i1, i2, i3);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform4i(int name, int i1, int i2, int i3, int i4) {
        GL20.glUniform4i(name, i1, i2, i3, i4);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniform1iv(int name, Int32Array buffer) {
        GL20.nglUniform1iv(name, buffer.remaining(), MemoryUtil.memAddress(buffer.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniformMatrix3fv(int name, boolean transpose, Float32Array buffer) {
        GL20.nglUniformMatrix3fv(name, (buffer.remaining() >> 2) / 9, transpose,
                MemoryUtil.memAddress(buffer.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glUniformMatrix4fv(int name, boolean transpose, Float32Array buffer) {
        GL20.nglUniformMatrix4fv(name, buffer.remaining() >> 6, transpose,
                MemoryUtil.memAddress(buffer.<ByteBuffer>data()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void glBindFragDataLocation(int name, int index, String attribute) {
        GL30.glBindFragDataLocation(name, index, attribute);
    }

    /**
     * @see <a href="https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt">Link</a>
     */
    private enum EXT_Frame_Buffer_Object {
        /**
         * Handle when {@link EXT_Frame_Buffer_Object} is not supported.
         */
        NONE,

        /**
         * Handle when {@link EXT_Frame_Buffer_Object} is supported by extension.
         */
        ARB,

        /**
         * Handle when {@link EXT_Frame_Buffer_Object} is supported by extension.
         */
        EXT,

        /**
         * Handle when {@link EXT_Frame_Buffer_Object} is fully supported.
         */
        CORE;

        /**
         * @see Render.GLES2#glGenFramebuffers()
         */
        public int glGenFramebuffers() {
            switch (this) {
            case ARB:
                return ARBFramebufferObject.glGenFramebuffers();
            case EXT:
                return EXTFramebufferObject.glGenFramebuffersEXT();
            case CORE:
                return GL30.glGenFramebuffers();
            }
            return Manageable.INVALID_HANDLE;
        }

        /**
         * @see Render.GLES2#glGenRenderbuffers()
         */
        public int glGenRenderbuffers() {
            switch (this) {
            case ARB:
                return ARBFramebufferObject.glGenRenderbuffers();
            case EXT:
                return EXTFramebufferObject.glGenRenderbuffersEXT();
            case CORE:
                return GL30.glGenRenderbuffers();
            }
            return Manageable.INVALID_HANDLE;
        }

        /**
         * @see Render.GLES2#glBindFramebuffer(int, int)
         */
        public void glBindFramebuffer(int type, int name) {
            switch (this) {
            case ARB:
                ARBFramebufferObject.glBindFramebuffer(type, name);
                break;
            case EXT:
                EXTFramebufferObject.glBindFramebufferEXT(type, name);
                break;
            case CORE:
                GL30.glBindFramebuffer(type, name);
                break;
            }
        }

        /**
         * @see Render.GLES2#glBindRenderbuffer(int, int)
         */
        public void glBindRenderbuffer(int type, int name) {
            switch (this) {
            case ARB:
                ARBFramebufferObject.glBindRenderbuffer(type, name);
                break;
            case EXT:
                EXTFramebufferObject.glBindRenderbufferEXT(type, name);
                break;
            case CORE:
                GL30.glBindRenderbuffer(type, name);
                break;
            }
        }

        /**
         * @see Render.GLES2#glFramebufferTexture2D(int, int, int, int, int)
         */
        public void glFramebufferTexture2D(int target, int attachment, int texture, int name, int level) {
            switch (this) {
            case ARB:
                ARBFramebufferObject.glFramebufferTexture2D(target, attachment, texture, name, level);
                break;
            case EXT:
                EXTFramebufferObject.glFramebufferTexture2DEXT(target, attachment, texture, name, level);
                break;
            case CORE:
                GL30.glFramebufferTexture2D(target, attachment, texture, name, level);
                break;
            }
        }

        /**
         * @see Render.GLES2#glRenderbufferStorage(int, int, int, int)
         */
        public void glRenderbufferStorage(int target, int format, int width, int height) {
            switch (this) {
            case ARB:
                ARBFramebufferObject.glRenderbufferStorage(target, format, width, height);
                break;
            case EXT:
                EXTFramebufferObject.glRenderbufferStorageEXT(target, format, width, height);
                break;
            case CORE:
                GL30.glRenderbufferStorage(target, format, width, height);
                break;
            }
        }

        /**
         * @see Render.GLES2#glDeleteFramebuffers(int)
         */
        public void glDeleteFramebuffers(int name) {
            switch (this) {
            case ARB:
                ARBFramebufferObject.glDeleteFramebuffers(name);
                break;
            case EXT:
                EXTFramebufferObject.glDeleteFramebuffersEXT(name);
                break;
            case CORE:
                GL30.glDeleteFramebuffers(name);
                break;
            }
        }

        /**
         * @see Render.GLES2#glDeleteRenderbuffers(int)
         */
        public void glDeleteRenderbuffers(int name) {
            switch (this) {
            case ARB:
                ARBFramebufferObject.glDeleteRenderbuffers(name);
                break;
            case EXT:
                EXTFramebufferObject.glDeleteRenderbuffersEXT(name);
                break;
            case CORE:
                GL30.glDeleteRenderbuffers(name);
                break;
            }
        }
    }
}