Home | History | Annotate | Download | only in graphics
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.graphics;
     18 
     19 import com.badlogic.gdx.Gdx;
     20 import com.badlogic.gdx.graphics.Pixmap.Blending;
     21 import com.badlogic.gdx.graphics.Texture.TextureFilter;
     22 import com.badlogic.gdx.graphics.Texture.TextureWrap;
     23 import com.badlogic.gdx.graphics.TextureData.TextureDataType;
     24 import com.badlogic.gdx.graphics.glutils.MipMapGenerator;
     25 import com.badlogic.gdx.utils.Disposable;
     26 
     27 /** Class representing an OpenGL texture by its target and handle. Keeps track of its state like the TextureFilter and TextureWrap.
     28  * Also provides some (protected) static methods to create TextureData and upload image data.
     29  * @author badlogic, Xoppa */
     30 public abstract class GLTexture implements Disposable {
     31 	/** The target of this texture, used when binding the texture, e.g. GL_TEXTURE_2D */
     32 	public final int glTarget;
     33 	protected int glHandle;
     34 	protected TextureFilter minFilter = TextureFilter.Nearest;
     35 	protected TextureFilter magFilter = TextureFilter.Nearest;
     36 	protected TextureWrap uWrap = TextureWrap.ClampToEdge;
     37 	protected TextureWrap vWrap = TextureWrap.ClampToEdge;
     38 
     39 	/** @return the width of the texture in pixels */
     40 	public abstract int getWidth ();
     41 
     42 	/** @return the height of the texture in pixels */
     43 	public abstract int getHeight ();
     44 
     45 	/** @return the depth of the texture in pixels */
     46 	public abstract int getDepth ();
     47 
     48 	/** Generates a new OpenGL texture with the specified target. */
     49 	public GLTexture (int glTarget) {
     50 		this(glTarget, Gdx.gl.glGenTexture ());
     51 	}
     52 
     53 	public GLTexture (int glTarget, int glHandle) {
     54 		this.glTarget = glTarget;
     55 		this.glHandle = glHandle;
     56 	}
     57 
     58 	/** @return whether this texture is managed or not. */
     59 	public abstract boolean isManaged ();
     60 
     61 	protected abstract void reload ();
     62 
     63 	/** Binds this texture. The texture will be bound to the currently active texture unit specified via
     64 	 * {@link GL20#glActiveTexture(int)}. */
     65 	public void bind () {
     66 		Gdx.gl.glBindTexture(glTarget, glHandle);
     67 	}
     68 
     69 	/** Binds the texture to the given texture unit. Sets the currently active texture unit via {@link GL20#glActiveTexture(int)}.
     70 	 * @param unit the unit (0 to MAX_TEXTURE_UNITS). */
     71 	public void bind (int unit) {
     72 		Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0 + unit);
     73 		Gdx.gl.glBindTexture(glTarget, glHandle);
     74 	}
     75 
     76 	/** @return The {@link Texture.TextureFilter} used for minification. */
     77 	public TextureFilter getMinFilter () {
     78 		return minFilter;
     79 	}
     80 
     81 	/** @return The {@link Texture.TextureFilter} used for magnification. */
     82 	public TextureFilter getMagFilter () {
     83 		return magFilter;
     84 	}
     85 
     86 	/** @return The {@link Texture.TextureWrap} used for horizontal (U) texture coordinates. */
     87 	public TextureWrap getUWrap () {
     88 		return uWrap;
     89 	}
     90 
     91 	/** @return The {@link Texture.TextureWrap} used for vertical (V) texture coordinates. */
     92 	public TextureWrap getVWrap () {
     93 		return vWrap;
     94 	}
     95 
     96 	/** @return The OpenGL handle for this texture. */
     97 	public int getTextureObjectHandle () {
     98 		return glHandle;
     99 	}
    100 
    101 	/** Sets the {@link TextureWrap} for this texture on the u and v axis. Assumes the texture is bound and active!
    102 	 * @param u the u wrap
    103 	 * @param v the v wrap */
    104 	public void unsafeSetWrap (TextureWrap u, TextureWrap v) {
    105 		unsafeSetWrap(u, v, false);
    106 	}
    107 
    108 	/** Sets the {@link TextureWrap} for this texture on the u and v axis. Assumes the texture is bound and active!
    109 	 * @param u the u wrap
    110 	 * @param v the v wrap
    111 	 * @param force True to always set the values, even if they are the same as the current values. */
    112 	public void unsafeSetWrap (TextureWrap u, TextureWrap v, boolean force) {
    113 		if (u != null && (force || uWrap != u)) {
    114 			Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_WRAP_S, u.getGLEnum());
    115 			uWrap = u;
    116 		}
    117 		if (v != null && (force || vWrap != v)) {
    118 			Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_WRAP_T, v.getGLEnum());
    119 			vWrap = v;
    120 		}
    121 	}
    122 
    123 	/** Sets the {@link TextureWrap} for this texture on the u and v axis. This will bind this texture!
    124 	 * @param u the u wrap
    125 	 * @param v the v wrap */
    126 	public void setWrap (TextureWrap u, TextureWrap v) {
    127 		this.uWrap = u;
    128 		this.vWrap = v;
    129 		bind();
    130 		Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_WRAP_S, u.getGLEnum());
    131 		Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_WRAP_T, v.getGLEnum());
    132 	}
    133 
    134 	/** Sets the {@link TextureFilter} for this texture for minification and magnification. Assumes the texture is bound and active!
    135 	 * @param minFilter the minification filter
    136 	 * @param magFilter the magnification filter */
    137 	public void unsafeSetFilter (TextureFilter minFilter, TextureFilter magFilter) {
    138 		unsafeSetFilter(minFilter, magFilter, false);
    139 	}
    140 
    141 	/** Sets the {@link TextureFilter} for this texture for minification and magnification. Assumes the texture is bound and active!
    142 	 * @param minFilter the minification filter
    143 	 * @param magFilter the magnification filter
    144 	 * @param force True to always set the values, even if they are the same as the current values. */
    145 	public void unsafeSetFilter (TextureFilter minFilter, TextureFilter magFilter, boolean force) {
    146 		if (minFilter != null && (force || this.minFilter != minFilter)) {
    147 			Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_MIN_FILTER, minFilter.getGLEnum());
    148 			this.minFilter = minFilter;
    149 		}
    150 		if (magFilter != null && (force || this.magFilter != magFilter)) {
    151 			Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_MAG_FILTER, magFilter.getGLEnum());
    152 			this.magFilter = magFilter;
    153 		}
    154 	}
    155 
    156 	/** Sets the {@link TextureFilter} for this texture for minification and magnification. This will bind this texture!
    157 	 * @param minFilter the minification filter
    158 	 * @param magFilter the magnification filter */
    159 	public void setFilter (TextureFilter minFilter, TextureFilter magFilter) {
    160 		this.minFilter = minFilter;
    161 		this.magFilter = magFilter;
    162 		bind();
    163 		Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_MIN_FILTER, minFilter.getGLEnum());
    164 		Gdx.gl.glTexParameterf(glTarget, GL20.GL_TEXTURE_MAG_FILTER, magFilter.getGLEnum());
    165 	}
    166 
    167 	/** Destroys the OpenGL Texture as specified by the glHandle. */
    168 	protected void delete () {
    169 		if (glHandle != 0) {
    170 			Gdx.gl.glDeleteTexture (glHandle);
    171 			glHandle = 0;
    172 		}
    173 	}
    174 
    175 	@Override
    176 	public void dispose () {
    177 		delete();
    178 	}
    179 
    180 	protected static void uploadImageData (int target, TextureData data) {
    181 		uploadImageData(target, data, 0);
    182 	}
    183 
    184 	public static void uploadImageData (int target, TextureData data, int miplevel) {
    185 		if (data == null) {
    186 			// FIXME: remove texture on target?
    187 			return;
    188 		}
    189 
    190 		if (!data.isPrepared()) data.prepare();
    191 
    192 		final TextureDataType type = data.getType();
    193 		if (type == TextureDataType.Custom) {
    194 			data.consumeCustomData(target);
    195 			return;
    196 		}
    197 
    198 		Pixmap pixmap = data.consumePixmap();
    199 		boolean disposePixmap = data.disposePixmap();
    200 		if (data.getFormat() != pixmap.getFormat()) {
    201 			Pixmap tmp = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), data.getFormat());
    202 			Blending blend = Pixmap.getBlending();
    203 			Pixmap.setBlending(Blending.None);
    204 			tmp.drawPixmap(pixmap, 0, 0, 0, 0, pixmap.getWidth(), pixmap.getHeight());
    205 			Pixmap.setBlending(blend);
    206 			if (data.disposePixmap()) {
    207 				pixmap.dispose();
    208 			}
    209 			pixmap = tmp;
    210 			disposePixmap = true;
    211 		}
    212 
    213 		Gdx.gl.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 1);
    214 		if (data.useMipMaps()) {
    215 			MipMapGenerator.generateMipMap(target, pixmap, pixmap.getWidth(), pixmap.getHeight());
    216 		} else {
    217 			Gdx.gl.glTexImage2D(target, miplevel, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0,
    218 				pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels());
    219 		}
    220 		if (disposePixmap) pixmap.dispose();
    221 	}
    222 }
    223