aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2007-09-04 02:35:52 +0000
committerKenneth Russel <[email protected]>2007-09-04 02:35:52 +0000
commit6cead503317fa6e771b371bfb4dd381472b60113 (patch)
tree7343627d103c91f577069b8fd1c866e1aeb5750e /src
parentfb452d0124202c707d3dac9488a5c97233dc7635 (diff)
Added support for loading non-mipmapped, non-power-of-two compressed
textures on pre-OpenGL 2.0 hardware by first loading an "empty" compressed texture and then updating a sub-rectangle of its image. Straightforward port of this code to the mipmapped case did not work; added error checking for this case and throwing of GLException. Bug pointed out by Dave Collins from NASA World Wind Java project. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1354 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src')
-rwxr-xr-xsrc/classes/com/sun/opengl/util/texture/Texture.java44
-rwxr-xr-xsrc/classes/com/sun/opengl/util/texture/spi/DDSImage.java36
2 files changed, 75 insertions, 5 deletions
diff --git a/src/classes/com/sun/opengl/util/texture/Texture.java b/src/classes/com/sun/opengl/util/texture/Texture.java
index 3518d8c38..d634f66fb 100755
--- a/src/classes/com/sun/opengl/util/texture/Texture.java
+++ b/src/classes/com/sun/opengl/util/texture/Texture.java
@@ -41,6 +41,7 @@ import java.nio.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import com.sun.opengl.impl.*;
+import com.sun.opengl.util.texture.spi.*;
/**
* Represents an OpenGL texture object. Contains convenience routines
@@ -405,6 +406,7 @@ public class Texture {
haveAutoMipmapGeneration = false;
}
+ boolean expandingCompressedTexture = false;
if (data.getMipmap() && !haveAutoMipmapGeneration) {
// GLU always scales the texture's dimensions to be powers of
// two. It also doesn't really matter exactly what the texture
@@ -428,7 +430,8 @@ public class Texture {
texWidth = imgWidth;
texHeight = imgHeight;
texTarget = GL.GL_TEXTURE_2D;
- } else if (haveTexRect(gl)) {
+ } else if (haveTexRect(gl) && !data.isDataCompressed()) {
+ // GL_ARB_texture_rectangle does not work for compressed textures
if (DEBUG) {
System.err.println("Using GL_ARB_texture_rectangle");
}
@@ -437,6 +440,25 @@ public class Texture {
texHeight = imgHeight;
texTarget = GL.GL_TEXTURE_RECTANGLE_ARB;
} else {
+ // If we receive non-power-of-two compressed texture data and
+ // don't have true hardware support for compressed textures, we
+ // can fake this support by producing an empty "compressed"
+ // texture image, using glCompressedTexImage2D with that to
+ // allocate the texture, and glCompressedTexSubImage2D with the
+ // incoming data.
+ if (data.isDataCompressed()) {
+ if (data.getMipmapData() != null) {
+
+ // We don't currently support expanding of compressed,
+ // mipmapped non-power-of-two textures to the nearest power
+ // of two; the obvious port of the non-mipmapped code didn't
+ // work
+ throw new GLException("Mipmapped non-power-of-two compressed textures only supported on OpenGL 2.0 hardware (GL_ARB_texture_non_power_of_two)");
+ }
+
+ expandingCompressedTexture = true;
+ }
+
if (DEBUG) {
System.err.println("Expanding texture to power-of-two dimensions");
}
@@ -491,6 +513,7 @@ public class Texture {
for (int i = 0; i < mipmapData.length; i++) {
if (data.isDataCompressed()) {
// Need to use glCompressedTexImage2D directly to allocate and fill this image
+ // Avoid spurious memory allocation when possible
gl.glCompressedTexImage2D(texTarget, i, data.getInternalFormat(),
width, height, data.getBorder(),
mipmapData[i].remaining(), mipmapData[i]);
@@ -507,10 +530,21 @@ public class Texture {
}
} else {
if (data.isDataCompressed()) {
- // Need to use glCompressedTexImage2D directly to allocate and fill this image
- gl.glCompressedTexImage2D(texTarget, 0, data.getInternalFormat(),
- texWidth, texHeight, data.getBorder(),
- data.getBuffer().capacity(), data.getBuffer());
+ if (!expandingCompressedTexture) {
+ // Need to use glCompressedTexImage2D directly to allocate and fill this image
+ // Avoid spurious memory allocation when possible
+ gl.glCompressedTexImage2D(texTarget, 0, data.getInternalFormat(),
+ texWidth, texHeight, data.getBorder(),
+ data.getBuffer().capacity(), data.getBuffer());
+ } else {
+ ByteBuffer buf = DDSImage.allocateBlankBuffer(texWidth,
+ texHeight,
+ data.getInternalFormat());
+ gl.glCompressedTexImage2D(texTarget, 0, data.getInternalFormat(),
+ texWidth, texHeight, data.getBorder(),
+ buf.capacity(), buf);
+ updateSubImageImpl(data, texTarget, 0, 0, 0, 0, 0, data.getWidth(), data.getHeight());
+ }
} else {
if (data.getMipmap() && haveAutoMipmapGeneration) {
// For now, only use hardware mipmapping for uncompressed 2D
diff --git a/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java b/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java
index 52dbc25b1..835025b5c 100755
--- a/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java
+++ b/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java
@@ -43,6 +43,9 @@ import java.io.*;
import java.nio.*;
import java.nio.channels.*;
+import javax.media.opengl.*;
+import com.sun.opengl.util.*;
+
/** A reader and writer for DirectDraw Surface (.dds) files, which are
used to describe textures. These files can contain multiple mipmap
levels in one file. This class is currently minimal and does not
@@ -469,6 +472,39 @@ public class DDSImage {
return buf.toString();
}
+ /** Allocates a temporary, empty ByteBuffer suitable for use in a
+ call to glCompressedTexImage2D. This is used by the Texture
+ class to expand non-power-of-two DDS compressed textures to
+ power-of-two sizes on hardware not supporting OpenGL 2.0 and the
+ NPOT texture extension. The specified OpenGL internal format
+ must be one of GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, or
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT.
+ */
+ public static ByteBuffer allocateBlankBuffer(int width,
+ int height,
+ int openGLInternalFormat) {
+ int size = width * height;
+ switch (openGLInternalFormat) {
+ case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ size /= 2;
+ break;
+
+ case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ break;
+
+ default:
+ throw new IllegalArgumentException("Illegal OpenGL texture internal format " +
+ openGLInternalFormat);
+ }
+ if (size == 0)
+ size = 1;
+ return BufferUtil.newByteBuffer(size);
+ }
+
public void debugPrint() {
PrintStream tty = System.err;
tty.println("Compressed texture: " + isCompressed());