diff --git a/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidGraphics.java b/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidGraphics.java index 22f16f7d7a0..3a133483252 100644 --- a/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidGraphics.java +++ b/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidGraphics.java @@ -546,7 +546,7 @@ protected AndroidDisplayMode (int width, int height, int refreshRate, int bitsPe @Override public void setVSync (boolean vsync) { } - @Override public boolean hasExtension (String extension) { + @Override public boolean supportsExtension (String extension) { if(extensions == null) extensions = Gdx.gl.glGetString(GL10.GL_EXTENSIONS); return extensions.contains(extension); } diff --git a/backends/gdx-backend-jogl/src/com/badlogic/gdx/backends/jogl/JoglGraphics.java b/backends/gdx-backend-jogl/src/com/badlogic/gdx/backends/jogl/JoglGraphics.java index a50d822eda1..bb3517b48c6 100644 --- a/backends/gdx-backend-jogl/src/com/badlogic/gdx/backends/jogl/JoglGraphics.java +++ b/backends/gdx-backend-jogl/src/com/badlogic/gdx/backends/jogl/JoglGraphics.java @@ -25,6 +25,7 @@ import java.awt.Toolkit; import java.util.List; +import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCanvas; import javax.media.opengl.GLCapabilities; @@ -332,8 +333,8 @@ protected static JFrame findJFrame(Component component) { return new BufferFormat(caps.getRedBits(), caps.getGreenBits(), caps.getBlueBits(), caps.getAlphaBits(), caps.getDepthBits(), caps.getStencilBits(), caps.getNumSamples(), false); } - @Override public boolean hasExtension (String extension) { + @Override public boolean supportsExtension (String extension) { if(extensions == null) extensions = Gdx.gl.glGetString(GL10.GL_EXTENSIONS); - return extensions.contains(extension); + return extensions.contains(extension); } } diff --git a/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java b/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java index c911448fb19..59161e3a6cf 100644 --- a/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java +++ b/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglGraphics.java @@ -361,7 +361,7 @@ public LwjglDisplayMode (int width, int height, int refreshRate, int bitsPerPixe if(!vsync && !config.useCPUSynch) Display.setVSyncEnabled(false); } - @Override public boolean hasExtension (String extension) { + @Override public boolean supportsExtension (String extension) { if(extensions == null) extensions = Gdx.gl.glGetString(GL10.GL_EXTENSIONS); return extensions.contains(extension); } diff --git a/backends/gdx-backends-angle/src/com/badlogic/gdx/backends/angle/AngleGraphics.java b/backends/gdx-backends-angle/src/com/badlogic/gdx/backends/angle/AngleGraphics.java index 5f1dfce948e..57c0b856a30 100644 --- a/backends/gdx-backends-angle/src/com/badlogic/gdx/backends/angle/AngleGraphics.java +++ b/backends/gdx-backends-angle/src/com/badlogic/gdx/backends/angle/AngleGraphics.java @@ -158,7 +158,7 @@ void updateTime () { return null; } - @Override public boolean hasExtension (String extension) { + @Override public boolean supportsExtension (String extension) { if(extensions == null) extensions = Gdx.gl.glGetString(GL10.GL_EXTENSIONS); return extensions.contains(extension); } diff --git a/gdx/src/com/badlogic/gdx/Graphics.java b/gdx/src/com/badlogic/gdx/Graphics.java index 1c68e3aa619..7feb4f9ae4d 100644 --- a/gdx/src/com/badlogic/gdx/Graphics.java +++ b/gdx/src/com/badlogic/gdx/Graphics.java @@ -278,7 +278,7 @@ public String toString() { * @param extension the extension name * @return whether the extension is supported */ - public boolean hasExtension(String extension); + public boolean supportsExtension(String extension); // /** // * Opens the first back facing video camera. Only one camera diff --git a/gdx/src/com/badlogic/gdx/graphics/GLCommon.java b/gdx/src/com/badlogic/gdx/graphics/GLCommon.java index 2abaa32b909..7472ff3803e 100644 --- a/gdx/src/com/badlogic/gdx/graphics/GLCommon.java +++ b/gdx/src/com/badlogic/gdx/graphics/GLCommon.java @@ -24,6 +24,8 @@ * */ public interface GLCommon { + public static final int GL_GENERATE_MIPMAP = 0x8191; + public void glActiveTexture (int texture); public void glBindTexture (int target, int texture); diff --git a/gdx/src/com/badlogic/gdx/graphics/Texture.java b/gdx/src/com/badlogic/gdx/graphics/Texture.java index 57145f5e26a..4433c880bf9 100644 --- a/gdx/src/com/badlogic/gdx/graphics/Texture.java +++ b/gdx/src/com/badlogic/gdx/graphics/Texture.java @@ -22,6 +22,7 @@ import java.util.Map; import com.badlogic.gdx.Application; +import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Files.FileType; import com.badlogic.gdx.files.FileHandle; @@ -309,32 +310,70 @@ private void uploadImageData(Pixmap pixmap) { this.height = pixmap.getHeight(); if(enforcePotImages && Gdx.gl20 == null && (!MathUtils.isPowerOfTwo(width) || !MathUtils.isPowerOfTwo(height))) throw new GdxRuntimeException("texture width and height must be powers of two"); - Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, glHandle); - Gdx.gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); - if(isMipMap) { - if(!(Gdx.gl20==null) && width != height) - throw new GdxRuntimeException("texture width and height must be square when using mipmapping in OpenGL ES 1.x"); - int width = pixmap.getWidth() / 2; - int height = pixmap.getHeight() / 2; - int level = 1; - while(width > 0 && height > 0) { - Pixmap tmp = new Pixmap(width, height, pixmap.getFormat()); - tmp.drawPixmap(pixmap, 0, 0, pixmap.getWidth(), pixmap.getHeight(), 0, 0, width, height); - if(level > 1 || disposePixmap) - pixmap.dispose(); - pixmap = tmp; - - Gdx.gl.glTexImage2D(GL10.GL_TEXTURE_2D, level, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); - - width = pixmap.getWidth() / 2; - height = pixmap.getHeight() / 2; - level++; - } - pixmap.dispose(); + Gdx.gl.glBindTexture(GL10.GL_TEXTURE_2D, glHandle); + if(isMipMap) { + generateMipMap(pixmap, disposePixmap); } else { + Gdx.gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); if(disposePixmap) pixmap.dispose(); } } + + private void generateMipMap(Pixmap pixmap, boolean disposePixmap) { + if(Gdx.app.getType() == ApplicationType.Android) { + if(Gdx.graphics.isGL20Available()) + generateMipMapGLES20(pixmap, disposePixmap); + else + generateMipMapCPU(pixmap, disposePixmap); + } else { + generateMipMapDesktop(pixmap, disposePixmap); + } + } + + private void generateMipMapGLES20(Pixmap pixmap, boolean disposePixmap) { + Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); + Gdx.gl20.glGenerateMipmap(GL20.GL_TEXTURE_2D); + if(disposePixmap) pixmap.dispose(); + } + + private void generateMipMapDesktop(Pixmap pixmap, boolean disposePixmap) { + if(Gdx.graphics.isGL20Available() && + (Gdx.graphics.supportsExtension("GL_ARB_framebuffer_object") || + Gdx.graphics.supportsExtension("GL_EXT_framebuffer_object"))) { + Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); + Gdx.gl20.glGenerateMipmap(GL20.GL_TEXTURE_2D); + if(disposePixmap) pixmap.dispose(); + } else if(Gdx.graphics.supportsExtension("GL_SGIS_generate_mipmap")) { + Gdx.gl.glTexParameterf(GL20.GL_TEXTURE_2D, GLCommon.GL_GENERATE_MIPMAP, GL10.GL_TRUE); + Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); + if(disposePixmap) pixmap.dispose(); + } else { + generateMipMapCPU(pixmap, disposePixmap); + } + } + + private void generateMipMapCPU(Pixmap pixmap, boolean disposePixmap) { + Gdx.gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); + if(!(Gdx.gl20==null) && width != height) + throw new GdxRuntimeException("texture width and height must be square when using mipmapping in OpenGL ES 1.x"); + int width = pixmap.getWidth() / 2; + int height = pixmap.getHeight() / 2; + int level = 1; + while(width > 0 && height > 0) { + Pixmap tmp = new Pixmap(width, height, pixmap.getFormat()); + tmp.drawPixmap(pixmap, 0, 0, pixmap.getWidth(), pixmap.getHeight(), 0, 0, width, height); + if(level > 1 || disposePixmap) + pixmap.dispose(); + pixmap = tmp; + + Gdx.gl.glTexImage2D(GL10.GL_TEXTURE_2D, level, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(), 0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); + + width = pixmap.getWidth() / 2; + height = pixmap.getHeight() / 2; + level++; + } + pixmap.dispose(); + } /** * Binds this texture. The texture will be bound to the currently active texture unit specified via @@ -370,23 +409,7 @@ public void draw (Pixmap pixmap, int x, int y) { Gdx.gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, 0, x, y, pixmap.getWidth(), pixmap.getHeight(), pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); if(isMipMap) { - int level = 1; - int height = pixmap.getHeight(); - int width = pixmap.getWidth(); - - while (height > 0 && width > 0) { - Pixmap tmp = new Pixmap(width, height, pixmap.getFormat()); - tmp.drawPixmap(pixmap, 0, 0, pixmap.getWidth(), pixmap.getHeight(), 0, 0, width, height); - if(level > 1) - pixmap.dispose(); - pixmap = tmp; - - Gdx.gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, level, x, y, pixmap.getWidth(), pixmap.getHeight(), pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels()); - - width = pixmap.getWidth() / 2; - height = pixmap.getHeight() / 2; - level++; - } + generateMipMap(pixmap, false); } }