--- /dev/null
+package com.badlogic.gdx.graphics;
+
+import java.nio.IntBuffer;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.Pixmap.Blending;
+import com.badlogic.gdx.graphics.Pixmap.Format;
+import com.badlogic.gdx.graphics.Texture.TextureFilter;
+import com.badlogic.gdx.graphics.Texture.TextureWrap;
+import com.badlogic.gdx.graphics.TextureData.TextureDataType;
+import com.badlogic.gdx.graphics.glutils.FileTextureData;
+import com.badlogic.gdx.graphics.glutils.MipMapGenerator;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.utils.BufferUtils;
+import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.GdxRuntimeException;
+
+/**
+ * Class representing an OpenGL texture by its target and handle.
+ * Keeps track of its state like the TextureFilter and TextureWrap.
+ * Also provides some (protected) static methods to create TextureData and upload image data.
+ * @author badlogic, Xoppa
+ */
+public abstract class GLTexture implements Disposable {
+ /** The target of this texture, used when binding the texture, e.g. GL_TEXTURE_2D */
+ public final int glTarget;
+ protected int glHandle;
+ protected TextureFilter minFilter = TextureFilter.Nearest;
+ protected TextureFilter magFilter = TextureFilter.Nearest;
+ protected TextureWrap uWrap = TextureWrap.ClampToEdge;
+ protected TextureWrap vWrap = TextureWrap.ClampToEdge;
+
+ /** @return the width of the texture in pixels */
+ public abstract int getWidth();
+
+ /** @return the height of the texture in pixels */
+ public abstract int getHeight();
+
+ /** @return the depth of the texture in pixels */
+ public abstract int getDepth();
+
+ /** Generates a new OpenGL texture with the specified target. */
+ public GLTexture(int glTarget) {
+ this(glTarget, createGLHandle());
+ }
+
+ public GLTexture(int glTarget, int glHandle) {
+ this.glTarget = glTarget;
+ this.glHandle = glHandle;
+ }
+
+ /** @return whether this texture is managed or not. */
+ public abstract boolean isManaged ();
+
+ protected abstract void reload();
+
+ /** Binds this texture. The texture will be bound to the currently active texture unit specified via
+ * {@link GLCommon#glActiveTexture(int)}. */
+ public void bind () {
+ Gdx.gl.glBindTexture(glTarget, glHandle);
+ }
+
+ /** Binds the texture to the given texture unit. Sets the currently active texture unit via
+ * {@link GLCommon#glActiveTexture(int)}.
+ * @param unit the unit (0 to MAX_TEXTURE_UNITS). */
+ public void bind (int unit) {
+ Gdx.gl.glActiveTexture(GL10.GL_TEXTURE0 + unit);
+ Gdx.gl.glBindTexture(glTarget, glHandle);
+ }
+
+ /** @return The {@link Texture.TextureFilter} used for minification. */
+ public TextureFilter getMinFilter () {
+ return minFilter;
+ }
+
+ /** @return The {@link Texture.TextureFilter} used for magnification. */
+ public TextureFilter getMagFilter () {
+ return magFilter;
+ }
+
+ /** @return The {@link Texture.TextureWrap} used for horizontal (U) texture coordinates. */
+ public TextureWrap getUWrap () {
+ return uWrap;
+ }
+
+ /** @return The {@link Texture.TextureWrap} used for vertical (V) texture coordinates. */
+ public TextureWrap getVWrap () {
+ return vWrap;
+ }
+
+ /** @return The OpenGL handle for this texture. */
+ public int getTextureObjectHandle () {
+ return glHandle;
+ }
+
+ /** Sets the {@link TextureWrap} for this texture on the u and v axis. Assumes the texture is bound and active!
+ * @param u the u wrap
+ * @param v the v wrap */
+ public void unsafeSetWrap(TextureWrap u, TextureWrap v) {
+ unsafeSetWrap(u, v, false);
+ }
+
+ /** Sets the {@link TextureWrap} for this texture on the u and v axis. Assumes the texture is bound and active!
+ * @param u the u wrap
+ * @param v the v wrap
+ * @param force True to always set the values, even if they are the same as the current values. */
+ public void unsafeSetWrap(TextureWrap u, TextureWrap v, boolean force) {
+ if (u != null && (force || uWrap != u)) {
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_WRAP_S, u.getGLEnum());
+ uWrap = u;
+ }
+ if (v != null && (force || vWrap != v)) {
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_WRAP_T, v.getGLEnum());
+ vWrap = v;
+ }
+ }
+
+ /** Sets the {@link TextureWrap} for this texture on the u and v axis. This will bind this texture!
+ * @param u the u wrap
+ * @param v the v wrap */
+ public void setWrap (TextureWrap u, TextureWrap v) {
+ this.uWrap = u;
+ this.vWrap = v;
+ bind();
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_WRAP_S, u.getGLEnum());
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_WRAP_T, v.getGLEnum());
+ }
+
+ /** Sets the {@link TextureFilter} for this texture for minification and magnification.
+ * Assumes the texture is bound and active!
+ * @param minFilter the minification filter
+ * @param magFilter the magnification filter */
+ public void unsafeSetFilter(TextureFilter minFilter, TextureFilter magFilter) {
+ unsafeSetFilter(minFilter, magFilter, false);
+ }
+
+
+ /** Sets the {@link TextureFilter} for this texture for minification and magnification.
+ * Assumes the texture is bound and active!
+ * @param minFilter the minification filter
+ * @param magFilter the magnification filter
+ * @param force True to always set the values, even if they are the same as the current values. */
+ public void unsafeSetFilter(TextureFilter minFilter, TextureFilter magFilter, boolean force) {
+ if (minFilter != null && (force || this.minFilter != minFilter)) {
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MIN_FILTER, minFilter.getGLEnum());
+ this.minFilter = minFilter;
+ }
+ if (magFilter != null && (force || this.magFilter != magFilter)) {
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MAG_FILTER, magFilter.getGLEnum());
+ this.magFilter = magFilter;
+ }
+ }
+
+ /** Sets the {@link TextureFilter} for this texture for minification and magnification.
+ * This will bind this texture!
+ * @param minFilter the minification filter
+ * @param magFilter the magnification filter */
+ public void setFilter (TextureFilter minFilter, TextureFilter magFilter) {
+ this.minFilter = minFilter;
+ this.magFilter = magFilter;
+ bind();
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MIN_FILTER, minFilter.getGLEnum());
+ Gdx.gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MAG_FILTER, magFilter.getGLEnum());
+ }
+
+ /** Destroys the OpenGL Texture as specified by the glHandle. */
+ protected void delete() {
+ if (glHandle != 0) {
+ buffer.put(0, glHandle);
+ Gdx.gl.glDeleteTextures(1, buffer);
+ glHandle = 0;
+ }
+ }
+
+ @Override
+ public void dispose () {
+ delete();
+ }
+
+
+ private static boolean enforcePotImages = true;
+ private static final IntBuffer buffer = BufferUtils.newIntBuffer(1);
+
+ /** @param enforcePotImages whether to enforce power of two images in OpenGL ES 1.0 or not. */
+ public static void setEnforcePotImages (boolean enforcePotImages) {
+ GLTexture.enforcePotImages = enforcePotImages;
+ }
+
+ public static boolean getEnforcePotImage () {
+ return enforcePotImages;
+ }
+
+ protected static TextureData createTextureData(FileHandle file, Format format, boolean useMipMaps) {
+ if (file == null)
+ return null;
+ return new FileTextureData(file, null, format, useMipMaps);
+ }
+
+ protected static TextureData createTextureData(FileHandle file, boolean useMipMaps) {
+ return createTextureData(file, null, useMipMaps);
+ }
+
+ protected static int createGLHandle () {
+ buffer.position(0);
+ buffer.limit(buffer.capacity());
+ Gdx.gl.glGenTextures(1, buffer);
+ return buffer.get(0);
+ }
+
+ protected static void uploadImageData (int target, TextureData data) {
+ if (data == null) {
+ // FIXME: remove texture on target?
+ return;
+ }
+
+ if (!data.isPrepared())
+ data.prepare();
+
+ if (enforcePotImages && Gdx.gl20 == null
+ && (!MathUtils.isPowerOfTwo(data.getWidth()) || !MathUtils.isPowerOfTwo(data.getHeight()))) {
+ throw new GdxRuntimeException("Texture width and height must be powers of two: " + data.getWidth() + "x"
+ + data.getHeight());
+ }
+
+ final TextureDataType type = data.getType();
+ if (type == TextureDataType.Compressed || type == TextureDataType.Float) {
+ data.consumeCompressedData(target);
+ return;
+ }
+
+ Pixmap pixmap = data.consumePixmap();
+ boolean disposePixmap = false;
+ if (data.getFormat() != pixmap.getFormat()) {
+ Pixmap tmp = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), data.getFormat());
+ Blending blend = Pixmap.getBlending();
+ Pixmap.setBlending(Blending.None);
+ tmp.drawPixmap(pixmap, 0, 0, 0, 0, pixmap.getWidth(), pixmap.getHeight());
+ Pixmap.setBlending(blend);
+ pixmap = tmp;
+ disposePixmap = true;
+ }
+
+ Gdx.gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1);
+ if (data.useMipMaps()) {
+ MipMapGenerator.generateMipMap(target, pixmap, pixmap.getWidth(), pixmap.getHeight(), disposePixmap);
+ } else {
+ Gdx.gl.glTexImage2D(target, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0,
+ pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels());
+ if (disposePixmap) {
+ pixmap.dispose();
+ }
+ }
+ if (data.disposePixmap())
+ pixmap.dispose();
+ }
+}
+++ /dev/null
-/*******************************************************************************\r
- * Copyright 2011 See AUTHORS file.\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- ******************************************************************************/\r
-\r
-package com.badlogic.gdx.graphics;\r
-\r
-import java.nio.IntBuffer;\r
-\r
-import com.badlogic.gdx.Gdx;\r
-import com.badlogic.gdx.assets.AssetManager;\r
-import com.badlogic.gdx.files.FileHandle;\r
-import com.badlogic.gdx.graphics.Pixmap.Format;\r
-import com.badlogic.gdx.graphics.TextureData.TextureDataType;\r
-import com.badlogic.gdx.graphics.glutils.FileTextureData;\r
-import com.badlogic.gdx.graphics.glutils.PixmapTextureData;\r
-import com.badlogic.gdx.utils.BufferUtils;\r
-import com.badlogic.gdx.utils.Disposable;\r
-import com.badlogic.gdx.utils.GdxRuntimeException;\r
-\r
-public class Texture extends GLTexture {\r
- //static IntBuffer buffer = BufferUtils.newIntBuffer(1);\r
-\r
- public enum TextureFilter {\r
- Nearest(GL10.GL_NEAREST), Linear(GL10.GL_LINEAR), MipMap(GL10.GL_LINEAR_MIPMAP_LINEAR), MipMapNearestNearest(\r
- GL10.GL_NEAREST_MIPMAP_NEAREST), MipMapLinearNearest(GL10.GL_LINEAR_MIPMAP_NEAREST), MipMapNearestLinear(\r
- GL10.GL_NEAREST_MIPMAP_LINEAR), MipMapLinearLinear(GL10.GL_LINEAR_MIPMAP_LINEAR);\r
-\r
- final int glEnum;\r
-\r
- TextureFilter (int glEnum) {\r
- this.glEnum = glEnum;\r
- }\r
-\r
- public boolean isMipMap () {\r
- return glEnum != GL10.GL_NEAREST && glEnum != GL10.GL_LINEAR;\r
- }\r
-\r
- public int getGLEnum () {\r
- return glEnum;\r
- }\r
- }\r
-\r
- public enum TextureWrap {\r
- MirroredRepeat(GL20.GL_MIRRORED_REPEAT),ClampToEdge(GL10.GL_CLAMP_TO_EDGE), Repeat(GL10.GL_REPEAT);\r
-\r
- final int glEnum;\r
-\r
- TextureWrap (int glEnum) {\r
- this.glEnum = glEnum;\r
- }\r
-\r
- public int getGLEnum () {\r
- return glEnum;\r
- }\r
- }\r
-\r
- TextureData data;\r
-\r
- public Texture (String internalPath) {\r
- this(Gdx.files.internal(internalPath));\r
- }\r
-\r
- public Texture (FileHandle file) {\r
- this(file, null, false);\r
- }\r
-\r
- public Texture (FileHandle file, boolean useMipMaps) {\r
- this(file, null, useMipMaps);\r
- }\r
-\r
- public Texture (FileHandle file, Format format, boolean useMipMaps) {\r
- this(createTextureData(file, format, useMipMaps));\r
- }\r
-\r
- public Texture (Pixmap pixmap) {\r
- this(new PixmapTextureData(pixmap, null, false, false));\r
- }\r
-\r
- public Texture (Pixmap pixmap, boolean useMipMaps) {\r
- this(new PixmapTextureData(pixmap, null, useMipMaps, false));\r
- }\r
-\r
- public Texture (Pixmap pixmap, Format format, boolean useMipMaps) {\r
- this(new PixmapTextureData(pixmap, format, useMipMaps, false));\r
- }\r
-\r
- public Texture (int width, int height, Format format) {\r
- this(new PixmapTextureData(new Pixmap(width, height, format), null, false, true));\r
- }\r
-\r
- public Texture (TextureData data) {\r
- super(GL10.GL_TEXTURE_2D, createGLHandle());\r
- load(data);\r
- }\r
-\r
- public void load (TextureData data) {\r
- this.data = data;\r
- if (data.getType() == TextureDataType.Pixmap) {\r
- if (!data.isPrepared()) data.prepare();\r
- Pixmap pixmap = data.consumePixmap();\r
- uploadImageData(pixmap);\r
- if (data.disposePixmap()) pixmap.dispose();\r
- setFilter(minFilter, magFilter);\r
- setWrap(uWrap, vWrap);\r
- if (data.useMipMaps()) Gdx.gl20.glGenerateMipmap(GL10.GL_TEXTURE_2D);\r
- }\r
- Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);\r
- }\r
-\r
- private void uploadImageData (Pixmap pixmap) {\r
- Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, glHandle);\r
- Gdx.gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1);\r
- Gdx.gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, pixmap.getWidth(), pixmap.getHeight(), 0, GL10.GL_RGBA,\r
- GL10.GL_UNSIGNED_BYTE, pixmap.getPixels());\r
- }\r
-\r
- /** Binds this texture. The texture will be bound to the currently active texture unit specified via\r
- * {@link GLCommon#glActiveTexture(int)}. */\r
- public void bind () {\r
- Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, glHandle);\r
- }\r
-\r
- /** Binds the texture to the given texture unit. Sets the currently active texture unit via\r
- * {@link GLCommon#glActiveTexture(int)}.\r
- * @param unit the unit (0 to MAX_TEXTURE_UNITS). */\r
- public void bind (int unit) {\r
- Gdx.gl.glActiveTexture(GL10.GL_TEXTURE0 + unit);\r
- Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, glHandle);\r
- }\r
-\r
- /** Draws the given {@link Pixmap} to the texture at position x, y. No clipping is performed so you have to make sure that you\r
- * draw only inside the texture region. Note that this will only draw to mipmap level 0!\r
- * \r
- * @param pixmap The Pixmap\r
- * @param x The x coordinate in pixels\r
- * @param y The y coordinate in pixels */\r
- public void draw (Pixmap pixmap, int x, int y) {\r
- if (data.isManaged()) throw new GdxRuntimeException("can't draw to a managed texture");\r
-\r
- Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, glHandle);\r
- Gdx.gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, 0, x, y, pixmap.getWidth(), pixmap.getHeight(), pixmap.getGLFormat(),\r
- pixmap.getGLType(), pixmap.getPixels());\r
- }\r
-\r
- static public void setEnforcePotImages (boolean enforcePotImages) {\r
- /* doesn't matter on GWT ... hopefully? */\r
- }\r
- \r
- /** @return the width of the texture in pixels */\r
- public int getWidth () {\r
- return data.getWidth();\r
- }\r
-\r
- /** @return the height of the texture in pixels */\r
- public int getHeight () {\r
- return data.getHeight();\r
- }\r
- \r
- @Override\r
- public int getDepth() {\r
- return 0;\r
- }\r
-\r
- public TextureFilter getMinFilter () {\r
- return minFilter;\r
- }\r
-\r
- public TextureFilter getMagFilter () {\r
- return magFilter;\r
- }\r
-\r
- public TextureWrap getUWrap () {\r
- return uWrap;\r
- }\r
-\r
- public TextureWrap getVWrap () {\r
- return vWrap;\r
- }\r
-\r
- public TextureData getTextureData () {\r
- return data;\r
- }\r
-\r
- /** @return whether this texture is managed or not. */\r
- public boolean isManaged () {\r
- return data.isManaged();\r
- }\r
-\r
- public int getTextureObjectHandle () {\r
- return glHandle;\r
- }\r
-\r
- /** Sets the {@link TextureWrap} for this texture on the u and v axis. This will bind this texture!\r
- * \r
- * @param u the u wrap\r
- * @param v the v wrap */\r
- public void setWrap (TextureWrap u, TextureWrap v) {\r
- this.uWrap = u;\r
- this.vWrap = v;\r
- bind();\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, u.getGLEnum());\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, v.getGLEnum());\r
- }\r
- \r
- /** Sets the {@link TextureWrap} for this texture on the u and v axis. Assumes the texture is bound and active!\r
- * \r
- * @param u the u wrap\r
- * @param v the v wrap */\r
- public void unsafeSetWrap(TextureWrap u, TextureWrap v) {\r
- if (u != null && uWrap != u) {\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, u.getGLEnum());\r
- uWrap = u;\r
- }\r
- if (v != null && vWrap != v) {\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, v.getGLEnum());\r
- vWrap = v;\r
- }\r
- }\r
- \r
- /** Sets the {@link TextureFilter} for this texture for minification and magnification.\r
- * Assumes the texture is bound and active!\r
- * \r
- * @param minFilter the minification filter\r
- * @param magFilter the magnification filter */\r
- public void unsafeSetFilter(TextureFilter minFilter, TextureFilter magFilter) {\r
- if (minFilter != null && this.minFilter != minFilter) {\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter.getGLEnum());\r
- this.minFilter = minFilter;\r
- }\r
- if (magFilter != null && this.magFilter != magFilter) {\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter.getGLEnum());\r
- this.magFilter = magFilter;\r
- }\r
- }\r
-\r
- public void setFilter (TextureFilter minFilter, TextureFilter magFilter) {\r
- this.minFilter = minFilter;\r
- this.magFilter = magFilter;\r
- bind();\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter.getGLEnum());\r
- Gdx.gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter.getGLEnum());\r
- }\r
-\r
- /** Disposes all resources associated with the texture */\r
- public void dispose () {\r
- if (glHandle == 0) return;\r
- delete();\r
- glHandle = 0;\r
- }\r
-\r
- public static void setAssetManager (AssetManager manager) {\r
- // nothing to do, no pause/resume cycle\r
- }\r
-}\r
<include name="graphics/GL11.java"/>
<include name="graphics/GL20.java"/>
<include name="graphics/GLCommon.java"/>
- <include name="graphics/GLTexture.java"/>
+ <include name="graphics/GLTexture.java"/> <!-- emulated -->
<include name="graphics/Mesh.java"/>
<include name="graphics/OrthographicCamera.java"/>
<include name="graphics/PerspectiveCamera.java"/>
return;\r
}\r
\r
- if (Gdx.app.getType() == ApplicationType.Android) {\r
+ if (Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.WebGL) {\r
if (Gdx.graphics.isGL20Available())\r
generateMipMapGLES20(target, pixmap, disposePixmap);\r
else\r