aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/sun/opengl/util/texture/Texture.java
diff options
context:
space:
mode:
authorMichael Bien <[email protected]>2010-03-27 23:24:13 +0100
committerMichael Bien <[email protected]>2010-03-27 23:24:13 +0100
commit2b954ff1fe88f35b59da6c6f6b82fde70274a6ef (patch)
tree4f83912cec4d43742cd3d39115b72a900c2aefe7 /src/jogl/classes/com/sun/opengl/util/texture/Texture.java
parentb5bc1819925148adfdb1f2baccdfe9ecd3dc4dbf (diff)
refactoring: renamed com.sun.opengl -> com.jogamp.opengl.
Diffstat (limited to 'src/jogl/classes/com/sun/opengl/util/texture/Texture.java')
-rwxr-xr-xsrc/jogl/classes/com/sun/opengl/util/texture/Texture.java1120
1 files changed, 0 insertions, 1120 deletions
diff --git a/src/jogl/classes/com/sun/opengl/util/texture/Texture.java b/src/jogl/classes/com/sun/opengl/util/texture/Texture.java
deleted file mode 100755
index 3a2799cf3..000000000
--- a/src/jogl/classes/com/sun/opengl/util/texture/Texture.java
+++ /dev/null
@@ -1,1120 +0,0 @@
-/*
- * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- */
-
-package com.sun.opengl.util.texture;
-
-import java.nio.*;
-import java.security.*;
-
-import javax.media.opengl.*;
-import javax.media.opengl.glu.*;
-import javax.media.nativewindow.NativeWindowFactory;
-import com.sun.opengl.impl.*;
-import com.sun.opengl.util.texture.*;
-import com.sun.opengl.util.texture.spi.*;
-
-/**
- * Represents an OpenGL texture object. Contains convenience routines
- * for enabling/disabling OpenGL texture state, binding this texture,
- * and computing texture coordinates for both the entire image as well
- * as a sub-image.
- *
- * <p><a name="nonpow2"><b>Non-power-of-two restrictions</b></a>
- * <br> When creating an OpenGL texture object, the Texture class will
- * attempt to leverage the <a
- * href="http://www.opengl.org/registry/specs/ARB/texture_non_power_of_two.txt">GL_ARB_texture_non_power_of_two</a>
- * and <a
- * href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a>
- * extensions (in that order) whenever possible. If neither extension
- * is available, the Texture class will simply upload a non-pow2-sized
- * image into a standard pow2-sized texture (without any special
- * scaling). Since the choice of extension (or whether one is used at
- * all) depends on the user's machine configuration, developers are
- * recommended to use {@link #getImageTexCoords} and {@link
- * #getSubImageTexCoords}, as those methods will calculate the
- * appropriate texture coordinates for the situation.
- *
- * <p>One caveat in this approach is that certain texture wrap modes
- * (e.g. <code>GL_REPEAT</code>) are not legal when the GL_ARB_texture_rectangle
- * extension is in use. Another issue to be aware of is that in the
- * default pow2 scenario, if the original image does not have pow2
- * dimensions, then wrapping may not work as one might expect since
- * the image does not extend to the edges of the pow2 texture. If
- * texture wrapping is important, it is recommended to use only
- * pow2-sized images with the Texture class.
- *
- * <p><a name="perftips"><b>Performance Tips</b></a>
- * <br> For best performance, try to avoid calling {@link #enable} /
- * {@link #bind} / {@link #disable} any more than necessary. For
- * example, applications using many Texture objects in the same scene
- * may want to reduce the number of calls to both {@link #enable} and
- * {@link #disable}. To do this it is necessary to call {@link
- * #getTarget} to make sure the OpenGL texture target is the same for
- * all of the Texture objects in use; non-power-of-two textures using
- * the GL_ARB_texture_rectangle extension use a different target than
- * power-of-two textures using the GL_TEXTURE_2D target. Note that
- * when switching between textures it is necessary to call {@link
- * #bind}, but when drawing many triangles all using the same texture,
- * for best performance only one call to {@link #bind} should be made.
- *
- * <p><a name="premult"><b>Alpha premultiplication and blending</b></a>
- * <br> The mathematically correct way to perform blending in OpenGL
- * (with the SrcOver "source over destination" mode, or any other
- * Porter-Duff rule) is to use "premultiplied color components", which
- * means the R/G/ B color components have already been multiplied by
- * the alpha value. To make things easier for developers, the Texture
- * class will automatically convert non-premultiplied image data into
- * premultiplied data when storing it into an OpenGL texture. As a
- * result, it is important to use the correct blending function; for
- * example, the SrcOver rule is expressed as:
-<pre>
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
-</pre>
- * Also, when using a texture function like <code>GL_MODULATE</code> where
- * the current color plays a role, it is important to remember to make
- * sure that the color is specified in a premultiplied form, for
- * example:
-<pre>
- float a = ...;
- float r = r * a;
- float g = g * a;
- float b = b * a;
- gl.glColor4f(r, g, b, a);
-</pre>
- *
- * For reference, here is a list of the Porter-Duff compositing rules
- * and the associated OpenGL blend functions (source and destination
- * factors) to use in the face of premultiplied alpha:
- *
-<CENTER>
-<TABLE WIDTH="75%">
-<TR> <TD> Rule <TD> Source <TD> Dest
-<TR> <TD> Clear <TD> GL_ZERO <TD> GL_ZERO
-<TR> <TD> Src <TD> GL_ONE <TD> GL_ZERO
-<TR> <TD> SrcOver <TD> GL_ONE <TD> GL_ONE_MINUS_SRC_ALPHA
-<TR> <TD> DstOver <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE
-<TR> <TD> SrcIn <TD> GL_DST_ALPHA <TD> GL_ZERO
-<TR> <TD> DstIn <TD> GL_ZERO <TD> GL_SRC_ALPHA
-<TR> <TD> SrcOut <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ZERO
-<TR> <TD> DstOut <TD> GL_ZERO <TD> GL_ONE_MINUS_SRC_ALPHA
-<TR> <TD> Dst <TD> GL_ZERO <TD> GL_ONE
-<TR> <TD> SrcAtop <TD> GL_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA
-<TR> <TD> DstAtop <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_SRC_ALPHA
-<TR> <TD> AlphaXor <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA
-</TABLE>
-</CENTER>
- *
- * @author Chris Campbell
- * @author Kenneth Russell
- */
-public class Texture {
- /** The GL target type. */
- private int target;
- /** The GL texture ID. */
- private int texID;
- /** The width of the texture. */
- private int texWidth;
- /** The height of the texture. */
- private int texHeight;
- /** The width of the image. */
- private int imgWidth;
- /** The height of the image. */
- private int imgHeight;
- /** The original aspect ratio of the image, before any rescaling
- that might have occurred due to using the GLU mipmap routines. */
- private float aspectRatio;
- /** 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;
-
- /** An estimate of the amount of texture memory this texture consumes. */
- private int estimatedMemorySize;
-
- private static final AccessControlContext localACC = AccessController.getContext();
-
- private static final boolean DEBUG = Debug.debug("Texture");
- private static final boolean VERBOSE = Debug.verbose();
-
- // For testing alternate code paths on more capable hardware
- private static final boolean disableNPOT = Debug.isPropertyDefined("jogl.texture.nonpot", true, localACC);
- private static final boolean disableTexRect = Debug.isPropertyDefined("jogl.texture.notexrect", true, localACC);
-
- public Texture(TextureData data) throws GLException {
- texID = 0;
- updateImage(data);
- }
-
- // Constructor for use when creating e.g. cube maps, where there is
- // no initial texture data
- public Texture(int target) throws GLException {
- texID = 0;
- this.target = target;
- }
-
- // Package-private constructor for creating a texture object which wraps
- // an existing texture ID from another package
- Texture(int textureID,
- int target,
- int texWidth,
- int texHeight,
- int imgWidth,
- int imgHeight,
- boolean mustFlipVertically) {
- this.texID = textureID;
- this.target = target;
- this.mustFlipVertically = mustFlipVertically;
- this.texWidth = texWidth;
- this.texHeight = texHeight;
- setImageSize(imgWidth, imgHeight, target);
- }
-
- /**
- * Enables this texture's target (e.g., GL_TEXTURE_2D) in the
- * current GL context's state. This method is a shorthand equivalent
- * of the following OpenGL code:
- <pre>
- gl.glEnable(texture.getTarget());
- </pre>
- *
- * See the <a href="#perftips">performance tips</a> above for hints
- * on how to maximize performance when using many Texture objects.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void enable() throws GLException {
- GLContext.getCurrentGL().glEnable(target);
- }
-
- /**
- * Disables this texture's target (e.g., GL_TEXTURE_2D) in the
- * current GL context's state. This method is a shorthand equivalent
- * of the following OpenGL code:
- <pre>
- gl.glDisable(texture.getTarget());
- </pre>
- *
- * See the <a href="#perftips">performance tips</a> above for hints
- * on how to maximize performance when using many Texture objects.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void disable() throws GLException {
- GLContext.getCurrentGL().glDisable(target);
- }
-
- /**
- * Binds this texture to the current GL context. This method is a
- * shorthand equivalent of the following OpenGL code:
- <pre>
- gl.glBindTexture(texture.getTarget(), texture.getTextureObject());
- </pre>
- *
- * See the <a href="#perftips">performance tips</a> above for hints
- * on how to maximize performance when using many Texture objects.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void bind() throws GLException {
- validateTexID(null, true);
- GLContext.getCurrentGL().glBindTexture(target, texID);
- }
-
- /**
- * Disposes the native resources used by this texture object.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- * @deprecated use destroy(GL)
- */
- public void dispose() throws GLException {
- destroy(GLContext.getCurrentGL());
- }
-
- /**
- * Disposes the native resources used by this texture object.
- *
- * @throws GLException if any OpenGL-related errors occurred
- * @deprecated use destroy(GL)
- */
- public void dispose(GL gl) throws GLException {
- destroy(gl);
- }
-
- /**
- * Destroys the native resources used by this texture object.
- *
- * @throws GLException if any OpenGL-related errors occurred
- */
- public void destroy(GL gl) throws GLException {
- if(0<texID) {
- gl.glDeleteTextures(1, new int[] {texID}, 0);
- texID = 0;
- }
- }
-
- /**
- * Returns the OpenGL "target" of this texture.
- *
- * @return the OpenGL target of this texture
- * @see javax.media.opengl.GL#GL_TEXTURE_2D
- * @see javax.media.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB
- */
- public int getTarget() {
- return target;
- }
-
- /**
- * Returns the width of the allocated OpenGL texture in pixels.
- * Note that the texture width will be greater than or equal to the
- * width of the image contained within.
- *
- * @return the width of the texture
- */
- public int getWidth() {
- return texWidth;
- }
-
- /**
- * Returns the height of the allocated OpenGL texture in pixels.
- * Note that the texture height will be greater than or equal to the
- * height of the image contained within.
- *
- * @return the height of the texture
- */
- public int getHeight() {
- return texHeight;
- }
-
- /**
- * Returns the width of the image contained within this texture.
- * Note that for non-power-of-two textures in particular this may
- * not be equal to the result of {@link #getWidth}. It is
- * recommended that applications call {@link #getImageTexCoords} and
- * {@link #getSubImageTexCoords} rather than using this API
- * directly.
- *
- * @return the width of the image
- */
- public int getImageWidth() {
- return imgWidth;
- }
-
- /**
- * Returns the height of the image contained within this texture.
- * Note that for non-power-of-two textures in particular this may
- * not be equal to the result of {@link #getHeight}. It is
- * recommended that applications call {@link #getImageTexCoords} and
- * {@link #getSubImageTexCoords} rather than using this API
- * directly.
- *
- * @return the height of the image
- */
- public int getImageHeight() {
- return imgHeight;
- }
-
- /**
- * Returns the original aspect ratio of the image, defined as (image
- * width) / (image height), before any scaling that might have
- * occurred as a result of using the GLU mipmap routines.
- */
- public float getAspectRatio() {
- return aspectRatio;
- }
-
- /**
- * Returns the set of texture coordinates corresponding to the
- * entire image. If the TextureData indicated that the texture
- * coordinates must be flipped vertically, the returned
- * TextureCoords will take that into account.
- *
- * @return the texture coordinates corresponding to the entire image
- */
- public TextureCoords getImageTexCoords() {
- return coords;
- }
-
- /**
- * Returns the set of texture coordinates corresponding to the
- * specified sub-image. The (x1, y1) and (x2, y2) points are
- * specified in terms of pixels starting from the lower-left of the
- * image. (x1, y1) should specify the lower-left corner of the
- * sub-image and (x2, y2) the upper-right corner of the sub-image.
- * If the TextureData indicated that the texture coordinates must be
- * flipped vertically, the returned TextureCoords will take that
- * into account; this should not be handled by the end user in the
- * specification of the y1 and y2 coordinates.
- *
- * @return the texture coordinates corresponding to the specified sub-image
- */
- public TextureCoords getSubImageTexCoords(int x1, int y1, int x2, int y2) {
- if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) {
- if (mustFlipVertically) {
- return new TextureCoords(x1, texHeight - y1, x2, texHeight - y2);
- } else {
- return new TextureCoords(x1, y1, x2, y2);
- }
- } else {
- float tx1 = (float)x1 / (float)texWidth;
- float ty1 = (float)y1 / (float)texHeight;
- float tx2 = (float)x2 / (float)texWidth;
- float ty2 = (float)y2 / (float)texHeight;
- if (mustFlipVertically) {
- float yMax = (float) imgHeight / (float) texHeight;
- return new TextureCoords(tx1, yMax - ty1, tx2, yMax - ty2);
- } else {
- return new TextureCoords(tx1, ty1, tx2, ty2);
- }
- }
- }
-
- /**
- * Updates the entire content area of this texture using the data in
- * the given image.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void updateImage(TextureData data) throws GLException {
- updateImage(data, 0);
- }
-
- /**
- * 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
- * getImageTexCoords} and {@link #getSubImageTexCoords
- * getSubImageTexCoords}, but applications may generate or otherwise
- * produce texture coordinates which must be corrected.
- */
- public boolean getMustFlipVertically() {
- return mustFlipVertically;
- }
-
- /**
- * Updates the content area of the specified target of this texture
- * using the data in the given image. In general this is intended
- * for construction of cube maps.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void updateImage(TextureData data, int target) throws GLException {
- GL gl = GLContext.getCurrentGL();
- validateTexID(gl, true);
-
- imgWidth = data.getWidth();
- imgHeight = data.getHeight();
- aspectRatio = (float) imgWidth / (float) imgHeight;
- mustFlipVertically = data.getMustFlipVertically();
-
- int texTarget = 0;
- int texParamTarget = this.target;
-
- // See whether we have automatic mipmap generation support
- boolean haveAutoMipmapGeneration =
- (gl.isExtensionAvailable("GL_VERSION_1_4") ||
- gl.isExtensionAvailable("GL_SGIS_generate_mipmap"));
-
- // Indicate to the TextureData what functionality is available
- data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr"));
- data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2"));
-
- // Indicates whether both width and height are power of two
- boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight);
-
- // Note that automatic mipmap generation doesn't work for
- // GL_ARB_texture_rectangle
- if (!isPOT && !haveNPOT(gl)) {
- haveAutoMipmapGeneration = false;
- }
-
- boolean expandingCompressedTexture = false;
- boolean done = 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
- // 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;
- texTarget = GL.GL_TEXTURE_2D;
- done = true;
- }
-
- if (!done && preferTexRect(gl) && !isPOT &&
- haveTexRect(gl) && !data.isDataCompressed() && gl.isGL2()) {
- // GL_ARB_texture_rectangle does not work for compressed textures
- if (DEBUG) {
- System.err.println("Using GL_ARB_texture_rectangle preferentially on this hardware");
- }
-
- texWidth = imgWidth;
- texHeight = imgHeight;
- texTarget = GL2.GL_TEXTURE_RECTANGLE_ARB;
- done = true;
- }
-
- if (!done && (isPOT || haveNPOT(gl))) {
- if (DEBUG) {
- if (isPOT) {
- System.err.println("Power-of-two texture");
- } else {
- System.err.println("Using GL_ARB_texture_non_power_of_two");
- }
- }
-
- texWidth = imgWidth;
- texHeight = imgHeight;
- texTarget = GL.GL_TEXTURE_2D;
- done = true;
- }
-
- if (!done && haveTexRect(gl) && !data.isDataCompressed() && gl.isGL2()) {
- // GL_ARB_texture_rectangle does not work for compressed textures
- if (DEBUG) {
- System.err.println("Using GL_ARB_texture_rectangle");
- }
-
- texWidth = imgWidth;
- texHeight = imgHeight;
- texTarget = GL2.GL_TEXTURE_RECTANGLE_ARB;
- done = true;
- }
-
- if (!done) {
- // 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");
- }
-
- if (data.getBorder() != 0) {
- throw new RuntimeException("Scaling up a non-power-of-two texture which has a border won't work");
- }
- texWidth = nextPowerOfTwo(imgWidth);
- texHeight = nextPowerOfTwo(imgHeight);
- texTarget = GL.GL_TEXTURE_2D;
- }
-
- texParamTarget = texTarget;
- setImageSize(imgWidth, imgHeight, texTarget);
-
- if (target != 0) {
- // Allow user to override auto detection and skip bind step (for
- // cubemap construction)
- texTarget = target;
- if (this.target == 0) {
- throw new GLException("Override of target failed; no target specified yet");
- }
- texParamTarget = this.target;
- gl.glBindTexture(texParamTarget, texID);
- } else {
- gl.glBindTexture(texTarget, texID);
- }
-
- 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());
-
- if (data.isDataCompressed()) {
- throw new GLException("May not request mipmap generation for compressed textures");
- }
-
- try {
- // FIXME: may need check for GLUnsupportedException
- GLU glu = GLU.createGLU(gl);
- glu.gluBuild2DMipmaps(texTarget, data.getInternalFormat(),
- data.getWidth(), data.getHeight(),
- data.getPixelFormat(), data.getPixelType(), data.getBuffer());
- } finally {
- gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore alignment
- }
- } else {
- checkCompressedTextureExtensions(data);
- Buffer[] mipmapData = data.getMipmapData();
- if (mipmapData != null) {
- int width = texWidth;
- int height = texHeight;
- 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]);
- } else {
- // Allocate texture image at this level
- gl.glTexImage2D(texTarget, i, data.getInternalFormat(),
- width, height, data.getBorder(),
- data.getPixelFormat(), data.getPixelType(), null);
- updateSubImageImpl(data, texTarget, i, 0, 0, 0, 0, data.getWidth(), data.getHeight());
- }
-
- width = Math.max(width / 2, 1);
- height = Math.max(height / 2, 1);
- }
- } else {
- if (data.isDataCompressed()) {
- 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 && gl.isGL2ES1()) {
- // 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(texParamTarget, GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE);
- usingAutoMipmapGeneration = true;
- }
-
- gl.glTexImage2D(texTarget, 0, data.getInternalFormat(),
- texWidth, texHeight, data.getBorder(),
- data.getPixelFormat(), data.getPixelType(), null);
- updateSubImageImpl(data, texTarget, 0, 0, 0, 0, 0, data.getWidth(), data.getHeight());
- }
- }
- }
-
- int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR);
- int magFilter = GL.GL_LINEAR;
- int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP;
-
- // REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB
- if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) {
- gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MIN_FILTER, minFilter);
- gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MAG_FILTER, magFilter);
- gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_S, wrapMode);
- gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_T, wrapMode);
- if (this.target == GL2.GL_TEXTURE_CUBE_MAP) {
- gl.glTexParameteri(texParamTarget, GL2.GL_TEXTURE_WRAP_R, wrapMode);
- }
- }
-
- // Don't overwrite target if we're loading e.g. faces of a cube
- // map
- if ((this.target == 0) ||
- (this.target == GL.GL_TEXTURE_2D) ||
- (this.target == GL2.GL_TEXTURE_RECTANGLE_ARB)) {
- this.target = texTarget;
- }
-
- // This estimate will be wrong for cube maps
- estimatedMemorySize = data.getEstimatedMemorySize();
- }
-
- /**
- * Updates a subregion of the content area of this texture using 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.
- *
- * @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
- * of this texture
- *
- * @throws GLException if no OpenGL context was current or if any
- * 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;
- }
- bind();
- 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. 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.
- *
- * @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 dstx the x offset (in pixels) relative to the lower-left corner
- * of this texture where the update will be applied
- * @param dsty the y offset (in pixels) relative to the lower-left corner
- * of this texture where the update will be applied
- * @param srcx the x offset (in pixels) relative to the lower-left corner
- * of the supplied TextureData from which to fetch the update rectangle
- * @param srcy the y offset (in pixels) relative to the lower-left corner
- * of the supplied TextureData from which to fetch the update rectangle
- * @param width the width (in pixels) of the rectangle to be updated
- * @param height the height (in pixels) of the rectangle to be updated
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void updateSubImage(TextureData data, int mipmapLevel,
- int dstx, int dsty,
- int srcx, int srcy,
- int width, int height) throws GLException {
- 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;
- }
- bind();
- updateSubImageImpl(data, target, mipmapLevel, dstx, dsty, srcx, srcy, width, height);
- }
-
- /**
- * Sets the OpenGL floating-point texture parameter for the
- * texture's target. This gives control over parameters such as
- * GL_TEXTURE_MAX_ANISOTROPY_EXT. Causes this texture to be bound to
- * the current texture state.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void setTexParameterf(int parameterName,
- float value) {
- bind();
- GL gl = GLContext.getCurrentGL();
- gl.glTexParameterf(target, parameterName, value);
- }
-
- /**
- * Sets the OpenGL multi-floating-point texture parameter for the
- * texture's target. Causes this texture to be bound to the current
- * texture state.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void setTexParameterfv(int parameterName,
- FloatBuffer params) {
- bind();
- GL gl = GLContext.getCurrentGL();
- gl.glTexParameterfv(target, parameterName, params);
- }
-
- /**
- * Sets the OpenGL multi-floating-point texture parameter for the
- * texture's target. Causes this texture to be bound to the current
- * texture state.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void setTexParameterfv(int parameterName,
- float[] params, int params_offset) {
- bind();
- GL gl = GLContext.getCurrentGL();
- gl.glTexParameterfv(target, parameterName, params, params_offset);
- }
-
- /**
- * Sets the OpenGL integer texture parameter for the texture's
- * target. This gives control over parameters such as
- * GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T, which by default are set
- * to GL_CLAMP_TO_EDGE if OpenGL 1.2 is supported on the current
- * platform and GL_CLAMP if not. Causes this texture to be bound to
- * the current texture state.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void setTexParameteri(int parameterName,
- int value) {
- bind();
- GL gl = GLContext.getCurrentGL();
- gl.glTexParameteri(target, parameterName, value);
- }
-
- /**
- * Sets the OpenGL multi-integer texture parameter for the texture's
- * target. Causes this texture to be bound to the current texture
- * state.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void setTexParameteriv(int parameterName,
- IntBuffer params) {
- bind();
- GL gl = GLContext.getCurrentGL();
- gl.glTexParameteriv(target, parameterName, params);
- }
-
- /**
- * Sets the OpenGL multi-integer texture parameter for the texture's
- * target. Causes this texture to be bound to the current texture
- * state.
- *
- * @throws GLException if no OpenGL context was current or if any
- * OpenGL-related errors occurred
- */
- public void setTexParameteriv(int parameterName,
- int[] params, int params_offset) {
- bind();
- GL gl = GLContext.getCurrentGL();
- gl.glTexParameteriv(target, parameterName, params, params_offset);
- }
-
- /**
- * Returns the underlying OpenGL texture object for this texture.
- * Most applications will not need to access this, since it is
- * handled automatically by the bind() and dispose() APIs.
- */
- public int getTextureObject() {
- validateTexID(null, false);
- return texID;
- }
-
- /** Returns an estimate of the amount of texture memory in bytes
- this Texture consumes. It should only be treated as an estimate;
- most applications should not need to query this but instead let
- the OpenGL implementation page textures in and out as
- necessary. */
- public int getEstimatedMemorySize() {
- 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
- //
-
- /**
- * Returns true if the given value is a power of two.
- *
- * @return true if the given value is a power of two, false otherwise
- */
- private static boolean isPowerOfTwo(int val) {
- return ((val & (val - 1)) == 0);
- }
-
- /**
- * Returns the nearest power of two that is larger than the given value.
- * If the given value is already a power of two, this method will simply
- * return that value.
- *
- * @param val the value
- * @return the next power of two
- */
- private static int nextPowerOfTwo(int val) {
- int ret = 1;
- while (ret < val) {
- ret <<= 1;
- }
- return ret;
- }
-
- /**
- * Updates the actual image dimensions; usually only called from
- * <code>updateImage</code>.
- */
- private void setImageSize(int width, int height, int target) {
- imgWidth = width;
- imgHeight = height;
- if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) {
- if (mustFlipVertically) {
- coords = new TextureCoords(0, imgHeight, imgWidth, 0);
- } else {
- coords = new TextureCoords(0, 0, imgWidth, imgHeight);
- }
- } else {
- if (mustFlipVertically) {
- coords = new TextureCoords(0, (float) imgHeight / (float) texHeight,
- (float) imgWidth / (float) texWidth, 0);
- } else {
- coords = new TextureCoords(0, 0,
- (float) imgWidth / (float) texWidth,
- (float) imgHeight / (float) texHeight);
- }
- }
- }
-
- private void updateSubImageImpl(TextureData data, int newTarget, int mipmapLevel,
- int dstx, int dsty,
- int srcx, int srcy, int width, int height) throws GLException {
- GL gl = GLContext.getCurrentGL();
- data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr"));
- data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2"));
-
- Buffer buffer = data.getBuffer();
- if (buffer == null && data.getMipmapData() == null) {
- // Assume user just wanted to get the Texture object allocated
- return;
- }
-
- int rowlen = data.getRowLength();
- int dataWidth = data.getWidth();
- int dataHeight = data.getHeight();
- if (data.getMipmapData() != null) {
- // Compute the width, height and row length at the specified mipmap level
- // Note we do not support specification of the row length for
- // mipmapped textures at this point
- for (int i = 0; i < mipmapLevel; i++) {
- width = Math.max(width / 2, 1);
- height = Math.max(height / 2, 1);
-
- dataWidth = Math.max(dataWidth / 2, 1);
- dataHeight = Math.max(dataHeight / 2, 1);
- }
- rowlen = 0;
- buffer = data.getMipmapData()[mipmapLevel];
- }
-
- // Clip incoming rectangles to what is available both on this
- // texture and in the incoming TextureData
- if (srcx < 0) {
- width += srcx;
- srcx = 0;
- }
- if (srcy < 0) {
- height += srcy;
- srcy = 0;
- }
- // NOTE: not sure whether the following two are the correct thing to do
- if (dstx < 0) {
- width += dstx;
- dstx = 0;
- }
- if (dsty < 0) {
- height += dsty;
- dsty = 0;
- }
-
- if (srcx + width > dataWidth) {
- width = dataWidth - srcx;
- }
- if (srcy + height > dataHeight) {
- height = dataHeight - srcy;
- }
- if (dstx + width > texWidth) {
- width = texWidth - dstx;
- }
- if (dsty + height > texHeight) {
- height = texHeight - dsty;
- }
-
- checkCompressedTextureExtensions(data);
-
- if (data.isDataCompressed()) {
- gl.glCompressedTexSubImage2D(newTarget, mipmapLevel,
- dstx, dsty, width, height,
- data.getInternalFormat(),
- buffer.remaining(), buffer);
- } else {
- int[] align = { 0 };
- int[] rowLength = { 0 };
- int[] skipRows = { 0 };
- int[] skipPixels = { 0 };
- gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment
- if(gl.isGL2()) {
- gl.glGetIntegerv(GL2.GL_UNPACK_ROW_LENGTH, rowLength, 0); // save row length
- gl.glGetIntegerv(GL2.GL_UNPACK_SKIP_ROWS, skipRows, 0); // save skipped rows
- gl.glGetIntegerv(GL2.GL_UNPACK_SKIP_PIXELS, skipPixels, 0); // save skipped pixels
- }
- gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment());
- if (DEBUG && VERBOSE) {
- System.out.println("Row length = " + rowlen);
- System.out.println("skip pixels = " + srcx);
- System.out.println("skip rows = " + srcy);
- System.out.println("dstx = " + dstx);
- System.out.println("dsty = " + dsty);
- System.out.println("width = " + width);
- System.out.println("height = " + height);
- }
- if(gl.isGL2()) {
- gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, rowlen);
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, srcy);
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, srcx);
- } else {
- if ( rowlen!=0 && rowlen!=width &&
- srcy!=0 && srcx!=0 ) {
- throw new GLException("rowlen and/or x/y offset only available for GL2");
- }
- }
-
- gl.glTexSubImage2D(newTarget, mipmapLevel,
- dstx, dsty, width, height,
- data.getPixelFormat(), data.getPixelType(),
- buffer);
- gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore alignment
- if(gl.isGL2()) {
- gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, rowLength[0]); // restore row length
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, skipRows[0]); // restore skipped rows
- gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, skipPixels[0]); // restore skipped pixels
- }
- }
- }
-
- private void checkCompressedTextureExtensions(TextureData data) {
- GL gl = GLContext.getCurrentGL();
- if (data.isDataCompressed()) {
- 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:
- // FI1027GXME: should test availability of more texture
- // compression extensions here
- break;
- }
- }
- }
-
- private void validateTexID(GL gl, boolean throwException) {
- if( 0 < texID ) return;
- if(null==gl) {
- GLContext ctx = GLContext.getCurrent();
- if(null!=ctx) {
- gl = ctx.getGL();
- } else if(throwException) {
- throw new GLException("No context current, can't create texture ID");
- }
- }
-
- if(null!=gl) {
- int[] tmp = new int[1];
- gl.glGenTextures(1, tmp, 0);
- texID = tmp[0];
- }
- }
-
- // Helper routines for disabling certain codepaths
- private static boolean haveNPOT(GL gl) {
- return (!disableNPOT &&
- ( gl.isGLES2() ||
- gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") ) );
- }
-
- private static boolean haveTexRect(GL gl) {
- return (!disableTexRect &&
- TextureIO.isTexRectEnabled() &&
- gl.isExtensionAvailable("GL_ARB_texture_rectangle"));
- }
-
- private static boolean preferTexRect(GL gl) {
- // Prefer GL_ARB_texture_rectangle on ATI hardware on Mac OS X
- // due to software fallbacks
-
- if (NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false))) {
- String vendor = gl.glGetString(GL.GL_VENDOR);
- if (vendor != null && vendor.startsWith("ATI")) {
- return true;
- }
- }
-
- return false;
- }
-}