summaryrefslogtreecommitdiffstats
path: root/src/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes')
-rwxr-xr-xsrc/classes/com/sun/opengl/utils/Texture.java96
-rwxr-xr-xsrc/classes/com/sun/opengl/utils/TextureData.java114
-rwxr-xr-xsrc/classes/com/sun/opengl/utils/TextureIO.java300
-rwxr-xr-xsrc/classes/com/sun/opengl/utils/TextureProvider.java36
4 files changed, 376 insertions, 170 deletions
diff --git a/src/classes/com/sun/opengl/utils/Texture.java b/src/classes/com/sun/opengl/utils/Texture.java
index a21facb65..fc3b0d604 100755
--- a/src/classes/com/sun/opengl/utils/Texture.java
+++ b/src/classes/com/sun/opengl/utils/Texture.java
@@ -36,7 +36,10 @@
package com.sun.opengl.utils;
+import java.nio.*;
+
import javax.media.opengl.*;
+import javax.media.opengl.glu.*;
import com.sun.opengl.impl.*;
/**
@@ -68,8 +71,7 @@ public class Texture {
the texture coords. */
private boolean mustFlipVertically;
- /** The texture coordinates corresponding to the entire texture
- image. */
+ /** The texture coordinates corresponding to the entire image. */
private TextureCoords coords;
private static final boolean DEBUG = Debug.debug("Texture");
@@ -83,8 +85,18 @@ public class Texture {
imgHeight = data.getHeight();
mustFlipVertically = data.getMustFlipVertically();
- if ((isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight)) ||
- gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two")) {
+ if (data.getMipmap()) {
+ // GLU always targets GL_TEXTURE_2D and scales the texture to be
+ // a power of two. It also doesn't really matter exactly what
+ // the texture width and height are because the texture coords
+ // are always between 0.0 and 1.0.
+ imgWidth = nextPowerOfTwo(imgWidth);
+ imgHeight = nextPowerOfTwo(imgHeight);
+ texWidth = imgWidth;
+ texHeight = imgHeight;
+ target = GL.GL_TEXTURE_2D;
+ } else if ((isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight)) ||
+ gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two")) {
if (DEBUG) {
if (isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight)) {
System.err.println("Power-of-two texture");
@@ -125,10 +137,6 @@ public class Texture {
texID = createTextureID(gl);
setImageSize(imgWidth, imgHeight);
gl.glBindTexture(target, texID);
- gl.glTexImage2D(target, 0, data.getInternalFormat(),
- texWidth, texHeight, data.getBorder(),
- data.getPixelFormat(), data.getPixelType(), null);
-
// REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB
if (target == GL.GL_TEXTURE_2D) {
gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter);
@@ -137,7 +145,24 @@ public class Texture {
gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, wrapMode);
}
- updateSubImage(data, 0, 0);
+ if (data.getMipmap()) {
+ GLU glu = new GLU();
+ glu.gluBuild2DMipmaps(target, data.getInternalFormat(),
+ data.getWidth(), data.getHeight(),
+ data.getPixelFormat(), data.getPixelType(), data.getBuffer());
+ } else {
+ gl.glTexImage2D(target, 0, data.getInternalFormat(),
+ texWidth, texHeight, data.getBorder(),
+ data.getPixelFormat(), data.getPixelType(), null);
+ Buffer[] mipmapData = data.getMipmapData();
+ if (mipmapData != null) {
+ for (int i = 0; i < mipmapData.length; i++) {
+ updateSubImage(data, i, 0, 0);
+ }
+ } else {
+ updateSubImage(data, 0, 0, 0);
+ }
+ }
}
/**
@@ -279,9 +304,14 @@ public class Texture {
/**
* Updates a subregion of the content area of this texture using the
- * data in the given image.
+ * data in the given image. Only updates the specified mipmap level
+ * and does not re-generate mipmaps if they were originally produced
+ * or loaded.
*
* @param data the image data to be uploaded to this texture
+ * @param mipmapLevel the mipmap level of the texture to set. If
+ * this is non-zero and the TextureData contains mipmap data, the
+ * appropriate mipmap level will be selected.
* @param x the x offset (in pixels) relative to the lower-left corner
* of this texture
* @param y the y offset (in pixels) relative to the lower-left corner
@@ -290,25 +320,51 @@ public class Texture {
* @throws GLException if no OpenGL context was current or if any
* OpenGL-related errors occurred
*/
- public void updateSubImage(TextureData data, int x, int y) throws GLException {
+ public void updateSubImage(TextureData data, int mipmapLevel, int x, int y) throws GLException {
GL gl = getCurrentGL();
bind();
+ int width = data.getWidth();
+ int height = data.getHeight();
+ Buffer buffer = data.getBuffer();
+ if (data.getMipmapData() != null) {
+ // Compute the width and height at the specified mipmap level
+ for (int i = 0; i < mipmapLevel; i++) {
+ width /= 2;
+ height /= 2;
+ }
+ buffer = data.getMipmapData()[mipmapLevel];
+ }
+
if (data.isDataCompressed()) {
- // FIXME: should test availability of appropriate texture
- // compression extension here
- gl.glCompressedTexSubImage2D(target, data.getMipmapLevel(),
- x, y, data.getWidth(), data.getHeight(),
- data.getInternalFormat(), data.getBuffer().remaining(),
- data.getBuffer());
+ switch (data.getInternalFormat()) {
+ case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc") &&
+ !gl.isExtensionAvailable("GL_NV_texture_compression_vtc")) {
+ throw new GLException("DXTn compressed textures not supported by this graphics card");
+ }
+ break;
+ default:
+ // FIXME: should test availability of more texture
+ // compression extensions here
+ break;
+ }
+
+ gl.glCompressedTexSubImage2D(target, mipmapLevel,
+ x, y, width, height,
+ data.getInternalFormat(),
+ buffer.remaining(), buffer);
} else {
int[] align = new int[1];
gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment());
- gl.glTexSubImage2D(target, data.getMipmapLevel(),
- x, y, data.getWidth(), data.getHeight(),
+ gl.glTexSubImage2D(target, mipmapLevel,
+ x, y, width, height,
data.getPixelFormat(), data.getPixelType(),
- data.getBuffer());
+ buffer);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore align
}
}
diff --git a/src/classes/com/sun/opengl/utils/TextureData.java b/src/classes/com/sun/opengl/utils/TextureData.java
index d88a18233..a6fcd9073 100755
--- a/src/classes/com/sun/opengl/utils/TextureData.java
+++ b/src/classes/com/sun/opengl/utils/TextureData.java
@@ -63,12 +63,14 @@ public class TextureData {
private int pixelFormat;
private int pixelType;
private int internalFormat; // perhaps inferred from pixelFormat?
- private int mipmapLevel;
+ private boolean mipmap; // indicates whether mipmaps should be generated
+ // (ignored if mipmaps are supplied from the file)
private boolean dataIsCompressed;
private boolean mustFlipVertically; // Must flip texture coordinates
// vertically to get OpenGL output
// to look correct
- private Buffer buffer; // the actual data
+ private Buffer buffer; // the actual data...
+ private Buffer[] mipmapData; // ...or a series of mipmaps
private Flusher flusher;
private int alignment; // 1, 2, or 4 bytes
@@ -91,9 +93,6 @@ public class TextureData {
* memory-mapped files that might otherwise require a garbage
* collection to reclaim and close.
*
- * @param mipmapLevel the mipmap level for the resulting texture
- * this data represents (FIXME: needs
- * rethinking, currently unused)
* @param internalFormat the OpenGL internal format for the
* resulting texture; must be specified, may
* not be 0
@@ -105,6 +104,10 @@ public class TextureData {
* resulting texture; must be specified, may
* not be 0
* @param pixelType the OpenGL type of the pixels of the texture
+ * @param mipmap indicates whether mipmaps should be
+ * autogenerated (using GLU) for the resulting
+ * texture. Currently if mipmap is true then
+ * dataIsCompressed may not be true.
* @param dataIsCompressed indicates whether the texture data is in
* compressed form
* (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
@@ -115,25 +118,33 @@ public class TextureData {
* @param buffer the buffer containing the texture data
* @param flusher optional flusher to perform cleanup tasks
* upon call to flush()
+ *
+ * @throws IllegalArgumentException if any parameters of the texture
+ * data were invalid, such as requesting mipmap generation for a
+ * compressed texture
*/
- public TextureData(int mipmapLevel,
- int internalFormat,
+ public TextureData(int internalFormat,
int width,
int height,
int border,
int pixelFormat,
int pixelType,
+ boolean mipmap,
boolean dataIsCompressed,
boolean mustFlipVertically,
Buffer buffer,
- Flusher flusher) {
+ Flusher flusher) throws IllegalArgumentException {
+ if (mipmap && dataIsCompressed) {
+ throw new IllegalArgumentException("Can not generate mipmaps for compressed textures");
+ }
+
this.width = width;
this.height = height;
this.border = border;
this.pixelFormat = pixelFormat;
this.pixelType = pixelType;
this.internalFormat = internalFormat;
- this.mipmapLevel = mipmapLevel;
+ this.mipmap = mipmap;
this.dataIsCompressed = dataIsCompressed;
this.mustFlipVertically = mustFlipVertically;
this.buffer = buffer;
@@ -143,11 +154,68 @@ public class TextureData {
/**
* Constructs a new TextureData object with the specified parameters
+ * and data for multiple mipmap levels contained in the given array
+ * of Buffers. The optional Flusher can be used to clean up native
+ * resources associated with this TextureData when processing is
+ * complete; for example, closing of memory-mapped files that might
+ * otherwise require a garbage collection to reclaim and close.
+ *
+ * @param internalFormat the OpenGL internal format for the
+ * resulting texture; must be specified, may
+ * not be 0
+ * @param width the width in pixels of the topmost mipmap
+ * level of the texture
+ * @param height the height in pixels of the topmost mipmap
+ * level of the texture
+ * @param border the number of pixels of border this texture
+ * data has (0 or 1)
+ * @param pixelFormat the OpenGL pixel format for the
+ * resulting texture; must be specified, may
+ * not be 0
+ * @param pixelType the OpenGL type of the pixels of the texture
+ * @param dataIsCompressed indicates whether the texture data is in
+ * compressed form
+ * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+ * @param mustFlipVertically indicates whether the texture
+ * coordinates must be flipped vertically
+ * in order to properly display the
+ * texture
+ * @param mipmapData the buffers containing all mipmap levels
+ * of the texture's data
+ * @param flusher optional flusher to perform cleanup tasks
+ * upon call to flush()
+ *
+ * @throws IllegalArgumentException if any parameters of the texture
+ * data were invalid, such as requesting mipmap generation for a
+ * compressed texture
+ */
+ public TextureData(int internalFormat,
+ int width,
+ int height,
+ int border,
+ int pixelFormat,
+ int pixelType,
+ boolean dataIsCompressed,
+ boolean mustFlipVertically,
+ Buffer[] mipmapData,
+ Flusher flusher) throws IllegalArgumentException {
+ this.width = width;
+ this.height = height;
+ this.border = border;
+ this.pixelFormat = pixelFormat;
+ this.pixelType = pixelType;
+ this.internalFormat = internalFormat;
+ this.dataIsCompressed = dataIsCompressed;
+ this.mustFlipVertically = mustFlipVertically;
+ this.mipmapData = (Buffer[]) mipmapData.clone();
+ this.flusher = flusher;
+ alignment = 1; // FIXME: is this correct enough in all situations?
+ }
+
+ /**
+ * Constructs a new TextureData object with the specified parameters
* and data contained in the given BufferedImage.
*
- * @param mipmapLevel the mipmap level for the resulting texture
- * this data represents (FIXME: needs
- * rethinking, currently unused)
* @param internalFormat the OpenGL internal format for the
* resulting texture; may be 0, in which case
* it is inferred from the image's type
@@ -155,11 +223,14 @@ public class TextureData {
* resulting texture; may be 0, in which case
* it is inferred from the image's type (note:
* this argument is currently always ignored)
+ * @param mipmap indicates whether mipmaps should be
+ * autogenerated (using GLU) for the resulting
+ * texture
* @param image the image containing the texture data
*/
- public TextureData(int mipmapLevel,
- int internalFormat,
+ public TextureData(int internalFormat,
int pixelFormat,
+ boolean mipmap,
BufferedImage image) {
if (internalFormat == 0) {
this.internalFormat = image.getColorModel().hasAlpha() ? GL.GL_RGBA : GL.GL_RGB;
@@ -167,7 +238,7 @@ public class TextureData {
this.internalFormat = internalFormat;
}
createFromImage(image);
- this.mipmapLevel = mipmapLevel;
+ this.mipmap = mipmap;
}
/** Returns the width in pixels of the texture data. */
@@ -182,15 +253,18 @@ public class TextureData {
public int getPixelType() { return pixelType; }
/** Returns the intended OpenGL internal format of the texture data. */
public int getInternalFormat() { return internalFormat; }
- /** Returns the intended mipmap level of the texture data. */
- public int getMipmapLevel() { return mipmapLevel; }
+ /** Returns whether mipmaps should be generated for the texture data. */
+ public boolean getMipmap() { return mipmap; }
/** Indicates whether the texture data is in compressed form. */
public boolean isDataCompressed() { return dataIsCompressed; }
/** Indicates whether the texture coordinates must be flipped
vertically for proper display. */
public boolean getMustFlipVertically() { return mustFlipVertically; }
- /** Returns the texture data. */
+ /** Returns the texture data, or null if it is specified as a set of mipmaps. */
public Buffer getBuffer() { return buffer; }
+ /** Returns all mipmap levels for the texture data, or null if it is
+ specified as a single image. */
+ public Buffer[] getMipmapData() { return mipmapData; }
/** Returns the required byte alignment for the texture data. */
public int getAlignment() { return alignment; }
@@ -206,8 +280,8 @@ public class TextureData {
public void setPixelType(int pixelType) { this.pixelType = pixelType; }
/** Sets the intended OpenGL internal format of the texture data. */
public void setInternalFormat(int internalFormat) { this.internalFormat = internalFormat; }
- /** Sets the intended mipmap level of the texture data. */
- public void setMipmapLevel(int mipmapLevel) { this.mipmapLevel = mipmapLevel; }
+ /** Sets whether mipmaps should be generated for the texture data. */
+ public void setMipmap(boolean mipmap) { this.mipmap = mipmap; }
/** Sets whether the texture data is in compressed form. */
public void setIsDataCompressed(boolean compressed) { this.dataIsCompressed = compressed; }
/** Sets whether the texture coordinates must be flipped vertically
diff --git a/src/classes/com/sun/opengl/utils/TextureIO.java b/src/classes/com/sun/opengl/utils/TextureIO.java
index c39cf65e1..aa2e3c0ac 100755
--- a/src/classes/com/sun/opengl/utils/TextureIO.java
+++ b/src/classes/com/sun/opengl/utils/TextureIO.java
@@ -129,12 +129,15 @@ public class TextureIO {
// i.e., reading from a file as opposed to a stream.
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given file. Does no OpenGL work.
+ * Creates a TextureData from the given file. Does no OpenGL work.
*
* @param file the file from which to read the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @param fileSuffix the suffix of the file name to be used as a
* hint of the file format to the underlying
* texture provider, or null if none and should be
@@ -145,18 +148,21 @@ public class TextureIO {
* @throws IOException if an error occurred while reading the file
*/
public static TextureData newTextureData(File file,
- int mipmapLevel,
+ boolean mipmap,
String fileSuffix) throws IOException {
- return newTextureDataImpl(file, mipmapLevel, 0, 0, fileSuffix);
+ return newTextureDataImpl(file, 0, 0, mipmap, fileSuffix);
}
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given stream. Does no OpenGL work.
+ * Creates a TextureData from the given stream. Does no OpenGL work.
*
* @param stream the stream from which to read the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @param fileSuffix the suffix of the file name to be used as a
* hint of the file format to the underlying
* texture provider, or null if none and should be
@@ -167,18 +173,21 @@ public class TextureIO {
* @throws IOException if an error occurred while reading the stream
*/
public static TextureData newTextureData(InputStream stream,
- int mipmapLevel,
+ boolean mipmap,
String fileSuffix) throws IOException {
- return newTextureDataImpl(stream, mipmapLevel, 0, 0, fileSuffix);
+ return newTextureDataImpl(stream, 0, 0, mipmap, fileSuffix);
}
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given URL. Does no OpenGL work.
+ * Creates a TextureData from the given URL. Does no OpenGL work.
*
* @param url the URL from which to read the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @param fileSuffix the suffix of the file name to be used as a
* hint of the file format to the underlying
* texture provider, or null if none and should be
@@ -189,23 +198,23 @@ public class TextureIO {
* @throws IOException if an error occurred while reading the URL
*/
public static TextureData newTextureData(URL url,
- int mipmapLevel,
+ boolean mipmap,
String fileSuffix) throws IOException {
- return newTextureDataImpl(url, mipmapLevel, 0, 0, fileSuffix);
+ return newTextureDataImpl(url, 0, 0, mipmap, fileSuffix);
}
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given BufferedImage. Does no OpenGL work.
+ * Creates a TextureData from the given BufferedImage. Does no
+ * OpenGL work.
*
* @param image the BufferedImage containing the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
+ * @param mipmap whether mipmaps should be produced for this
+ * texture by autogenerating them
* @return the texture data from the image
*/
public static TextureData newTextureData(BufferedImage image,
- int mipmapLevel) {
- return newTextureDataImpl(image, mipmapLevel, 0, 0);
+ boolean mipmap) {
+ return newTextureDataImpl(image, 0, 0, mipmap);
}
//----------------------------------------------------------------------
@@ -216,21 +225,24 @@ public class TextureIO {
// IllegalArgumentException will be thrown in this case.
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given file, using the specified OpenGL
- * internal format and pixel format for the texture which will
- * eventually result. The internalFormat and pixelFormat must be
- * specified and may not be zero; to use default values, use the
+ * Creates a TextureData from the given file, using the specified
+ * OpenGL internal format and pixel format for the texture which
+ * will eventually result. The internalFormat and pixelFormat must
+ * be specified and may not be zero; to use default values, use the
* variant of this method which does not take these arguments. Does
* no OpenGL work.
*
* @param file the file from which to read the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
* @param internalFormat the OpenGL internal format of the texture
* which will eventually result from the TextureData
* @param pixelFormat the OpenGL pixel format of the texture
* which will eventually result from the TextureData
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @param fileSuffix the suffix of the file name to be used as a
* hint of the file format to the underlying
* texture provider, or null if none and should be
@@ -243,33 +255,36 @@ public class TextureIO {
* @throws IOException if an error occurred while reading the file
*/
public static TextureData newTextureData(File file,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException, IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
}
- return newTextureDataImpl(file, mipmapLevel, internalFormat, pixelFormat, fileSuffix);
+ return newTextureDataImpl(file, internalFormat, pixelFormat, mipmap, fileSuffix);
}
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given stream, using the specified OpenGL
- * internal format and pixel format for the texture which will
- * eventually result. The internalFormat and pixelFormat must be
- * specified and may not be zero; to use default values, use the
+ * Creates a TextureData from the given stream, using the specified
+ * OpenGL internal format and pixel format for the texture which
+ * will eventually result. The internalFormat and pixelFormat must
+ * be specified and may not be zero; to use default values, use the
* variant of this method which does not take these arguments. Does
* no OpenGL work.
*
* @param stream the stream from which to read the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
* @param internalFormat the OpenGL internal format of the texture
* which will eventually result from the TextureData
* @param pixelFormat the OpenGL pixel format of the texture
* which will eventually result from the TextureData
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @param fileSuffix the suffix of the file name to be used as a
* hint of the file format to the underlying
* texture provider, or null if none and should be
@@ -282,33 +297,36 @@ public class TextureIO {
* @throws IOException if an error occurred while reading the stream
*/
public static TextureData newTextureData(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException, IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
}
- return newTextureDataImpl(stream, mipmapLevel, internalFormat, pixelFormat, fileSuffix);
+ return newTextureDataImpl(stream, internalFormat, pixelFormat, mipmap, fileSuffix);
}
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given URL, using the specified OpenGL
- * internal format and pixel format for the texture which will
- * eventually result. The internalFormat and pixelFormat must be
- * specified and may not be zero; to use default values, use the
+ * Creates a TextureData from the given URL, using the specified
+ * OpenGL internal format and pixel format for the texture which
+ * will eventually result. The internalFormat and pixelFormat must
+ * be specified and may not be zero; to use default values, use the
* variant of this method which does not take these arguments. Does
* no OpenGL work.
*
* @param url the URL from which to read the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
* @param internalFormat the OpenGL internal format of the texture
* which will eventually result from the TextureData
* @param pixelFormat the OpenGL pixel format of the texture
* which will eventually result from the TextureData
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @param fileSuffix the suffix of the file name to be used as a
* hint of the file format to the underlying
* texture provider, or null if none and should be
@@ -321,46 +339,49 @@ public class TextureIO {
* @throws IOException if an error occurred while reading the URL
*/
public static TextureData newTextureData(URL url,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException, IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
}
- return newTextureDataImpl(url, mipmapLevel, internalFormat, pixelFormat, fileSuffix);
+ return newTextureDataImpl(url, internalFormat, pixelFormat, mipmap, fileSuffix);
}
/**
- * Creates a TextureData representing the specified mipmap level of
- * a texture from the given BufferedImage, using the specified
- * OpenGL internal format and pixel format for the texture which
- * will eventually result. The internalFormat and pixelFormat must
- * be specified and may not be zero; to use default values, use the
- * variant of this method which does not take these arguments. Does
- * no OpenGL work.
+ * Creates a TextureData from the given BufferedImage, using the
+ * specified OpenGL internal format and pixel format for the texture
+ * which will eventually result. The internalFormat and pixelFormat
+ * must be specified and may not be zero; to use default values, use
+ * the variant of this method which does not take these
+ * arguments. Does no OpenGL work.
*
* @param image the BufferedImage containing the texture data
- * @param mipmapLevel the mipmap level this data represents (FIXME:
- * not currently used, needs to be rethought)
* @param internalFormat the OpenGL internal format of the texture
* which will eventually result from the TextureData
* @param pixelFormat the OpenGL pixel format of the texture
* which will eventually result from the TextureData
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @return the texture data from the image
* @throws IllegalArgumentException if either internalFormat or
* pixelFormat was 0
*/
public static TextureData newTextureData(BufferedImage image,
- int mipmapLevel,
int internalFormat,
- int pixelFormat) throws IllegalArgumentException {
+ int pixelFormat,
+ boolean mipmap) throws IllegalArgumentException {
if ((internalFormat == 0) || (pixelFormat == 0)) {
throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero");
}
- return newTextureDataImpl(image, mipmapLevel, internalFormat, pixelFormat);
+ return newTextureDataImpl(image, internalFormat, pixelFormat, mipmap);
}
//----------------------------------------------------------------------
@@ -369,7 +390,8 @@ public class TextureIO {
/**
* Creates an OpenGL texture object from the specified TextureData
- * using the current OpenGL context.
+ * using the current OpenGL context. Does not automatically generate
+ * mipmaps for the resulting texture.
*
* @param data the texture data to turn into an OpenGL texture
* @throws GLException if no OpenGL context is current or if an
@@ -384,15 +406,22 @@ public class TextureIO {
/**
* Creates an OpenGL texture object from the specified file using
- * the current OpenGL context.
+ * the current OpenGL context. Does not automatically generate
+ * mipmaps for the resulting texture.
*
* @param file the file from which to read the texture data
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @throws IOException if an error occurred while reading the file
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(File file) throws IOException, GLException {
- TextureData data = newTextureData(file, 0, getFileSuffix(file));
+ public static Texture newTexture(File file, boolean mipmap) throws IOException, GLException {
+ TextureData data = newTextureData(file, mipmap, getFileSuffix(file));
Texture texture = newTexture(data);
data.flush();
return texture;
@@ -400,31 +429,45 @@ public class TextureIO {
/**
* Creates an OpenGL texture object from the specified stream using
- * the current OpenGL context.
+ * the current OpenGL context. Does not automatically generate
+ * mipmaps for the resulting texture.
*
* @param stream the stream from which to read the texture data
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @throws IOException if an error occurred while reading the stream
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(InputStream stream) throws IOException, GLException {
- TextureData data = newTextureData(stream, 0, null);
+ public static Texture newTexture(InputStream stream, boolean mipmap) throws IOException, GLException {
+ TextureData data = newTextureData(stream, mipmap, null);
Texture texture = newTexture(data);
data.flush();
return texture;
}
/**
- * Creates an OpenGL texture object from the specified URL using
- * the current OpenGL context.
+ * Creates an OpenGL texture object from the specified URL using the
+ * current OpenGL context. Does not automatically generate mipmaps
+ * for the resulting texture.
*
* @param url the URL from which to read the texture data
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
* @throws IOException if an error occurred while reading the URL
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(URL url) throws IOException, GLException {
- TextureData data = newTextureData(url, 0, null);
+ public static Texture newTexture(URL url, boolean mipmap) throws IOException, GLException {
+ TextureData data = newTextureData(url, mipmap, null);
Texture texture = newTexture(data);
data.flush();
return texture;
@@ -435,11 +478,13 @@ public class TextureIO {
* using the current OpenGL context.
*
* @param image the BufferedImage from which to read the texture data
+ * @param mipmap whether mipmaps should be produced for this
+ * texture by autogenerating them
* @throws GLException if no OpenGL context is current or if an
* OpenGL error occurred
*/
- public static Texture newTexture(BufferedImage image) throws GLException {
- TextureData data = newTextureData(image, 0);
+ public static Texture newTexture(BufferedImage image, boolean mipmap) throws GLException {
+ TextureData data = newTextureData(image, mipmap);
Texture texture = newTexture(data);
data.flush();
return texture;
@@ -479,16 +524,16 @@ public class TextureIO {
// Implementation methods
private static TextureData newTextureDataImpl(File file,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) {
TextureProvider provider = (TextureProvider) iter.next();
TextureData data = provider.newTextureData(file,
- mipmapLevel,
internalFormat,
pixelFormat,
+ mipmap,
fileSuffix);
if (data != null) {
return data;
@@ -498,16 +543,16 @@ public class TextureIO {
}
private static TextureData newTextureDataImpl(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) {
TextureProvider provider = (TextureProvider) iter.next();
TextureData data = provider.newTextureData(stream,
- mipmapLevel,
internalFormat,
pixelFormat,
+ mipmap,
fileSuffix);
if (data != null) {
return data;
@@ -518,16 +563,16 @@ public class TextureIO {
}
private static TextureData newTextureDataImpl(URL url,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) {
TextureProvider provider = (TextureProvider) iter.next();
TextureData data = provider.newTextureData(url,
- mipmapLevel,
internalFormat,
pixelFormat,
+ mipmap,
fileSuffix);
if (data != null) {
return data;
@@ -538,47 +583,47 @@ public class TextureIO {
}
private static TextureData newTextureDataImpl(BufferedImage image,
- int mipmapLevel,
int internalFormat,
- int pixelFormat) {
- return new TextureData(mipmapLevel, internalFormat, pixelFormat, image);
+ int pixelFormat,
+ boolean mipmap) {
+ return new TextureData(internalFormat, pixelFormat, mipmap, image);
}
//----------------------------------------------------------------------
// Base provider - used last
static class IIOTextureProvider implements TextureProvider {
public TextureData newTextureData(File file,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
BufferedImage img = ImageIO.read(file);
if (img == null) {
return null;
}
- return new TextureData(mipmapLevel, internalFormat, pixelFormat, img);
+ return new TextureData(internalFormat, pixelFormat, mipmap, img);
}
public TextureData newTextureData(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
BufferedImage img = ImageIO.read(stream);
if (img == null) {
return null;
}
- return new TextureData(mipmapLevel, internalFormat, pixelFormat, img);
+ return new TextureData(internalFormat, pixelFormat, mipmap, img);
}
public TextureData newTextureData(URL url,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
InputStream stream = url.openStream();
try {
- return newTextureData(stream, mipmapLevel, internalFormat, pixelFormat, fileSuffix);
+ return newTextureData(stream, internalFormat, pixelFormat, mipmap, fileSuffix);
} finally {
stream.close();
}
@@ -589,17 +634,15 @@ public class TextureIO {
// DDS provider -- supports files only for now
static class DDSTextureProvider implements TextureProvider {
public TextureData newTextureData(File file,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
if (DDS.equals(fileSuffix) ||
DDS.equals(getFileSuffix(file))) {
final DDSReader reader = new DDSReader();
reader.loadFile(file);
- // FIXME: handle case where all mipmaps are requested -- this
- // will require API changes
- DDSReader.ImageInfo info = reader.getMipMap(mipmapLevel);
+ DDSReader.ImageInfo info = reader.getMipMap(0);
if (pixelFormat == 0) {
switch (reader.getPixelFormat()) {
case DDSReader.D3DFMT_R8G8B8:
@@ -641,17 +684,38 @@ public class TextureIO {
reader.close();
}
};
- TextureData data = new TextureData(mipmapLevel,
- internalFormat,
- info.getWidth(),
- info.getHeight(),
- 0,
- pixelFormat,
- GL.GL_UNSIGNED_BYTE,
- info.isCompressed(),
- true,
- info.getData(),
- flusher);
+ TextureData data;
+ if (mipmap && reader.getNumMipMaps() > 0) {
+ Buffer[] mipmapData = new Buffer[reader.getNumMipMaps()];
+ for (int i = 0; i < reader.getNumMipMaps(); i++) {
+ mipmapData[i] = reader.getMipMap(i).getData();
+ }
+ data = new TextureData(internalFormat,
+ info.getWidth(),
+ info.getHeight(),
+ 0,
+ pixelFormat,
+ GL.GL_UNSIGNED_BYTE,
+ info.isCompressed(),
+ true,
+ mipmapData,
+ flusher);
+ } else {
+ // Fix this up for the end user because we can't generate
+ // mipmaps for compressed textures
+ mipmap = false;
+ data = new TextureData(internalFormat,
+ info.getWidth(),
+ info.getHeight(),
+ 0,
+ pixelFormat,
+ GL.GL_UNSIGNED_BYTE,
+ mipmap,
+ info.isCompressed(),
+ true,
+ info.getData(),
+ flusher);
+ }
return data;
}
@@ -659,17 +723,17 @@ public class TextureIO {
}
public TextureData newTextureData(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
return null;
}
public TextureData newTextureData(URL url,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
return null;
}
@@ -679,9 +743,9 @@ public class TextureIO {
// Base class for SGI RGB and TGA image providers
static abstract class StreamBasedTextureProvider implements TextureProvider {
public TextureData newTextureData(File file,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
InputStream inStream = new BufferedInputStream(new FileInputStream(file));
try {
@@ -689,9 +753,9 @@ public class TextureIO {
// anyway so there isn't much point in having a separate code
// path for files
return newTextureData(inStream,
- mipmapLevel,
internalFormat,
pixelFormat,
+ mipmap,
((fileSuffix != null) ? fileSuffix : getFileSuffix(file)));
} finally {
inStream.close();
@@ -699,13 +763,13 @@ public class TextureIO {
}
public TextureData newTextureData(URL url,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
InputStream stream = url.openStream();
try {
- return newTextureData(stream, mipmapLevel, internalFormat, pixelFormat, fileSuffix);
+ return newTextureData(stream, internalFormat, pixelFormat, mipmap, fileSuffix);
} finally {
stream.close();
}
@@ -716,9 +780,9 @@ public class TextureIO {
// SGI RGB image provider
static class SGITextureProvider extends StreamBasedTextureProvider {
public TextureData newTextureData(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
if (SGI.equals(fileSuffix) ||
SGI_RGB.equals(fileSuffix) ||
@@ -730,13 +794,13 @@ public class TextureIO {
if (internalFormat == 0) {
internalFormat = image.getFormat();
}
- return new TextureData(mipmapLevel,
- internalFormat,
+ return new TextureData(internalFormat,
image.getWidth(),
image.getHeight(),
0,
pixelFormat,
GL.GL_UNSIGNED_BYTE,
+ mipmap,
false,
false,
ByteBuffer.wrap(image.getData()),
@@ -751,9 +815,9 @@ public class TextureIO {
// TGA (Targa) image provider
static class TGATextureProvider extends StreamBasedTextureProvider {
public TextureData newTextureData(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException {
if (TGA.equals(fileSuffix)) {
TGAImage image = TGAImage.read(stream);
@@ -763,13 +827,13 @@ public class TextureIO {
if (internalFormat == 0) {
internalFormat = GL.GL_RGBA8;
}
- return new TextureData(mipmapLevel,
- internalFormat,
+ return new TextureData(internalFormat,
image.getWidth(),
image.getHeight(),
0,
pixelFormat,
GL.GL_UNSIGNED_BYTE,
+ mipmap,
false,
false,
ByteBuffer.wrap(image.getData()),
diff --git a/src/classes/com/sun/opengl/utils/TextureProvider.java b/src/classes/com/sun/opengl/utils/TextureProvider.java
index 4b71ae982..fcc62c894 100755
--- a/src/classes/com/sun/opengl/utils/TextureProvider.java
+++ b/src/classes/com/sun/opengl/utils/TextureProvider.java
@@ -58,9 +58,6 @@ public interface TextureProvider {
*
* @param file the file from which to read the texture data
*
- * @param mipmapLevel the mipmap level of the resulting texture being
- * read (FIXME: needs rethinking, not yet working)
- *
* @param internalFormat the OpenGL internal format to be used for
* the texture, or 0 if it should be inferred
* from the file's contents
@@ -69,6 +66,13 @@ public interface TextureProvider {
* the texture, or 0 if it should be inferred
* from the file's contents
*
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
+ *
* @param fileSuffix the file suffix to be used as a hint to the
* provider to more quickly decide whether it
* can handle the file, or null if the
@@ -78,9 +82,9 @@ public interface TextureProvider {
* @throws IOException if an error occurred while reading the file
*/
public TextureData newTextureData(File file,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException;
/**
@@ -91,9 +95,6 @@ public interface TextureProvider {
*
* @param stream the stream from which to read the texture data
*
- * @param mipmapLevel the mipmap level of the resulting texture being
- * read (FIXME: needs rethinking, not yet working)
- *
* @param internalFormat the OpenGL internal format to be used for
* the texture, or 0 if it should be inferred
* from the file's contents
@@ -102,6 +103,13 @@ public interface TextureProvider {
* the texture, or 0 if it should be inferred
* from the file's contents
*
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
+ *
* @param fileSuffix the file suffix to be used as a hint to the
* provider to more quickly decide whether it
* can handle the file, or null if the
@@ -111,9 +119,9 @@ public interface TextureProvider {
* @throws IOException if an error occurred while reading the stream
*/
public TextureData newTextureData(InputStream stream,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException;
/**
@@ -124,9 +132,6 @@ public interface TextureProvider {
*
* @param url the URL from which to read the texture data
*
- * @param mipmapLevel the mipmap level of the resulting texture being
- * read (FIXME: needs rethinking, not yet working)
- *
* @param internalFormat the OpenGL internal format to be used for
* the texture, or 0 if it should be inferred
* from the file's contents
@@ -135,6 +140,13 @@ public interface TextureProvider {
* the texture, or 0 if it should be inferred
* from the file's contents
*
+ * @param mipmap whether mipmaps should be produced for this
+ * texture either by autogenerating them or
+ * reading them from the file. Some file formats
+ * support multiple mipmaps in a single file in
+ * which case those mipmaps will be used rather
+ * than generating them.
+ *
* @param fileSuffix the file suffix to be used as a hint to the
* provider to more quickly decide whether it
* can handle the file, or null if the
@@ -144,8 +156,8 @@ public interface TextureProvider {
* @throws IOException if an error occurred while reading the URL
*/
public TextureData newTextureData(URL url,
- int mipmapLevel,
int internalFormat,
int pixelFormat,
+ boolean mipmap,
String fileSuffix) throws IOException;
}