com.samrj.devil.gl.Texture.java Source code

Java tutorial

Introduction

Here is the source code for com.samrj.devil.gl.Texture.java

Source

/*
 * Copyright (c) 2015 Sam Johnson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.samrj.devil.gl;

import com.samrj.devil.io.MemStack;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL33;

/**
 * Abstract OpenGL texture class.
 * 
 * @author Samuel Johnson (SmashMaster)
 * @param <T> This texture's own type.
 */
public abstract class Texture<T extends Texture<T>> extends DGLObj {
    public final int id, target, binding;
    private boolean deleted;
    private boolean hasMipmaps;
    private long vramUsage;

    Texture(int target, int binding) {
        DGL.checkState();
        id = GL11.glGenTextures();
        this.target = target;
        this.binding = binding;
    }

    abstract T getThis();

    /**
     * @return Whether this texture is bound to the currently active texture channel.
     */
    public final boolean isBound() {
        return !deleted && GL11.glGetInteger(binding) == id;
    }

    final int tempBind() {
        int oldID = GL11.glGetInteger(binding);
        if (oldID != id)
            GL11.glBindTexture(target, id);
        return oldID;
    }

    final void tempUnbind(int oldID) {
        if (oldID == id)
            return;
        GL11.glBindTexture(target, oldID);
    }

    final void setVRAMUsage(long bits) {
        if (bits < 0)
            throw new IllegalArgumentException();
        if (deleted)
            return;
        if (hasMipmaps)
            bits *= 2;
        Profiler.addUsedVRAM(bits - vramUsage);
        vramUsage = bits;
    }

    /**
     * Binds this OpenGL texture to whichever texture unit is currently active.
     * 
     * @return This texture.
     */
    public final T bind() {
        if (deleted)
            throw new IllegalStateException("Cannot bind deleted texture.");
        GL11.glBindTexture(target, id);
        return getThis();
    }

    /**
     * Temporarily activates the given texture unit, binds this texture to it,
     * then activates whichever unit was active before this method was called.
     * 
     * @param texture The OpenGL texture unit enum to bind to.
     * @return This texture.
     */
    public final T bind(int texture) {
        if (deleted)
            throw new IllegalStateException("Cannot bind deleted texture.");
        if (texture < GL13.GL_TEXTURE0)
            throw new IllegalArgumentException();
        int old = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE);
        GL13.glActiveTexture(texture);
        bind();
        GL13.glActiveTexture(old);
        return getThis();
    }

    /**
     * Unbinds any texture currently bound to the current texture unit. Might
     * not be this texture! Manage your texture state carefully.
     * 
     * @return This texture.
     */
    public final T unbind() {
        if (isBound())
            GL11.glBindTexture(target, 0);
        return getThis();
    }

    @Override
    final void delete() {
        Profiler.removeUsedVRAM(vramUsage);
        GL11.glDeleteTextures(id);
        deleted = true;
    }

    /**
     * Sets the given parameter to the given int for this texture. The texture
     * must be bound.
     * 
     * @param param The OpenGL texture parameter to set.
     * @param value The value to set the parameter to.
     * @return This texture.
     */
    public final T parami(int param, int value) {
        if (!isBound())
            throw new IllegalStateException("Texture must be bound.");
        GL11.glTexParameteri(target, param, value);
        return getThis();
    }

    //    public final T paramiv(int param, int... values)
    //    {
    //        if (!isBound()) throw new IllegalStateException("Texture must be bound.");
    //        long address = MemStack.wrapi(values);
    //        GL11.nglTexParameteriv(target, param, address);
    //        MemStack.pop();
    //        return getThis();
    //    }

    /**
     * Sets the given parameter to the given float for this texture. The texture
     * must be bound.
     * 
     * @param param The OpenGL texture parameter to set.
     * @param value The value to set the parameter to.
     * @return This texture.
     */
    public final T paramf(int param, float value) {
        if (!isBound())
            throw new IllegalStateException("Texture must be bound.");
        GL11.glTexParameterf(target, param, value);
        return getThis();
    }

    //    public final T paramfv(int param, float... values)
    //    {
    //        if (!isBound()) throw new IllegalStateException("Texture must be bound.");
    //        long address = MemStack.wrapf(values);
    //        GL11.nglTexParameterfv(target, param, address);
    //        MemStack.pop();
    //        return getThis();
    //    }

    public final T swizzle(int r, int g, int b, int a) {
        if (!isBound())
            throw new IllegalStateException("Texture must be bound.");
        long address = MemStack.wrapi(r, g, b, a);
        GL11.nglTexParameteriv(target, GL33.GL_TEXTURE_SWIZZLE_RGBA, address);
        MemStack.pop();
        return getThis();
    }

    /**
     * Generates mipmaps for this texture.
     * 
     * @return This texture.
     */
    public final T generateMipmap() {
        int oldID = tempBind();
        GL30.glGenerateMipmap(target);
        if (!hasMipmaps)
            setVRAMUsage(vramUsage * 2);
        hasMipmaps = true;
        tempUnbind(oldID);
        return getThis();
    }
}