Merge pull request #264 from kostyantyn-dev/master
iOS: Fixed incorrect behaviour in J3MLoader. Added ogg loaderexperimental
commit
544bbcda4e
File diff suppressed because it is too large
Load Diff
@ -1,576 +0,0 @@ |
||||
package com.jme3.renderer.ios; |
||||
|
||||
//import android.graphics.Bitmap;
|
||||
//import android.opengl.ETC1;
|
||||
//import android.opengl.ETC1Util.ETC1Texture;
|
||||
//import android.opengl.JmeIosGLES;
|
||||
//import android.opengl.GLUtils;
|
||||
//import com.jme3.asset.AndroidImageInfo;
|
||||
import com.jme3.renderer.ios.JmeIosGLES; |
||||
import com.jme3.math.FastMath; |
||||
import com.jme3.renderer.RendererException; |
||||
import com.jme3.texture.Image; |
||||
import com.jme3.texture.Image.Format; |
||||
import com.jme3.util.BufferUtils; |
||||
import java.nio.ByteBuffer; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.Logger; |
||||
|
||||
public class TextureUtil { |
||||
|
||||
private static final Logger logger = Logger.getLogger(TextureUtil.class.getName()); |
||||
//TODO Make this configurable through appSettings
|
||||
public static boolean ENABLE_COMPRESSION = true; |
||||
private static boolean NPOT = false; |
||||
private static boolean ETC1support = false; |
||||
private static boolean DXT1 = false; |
||||
private static boolean PVRTC = false; |
||||
private static boolean DEPTH24_STENCIL8 = false; |
||||
private static boolean DEPTH_TEXTURE = false; |
||||
private static boolean RGBA8 = false; |
||||
|
||||
// Same constant used by both GL_ARM_rgba8 and GL_OES_rgb8_rgba8.
|
||||
private static final int GL_RGBA8 = 0x8058; |
||||
|
||||
private static final int GL_DXT1 = 0x83F0; |
||||
private static final int GL_DXT1A = 0x83F1; |
||||
|
||||
private static final int GL_DEPTH_STENCIL_OES = 0x84F9; |
||||
private static final int GL_UNSIGNED_INT_24_8_OES = 0x84FA; |
||||
private static final int GL_DEPTH24_STENCIL8_OES = 0x88F0; |
||||
|
||||
public static void loadTextureFeatures(String extensionString) { |
||||
ETC1support = extensionString.contains("GL_OES_compressed_ETC1_RGB8_texture"); |
||||
DEPTH24_STENCIL8 = extensionString.contains("GL_OES_packed_depth_stencil"); |
||||
NPOT = extensionString.contains("GL_IMG_texture_npot") |
||||
|| extensionString.contains("GL_OES_texture_npot") |
||||
|| extensionString.contains("GL_NV_texture_npot_2D_mipmap"); |
||||
|
||||
PVRTC = extensionString.contains("GL_IMG_texture_compression_pvrtc"); |
||||
|
||||
DXT1 = extensionString.contains("GL_EXT_texture_compression_dxt1"); |
||||
DEPTH_TEXTURE = extensionString.contains("GL_OES_depth_texture"); |
||||
|
||||
RGBA8 = extensionString.contains("GL_ARM_rgba8") || |
||||
extensionString.contains("GL_OES_rgb8_rgba8"); |
||||
|
||||
logger.log(Level.FINE, "Supports ETC1? {0}", ETC1support); |
||||
logger.log(Level.FINE, "Supports DEPTH24_STENCIL8? {0}", DEPTH24_STENCIL8); |
||||
logger.log(Level.FINE, "Supports NPOT? {0}", NPOT); |
||||
logger.log(Level.FINE, "Supports PVRTC? {0}", PVRTC); |
||||
logger.log(Level.FINE, "Supports DXT1? {0}", DXT1); |
||||
logger.log(Level.FINE, "Supports DEPTH_TEXTURE? {0}", DEPTH_TEXTURE); |
||||
logger.log(Level.FINE, "Supports RGBA8? {0}", RGBA8); |
||||
} |
||||
|
||||
/* |
||||
private static void buildMipmap(Bitmap bitmap, boolean compress) { |
||||
int level = 0; |
||||
int height = bitmap.getHeight(); |
||||
int width = bitmap.getWidth(); |
||||
|
||||
logger.log(Level.FINEST, " - Generating mipmaps for bitmap using SOFTWARE"); |
||||
|
||||
JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1); |
||||
|
||||
while (height >= 1 || width >= 1) { |
||||
//First of all, generate the texture from our bitmap and set it to the according level
|
||||
if (compress) { |
||||
logger.log(Level.FINEST, " - Uploading LOD level {0} ({1}x{2}) with compression.", new Object[]{level, width, height}); |
||||
uploadBitmapAsCompressed(JmeIosGLES.GL_TEXTURE_2D, level, bitmap, false, 0, 0); |
||||
} else { |
||||
logger.log(Level.FINEST, " - Uploading LOD level {0} ({1}x{2}) directly.", new Object[]{level, width, height}); |
||||
GLUtils.texImage2D(JmeIosGLES.GL_TEXTURE_2D, level, bitmap, 0); |
||||
} |
||||
|
||||
if (height == 1 || width == 1) { |
||||
break; |
||||
} |
||||
|
||||
//Increase the mipmap level
|
||||
height /= 2; |
||||
width /= 2; |
||||
Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true); |
||||
|
||||
// Recycle any bitmaps created as a result of scaling the bitmap.
|
||||
// Do not recycle the original image (mipmap level 0)
|
||||
if (level != 0) { |
||||
bitmap.recycle(); |
||||
} |
||||
|
||||
bitmap = bitmap2; |
||||
|
||||
level++; |
||||
} |
||||
} |
||||
|
||||
private static void uploadBitmapAsCompressed(int target, int level, Bitmap bitmap, boolean subTexture, int x, int y) { |
||||
if (bitmap.hasAlpha()) { |
||||
logger.log(Level.FINEST, " - Uploading bitmap directly. Cannot compress as alpha present."); |
||||
if (subTexture) { |
||||
GLUtils.texSubImage2D(target, level, x, y, bitmap); |
||||
JmeIosGLES.checkGLError(); |
||||
} else { |
||||
GLUtils.texImage2D(target, level, bitmap, 0); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
} else { |
||||
// Convert to RGB565
|
||||
int bytesPerPixel = 2; |
||||
Bitmap rgb565 = bitmap.copy(Bitmap.Config.RGB_565, true); |
||||
|
||||
// Put texture data into ByteBuffer
|
||||
ByteBuffer inputImage = BufferUtils.createByteBuffer(bitmap.getRowBytes() * bitmap.getHeight()); |
||||
rgb565.copyPixelsToBuffer(inputImage); |
||||
inputImage.position(0); |
||||
|
||||
// Delete the copied RGB565 image
|
||||
rgb565.recycle(); |
||||
|
||||
// Encode the image into the output bytebuffer
|
||||
int encodedImageSize = ETC1.getEncodedDataSize(bitmap.getWidth(), bitmap.getHeight()); |
||||
ByteBuffer compressedImage = BufferUtils.createByteBuffer(encodedImageSize); |
||||
ETC1.encodeImage(inputImage, bitmap.getWidth(), |
||||
bitmap.getHeight(), |
||||
bytesPerPixel, |
||||
bytesPerPixel * bitmap.getWidth(), |
||||
compressedImage); |
||||
|
||||
// Delete the input image buffer
|
||||
BufferUtils.destroyDirectBuffer(inputImage); |
||||
|
||||
// Create an ETC1Texture from the compressed image data
|
||||
ETC1Texture etc1tex = new ETC1Texture(bitmap.getWidth(), bitmap.getHeight(), compressedImage); |
||||
|
||||
// Upload the ETC1Texture
|
||||
if (bytesPerPixel == 2) { |
||||
int oldSize = (bitmap.getRowBytes() * bitmap.getHeight()); |
||||
int newSize = compressedImage.capacity(); |
||||
logger.log(Level.FINEST, " - Uploading compressed image to GL, oldSize = {0}, newSize = {1}, ratio = {2}", new Object[]{oldSize, newSize, (float) oldSize / newSize}); |
||||
if (subTexture) { |
||||
JmeIosGLES.glCompressedTexSubImage2D(target, |
||||
level, |
||||
x, y, |
||||
bitmap.getWidth(), |
||||
bitmap.getHeight(), |
||||
ETC1.ETC1_RGB8_OES, |
||||
etc1tex.getData().capacity(), |
||||
etc1tex.getData()); |
||||
|
||||
JmeIosGLES.checkGLError(); |
||||
} else { |
||||
JmeIosGLES.glCompressedTexImage2D(target, |
||||
level, |
||||
ETC1.ETC1_RGB8_OES, |
||||
bitmap.getWidth(), |
||||
bitmap.getHeight(), |
||||
0, |
||||
etc1tex.getData().capacity(), |
||||
etc1tex.getData()); |
||||
|
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
|
||||
// ETC1Util.loadTexture(target, level, 0, JmeIosGLES.GL_RGB,
|
||||
// JmeIosGLES.GL_UNSIGNED_SHORT_5_6_5, etc1Texture);
|
||||
// } else if (bytesPerPixel == 3) {
|
||||
// ETC1Util.loadTexture(target, level, 0, JmeIosGLES.GL_RGB,
|
||||
// JmeIosGLES.GL_UNSIGNED_BYTE, etc1Texture);
|
||||
} |
||||
|
||||
BufferUtils.destroyDirectBuffer(compressedImage); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <code>uploadTextureBitmap</code> uploads a native android bitmap |
||||
*/ |
||||
/* |
||||
public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips) { |
||||
uploadTextureBitmap(target, bitmap, needMips, false, 0, 0); |
||||
} |
||||
|
||||
/** |
||||
* <code>uploadTextureBitmap</code> uploads a native android bitmap |
||||
*/ |
||||
/* |
||||
public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips, boolean subTexture, int x, int y) { |
||||
boolean recycleBitmap = false; |
||||
//TODO, maybe this should raise an exception when NPOT is not supported
|
||||
|
||||
boolean willCompress = ENABLE_COMPRESSION && ETC1support && !bitmap.hasAlpha(); |
||||
if (needMips && willCompress) { |
||||
// Image is compressed and mipmaps are desired, generate them
|
||||
// using software.
|
||||
buildMipmap(bitmap, willCompress); |
||||
} else { |
||||
if (willCompress) { |
||||
// Image is compressed but mipmaps are not desired, upload directly.
|
||||
logger.log(Level.FINEST, " - Uploading compressed bitmap. Mipmaps are not generated."); |
||||
uploadBitmapAsCompressed(target, 0, bitmap, subTexture, x, y); |
||||
|
||||
} else { |
||||
// Image is not compressed, mipmaps may or may not be desired.
|
||||
logger.log(Level.FINEST, " - Uploading bitmap directly.{0}", |
||||
(needMips |
||||
? " Mipmaps will be generated in HARDWARE" |
||||
: " Mipmaps are not generated.")); |
||||
if (subTexture) { |
||||
System.err.println("x : " + x + " y :" + y + " , " + bitmap.getWidth() + "/" + bitmap.getHeight()); |
||||
GLUtils.texSubImage2D(target, 0, x, y, bitmap); |
||||
JmeIosGLES.checkGLError(); |
||||
} else { |
||||
GLUtils.texImage2D(target, 0, bitmap, 0); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
|
||||
if (needMips) { |
||||
// No pregenerated mips available,
|
||||
// generate from base level if required
|
||||
JmeIosGLES.glGenerateMipmap(target); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (recycleBitmap) { |
||||
bitmap.recycle(); |
||||
} |
||||
} |
||||
*/ |
||||
|
||||
public static void uploadTextureAny(Image img, int target, int index, boolean needMips) { |
||||
/* |
||||
if (img.getEfficentData() instanceof AndroidImageInfo) { |
||||
logger.log(Level.FINEST, " === Uploading image {0}. Using BITMAP PATH === ", img); |
||||
// If image was loaded from asset manager, use fast path
|
||||
AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData(); |
||||
uploadTextureBitmap(target, imageInfo.getBitmap(), needMips); |
||||
} else { |
||||
*/ |
||||
logger.log(Level.FINEST, " === Uploading image {0}. Using BUFFER PATH === ", img); |
||||
boolean wantGeneratedMips = needMips && !img.hasMipmaps(); |
||||
if (wantGeneratedMips && img.getFormat().isCompressed()) { |
||||
logger.log(Level.WARNING, "Generating mipmaps is only" |
||||
+ " supported for Bitmap based or non-compressed images!"); |
||||
} |
||||
|
||||
// Upload using slower path
|
||||
logger.log(Level.FINEST, " - Uploading bitmap directly.{0}", |
||||
(wantGeneratedMips |
||||
? " Mipmaps will be generated in HARDWARE" |
||||
: " Mipmaps are not generated.")); |
||||
|
||||
uploadTexture(img, target, index); |
||||
|
||||
// Image was uploaded using slower path, since it is not compressed,
|
||||
// then compress it
|
||||
if (wantGeneratedMips) { |
||||
// No pregenerated mips available,
|
||||
// generate from base level if required
|
||||
JmeIosGLES.glGenerateMipmap(target); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
//}
|
||||
} |
||||
|
||||
private static void unsupportedFormat(Format fmt) { |
||||
throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware."); |
||||
} |
||||
|
||||
public static IosGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException { |
||||
IosGLImageFormat imageFormat = new IosGLImageFormat(); |
||||
switch (fmt) { |
||||
case Depth32: |
||||
case Depth32F: |
||||
throw new UnsupportedOperationException("The image format '" |
||||
+ fmt + "' is not supported by OpenGL ES 2.0 specification."); |
||||
case Alpha8: |
||||
imageFormat.format = JmeIosGLES.GL_ALPHA; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
if (RGBA8) { |
||||
imageFormat.renderBufferStorageFormat = GL_RGBA8; |
||||
} else { |
||||
// Highest precision alpha supported by vanilla OGLES2
|
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4; |
||||
} |
||||
break; |
||||
case Luminance8: |
||||
imageFormat.format = JmeIosGLES.GL_LUMINANCE; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
if (RGBA8) { |
||||
imageFormat.renderBufferStorageFormat = GL_RGBA8; |
||||
} else { |
||||
// Highest precision luminance supported by vanilla OGLES2
|
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; |
||||
} |
||||
break; |
||||
case Luminance8Alpha8: |
||||
imageFormat.format = JmeIosGLES.GL_LUMINANCE_ALPHA; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
if (RGBA8) { |
||||
imageFormat.renderBufferStorageFormat = GL_RGBA8; |
||||
} else { |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4; |
||||
} |
||||
break; |
||||
case RGB565: |
||||
imageFormat.format = JmeIosGLES.GL_RGB; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT_5_6_5; |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; |
||||
break; |
||||
case RGB5A1: |
||||
imageFormat.format = JmeIosGLES.GL_RGBA; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT_5_5_5_1; |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB5_A1; |
||||
break; |
||||
case RGB8: |
||||
imageFormat.format = JmeIosGLES.GL_RGB; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
if (RGBA8) { |
||||
imageFormat.renderBufferStorageFormat = GL_RGBA8; |
||||
} else { |
||||
// Fallback: Use RGB565 if RGBA8 is not available.
|
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; |
||||
} |
||||
break; |
||||
case BGR8: |
||||
imageFormat.format = JmeIosGLES.GL_RGB; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
if (RGBA8) { |
||||
imageFormat.renderBufferStorageFormat = GL_RGBA8; |
||||
} else { |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGB565; |
||||
} |
||||
break; |
||||
case RGBA8: |
||||
imageFormat.format = JmeIosGLES.GL_RGBA; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
if (RGBA8) { |
||||
imageFormat.renderBufferStorageFormat = GL_RGBA8; |
||||
} else { |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_RGBA4; |
||||
} |
||||
break; |
||||
case Depth: |
||||
case Depth16: |
||||
if (!DEPTH_TEXTURE) { |
||||
unsupportedFormat(fmt); |
||||
} |
||||
imageFormat.format = JmeIosGLES.GL_DEPTH_COMPONENT; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT; |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_DEPTH_COMPONENT16; |
||||
break; |
||||
case Depth24: |
||||
case Depth24Stencil8: |
||||
if (!DEPTH_TEXTURE) { |
||||
unsupportedFormat(fmt); |
||||
} |
||||
if (DEPTH24_STENCIL8) { |
||||
// NEW: True Depth24 + Stencil8 format.
|
||||
imageFormat.format = GL_DEPTH_STENCIL_OES; |
||||
imageFormat.dataType = GL_UNSIGNED_INT_24_8_OES; |
||||
imageFormat.renderBufferStorageFormat = GL_DEPTH24_STENCIL8_OES; |
||||
} else { |
||||
// Vanilla OGLES2, only Depth16 available.
|
||||
imageFormat.format = JmeIosGLES.GL_DEPTH_COMPONENT; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_SHORT; |
||||
imageFormat.renderBufferStorageFormat = JmeIosGLES.GL_DEPTH_COMPONENT16; |
||||
} |
||||
break; |
||||
case DXT1: |
||||
if (!DXT1) { |
||||
unsupportedFormat(fmt); |
||||
} |
||||
imageFormat.format = GL_DXT1; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
imageFormat.compress = true; |
||||
break; |
||||
case DXT1A: |
||||
if (!DXT1) { |
||||
unsupportedFormat(fmt); |
||||
} |
||||
imageFormat.format = GL_DXT1A; |
||||
imageFormat.dataType = JmeIosGLES.GL_UNSIGNED_BYTE; |
||||
imageFormat.compress = true; |
||||
break; |
||||
default: |
||||
throw new UnsupportedOperationException("Unrecognized format: " + fmt); |
||||
} |
||||
return imageFormat; |
||||
} |
||||
|
||||
public static class IosGLImageFormat { |
||||
|
||||
boolean compress = false; |
||||
int format = -1; |
||||
int renderBufferStorageFormat = -1; |
||||
int dataType = -1; |
||||
} |
||||
|
||||
private static void uploadTexture(Image img, |
||||
int target, |
||||
int index) { |
||||
|
||||
/* |
||||
if (img.getEfficentData() instanceof AndroidImageInfo) { |
||||
throw new RendererException("This image uses efficient data. " |
||||
+ "Use uploadTextureBitmap instead."); |
||||
} |
||||
*/ |
||||
|
||||
// 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(); |
||||
|
||||
if (!NPOT && img.isNPOT()) { |
||||
// Check if texture is POT
|
||||
throw new RendererException("Non-power-of-2 textures " |
||||
+ "are not supported by the video hardware " |
||||
+ "and no scaling path available for image: " + img); |
||||
} |
||||
IosGLImageFormat imageFormat = getImageFormat(fmt); |
||||
|
||||
if (data != null) { |
||||
JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
|
||||
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}; |
||||
} |
||||
} |
||||
|
||||
for (int i = 0; i < mipSizes.length; i++) { |
||||
int mipWidth = Math.max(1, width >> i); |
||||
int mipHeight = Math.max(1, height >> i); |
||||
|
||||
if (data != null) { |
||||
data.position(pos); |
||||
data.limit(pos + mipSizes[i]); |
||||
} |
||||
|
||||
if (imageFormat.compress && data != null) { |
||||
JmeIosGLES.glCompressedTexImage2D(target, |
||||
i, |
||||
imageFormat.format, |
||||
mipWidth, |
||||
mipHeight, |
||||
0, |
||||
data.remaining(), |
||||
data); |
||||
} else { |
||||
JmeIosGLES.glTexImage2D(target, |
||||
i, |
||||
imageFormat.format, |
||||
mipWidth, |
||||
mipHeight, |
||||
0, |
||||
imageFormat.format, |
||||
imageFormat.dataType, |
||||
data); |
||||
} |
||||
JmeIosGLES.checkGLError(); |
||||
|
||||
pos += mipSizes[i]; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Update the texture currently bound to target at with data from the given |
||||
* Image at position x and y. The parameter index is used as the zoffset in |
||||
* case a 3d texture or texture 2d array is being updated. |
||||
* |
||||
* @param image Image with the source data (this data will be put into the |
||||
* texture) |
||||
* @param target the target texture |
||||
* @param index the mipmap level to update |
||||
* @param x the x position where to put the image in the texture |
||||
* @param y the y position where to put the image in the texture |
||||
*/ |
||||
public static void uploadSubTexture( |
||||
Image img, |
||||
int target, |
||||
int index, |
||||
int x, |
||||
int y) { |
||||
//TODO:
|
||||
/* |
||||
if (img.getEfficentData() instanceof AndroidImageInfo) { |
||||
AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData(); |
||||
uploadTextureBitmap(target, imageInfo.getBitmap(), true, true, x, y); |
||||
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(); |
||||
|
||||
if (!NPOT && img.isNPOT()) { |
||||
// Check if texture is POT
|
||||
throw new RendererException("Non-power-of-2 textures " |
||||
+ "are not supported by the video hardware " |
||||
+ "and no scaling path available for image: " + img); |
||||
} |
||||
IosGLImageFormat imageFormat = getImageFormat(fmt); |
||||
|
||||
if (data != null) { |
||||
JmeIosGLES.glPixelStorei(JmeIosGLES.GL_UNPACK_ALIGNMENT, 1); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
|
||||
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}; |
||||
} |
||||
} |
||||
|
||||
for (int i = 0; i < mipSizes.length; i++) { |
||||
int mipWidth = Math.max(1, width >> i); |
||||
int mipHeight = Math.max(1, height >> i); |
||||
|
||||
if (data != null) { |
||||
data.position(pos); |
||||
data.limit(pos + mipSizes[i]); |
||||
} |
||||
|
||||
if (imageFormat.compress && data != null) { |
||||
JmeIosGLES.glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, data.remaining(), data); |
||||
JmeIosGLES.checkGLError(); |
||||
} else { |
||||
JmeIosGLES.glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, imageFormat.dataType, data); |
||||
JmeIosGLES.checkGLError(); |
||||
} |
||||
|
||||
pos += mipSizes[i]; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue