aboutsummaryrefslogtreecommitdiff
path: root/engine/src/android/com/jme3/renderer/android/TextureUtil.java
diff options
context:
space:
mode:
authorScott Barta <sbarta@google.com>2012-03-01 12:35:35 -0800
committerScott Barta <sbarta@google.com>2012-03-01 12:40:08 -0800
commit59b2e6871c65f58fdad78cd7229c292f6a177578 (patch)
tree2d4e7bfc05b93f40b34675d77e403dd1c25efafd /engine/src/android/com/jme3/renderer/android/TextureUtil.java
parentf9b30489e75ac1eabc365064959804e99534f7ab (diff)
downloadjmonkeyengine-59b2e6871c65f58fdad78cd7229c292f6a177578.tar.gz
Adds the jMonkeyEngine library to the build.
Adds the jMonkeyEngine open source 3D game engine to the build. This is built as a static library and is only used by the Finsky client. Change-Id: I06a3f054df7b8a67757267d884854f70c5a16ca0
Diffstat (limited to 'engine/src/android/com/jme3/renderer/android/TextureUtil.java')
-rw-r--r--engine/src/android/com/jme3/renderer/android/TextureUtil.java297
1 files changed, 297 insertions, 0 deletions
diff --git a/engine/src/android/com/jme3/renderer/android/TextureUtil.java b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
new file mode 100644
index 0000000..53b96b4
--- /dev/null
+++ b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
@@ -0,0 +1,297 @@
+package com.jme3.renderer.android;
+
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+import com.jme3.asset.AndroidImageInfo;
+import com.jme3.math.FastMath;
+import com.jme3.texture.Image;
+import com.jme3.texture.Image.Format;
+import java.nio.ByteBuffer;
+import javax.microedition.khronos.opengles.GL10;
+
+public class TextureUtil {
+
+ public static int convertTextureFormat(Format fmt){
+ switch (fmt){
+ case Alpha16:
+ case Alpha8:
+ return GL10.GL_ALPHA;
+ case Luminance8Alpha8:
+ case Luminance16Alpha16:
+ return GL10.GL_LUMINANCE_ALPHA;
+ case Luminance8:
+ case Luminance16:
+ return GL10.GL_LUMINANCE;
+ case RGB10:
+ case RGB16:
+ case BGR8:
+ case RGB8:
+ case RGB565:
+ return GL10.GL_RGB;
+ case RGB5A1:
+ case RGBA16:
+ case RGBA8:
+ return GL10.GL_RGBA;
+
+ case Depth:
+ return GLES20.GL_DEPTH_COMPONENT;
+ case Depth16:
+ return GLES20.GL_DEPTH_COMPONENT16;
+ case Depth24:
+ case Depth32:
+ case Depth32F:
+ throw new UnsupportedOperationException("Unsupported depth format: " + fmt);
+
+ case DXT1A:
+ throw new UnsupportedOperationException("Unsupported format: " + fmt);
+ default:
+ throw new UnsupportedOperationException("Unrecognized format: " + fmt);
+ }
+ }
+
+ private static void buildMipmap(Bitmap bitmap) {
+ int level = 0;
+ int height = bitmap.getHeight();
+ int width = bitmap.getWidth();
+
+ while (height >= 1 || width >= 1) {
+ //First of all, generate the texture from our bitmap and set it to the according level
+ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
+
+ if (height == 1 || width == 1) {
+ break;
+ }
+
+ //Increase the mipmap level
+ level++;
+
+ height /= 2;
+ width /= 2;
+ Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
+
+ bitmap.recycle();
+ bitmap = bitmap2;
+ }
+ }
+
+ /**
+ * <code>uploadTextureBitmap</code> uploads a native android bitmap
+ * @param target
+ * @param bitmap
+ * @param generateMips
+ * @param powerOf2
+ */
+ public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean generateMips, boolean powerOf2)
+ {
+ if (!powerOf2)
+ {
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+ if (!FastMath.isPowerOfTwo(width) || !FastMath.isPowerOfTwo(height))
+ {
+ // scale to power of two
+ width = FastMath.nearestPowerOfTwo(width);
+ height = FastMath.nearestPowerOfTwo(height);
+ Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
+ bitmap.recycle();
+ bitmap = bitmap2;
+ }
+ }
+
+ if (generateMips)
+ {
+ buildMipmap(bitmap);
+ }
+ else
+ {
+ GLUtils.texImage2D(target, 0, bitmap, 0);
+ //bitmap.recycle();
+ }
+ }
+
+ public static void uploadTexture(
+ Image img,
+ int target,
+ int index,
+ int border,
+ boolean tdc,
+ boolean generateMips,
+ boolean powerOf2){
+
+ if (img.getEfficentData() instanceof AndroidImageInfo){
+ // If image was loaded from asset manager, use fast path
+ AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData();
+ uploadTextureBitmap(target, imageInfo.getBitmap(), generateMips, powerOf2);
+ return;
+ }
+
+ // Otherwise upload image directly.
+ // Prefer to only use power of 2 textures here to avoid errors.
+
+ Image.Format fmt = img.getFormat();
+ ByteBuffer data;
+ if (index >= 0 || img.getData() != null && img.getData().size() > 0){
+ data = img.getData(index);
+ }else{
+ data = null;
+ }
+
+ int width = img.getWidth();
+ int height = img.getHeight();
+ int depth = img.getDepth();
+
+ boolean compress = false;
+ int internalFormat = -1;
+ int format = -1;
+ int dataType = -1;
+
+ switch (fmt){
+ case Alpha16:
+ case Alpha8:
+ format = GLES20.GL_ALPHA;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case Luminance8:
+ format = GLES20.GL_LUMINANCE;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case Luminance8Alpha8:
+ format = GLES20.GL_LUMINANCE_ALPHA;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case Luminance16Alpha16:
+ format = GLES20.GL_LUMINANCE_ALPHA;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case Luminance16:
+ format = GLES20.GL_LUMINANCE;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case RGB565:
+ format = GLES20.GL_RGB;
+ internalFormat = GLES20.GL_RGB565;
+ dataType = GLES20.GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case ARGB4444:
+ format = GLES20.GL_RGBA;
+ dataType = GLES20.GL_UNSIGNED_SHORT_4_4_4_4;
+ break;
+ case RGB10:
+ format = GLES20.GL_RGB;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case RGB16:
+ format = GLES20.GL_RGB;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case RGB5A1:
+ format = GLES20.GL_RGBA;
+ internalFormat = GLES20.GL_RGB5_A1;
+ dataType = GLES20.GL_UNSIGNED_SHORT_5_5_5_1;
+ break;
+ case RGB8:
+ format = GLES20.GL_RGB;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case BGR8:
+ format = GLES20.GL_RGB;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case RGBA16:
+ format = GLES20.GL_RGBA;
+ internalFormat = GLES20.GL_RGBA4;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case RGBA8:
+ format = GLES20.GL_RGBA;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case DXT1A:
+ format = GLES20.GL_COMPRESSED_TEXTURE_FORMATS;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ case Depth:
+ format = GLES20.GL_DEPTH_COMPONENT;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case Depth16:
+ format = GLES20.GL_DEPTH_COMPONENT;
+ internalFormat = GLES20.GL_DEPTH_COMPONENT16;
+ dataType = GLES20.GL_UNSIGNED_BYTE;
+ break;
+ case Depth24:
+ case Depth32:
+ case Depth32F:
+ throw new UnsupportedOperationException("Unsupported depth format: " + fmt);
+ default:
+ throw new UnsupportedOperationException("Unrecognized format: " + fmt);
+ }
+
+ if (internalFormat == -1)
+ {
+ internalFormat = format;
+ }
+
+ if (data != null)
+ GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
+
+ int[] mipSizes = img.getMipMapSizes();
+ int pos = 0;
+ if (mipSizes == null){
+ if (data != null)
+ mipSizes = new int[]{ data.capacity() };
+ else
+ mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 };
+ }
+
+ // XXX: might want to change that when support
+ // of more than paletted compressions is added..
+ if (compress){
+ data.clear();
+ GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
+ 1 - mipSizes.length,
+ format,
+ width,
+ height,
+ 0,
+ data.capacity(),
+ data);
+ return;
+ }
+
+ for (int i = 0; i < mipSizes.length; i++){
+ int mipWidth = Math.max(1, width >> i);
+ int mipHeight = Math.max(1, height >> i);
+ int mipDepth = Math.max(1, depth >> i);
+
+ if (data != null){
+ data.position(pos);
+ data.limit(pos + mipSizes[i]);
+ }
+
+ if (compress && data != null){
+ GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
+ i,
+ format,
+ mipWidth,
+ mipHeight,
+ 0,
+ data.remaining(),
+ data);
+ }else{
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,
+ i,
+ internalFormat,
+ mipWidth,
+ mipHeight,
+ 0,
+ format,
+ dataType,
+ data);
+ }
+
+ pos += mipSizes[i];
+ }
+ }
+
+}