Package org.newdawn.slick.opengl

Source Code of org.newdawn.slick.opengl.InternalTextureLoader

package org.newdawn.slick.opengl;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.HashMap;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.util.ResourceLoader;

/**
* A texture loaded based on many old versions that will load image data from a file
* and produce OpenGL textures.
*
* @see ImageData
*
* @author kevin
*/
public class InternalTextureLoader {
  /** The standard texture loaded used everywhere */
  private static final InternalTextureLoader loader = new InternalTextureLoader();
 
  /**
   * Get the single instance of this texture loader
   *
   * @return The single instance of the texture loader
   */
  public static InternalTextureLoader get() {
    return loader;
  }
 
    /** The table of textures that have been loaded in this loader */
    private HashMap texturesLinear = new HashMap();
    /** The table of textures that have been loaded in this loader */
    private HashMap texturesNearest = new HashMap();
    /** The destination pixel format */
    private int dstPixelFormat = GL11.GL_RGBA;
    /** True if we're using deferred loading */
    private boolean deferred;
   
    /**
     * Create a new texture loader based on the game panel
     */
    private InternalTextureLoader() {
    }
   
    /**
     * True if we should only record the request to load in the intention
     * of loading the texture later
     *
     * @param deferred True if the we should load a token
     */
    public void setDeferredLoading(boolean deferred) {
      this.deferred = deferred;
    }
   
    /**
     * Check if we're using deferred loading
     *
     * @return True if we're loading deferred textures
     */
    public boolean isDeferredLoading() {
      return deferred;
    }
   
    /**
     * Clear out the cached textures
     */
    public void clear() {
      texturesLinear.clear();
      texturesNearest.clear();
    }
   
    /**
     * Tell the loader to produce 16 bit textures
     */
    public void set16BitMode() {
      dstPixelFormat = GL11.GL_RGBA16;
    }
   
    /**
     * Create a new texture ID
     *
     * @return A new texture ID
     */
    public static int createTextureID()
    {
       IntBuffer tmp = createIntBuffer(1);
       GL11.glGenTextures(tmp);
       return tmp.get(0);
    }
   
    /**
     * Get a texture from a specific file
     *
     * @param source The file to load the texture from
     * @param flipped True if we should flip the texture on the y axis while loading
     * @param filter The filter to use
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    public Texture getTexture(File source, boolean flipped,int filter) throws IOException {
      String resourceName = source.getAbsolutePath();
      InputStream in = new FileInputStream(source);
     
      return getTexture(in, resourceName, flipped, filter, null);
    }
   
    /**
     * Get a texture from a specific file
     *
     * @param source The file to load the texture from
     * @param flipped True if we should flip the texture on the y axis while loading
     * @param filter The filter to use
   * @param transparent The colour to interpret as transparent or null if none
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    public Texture getTexture(File source, boolean flipped,int filter, int[] transparent) throws IOException {
      String resourceName = source.getAbsolutePath();
      InputStream in = new FileInputStream(source);
     
      return getTexture(in, resourceName, flipped, filter, transparent);
    }

    /**
     * Get a texture from a resource location
     *
     * @param resourceName The location to load the texture from
     * @param flipped True if we should flip the texture on the y axis while loading
     * @param filter The filter to use when scaling the texture
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    public Texture getTexture(String resourceName, boolean flipped, int filter) throws IOException {
      InputStream in = ResourceLoader.getResourceAsStream(resourceName);
     
      return getTexture(in, resourceName, flipped, filter, null);
    }
   
    /**
     * Get a texture from a resource location
     *
     * @param resourceName The location to load the texture from
     * @param flipped True if we should flip the texture on the y axis while loading
     * @param filter The filter to use when scaling the texture
   * @param transparent The colour to interpret as transparent or null if none
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    public Texture getTexture(String resourceName, boolean flipped, int filter, int[] transparent) throws IOException {
      HashMap hash = texturesLinear;
        if (filter == GL11.GL_NEAREST) {
          hash = texturesNearest;
        }       
        String resName = resourceName;
        if (transparent != null) {
          resName += ":"+transparent[0]+":"+transparent[1]+":"+transparent[2];
        }       
      SoftReference ref = (SoftReference) hash.get(resName);
      if (ref != null) {
        TextureImpl tex = (TextureImpl) ref.get();
          if (tex != null) {
            return tex;
          } else {
            hash.remove(resName);
          }
      }
     
      InputStream in = ResourceLoader.getResourceAsStream(resourceName);
     
      return getTexture(in, resourceName, flipped, filter, transparent);
    }
    /**
     * Get a texture from a image file
     *
     * @param in The stream from which we can load the image
     * @param resourceName The name to give this image in the internal cache
     * @param flipped True if we should flip the image on the y-axis while loading
     * @param filter The filter to use when scaling the texture
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    public Texture getTexture(InputStream in, String resourceName, boolean flipped, int filter) throws IOException {
      return getTexture(in, resourceName, flipped, filter, null);
    }
   
    /**
     * Get a texture from a image file
     *
     * @param in The stream from which we can load the image
     * @param resourceName The name to give this image in the internal cache
     * @param flipped True if we should flip the image on the y-axis while loading
     * @param filter The filter to use when scaling the texture
   * @param transparent The colour to interpret as transparent or null if none
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    public TextureImpl getTexture(InputStream in, String resourceName, boolean flipped, int filter, int[] transparent) throws IOException {
      if (deferred) {
        return new DeferredTexture(in, resourceName, flipped, filter, transparent);
      }
     
      HashMap hash = texturesLinear;
        if (filter == GL11.GL_NEAREST) {
          hash = texturesNearest;
        }
       
        String resName = resourceName;
        if (transparent != null) {
          resName += ":"+transparent[0]+":"+transparent[1]+":"+transparent[2];
        }
       
      SoftReference ref = (SoftReference) hash.get(resName);
      if (ref != null) {
        TextureImpl tex = (TextureImpl) ref.get();
          if (tex != null) {
            return tex;
          } else {
            hash.remove(resName);
          }
      }
       
        // horrible test until I can find something more suitable
        try {
          GL11.glGetError();
        } catch (NullPointerException e) {
          throw new RuntimeException("Image based resources must be loaded as part of init() or the game loop. They cannot be loaded before initialisation.");
        }
       
        TextureImpl tex = getTexture(in, resourceName,
                         GL11.GL_TEXTURE_2D,
                         filter,
                         filter, flipped, transparent);
       
        hash.put(resName, new SoftReference(tex));
       
        return tex;
    }

    /**
     * Get a texture from a image file
     *
     * @param in The stream from which we can load the image
     * @param resourceName The name to give this image in the internal cache
     * @param flipped True if we should flip the image on the y-axis while loading
     * @param target The texture target we're loading this texture into
     * @param minFilter The scaling down filter
     * @param magFilter The scaling up filter
   * @param transparent The colour to interpret as transparent or null if none
     * @return The texture loaded
     * @throws IOException Indicates a failure to load the image
     */
    private TextureImpl getTexture(InputStream in,
                  String resourceName,
                              int target,
                              int magFilter,
                              int minFilter, boolean flipped, int[] transparent) throws IOException
    {
        // create the texture ID for this texture
        int textureID = createTextureID();
        TextureImpl texture = new TextureImpl(resourceName, target, textureID);
       
        // bind this texture
        GL11.glBindTexture(target, textureID);
        ByteBuffer textureBuffer;
        int width;
        int height;
        int texWidth;
        int texHeight;
       
        boolean hasAlpha;
       
        LoadableImageData imageData = ImageDataFactory.getImageDataFor(resourceName);
      textureBuffer = imageData.loadImage(new BufferedInputStream(in), flipped, transparent);
     
      width = imageData.getWidth();
      height = imageData.getHeight();
      hasAlpha = imageData.getDepth() == 32;
     
      texture.setTextureWidth(imageData.getTexWidth());
      texture.setTextureHeight(imageData.getTexHeight());

        texWidth = texture.getTextureWidth();
        texHeight = texture.getTextureHeight();

        IntBuffer temp = BufferUtils.createIntBuffer(16);
        GL11.glGetInteger(GL11.GL_MAX_TEXTURE_SIZE, temp);
        int max = temp.get(0);
        if ((texWidth > max) || (texHeight > max)) {
          throw new IOException("Attempt to allocate a texture to big for the current hardware");
        }
       
        int srcPixelFormat = hasAlpha ? GL11.GL_RGBA : GL11.GL_RGB;
        int componentCount = hasAlpha ? 4 : 3;
       
        texture.setWidth(width);
        texture.setHeight(height);
        texture.setAlpha(hasAlpha);
       
        GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
        GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
       
        // produce a texture from the byte buffer
        GL11.glTexImage2D(target,
                      0,
                      dstPixelFormat,
                      get2Fold(width),
                      get2Fold(height),
                      0,
                      srcPixelFormat,
                      GL11.GL_UNSIGNED_BYTE,
                      textureBuffer);
       
        return texture;
    }
   
    /**
     * Create an empty texture
     *
     * @param width The width of the new texture
     * @param height The height of the new texture
     * @return The created empty texture
     * @throws IOException Indicates a failure to create the texture on the graphics hardware
     */
    public Texture createTexture(final int width, final int height) throws IOException {
      ImageData ds = new EmptyImageData(width, height);
     
      return getTexture(ds, GL11.GL_NEAREST);
    }
   
    /**
     * Get a texture from a image file
     *
     * @param dataSource The image data to generate the texture from
     * @param filter The filter to use when scaling the texture
     * @return The texture created
     * @throws IOException Indicates the texture is too big for the hardware
     */
    public Texture getTexture(ImageData dataSource, int filter) throws IOException
    {
      int target = GL11.GL_TEXTURE_2D;
     
        // create the texture ID for this texture
        int textureID = createTextureID();
        TextureImpl texture = new TextureImpl("generated:"+dataSource, target ,textureID);
       
        int minFilter = filter;
        int magFilter = filter;
        boolean flipped = false;
       
        // bind this texture
        GL11.glBindTexture(target, textureID);
        ByteBuffer textureBuffer;
        int width;
        int height;
        int texWidth;
        int texHeight;
       
        boolean hasAlpha;
      textureBuffer = dataSource.getImageBufferData();
     
      width = dataSource.getWidth();
      height = dataSource.getHeight();
      hasAlpha = dataSource.getDepth() == 32;
     
      texture.setTextureWidth(dataSource.getTexWidth());
      texture.setTextureHeight(dataSource.getTexHeight());

        texWidth = texture.getTextureWidth();
        texHeight = texture.getTextureHeight();
       
        int srcPixelFormat = hasAlpha ? GL11.GL_RGBA : GL11.GL_RGB;
        int componentCount = hasAlpha ? 4 : 3;
       
        texture.setWidth(width);
        texture.setHeight(height);
        texture.setAlpha(hasAlpha);
       
        IntBuffer temp = BufferUtils.createIntBuffer(16);
        GL11.glGetInteger(GL11.GL_MAX_TEXTURE_SIZE, temp);
        int max = temp.get(0);
        if ((texWidth > max) || (texHeight > max)) {
          throw new IOException("Attempt to allocate a texture to big for the current hardware");
        }
       
        GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
        GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
       
        // produce a texture from the byte buffer
        GL11.glTexImage2D(target,
                      0,
                      dstPixelFormat,
                      get2Fold(width),
                      get2Fold(height),
                      0,
                      srcPixelFormat,
                      GL11.GL_UNSIGNED_BYTE,
                      textureBuffer);
       
        return texture;
    }
   
    /**
     * Get the closest greater power of 2 to the fold number
     *
     * @param fold The target number
     * @return The power of 2
     */
    public static int get2Fold(int fold) {
        int ret = 2;
        while (ret < fold) {
            ret *= 2;
        }
        return ret;
    }
   
    /**
     * Creates an integer buffer to hold specified ints
     * - strictly a utility method
     *
     * @param size how many int to contain
     * @return created IntBuffer
     */
    public static IntBuffer createIntBuffer(int size) {
      ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
      temp.order(ByteOrder.nativeOrder());

      return temp.asIntBuffer();
    }   
}
TOP

Related Classes of org.newdawn.slick.opengl.InternalTextureLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.