aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2007-04-08 15:35:31 +0000
committerKenneth Russel <[email protected]>2007-04-08 15:35:31 +0000
commitd1c3191328fe9d1c15b1ac27cf0f0a05b176c300 (patch)
treee2db36a36540c7499e437c1b8f308716489b184e
parent01975af12221798e09a72783fadd3cd0d5e1f5bc (diff)
Added automatic mipmap generation support via GL_GENERATE_MIPMAP
texture parameter to Texture class. Exposed this support up through the TextureRenderer and TextRenderer classes. Tested by temporarily enabling mipmap support for TextCube demo; no visual improvement, however, so left it disabled for now. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1194 232f8b59-042b-4e1e-8c03-345bb8c30851
-rwxr-xr-xsrc/classes/com/sun/opengl/util/j2d/TextRenderer.java68
-rwxr-xr-xsrc/classes/com/sun/opengl/util/j2d/TextureRenderer.java68
-rwxr-xr-xsrc/classes/com/sun/opengl/util/texture/Texture.java65
3 files changed, 179 insertions, 22 deletions
diff --git a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
index d25888be2..468590b7d 100755
--- a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
+++ b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
@@ -113,6 +113,9 @@ public class TextRenderer {
private boolean antialiased;
private boolean useFractionalMetrics;
+ // Whether we're attempting to use automatic mipmap generation support
+ private boolean mipmap;
+
private RectanglePacker packer;
private boolean haveMaxSize;
private RenderDelegate renderDelegate;
@@ -227,15 +230,30 @@ public class TextRenderer {
@param font the font to render with
*/
public TextRenderer(Font font) {
- this(font, false, false);
+ this(font, false, false, null, false);
+ }
+
+ /** Creates a new TextRenderer with the given font, using no
+ antialiasing or fractional metrics, and the default
+ RenderDelegate. If <CODE>mipmap</CODE> is true, attempts to use
+ OpenGL's automatic mipmap generation for better smoothing when
+ rendering the TextureRenderer's contents at a distance.
+ Equivalent to <code>TextRenderer(font, false, false)</code>.
+
+ @param font the font to render with
+ @param mipmap whether to attempt use of automatic mipmap generation
+ */
+ public TextRenderer(Font font, boolean mipmap) {
+ this(font, false, false, null, mipmap);
}
/** Creates a new TextRenderer with the given Font, specified font
properties, and default RenderDelegate. The
<code>antialiased</code> and <code>useFractionalMetrics</code>
flags provide control over the same properties at the Java 2D
- level. Equivalent to <code>TextRenderer(font, antialiased,
- useFractionalMetrics, null)</code>.
+ level. No mipmap support is requested. Equivalent to
+ <code>TextRenderer(font, antialiased, useFractionalMetrics,
+ null)</code>.
@param font the font to render with
@param antialiased whether to use antialiased fonts
@@ -245,7 +263,7 @@ public class TextRenderer {
public TextRenderer(Font font,
boolean antialiased,
boolean useFractionalMetrics) {
- this(font, antialiased, useFractionalMetrics, null);
+ this(font, antialiased, useFractionalMetrics, null, false);
}
/** Creates a new TextRenderer with the given Font, specified font
@@ -253,7 +271,7 @@ public class TextRenderer {
<code>antialiased</code> and <code>useFractionalMetrics</code>
flags provide control over the same properties at the Java 2D
level. The <code>renderDelegate</code> provides more control
- over the text rendered.
+ over the text rendered. No mipmap support is requested.
@param font the font to render with
@param antialiased whether to use antialiased fonts
@@ -266,9 +284,35 @@ public class TextRenderer {
boolean antialiased,
boolean useFractionalMetrics,
RenderDelegate renderDelegate) {
+ this(font, antialiased, useFractionalMetrics, renderDelegate, false);
+ }
+
+ /** Creates a new TextRenderer with the given Font, specified font
+ properties, and given RenderDelegate. The
+ <code>antialiased</code> and <code>useFractionalMetrics</code>
+ flags provide control over the same properties at the Java 2D
+ level. The <code>renderDelegate</code> provides more control
+ over the text rendered. If <CODE>mipmap</CODE> is true, attempts
+ to use OpenGL's automatic mipmap generation for better smoothing
+ when rendering the TextureRenderer's contents at a distance.
+
+ @param font the font to render with
+ @param antialiased whether to use antialiased fonts
+ @param useFractionalMetrics whether to use fractional font
+ metrics at the Java 2D level
+ @param renderDelegate the render delegate to use to draw the
+ text's bitmap, or null to use the default one
+ @param mipmap whether to attempt use of automatic mipmap generation
+ */
+ public TextRenderer(Font font,
+ boolean antialiased,
+ boolean useFractionalMetrics,
+ RenderDelegate renderDelegate,
+ boolean mipmap) {
this.font = font;
this.antialiased = antialiased;
this.useFractionalMetrics = useFractionalMetrics;
+ this.mipmap = mipmap;
// FIXME: consider adjusting the size based on font size
// (it will already automatically resize if necessary)
@@ -631,6 +675,15 @@ public class TextRenderer {
}
needToResetColor = false;
}
+
+ // Disable future attempts to use mipmapping if TextureRenderer
+ // doesn't support it
+ if (mipmap && !getBackingStore().isUsingAutoMipmapGeneration()) {
+ if (DEBUG) {
+ System.err.println("Disabled mipmapping in TextRenderer");
+ }
+ mipmap = false;
+ }
}
private void endRendering(boolean ortho) throws GLException {
@@ -741,10 +794,11 @@ public class TextRenderer {
// store (i.e., non-default Paint, foreground color, etc.), but
// for now, let's just be more efficient
TextureRenderer renderer;
+
if (renderDelegate.intensityOnly()) {
- renderer = TextureRenderer.createAlphaOnlyRenderer(w, h);
+ renderer = TextureRenderer.createAlphaOnlyRenderer(w, h, mipmap);
} else {
- renderer = new TextureRenderer(w, h, true);
+ renderer = new TextureRenderer(w, h, true, mipmap);
}
if (DEBUG) {
System.err.println(" TextRenderer allocating backing store " + w + " x " + h);
diff --git a/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java b/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java
index be4b8b629..4ca3d03e0 100755
--- a/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java
+++ b/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java
@@ -73,6 +73,9 @@ public class TextureRenderer {
// Whether we're using only a GL_INTENSITY backing store
private boolean intensity;
+ // Whether we're attempting to use automatic mipmap generation support
+ private boolean mipmap;
+
// Whether smoothing is enabled for the OpenGL texture (switching
// between GL_LINEAR and GL_NEAREST filtering)
private boolean smoothing = true;
@@ -95,8 +98,9 @@ public class TextureRenderer {
private float a = 1.0f;
/** Creates a new renderer with backing store of the specified width
- and height. If alpha is true, allocates an alpha channel in the
- backing store image.
+ and height. If <CODE>alpha</CODE> is true, allocates an alpha
+ channel in the backing store image. No mipmap support is
+ requested.
@param width the width of the texture to render into
@param height the height of the texture to render into
@@ -106,19 +110,46 @@ public class TextureRenderer {
this(width, height, alpha, false);
}
+ /** Creates a new renderer with backing store of the specified width
+ and height. If <CODE>alpha</CODE> is true, allocates an alpha channel in the
+ backing store image. If <CODE>mipmap</CODE> is true, attempts to use OpenGL's
+ automatic mipmap generation for better smoothing when rendering
+ the TextureRenderer's contents at a distance.
+
+ @param width the width of the texture to render into
+ @param height the height of the texture to render into
+ @param alpha whether to allocate an alpha channel for the texture
+ @param mipmap whether to attempt use of automatic mipmap generation
+ */
+ public TextureRenderer(int width, int height, boolean alpha, boolean mipmap) {
+ this(width, height, alpha, false, mipmap);
+ }
+
// Internal constructor to avoid confusion since alpha only makes
// sense when intensity is not set
- private TextureRenderer(int width, int height, boolean alpha, boolean intensity) {
+ private TextureRenderer(int width, int height, boolean alpha, boolean intensity, boolean mipmap) {
this.alpha = alpha;
this.intensity = intensity;
+ this.mipmap = mipmap;
init(width, height);
}
/** Creates a new renderer with a special kind of backing store
- which acts only as an alpha channel. Internally, this associates
- a GL_INTENSITY OpenGL texture with the backing store. */
+ which acts only as an alpha channel. No mipmap support is
+ requested. Internally, this associates a GL_INTENSITY OpenGL
+ texture with the backing store. */
public static TextureRenderer createAlphaOnlyRenderer(int width, int height) {
- return new TextureRenderer(width, height, false, true);
+ return createAlphaOnlyRenderer(width, height, false);
+ }
+
+ /** Creates a new renderer with a special kind of backing store
+ which acts only as an alpha channel. If <CODE>mipmap</CODE> is
+ true, attempts to use OpenGL's automatic mipmap generation for
+ better smoothing when rendering the TextureRenderer's contents
+ at a distance. Internally, this associates a GL_INTENSITY OpenGL
+ texture with the backing store. */
+ public static TextureRenderer createAlphaOnlyRenderer(int width, int height, boolean mipmap) {
+ return new TextureRenderer(width, height, false, true, mipmap);
}
/** Returns the width of the backing store of this renderer.
@@ -504,6 +535,15 @@ public class TextureRenderer {
endRendering(false);
}
+ /** Indicates whether automatic mipmap generation is in use for this
+ TextureRenderer. The result of this method may change from true
+ to false if it is discovered during allocation of the
+ TextureRenderer's backing store that automatic mipmap generation
+ is not supported at the OpenGL level. */
+ public boolean isUsingAutoMipmapGeneration() {
+ return mipmap;
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -542,8 +582,12 @@ public class TextureRenderer {
if (smoothingChanged) {
smoothingChanged = false;
if (smoothing) {
- texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
+ if (mipmap) {
+ texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
+ } else {
+ texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
+ }
} else {
texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
@@ -583,7 +627,7 @@ public class TextureRenderer {
// BufferedImage; it's just a reference to the contents but we
// need it in order to update sub-regions of the underlying
// texture
- textureData = new TextureData(internalFormat, 0, false, image);
+ textureData = new TextureData(internalFormat, 0, mipmap, image);
// For now, always reallocate the underlying OpenGL texture when
// the backing store size changes
mustReallocateTexture = true;
@@ -630,6 +674,14 @@ public class TextureRenderer {
if (texture == null) {
texture = TextureIO.newTexture(textureData);
+ if (mipmap && !texture.isUsingAutoMipmapGeneration()) {
+ // Only try this once
+ texture.dispose();
+ mipmap = false;
+ textureData.setMipmap(false);
+ texture = TextureIO.newTexture(textureData);
+ }
+
if (!smoothing) {
// The TextureIO classes default to GL_LINEAR filtering
texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
diff --git a/src/classes/com/sun/opengl/util/texture/Texture.java b/src/classes/com/sun/opengl/util/texture/Texture.java
index 9ceff7cd8..85c2da52e 100755
--- a/src/classes/com/sun/opengl/util/texture/Texture.java
+++ b/src/classes/com/sun/opengl/util/texture/Texture.java
@@ -133,6 +133,9 @@ public class Texture {
/** Indicates whether the TextureData requires a vertical flip of
the texture coords. */
private boolean mustFlipVertically;
+ /** Indicates whether we're using automatic mipmap generation
+ support (GL_GENERATE_MIPMAP). */
+ private boolean usingAutoMipmapGeneration;
/** The texture coordinates corresponding to the entire image. */
private TextureCoords coords;
@@ -358,9 +361,10 @@ public class Texture {
/**
* Indicates whether this texture's texture coordinates must be
* flipped vertically in order to properly display the texture. This
- * is handled automatically by {@link #getImageTexCoords} and {@link
- * #getSubImageTexCoords}, but applications may generate or
- * otherwise produce texture coordinates which must be corrected.
+ * is handled automatically by {@link #getImageTexCoords
+ * getImageTexCoords} and {@link #getSubImageTexCoords
+ * getSubImageTexCoords}, but applications may generate or otherwise
+ * produce texture coordinates which must be corrected.
*/
public boolean getMustFlipVertically() {
return mustFlipVertically;
@@ -384,7 +388,12 @@ public class Texture {
int newTarget = 0;
- if (data.getMipmap()) {
+ // See whether we have automatic mipmap generation support
+ boolean haveAutoMipmapGeneration =
+ (gl.isExtensionAvailable("GL_VERSION_1_4") ||
+ gl.isExtensionAvailable("GL_SGIS_generate_mipmap"));
+
+ 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
// width and height are because the texture coords are always
@@ -457,7 +466,7 @@ public class Texture {
}
}
- if (data.getMipmap()) {
+ if (data.getMipmap() && !haveAutoMipmapGeneration) {
int[] align = new int[1];
gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment());
@@ -504,6 +513,15 @@ public class Texture {
texWidth, texHeight, data.getBorder(),
data.getBuffer().capacity(), data.getBuffer());
} else {
+ if (data.getMipmap() && haveAutoMipmapGeneration) {
+ // For now, only use hardware mipmapping for uncompressed 2D
+ // textures where the user hasn't explicitly specified
+ // mipmap data; don't know about interactions between
+ // GL_GENERATE_MIPMAP and glCompressedTexImage2D
+ gl.glTexParameteri(newTarget, GL.GL_GENERATE_MIPMAP, GL.GL_TRUE);
+ usingAutoMipmapGeneration = true;
+ }
+
gl.glTexImage2D(newTarget, 0, data.getInternalFormat(),
texWidth, texHeight, data.getBorder(),
data.getPixelFormat(), data.getPixelType(), null);
@@ -526,7 +544,12 @@ public class Texture {
/**
* Updates a subregion of the content area of this texture using the
- * given data. Only updates the specified mipmap level and does not
+ * given data. If automatic mipmap generation is in use (see {@link
+ * #isUsingAutoMipmapGeneration isUsingAutoMipmapGeneration}),
+ * updates to the base (level 0) mipmap will cause the lower-level
+ * mipmaps to be regenerated, and updates to other mipmap levels
+ * will be ignored. Otherwise, if automatic mipmap generation is not
+ * in use, 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
@@ -542,12 +565,22 @@ public class Texture {
* OpenGL-related errors occurred
*/
public void updateSubImage(TextureData data, int mipmapLevel, int x, int y) throws GLException {
+ if (usingAutoMipmapGeneration && mipmapLevel != 0) {
+ // When we're using mipmap generation via GL_GENERATE_MIPMAP, we
+ // don't need to update other mipmap levels
+ return;
+ }
updateSubImageImpl(data, target, mipmapLevel, x, y, 0, 0, data.getWidth(), data.getHeight());
}
/**
* Updates a subregion of the content area of this texture using the
- * specified sub-region of the given data. Only updates the
+ * specified sub-region of the given data. If automatic mipmap
+ * generation is in use (see {@link #isUsingAutoMipmapGeneration
+ * isUsingAutoMipmapGeneration}), updates to the base (level 0)
+ * mipmap will cause the lower-level mipmaps to be regenerated, and
+ * updates to other mipmap levels will be ignored. Otherwise, if
+ * automatic mipmap generation is not in use, only updates the
* specified mipmap level and does not re-generate mipmaps if they
* were originally produced or loaded. This method is only supported
* for uncompressed TextureData sources.
@@ -577,6 +610,11 @@ public class Texture {
if (data.isDataCompressed()) {
throw new GLException("updateSubImage specifying a sub-rectangle is not supported for compressed TextureData");
}
+ if (usingAutoMipmapGeneration && mipmapLevel != 0) {
+ // When we're using mipmap generation via GL_GENERATE_MIPMAP, we
+ // don't need to update other mipmap levels
+ return;
+ }
updateSubImageImpl(data, target, mipmapLevel, dstx, dsty, srcx, srcy, width, height);
}
@@ -692,6 +730,19 @@ public class Texture {
return estimatedMemorySize;
}
+ /** Indicates whether this Texture is using automatic mipmap
+ generation (via the OpenGL texture parameter
+ GL_GENERATE_MIPMAP). This will automatically be used when
+ mipmapping is requested via the TextureData and either OpenGL
+ 1.4 or the GL_SGIS_generate_mipmap extension is available. If
+ so, updates to the base image (mipmap level 0) will
+ automatically propagate down to the lower mipmap levels. Manual
+ updates of the mipmap data at these lower levels will be
+ ignored. */
+ public boolean isUsingAutoMipmapGeneration() {
+ return usingAutoMipmapGeneration;
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//