From 587ec1437ed762ed8cdfcbf27f940ab83813f4a5 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sat, 27 Apr 2013 08:28:46 +0200
Subject: TextureData: Add PixelAttributes and PixelBufferProvider; ColorSink
 back to JPEGDecode (not general enough)

- TextureData: Add PixelAttributes and PixelBufferProvider
  - PixelBufferProvider is intended as a pattern allowing
    producers (i.e. GLReadBufferUtil) to utilize custom pixel buffer
    for various intend.

  - PixelAttributes can be chosen by PixelBufferProvider implementation
    and groups the texture's pixel/data format and type.
    TextureData uses PixelAttributes internally now.

- ColorSink back to JPEGDecode (not general enough)
  - Partially reverts 94ea306d1809290db678d3181619bdc39d4334bb
---
 .../jogamp/opengl/util/texture/TextureData.java    | 252 ++++++++++++++++++---
 .../opengl/util/texture/awt/AWTTextureData.java    | 139 +++++++-----
 .../jogamp/opengl/util/texture/spi/JPEGImage.java  |   3 +-
 3 files changed, 312 insertions(+), 82 deletions(-)

(limited to 'src/jogl/classes/com/jogamp')

diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
index 15b8930bb..66fba98fe 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -37,9 +38,13 @@
 package com.jogamp.opengl.util.texture;
 
 import java.nio.Buffer;
+import java.nio.ByteBuffer;
 
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
 import javax.media.opengl.GLProfile;
 
+import com.jogamp.common.nio.Buffers;
 import com.jogamp.opengl.util.GLBuffers;
 
 /**
@@ -54,28 +59,92 @@ import com.jogamp.opengl.util.GLBuffers;
  */
 
 public class TextureData {
-    public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK };
+    /** ColorSpace of pixel data. */
+    public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK };   
     
-    public static interface ColorSink {
+    /** Pixel data attributes. */ 
+    public static class PixelAttributes {
+        /** Undefinded instance of {@link PixelAttributes}, having format:=0 and type:= 0. */ 
+        public static final PixelAttributes UNDEF = new PixelAttributes(0, 0);
+        
+        /** The OpenGL pixel data format */
+        public final int format;
+        /** The OpenGL pixel data type  */
+        public final int type;
+        public PixelAttributes(int dataFormat, int dataType) {
+            this.format = dataFormat;
+            this.type = dataType;
+        }
+        public String toString() {
+            return "PixelAttributes[fFmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+"]";
+        }
+    }    
+    /** Allows user to interface with another toolkit to define {@link PixelAttributes} and memory buffer to produce {@link TextureData}. */ 
+    public static interface PixelBufferProvider {
+        /** Called first to determine {@link PixelAttributes}. */
+        PixelAttributes getAttributes(GL gl, int componentCount);
+        
+        /** 
+         * Returns true, if implementation requires a new buffer based on the new size 
+         * and previous aquired {@link #getAttributes(GL, int) attributes} due to pixel alignment, otherwise false.
+         * @see #allocate(int, int, int)
+         */
+        boolean requiresNewBuffer(int width, int height);
+        
+        /** 
+         * Called after {@link #getAttributes(GL, int)} to retrieve the NIO or array backed pixel {@link Buffer}.
+         * <p>
+         * Being called to gather the initial {@link Buffer}, if the existing {@link Buffer} size is not sufficient,
+         * or if {@link #requiresNewBuffer(int, int)} returns false.
+         * </p>
+         * <p>
+         * Number of components was passed via {@link #getAttributes(GL, int)}.
+         * </p>
+         * <p>
+         * The returned buffer must have at least <code>minByteSize</code> {@link Buffer#remaining() remaining}.
+         * </p>
+         */
+        Buffer allocate(int width, int height, int minByteSize);
+    }
+    /** 
+     * Default {@link PixelBufferProvider} utilizing best match for {@link PixelAttributes}
+     * and {@link #allocate(int, int, int) allocating} a {@link ByteBuffer}.
+     */
+    public static class DefPixelBufferProvider implements PixelBufferProvider {
+        @Override
+        public PixelAttributes getAttributes(GL gl, int componentCount) {
+            final GLContext ctx = gl.getContext();
+            final int dFormat, dType;
+            
+            if(gl.isGL2GL3() && 3 == componentCount) {
+                dFormat = GL.GL_RGB;
+                dType   = GL.GL_UNSIGNED_BYTE;            
+            } else {
+                dFormat = ctx.getDefaultPixelDataFormat();
+                dType   = ctx.getDefaultPixelDataType();
+            }
+            return new TextureData.PixelAttributes(dFormat, dType);
+        }        
+        @Override
+        public boolean requiresNewBuffer(int width, int height) {
+            return false;
+        }
         /**
-         * @param width
-         * @param height
-         * @param sourceCS the color-space of the decoded JPEG
-         * @param sourceComponents number of components used for the given source color-space
-         * @return Either {@link ColorSpace#RGB} or {@link ColorSpace#YCbCr}. {@link ColorSpace#YCCK} and {@link ColorSpace#CMYK} will throw an exception! 
-         * @throws RuntimeException
+         * {@inheritDoc}
+         * <p>
+         * Returns an NIO {@link ByteBuffer} of <code>minByteSize</code>.
+         * </p>
          */
-        public ColorSpace allocate(int width, int height, ColorSpace sourceCS, int sourceComponents) throws RuntimeException;
-        public void store2(int x, int y, byte c1, byte c2);
-        public void storeRGB(int x, int y, byte r, byte g, byte b);
-        public void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr);        
+        @Override
+        public final Buffer allocate(int width, int height, int minByteSize) {
+            return Buffers.newDirectByteBuffer(minByteSize);
+        }
     }
     
     protected int width;
     protected int height;
     private int border;
-    protected int pixelFormat;
-    protected int pixelType;
+    protected PixelAttributes pixelAttributes;
     protected int internalFormat; // perhaps inferred from pixelFormat?
     protected boolean mipmap; // indicates whether mipmaps should be generated
     // (ignored if mipmaps are supplied from the file)
@@ -148,6 +217,60 @@ public class TextureData {
                        boolean mustFlipVertically,
                        Buffer buffer,
                        Flusher flusher) throws IllegalArgumentException {
+        this(glp, internalFormat, width, height, border, new PixelAttributes(pixelFormat, pixelType), 
+             mipmap, dataIsCompressed, mustFlipVertically, buffer, flusher);
+    }
+
+    /** 
+     * Constructs a new TextureData object with the specified parameters
+     * and data contained in the given Buffer. 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 glp the OpenGL Profile this texture data should be
+     *                  created for.
+     * @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 texture
+     * @param height         the height in pixels of the texture
+     * @param border         the number of pixels of border this texture
+     *                       data has (0 or 1)
+     * @param pixelAttributes the OpenGL pixel format and type for the
+     *                       resulting texture; must be specified, may
+     *                       not be 0
+     * @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)
+     * @param mustFlipVertically indicates whether the texture
+     *                           coordinates must be flipped vertically
+     *                           in order to properly display the
+     *                           texture
+     * @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(GLProfile glp, 
+                       int internalFormat,
+                       int width,
+                       int height,
+                       int border,
+                       PixelAttributes pixelAttributes,
+                       boolean mipmap,
+                       boolean dataIsCompressed,
+                       boolean mustFlipVertically,
+                       Buffer buffer,
+                       Flusher flusher) throws IllegalArgumentException {
         if (mipmap && dataIsCompressed) {
             throw new IllegalArgumentException("Can not generate mipmaps for compressed textures");
         }
@@ -156,8 +279,7 @@ public class TextureData {
         this.width = width;
         this.height = height;
         this.border = border;
-        this.pixelFormat = pixelFormat;
-        this.pixelType = pixelType;
+        this.pixelAttributes = pixelAttributes;
         this.internalFormat = internalFormat;
         this.mipmap = mipmap;
         this.dataIsCompressed = dataIsCompressed;
@@ -167,7 +289,7 @@ public class TextureData {
         alignment = 1;  // FIXME: is this correct enough in all situations?
         estimatedMemorySize = estimatedMemorySize(buffer);
     }
-
+    
     /** 
      * Constructs a new TextureData object with the specified parameters
      * and data for multiple mipmap levels contained in the given array
@@ -218,12 +340,63 @@ public class TextureData {
                        boolean mustFlipVertically,
                        Buffer[] mipmapData,
                        Flusher flusher) throws IllegalArgumentException {
+        this(glp, internalFormat, width, height, border, new PixelAttributes(pixelFormat, pixelType), 
+             dataIsCompressed, mustFlipVertically, mipmapData, flusher);
+    }
+
+    /** 
+     * 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 glp the OpenGL Profile this texture data should be
+     *                  created for.
+     * @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 pixelAttributes the OpenGL pixel format and type for the
+     *                       resulting texture; must be specified, may
+     *                       not be 0
+     * @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(GLProfile glp,
+                       int internalFormat,
+                       int width,
+                       int height,
+                       int border,
+                       PixelAttributes pixelAttributes,
+                       boolean dataIsCompressed,
+                       boolean mustFlipVertically,
+                       Buffer[] mipmapData,
+                       Flusher flusher) throws IllegalArgumentException {
         this.glProfile = glp;
         this.width = width;
         this.height = height;
         this.border = border;
-        this.pixelFormat = pixelFormat;
-        this.pixelType = pixelType;
+        this.pixelAttributes = pixelAttributes;
         this.internalFormat = internalFormat;
         this.dataIsCompressed = dataIsCompressed;
         this.mustFlipVertically = mustFlipVertically;
@@ -234,7 +407,7 @@ public class TextureData {
             estimatedMemorySize += estimatedMemorySize(mipmapData[i]);
         }
     }
-
+    
     /** 
      * Returns the color space of the pixel data.
      * @see #setColorSpace(ColorSpace) 
@@ -248,7 +421,7 @@ public class TextureData {
     public void setColorSpace(ColorSpace cs) { pixelCS = cs; }
     
     /** Used only by subclasses */
-    protected TextureData(GLProfile glp) { this.glProfile = glp; }
+    protected TextureData(GLProfile glp) { this.glProfile = glp; this.pixelAttributes = PixelAttributes.UNDEF; }
 
     /** Returns the width in pixels of the texture data. */
     public int getWidth() { return width; }
@@ -258,13 +431,17 @@ public class TextureData {
     public int getBorder() { 
         return border; 
     }
+    /** Returns the intended OpenGL {@link PixelAttributes} of the texture data, i.e. format and type. */
+    public PixelAttributes getPixelAttributes() {
+        return pixelAttributes;
+    }
     /** Returns the intended OpenGL pixel format of the texture data. */
     public int getPixelFormat() {
-        return pixelFormat;
+        return pixelAttributes.format;
     }
     /** Returns the intended OpenGL pixel type of the texture data. */
     public int getPixelType() {
-        return pixelType;
+        return pixelAttributes.type;
     }
     /** Returns the intended OpenGL internal format of the texture data. */
     public int getInternalFormat() { 
@@ -310,9 +487,29 @@ public class TextureData {
     /** Sets the border in pixels of the texture data. */
     public void setBorder(int border) { this.border = border; }
     /** Sets the intended OpenGL pixel format of the texture data. */
-    public void setPixelFormat(int pixelFormat) { this.pixelFormat = pixelFormat; }
-    /** Sets the intended OpenGL pixel type of the texture data. */
-    public void setPixelType(int pixelType) { this.pixelType = pixelType; }
+    public void setPixelAttributes(PixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; }     
+    /** 
+     * Sets the intended OpenGL pixel format component of {@link PixelAttributes} of the texture data.
+     * <p>
+     * Use {@link #setPixelAttributes(PixelAttributes)}, if setting format and type. 
+     * </p> 
+     */
+    public void setPixelFormat(int pixelFormat) {
+        if( pixelAttributes.format != pixelFormat ) {
+            pixelAttributes = new PixelAttributes(pixelFormat, pixelAttributes.type);
+        }
+    }
+    /** 
+     * Sets the intended OpenGL pixel type component of {@link PixelAttributes} of the texture data.
+     * <p>
+     * Use {@link #setPixelAttributes(PixelAttributes)}, if setting format and type. 
+     * </p> 
+     */
+    public void setPixelType(int pixelType) { 
+        if( pixelAttributes.type != pixelType) {
+            pixelAttributes = new PixelAttributes(pixelAttributes.format, pixelType);
+        }
+    }
     /** Sets the intended OpenGL internal format of the texture data. */
     public void setInternalFormat(int internalFormat) { this.internalFormat = internalFormat; }
     /** Sets whether mipmaps should be generated for the texture data. */
@@ -385,7 +582,8 @@ public class TextureData {
     }
 
     public String toString() {
-        return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", pixelFormat 0x"+Integer.toHexString(pixelFormat)+", pixelType 0x"+Integer.toHexString(pixelType)+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength;
+        return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", "+
+                pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength;
     }
 
     //----------------------------------------------------------------------
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
index 3b90fad65..d77bd835e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -65,9 +66,51 @@ import javax.media.opengl.GL2GL3;
 import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 
+import com.jogamp.common.nio.Buffers;
 import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureData.PixelBufferProvider;
 
 public class AWTTextureData extends TextureData {
+    public static final PixelAttributes awtPixelAttributesIntRGB = new PixelAttributes(GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+    
+    /** 
+     * AWT {@link PixelBufferProvider} backed by a {@link BufferedImage} of type 
+     * {@link BufferedImage#TYPE_INT_ARGB} or {@link BufferedImage#TYPE_INT_RGB}
+     * and {@link #allocate(int, int, int) allocating} am array backed  {@link IntBuffer}.
+     */
+    public static final class AWTPixelBufferProviderInt implements PixelBufferProvider {
+        private BufferedImage image = null;
+        private int componentCount = 0;
+        
+        @Override
+        public PixelAttributes getAttributes(GL gl, int componentCount) {
+            this.componentCount = componentCount;
+            return awtPixelAttributesIntRGB;
+        }
+        @Override
+        public boolean requiresNewBuffer(int width, int height) {
+            return null == image || image.getWidth() != width || image.getHeight() != height;
+        }
+        /**
+         * {@inheritDoc}
+         * <p>
+         * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+         * </p>
+         */
+        @Override
+        public Buffer allocate(int width, int height, int minByteSize) {
+            image = new BufferedImage(width, height, 4 == componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+            final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+            return IntBuffer.wrap( readBackIntBuffer );
+        }
+        
+        /** Returns the number source components being used as indicated at {@link #allocate(int, int, int)}. */
+        public int getComponentCount() { return componentCount; }
+        
+        /** Returns the underlying {@link BufferedImage} as allocated via {@link #allocate(int, int, int)}. */
+        public BufferedImage getImage() { return image; }
+    }
+    
     // Mechanism for lazily converting input BufferedImages with custom
     // ColorModels to standard ones for uploading to OpenGL, as well as
     // backing off from the optimizations of hoping that either
@@ -134,33 +177,38 @@ public class AWTTextureData extends TextureData {
         }
     }
 
-    /** Returns the intended OpenGL pixel format of the texture data. */
-    public int getPixelFormat() {
+    private void validatePixelAttributes() {
         if (imageForLazyCustomConversion != null) {
             if (!((expectingEXTABGR && haveEXTABGR) ||
                   (expectingGL12    && haveGL12))) {
-                revertPixelFormatAndType();
+                revertPixelAttributes();
             }
-        }
-        return pixelFormat;
+        }        
     }
-    /** Returns the intended OpenGL pixel type of the texture data. */
+    
+    @Override
+    public PixelAttributes getPixelAttributes() {
+        validatePixelAttributes();
+        return super.getPixelAttributes();
+    }
+    
+    @Override
+    public int getPixelFormat() {
+        validatePixelAttributes();
+        return super.getPixelFormat();
+    }
+    @Override
     public int getPixelType() {
-        if (imageForLazyCustomConversion != null) {
-            if (!((expectingEXTABGR && haveEXTABGR) ||
-                  (expectingGL12    && haveGL12))) {
-                revertPixelFormatAndType();
-            }
-        }
-        return pixelType;
+        validatePixelAttributes();
+        return super.getPixelType();
     }
 
-    /** Returns the texture data, or null if it is specified as a set of mipmaps. */
+    @Override
     public Buffer getBuffer() {
         if (imageForLazyCustomConversion != null) {
             if (!((expectingEXTABGR && haveEXTABGR) ||
                   (expectingGL12    && haveGL12))) {
-                revertPixelFormatAndType();
+                revertPixelAttributes();
                 // Must present the illusion to the end user that we are simply
                 // wrapping the input BufferedImage
                 createFromCustom(imageForLazyCustomConversion);
@@ -170,7 +218,7 @@ public class AWTTextureData extends TextureData {
     }
 
     private void createFromImage(GLProfile glp, BufferedImage image) {
-        pixelType = 0; // Determine from image
+        pixelAttributes = PixelAttributes.UNDEF; // Determine from image
         mustFlipVertically = true;
 
         width = image.getWidth();
@@ -200,24 +248,21 @@ public class AWTTextureData extends TextureData {
         if (glp.isGL2GL3()) {
             switch (image.getType()) {
                 case BufferedImage.TYPE_INT_RGB:
-                    pixelFormat = GL.GL_BGRA;
-                    pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+                    pixelAttributes = new PixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
                     rowLength = scanlineStride;
                     alignment = 4;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_INT_ARGB_PRE:
-                    pixelFormat = GL.GL_BGRA;
-                    pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+                    pixelAttributes = new PixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
                     rowLength = scanlineStride;
                     alignment = 4;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_INT_BGR:
-                    pixelFormat = GL.GL_RGBA;
-                    pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+                    pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
                     rowLength = scanlineStride;
                     alignment = 4;
                     expectingGL12 = true;
@@ -228,8 +273,7 @@ public class AWTTextureData extends TextureData {
                         // we can pass the image data directly to OpenGL only if
                         // we have an integral number of pixels in each scanline
                         if ((scanlineStride % 3) == 0) {
-                            pixelFormat = GL2GL3.GL_BGR;
-                            pixelType = GL.GL_UNSIGNED_BYTE;
+                            pixelAttributes = new PixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE);
                             rowLength = scanlineStride / 3;
                             alignment = 1;
                         } else {
@@ -249,8 +293,7 @@ public class AWTTextureData extends TextureData {
                         // the necessary byte swapping (FIXME: needs more
                         // investigation)
                         if ((scanlineStride % 4) == 0 && glp.isGL2() && false) {
-                            pixelFormat = GL2.GL_ABGR_EXT;
-                            pixelType = GL.GL_UNSIGNED_BYTE;
+                            pixelAttributes = new PixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE);
                             rowLength = scanlineStride / 4;
                             alignment = 4;
     
@@ -266,30 +309,26 @@ public class AWTTextureData extends TextureData {
                         }
                     }
                 case BufferedImage.TYPE_USHORT_565_RGB:
-                    pixelFormat = GL.GL_RGB;
-                    pixelType = GL.GL_UNSIGNED_SHORT_5_6_5;
+                    pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_USHORT_555_RGB:
-                    pixelFormat = GL.GL_BGRA;
-                    pixelType = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV;
+                    pixelAttributes = new PixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_BYTE_GRAY:
-                    pixelFormat = GL.GL_LUMINANCE;
-                    pixelType = GL.GL_UNSIGNED_BYTE;
+                    pixelAttributes = new PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
                     rowLength = scanlineStride;
                     alignment = 1;
                     break;
                 case BufferedImage.TYPE_USHORT_GRAY:
-                    pixelFormat = GL.GL_LUMINANCE;
-                    pixelType = GL.GL_UNSIGNED_SHORT;
+                    pixelAttributes = new PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT);
                     rowLength = scanlineStride;
                     alignment = 2;
                     break;
@@ -304,13 +343,11 @@ public class AWTTextureData extends TextureData {
                 default:
                     java.awt.image.ColorModel cm = image.getColorModel();
                     if (cm.equals(rgbColorModel)) {
-                        pixelFormat = GL.GL_RGB;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 3;
                         alignment = 1;
                     } else if (cm.equals(rgbaColorModel)) {
-                        pixelFormat = GL.GL_RGBA;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 4; // FIXME: correct?
                         alignment = 4;
                     } else {
@@ -322,8 +359,7 @@ public class AWTTextureData extends TextureData {
         } else {
             switch (image.getType()) {
                 case BufferedImage.TYPE_INT_RGB:
-                    pixelFormat = GL.GL_RGB;
-                    pixelType = GL.GL_UNSIGNED_BYTE;
+                    pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
                     rowLength = scanlineStride;
                     alignment = 3;
                     expectingGL12 = true;
@@ -338,24 +374,21 @@ public class AWTTextureData extends TextureData {
                 case BufferedImage.TYPE_4BYTE_ABGR_PRE:
                     throw new GLException("INT_BGR n.a.");
                 case BufferedImage.TYPE_USHORT_565_RGB:
-                    pixelFormat = GL.GL_RGB;
-                    pixelType = GL.GL_UNSIGNED_SHORT_5_6_5;
+                    pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_USHORT_555_RGB:
-                    pixelFormat = GL.GL_RGBA;
-                    pixelType = GL.GL_UNSIGNED_SHORT_5_5_5_1;
+                    pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_BYTE_GRAY:
-                    pixelFormat = GL.GL_LUMINANCE;
-                    pixelType = GL.GL_UNSIGNED_BYTE;
+                    pixelAttributes = new PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
                     rowLength = scanlineStride;
                     alignment = 1;
                     break;
@@ -372,13 +405,11 @@ public class AWTTextureData extends TextureData {
                 default:
                     java.awt.image.ColorModel cm = image.getColorModel();
                     if (cm.equals(rgbColorModel)) {
-                        pixelFormat = GL.GL_RGB;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 3;
                         alignment = 1;
                     } else if (cm.equals(rgbaColorModel)) {
-                        pixelFormat = GL.GL_RGBA;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 4; // FIXME: correct?
                         alignment = 4;
                     } else {
@@ -395,6 +426,8 @@ public class AWTTextureData extends TextureData {
     private void setupLazyCustomConversion(BufferedImage image) {
         imageForLazyCustomConversion = image;
         boolean hasAlpha = image.getColorModel().hasAlpha();
+        int pixelFormat = pixelAttributes.format;
+        int pixelType = pixelAttributes.type;
         if (pixelFormat == 0) {
             pixelFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
         }
@@ -421,6 +454,7 @@ public class AWTTextureData extends TextureData {
         } else {
             throw new RuntimeException("Unexpected DataBuffer type?");
         }
+        pixelAttributes = new PixelAttributes(pixelFormat, pixelType);
     }
 
     private void createFromCustom(BufferedImage image) {
@@ -474,13 +508,12 @@ public class AWTTextureData extends TextureData {
                 imgType == BufferedImage.TYPE_INT_ARGB_PRE);
     }
 
-    private void revertPixelFormatAndType() {
+    private void revertPixelAttributes() {
         // Knowing we don't have e.g. OpenGL 1.2 functionality available,
         // and knowing we're in the process of doing the fallback code
         // path, re-infer a vanilla pixel format and type compatible with
         // OpenGL 1.1
-        pixelFormat = 0;
-        pixelType = 0;
+        pixelAttributes = PixelAttributes.UNDEF;
         setupLazyCustomConversion(imageForLazyCustomConversion);
     }
 
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
index 14253e4af..4d3d088ba 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
@@ -38,7 +38,6 @@ import jogamp.opengl.util.jpeg.JPEGDecoder;
 
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
-import com.jogamp.opengl.util.texture.TextureData.ColorSink;
 
 public class JPEGImage {
     private static final boolean DEBUG = Debug.debug("JPEGImage");    
@@ -61,7 +60,7 @@ public class JPEGImage {
         return new JPEGImage(in, ColorSpace.RGB);
     }
     
-    private static class JPEGColorSink implements ColorSink  {
+    private static class JPEGColorSink implements JPEGDecoder.ColorSink  {
         int width=0, height=0;
         int sourceComponents=0;
         ColorSpace sourceCS = ColorSpace.YCbCr;
-- 
cgit v1.2.3