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