16d924649999a6a55d2314082adf1e03e27a05ec
[scilab.git] / scilab / modules / scirenderer / src / org / scilab / forge / scirenderer / implementation / jogl / texture / JoGLTextureManager.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2012 - DIGITEO - Pierre Lando
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  */
11
12 package org.scilab.forge.scirenderer.implementation.jogl.texture;
13
14 import com.jogamp.opengl.util.texture.TextureIO;
15 import com.jogamp.opengl.util.texture.TextureCoords;
16
17 import org.scilab.forge.scirenderer.SciRendererException;
18 import org.scilab.forge.scirenderer.buffers.ElementsBuffer;
19 import org.scilab.forge.scirenderer.implementation.jogl.JoGLCanvas;
20 import org.scilab.forge.scirenderer.implementation.jogl.JoGLDrawingTools;
21 import org.scilab.forge.scirenderer.texture.AbstractTexture;
22 import org.scilab.forge.scirenderer.texture.AnchorPosition;
23 import org.scilab.forge.scirenderer.texture.Texture;
24 import org.scilab.forge.scirenderer.texture.TextureManager;
25 import org.scilab.forge.scirenderer.texture.TextureDataProvider;
26 import org.scilab.forge.scirenderer.tranformations.Transformation;
27 import org.scilab.forge.scirenderer.tranformations.TransformationManager;
28 import org.scilab.forge.scirenderer.tranformations.Vector3d;
29
30
31 import javax.media.opengl.GL;
32 import javax.media.opengl.GL2;
33 import javax.media.opengl.GL2ES1;
34 import javax.media.opengl.GL2GL3;
35 import javax.media.opengl.GLProfile;
36 import java.awt.Dimension;
37 import java.nio.ByteBuffer;
38 import java.nio.FloatBuffer;
39 import java.util.Collection;
40 import java.util.HashSet;
41 import java.util.Set;
42
43 /**
44  * @author Pierre Lando
45  */
46 public class JoGLTextureManager implements TextureManager {
47
48     private final Set<JoGLTexture> allTextures = new HashSet<JoGLTexture>();
49     JoGLCanvas canvas;
50
51     public JoGLTextureManager(JoGLCanvas canvas) {
52         this.canvas = canvas;
53     }
54
55     /**
56      * Texture binder.
57      * Bind the given texture to the given OpenGl context.
58      * @param drawingTools drawing tools.
59      * @param texture given texture.
60      * @throws org.scilab.forge.scirenderer.SciRendererException if the texture can't be bind.
61      */
62     public void bind(JoGLDrawingTools drawingTools, Texture texture) throws SciRendererException {
63         if ((texture instanceof JoGLTexture) && (allTextures.contains((JoGLTexture) texture))) {
64             ((JoGLTexture) texture).bind(drawingTools);
65         }
66     }
67
68     /**
69      * Draw the given texture.
70      * @param drawingTools used drawing tools.
71      * @param texture the texture too drawn.
72      * @throws org.scilab.forge.scirenderer.SciRendererException if the texture is invalid.
73      */
74     public void draw(JoGLDrawingTools drawingTools, Texture texture) throws SciRendererException {
75         if ((texture instanceof JoGLTexture) && (allTextures.contains((JoGLTexture) texture))) {
76             final JoGLTexture jt = (JoGLTexture) texture;
77             if (jt.preDraw(drawingTools)) {
78                 jt.draw(drawingTools);
79                 jt.postDraw(drawingTools);
80             }
81         }
82     }
83
84     public void draw(JoGLDrawingTools drawingTools, Texture texture, AnchorPosition anchor, ElementsBuffer positions, double rotationAngle) throws SciRendererException {
85         if ((texture instanceof JoGLTexture) && (allTextures.contains((JoGLTexture) texture))) {
86             if (positions != null) {
87                 FloatBuffer data = positions.getData();
88                 if (data != null) {
89                     data.rewind();
90                     float[] position = {0, 0, 0, 1};
91                     final JoGLTexture jt = (JoGLTexture) texture;
92                     if (jt.preDraw(drawingTools)) {
93                         while (data.remaining() >= 4) {
94                             data.get(position);
95                             jt.draw(drawingTools, anchor, new Vector3d(position), rotationAngle);
96                         }
97                         jt.postDraw(drawingTools);
98                     }
99                 }
100             }
101         }
102     }
103
104     public void draw(JoGLDrawingTools drawingTools, Texture texture, AnchorPosition anchor, Vector3d position, double rotationAngle) throws SciRendererException {
105         if ((texture instanceof JoGLTexture) && (allTextures.contains((JoGLTexture) texture))) {
106             final JoGLTexture jt = (JoGLTexture) texture;
107             jt.preDraw(drawingTools);
108             jt.draw(drawingTools, anchor, position, rotationAngle);
109             jt.postDraw(drawingTools);
110         }
111     }
112
113     /** Called when gl context is gone. */
114     public void glReload() {
115         for (JoGLTexture texture : allTextures) {
116             texture.glReload();
117         }
118     }
119
120     @Override
121     public Texture createTexture() {
122         JoGLTexture texture = new JoGLTexture();
123         allTextures.add(texture);
124         return texture;
125     }
126
127     @Override
128     public void dispose(Collection<Texture> textures) {
129         for (Texture texture : textures) {
130             dispose(texture);
131         }
132     }
133
134     @Override
135     public void dispose(Texture texture) {
136         if ((texture instanceof JoGLTexture) && (allTextures.contains((JoGLTexture) texture))) {
137             allTextures.remove((JoGLTexture) texture);
138             ((JoGLTexture) texture).dispose();
139         }
140     }
141
142     /**
143      * Inner class for {@link Texture} implementation.
144      */
145     public class JoGLTexture extends AbstractTexture implements Texture {
146         private com.jogamp.opengl.util.texture.Texture[] textures;
147         private JoGLTextureData[] textureData;
148         private int wCuts;
149         private int hCuts;
150         private double sfactor = 1;
151         private double tfactor = 1;
152         private ByteBuffer buffer;
153         private TextureDataProvider.ImageType previousType;
154         private JoGLDrawingTools drawingTools;
155
156         /**
157          * Default constructor.
158          */
159         public JoGLTexture() {
160         }
161
162         public final boolean isRowMajorOrder() {
163             return getDataProvider().isRowMajorOrder();
164         }
165
166         /**
167          * Bind the texture in the OpenGl context.
168          * @param drawingTools current drawing tools.
169          * @throws SciRendererException if the texture is invalid.
170          */
171         public synchronized void bind(JoGLDrawingTools drawingTools) throws SciRendererException {
172             if (this.drawingTools == null) {
173                 this.drawingTools = this.drawingTools;
174             }
175
176             GL2 gl = drawingTools.getGl().getGL2();
177             if (isValid()) {
178                 checkData(drawingTools);
179                 if (textures.length == 1) {
180                     gl.glEnable(GL2.GL_TEXTURE_2D);
181                     gl.glEnable(GL2.GL_BLEND);
182                     gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA);
183                     gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE);
184
185                     textures[0].setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, getAsGLFilter(getMagnificationFilter(), false));
186                     textures[0].setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, getAsGLFilter(getMinifyingFilter(), false));
187                     if (gl.isNPOTTextureAvailable()) {
188                         textures[0].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, getAsGLWrappingMode(getSWrappingMode()));
189                         textures[0].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, getAsGLWrappingMode(getTWrappingMode()));
190                     } else {
191                         textures[0].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
192                         textures[0].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
193                     }
194                     textures[0].bind(gl);
195
196                     /* sfactor and tfactor are useful to have the correct texture coordinates when the texture
197                        was transformed into a power-of-two texture */
198                     Dimension textureSize = getDataProvider().getTextureSize();
199                     sfactor = (double) textureSize.width / (double) textures[0].getWidth();
200                     tfactor = (double) textureSize.height / (double) textures[0].getHeight();
201                 } else {
202                     throw new SciRendererException("Texture is too large");
203                 }
204             } else {
205                 throw new SciRendererException("Texture have no data.");
206             }
207         }
208
209         /**
210          * Check if the texture data are up to date.
211          * @param drawingTools the drawing tools.
212          * @throws SciRendererException if the texture is too big.
213          */
214         private synchronized void checkData(JoGLDrawingTools drawingTools) throws SciRendererException {
215             if (isValid() && !upToDate) {
216                 GL2 gl = drawingTools.getGl().getGL2();
217
218                 Dimension textureSize = getDataProvider().getTextureSize();
219                 int maxSize = drawingTools.getGLCapacity().getMaximumTextureSize();
220                 wCuts = (int) Math.ceil(textureSize.getWidth() / maxSize);
221                 hCuts = (int) Math.ceil(textureSize.getHeight() / maxSize);
222                 ByteBuffer newBuffer = getDataProvider().getData();
223                 TextureDataProvider.ImageType newType = getDataProvider().getImageType();
224
225                 if (newBuffer != null && textureSize.width != 0 && textureSize.height != 0) {
226                     boolean hasChanged = false;
227                     if (newBuffer != buffer || newType != previousType) {
228                         releaseTextures(gl);
229                         if (newBuffer != null) {
230                             textures = new com.jogamp.opengl.util.texture.Texture[wCuts * hCuts];
231                             textureData = new JoGLTextureData[wCuts * hCuts];
232                         }
233                         buffer = newBuffer;
234                         previousType = newType;
235                         hasChanged = true;
236                     }
237
238                     if (newBuffer != null || buffer != null) {
239                         if (wCuts == 1 && hCuts == 1) {
240                             if (hasChanged) {
241                                 if (isRowMajorOrder()) {
242                                     textureData[0] = new JoGLTextureData(gl.getGLProfile(), newType, buffer, textureSize.width, textureSize.height);
243                                 } else {
244                                     textureData[0] = new JoGLTextureData(gl.getGLProfile(), newType, buffer, textureSize.height, textureSize.width);
245                                 }
246                                 try {
247                                     textures[0] = TextureIO.newTexture(textureData[0]);
248                                 } catch (Exception e) {
249                                     System.err.println(e);
250                                 }
251                             } else {
252                                 try {
253                                     textures[0].updateSubImage(gl, textureData[0], 0, 0, 0);
254                                 } catch (Exception e) {
255                                     System.err.println(e);
256                                 }
257                             }
258                         } else {
259                             int k = 0;
260                             for (int i = 0; i < wCuts; i++) {
261                                 for (int j = 0; j < hCuts; j++) {
262                                     if (hasChanged) {
263                                         final int x = i * maxSize;
264                                         final int y = j * maxSize;
265                                         final int width = getSubTextureSize((i == (wCuts - 1)), textureSize.width, maxSize);
266                                         final int height = getSubTextureSize((j == (hCuts - 1)), textureSize.height, maxSize);
267                                         if (isRowMajorOrder()) {
268                                             textureData[k] = new JoGLTextureData(gl.getGLProfile(), newType, buffer, width, height, x, y, textureSize.width, textureSize.height);
269                                         } else {
270                                             textureData[k] = new JoGLTextureData(gl.getGLProfile(), newType, buffer, height, width, y, x, textureSize.height, textureSize.width);
271                                         }
272                                         textures[k] = TextureIO.newTexture(textureData[k]);
273                                     } else {
274                                         textures[k].updateSubImage(gl, textureData[k], 0, 0, 0);
275                                     }
276                                     k++;
277                                 }
278                             }
279                         }
280                     }
281                 }
282                 if (textures != null) {
283                     upToDate = true;
284                 }
285             }
286         }
287
288         private void releaseTextures(GL2 gl) {
289             if (textures != null) {
290                 for (com.jogamp.opengl.util.texture.Texture texture : textures) {
291                     if (texture != null) {
292                         texture.destroy(gl);
293                     }
294                 }
295                 textures = null;
296             }
297
298             if (textureData != null) {
299                 for (JoGLTextureData td : textureData) {
300                     if (td != null) {
301                         td.destroy();
302                     }
303                 }
304                 textureData = null;
305             }
306         }
307
308         public void dispose() {
309             if (drawingTools != null) {
310                 releaseTextures(drawingTools.getGl().getGL2());
311             }
312         }
313
314         public boolean preDraw(JoGLDrawingTools drawingTools) throws SciRendererException {
315             checkData(drawingTools);
316
317             if (textures == null) {
318                 return false;
319             }
320
321             final GL2 gl = drawingTools.getGl().getGL2();
322
323             gl.glMatrixMode(GL2.GL_TEXTURE);
324             gl.glPushMatrix();
325             gl.glLoadIdentity();
326
327             gl.glMatrixMode(GL2.GL_PROJECTION);
328             gl.glPushMatrix();
329             gl.glLoadIdentity();
330
331             gl.glEnable(GL2.GL_TEXTURE_2D);
332             gl.glEnable(GL2.GL_BLEND);
333             gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA);
334
335             gl.glEnable(GL2.GL_ALPHA_TEST);
336             gl.glAlphaFunc(GL2.GL_GREATER, 0.0f);
337
338             gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
339
340             gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE);
341
342             for (int k = 0; k < wCuts * hCuts; k++) {
343                 textures[k].enable(gl);
344                 textures[k].setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, getAsGLFilter(getMagnificationFilter(), false));
345                 textures[k].setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, getAsGLFilter(getMinifyingFilter(), false));
346                 if (gl.isNPOTTextureAvailable()) {
347                     textures[k].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, getAsGLWrappingMode(getSWrappingMode()));
348                     textures[k].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, getAsGLWrappingMode(getTWrappingMode()));
349                 } else {
350                     textures[k].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
351                     textures[k].setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
352                 }
353             }
354
355             return true;
356         }
357
358         public void draw(JoGLDrawingTools drawingTools, AnchorPosition anchor, Vector3d position, double rotationAngle) throws SciRendererException {
359             TransformationManager transformationManager = drawingTools.getTransformationManager();
360             Transformation canvasProjection = transformationManager.getCanvasProjection();
361             boolean sceneCoordinate = drawingTools.getTransformationManager().isUsingSceneCoordinate();
362             Dimension dimension = drawingTools.getCanvas().getDimension();
363             Vector3d projected;
364             final GL2 gl = drawingTools.getGl().getGL2();
365
366             if (sceneCoordinate) {
367                 projected = canvasProjection.project(position);
368             } else {
369                 projected = position;
370             }
371
372             gl.glMatrixMode(GL2.GL_MODELVIEW);
373             gl.glPushMatrix();
374             gl.glLoadIdentity();
375             gl.glOrtho(0, dimension.width, 0,  dimension.height, 1, -1);
376
377             if (rotationAngle == 0) {
378                 gl.glTranslated(Math.round(projected.getX() + getAnchorDeltaX(anchor)), Math.round(projected.getY() + getAnchorDeltaY(anchor)), projected.getZ());
379             } else {
380                 gl.glTranslated(Math.round(projected.getX()), Math.round(projected.getY()), projected.getZ());
381                 gl.glRotated(rotationAngle, 0, 0, 1);
382                 gl.glTranslated(Math.round(getAnchorDeltaX(anchor)), Math.round(getAnchorDeltaY(anchor)), 0);
383             }
384
385             draw(drawingTools);
386
387             gl.glMatrixMode(GL2.GL_MODELVIEW);
388             gl.glPopMatrix();
389         }
390
391         public void postDraw(JoGLDrawingTools drawingTools) {
392             final GL2 gl = drawingTools.getGl().getGL2();
393
394             for (int k = 0; k < wCuts * hCuts; k++) {
395                 textures[k].disable(gl);
396             }
397
398             gl.glPopAttrib();
399             gl.glDisable(GL2.GL_ALPHA_TEST);
400             gl.glDisable(GL2.GL_TEXTURE_2D);
401             gl.glDisable(GL2.GL_BLEND);
402
403             gl.glMatrixMode(GL2.GL_PROJECTION);
404             gl.glPopMatrix();
405
406             gl.glMatrixMode(GL2.GL_TEXTURE);
407             gl.glPopMatrix();
408         }
409
410         /**
411          * Draw the texture in XY plane.
412          * @param drawingTools the drawing tools.
413          * @throws SciRendererException if the texture is invalid.
414          */
415         public void draw(JoGLDrawingTools drawingTools) throws SciRendererException {
416             final int maxSize = drawingTools.getGLCapacity().getMaximumTextureSize();
417             final Dimension textureSize = getDataProvider().getTextureSize();
418             final GL2 gl = drawingTools.getGl().getGL2();
419
420             if (textureSize != null && textures != null) {
421                 if (wCuts == 1 && hCuts == 1) {
422                     final TextureCoords coords;
423                     if (isRowMajorOrder()) {
424                         coords = textures[0].getSubImageTexCoords(0, 0, textureSize.width, textureSize.height);
425                     } else {
426                         coords = textures[0].getSubImageTexCoords(0, 0, textureSize.height, textureSize.width);
427                     }
428                     textures[0].bind(gl);
429
430                     gl.glBegin(GL2.GL_QUADS);
431                     gl.glTexCoord2f(coords.left(), coords.bottom());
432                     if (isRowMajorOrder()) {
433                         gl.glVertex2f(0, 0);
434                     } else {
435                         gl.glVertex2f(textureSize.width, textureSize.height);
436                     }
437                     gl.glTexCoord2f(coords.right(), coords.bottom());
438                     gl.glVertex2f(textureSize.width, 0);
439                     gl.glTexCoord2f(coords.right(), coords.top());
440                     if (isRowMajorOrder()) {
441                         gl.glVertex2f(textureSize.width, textureSize.height);
442                     } else {
443                         gl.glVertex2f(0, 0);
444                     }
445                     gl.glTexCoord2f(coords.left(), coords.top());
446                     gl.glVertex2f(0, textureSize.height);
447                     gl.glEnd();
448                 } else {
449                     int k = 0;
450                     for (int i = 0; i < wCuts; i++) {
451                         for (int j = 0; j < hCuts; j++) {
452                             final int x = i * maxSize;
453                             final int y = j * maxSize;
454                             final int width = getSubTextureSize((i == (wCuts - 1)), textureSize.width, maxSize);
455                             final int height = getSubTextureSize((j == (hCuts - 1)), textureSize.height, maxSize);
456
457                             // if the texture has been transformed in a power-of-two texture we need to have the correct coords.
458                             final TextureCoords coords;
459                             if (isRowMajorOrder()) {
460                                 coords = textures[k].getSubImageTexCoords(0, 0, width, height);
461                             } else {
462                                 coords = textures[k].getSubImageTexCoords(0, 0, height, width);
463                             }
464                             textures[k].bind(gl);
465
466                             gl.glBegin(GL2.GL_QUADS);
467                             gl.glTexCoord2f(coords.left(), coords.top());
468                             gl.glVertex2f(x, textureSize.height - y);
469                             gl.glTexCoord2f(coords.right(), coords.top());
470                             if (isRowMajorOrder()) {
471                                 gl.glVertex2f(x + width, textureSize.height - y);
472                             } else {
473                                 gl.glVertex2f(x, textureSize.height - y - height);
474                             }
475                             gl.glTexCoord2f(coords.right(), coords.bottom());
476                             gl.glVertex2f(x + width, textureSize.height - y - height);
477                             gl.glTexCoord2f(coords.left(), coords.bottom());
478                             if (isRowMajorOrder()) {
479                                 gl.glVertex2f(x, textureSize.height - y - height);
480                             } else {
481                                 gl.glVertex2f(x + width, textureSize.height - y);
482                             }
483                             gl.glEnd();
484
485                             k++;
486                         }
487                     }
488                 }
489             }
490         }
491
492         @Override
493         public double getSScaleFactor() {
494             return sfactor;
495         }
496
497         @Override
498         public double getTScaleFactor() {
499             return tfactor;
500         }
501
502         /**
503          * Compute the sub texture size.
504          * @param lastPart true if this is the last part.
505          * @param textureSize the global texture size.
506          * @param maxSize the maximum sub-texture size.
507          * @return the sub texture size.
508          */
509         private int getSubTextureSize(boolean lastPart, int textureSize, int maxSize) {
510             if (lastPart) {
511                 int lastSize = textureSize % maxSize;
512                 if (lastSize == 0) {
513                     return maxSize;
514                 } else {
515                     return lastSize;
516                 }
517             } else {
518                 return maxSize;
519             }
520         }
521
522         private int getAsGLWrappingMode(Texture.Wrap wrappingMode) {
523             switch (wrappingMode) {
524                 case CLAMP:
525                     return GL2.GL_CLAMP_TO_EDGE;
526                 case REPEAT:
527                     return GL2.GL_REPEAT;
528                 default:
529                     return GL2.GL_REPEAT;
530             }
531         }
532
533         private int getAsGLFilter(Texture.Filter filter, boolean mipmap) {
534             int returnedValue;
535             if (mipmap) {
536                 switch (filter) {
537                     case LINEAR:
538                         returnedValue = GL2.GL_LINEAR_MIPMAP_LINEAR;
539                         break;
540                     case NEAREST:
541                         returnedValue = GL2.GL_NEAREST_MIPMAP_NEAREST;
542                         break;
543                     default:
544                         returnedValue = GL2.GL_NEAREST;
545                         break;
546                 }
547             } else {
548                 switch (filter) {
549                     case LINEAR:
550                         returnedValue = GL2.GL_LINEAR;
551                         break;
552                     case NEAREST:
553                         returnedValue = GL2.GL_NEAREST;
554                         break;
555                     default:
556                         returnedValue = GL2.GL_NEAREST;
557                         break;
558                 }
559             }
560             return returnedValue;
561         }
562
563         /** Called when gl context is gone. */
564         public void glReload() {
565             buffer = null;
566             textures = null;
567             upToDate = false;
568         }
569
570         /**
571          * Return the deltaX to apply to the sprite in regards to the given anchor.
572          * @param anchor the given anchor.
573          * @return the deltaX to apply to the sprite in regards to the given anchor.
574          */
575         protected double getAnchorDeltaX(AnchorPosition anchor) {
576             int spriteWidth = getDataProvider().getTextureSize().width;
577             switch (anchor) {
578                 case LEFT:
579                 case LOWER_LEFT:
580                 case UPPER_LEFT:
581                     return 0;
582                 case UP:
583                 case CENTER:
584                 case DOWN:
585                     return -spriteWidth / 2f;
586                 case RIGHT:
587                 case LOWER_RIGHT:
588                 case UPPER_RIGHT:
589                     return -spriteWidth;
590                 default:
591                     return 0;
592             }
593         }
594
595         /**
596          * Return the deltaY to apply to the sprite in regards to the given anchor.
597          * @param anchor the given anchor.
598          * @return the deltaY to apply to the sprite in regards to the given anchor.
599          */
600         protected double getAnchorDeltaY(AnchorPosition anchor) {
601             int spriteHeight = getDataProvider().getTextureSize().height;
602             switch (anchor) {
603                 case UPPER_LEFT:
604                 case UP:
605                 case UPPER_RIGHT:
606                     return -spriteHeight;
607                 case LEFT:
608                 case CENTER:
609                 case RIGHT:
610                     return -spriteHeight / 2f;
611                 case LOWER_LEFT:
612                 case DOWN:
613                 case LOWER_RIGHT:
614                     return 0;
615                 default:
616                     return 0;
617             }
618         }
619     }
620
621     private static class JoGLTextureData extends com.jogamp.opengl.util.texture.TextureData {
622
623         private ByteBuffer data;
624         private int shift;
625
626         public JoGLTextureData(GLProfile glp, TextureDataProvider.ImageType type, ByteBuffer data, int width, int height, int x, int y, int totalWidth, int totalHeight) {
627             super(glp);
628             this.data = data;
629             this.mipmap = false;
630             this.width = width;
631             this.height = height;
632             this.mustFlipVertically = true;
633             this.shift = ((x == 0 && y == 0) || data.capacity() == 0) ? 0 : (data.capacity() / (totalWidth * totalHeight) * (x + y * totalWidth));
634             this.rowLength = totalWidth;
635
636             switch (type) {
637                 case RGB:
638                     this.internalFormat = GL2.GL_RGB;
639                     setPixelFormat(GL.GL_RGB);
640                     setPixelType(GL2.GL_UNSIGNED_BYTE);
641                     this.alignment = 1;
642                     break;
643                 case RGB_RGBA:
644                     this.internalFormat = GL2.GL_RGB;
645                     setPixelFormat(GL.GL_RGBA);
646                     setPixelType(GL2.GL_UNSIGNED_INT_8_8_8_8);
647                     this.alignment = 4;
648                     break;
649                 case BGR:
650                     this.internalFormat = GL2GL3.GL_RGB;
651                     setPixelFormat(GL2GL3.GL_BGR);
652                     setPixelType(GL.GL_UNSIGNED_BYTE);
653                     this.alignment = 1;
654                     break;
655                 case GRAY:
656                     this.internalFormat = GL.GL_LUMINANCE;
657                     setPixelFormat(GL.GL_LUMINANCE);
658                     setPixelType(GL.GL_UNSIGNED_BYTE);
659                     this.alignment = 1;
660                     break;
661                 case GRAY_16:
662                     this.internalFormat = GL2.GL_LUMINANCE16;
663                     setPixelFormat(GL2.GL_LUMINANCE);
664                     setPixelType(GL2.GL_UNSIGNED_SHORT);
665                     this.alignment = 2;
666                     break;
667                 case RGBA:
668                     this.internalFormat = GL2.GL_RGBA;
669                     setPixelFormat(GL.GL_RGBA);
670                     setPixelType(GL2.GL_UNSIGNED_INT_8_8_8_8);
671                     this.alignment = 4;
672                     break;
673                 case RGBA_REV:
674                     this.internalFormat = GL2.GL_RGBA;
675                     setPixelFormat(GL2.GL_RGBA);
676                     setPixelType(GL2.GL_UNSIGNED_INT_8_8_8_8_REV);
677                     this.alignment = 4;
678                     break;
679                 case ABGR:
680                     this.internalFormat = GL2.GL_RGBA;
681                     setPixelFormat(GL2.GL_ABGR_EXT);
682                     setPixelType(GL.GL_UNSIGNED_BYTE);
683                     this.alignment = 1;
684                     break;
685                 case RGB_332:
686                     this.internalFormat = GL2.GL_R3_G3_B2;
687                     setPixelFormat(GL2.GL_RGB);
688                     setPixelType(GL2.GL_UNSIGNED_BYTE_3_3_2);
689                     this.alignment = 1;
690                     break;
691                 case RED:
692                     this.internalFormat = GL2.GL_RED;
693                     setPixelFormat(GL2.GL_RED);
694                     setPixelType(GL2.GL_UNSIGNED_BYTE);
695                     this.alignment = 1;
696                     break;
697                 case GREEN:
698                     this.internalFormat = GL2.GL_RGB8;
699                     setPixelFormat(GL2.GL_GREEN);
700                     setPixelType(GL2.GL_UNSIGNED_BYTE);
701                     this.alignment = 1;
702                     break;
703                 case BLUE:
704                     this.internalFormat = GL2.GL_RGB8;
705                     setPixelFormat(GL2.GL_BLUE);
706                     setPixelType(GL2.GL_UNSIGNED_BYTE);
707                     this.alignment = 1;
708                     break;
709                 case INTENSITY:
710                     this.internalFormat = GL2.GL_INTENSITY;
711                     setPixelFormat(GL2.GL_LUMINANCE);
712                     setPixelType(GL2.GL_UNSIGNED_BYTE);
713                     this.alignment = 1;
714                     break;
715                 case RGBA_4444:
716                     this.internalFormat = GL2.GL_RGBA4;
717                     setPixelFormat(GL2.GL_RGBA);
718                     setPixelType(GL2.GL_UNSIGNED_SHORT_4_4_4_4);
719                     this.alignment = 2;
720                     break;
721                 case RGBA_5551:
722                     this.internalFormat = GL2.GL_RGB5_A1;
723                     setPixelFormat(GL2.GL_RGBA);
724                     setPixelType(GL2.GL_UNSIGNED_SHORT_5_5_5_1);
725                     this.alignment = 2;
726                     break;
727                 case RGB_FLOAT:
728                     this.internalFormat = GL2ES1.GL_RGB16F;
729                     setPixelFormat(GL2.GL_RGB);
730                     setPixelType(GL2.GL_FLOAT);
731                     this.alignment = 4;
732                     break;
733                 case RGBA_FLOAT:
734                     this.internalFormat = GL2.GL_RGBA16F;
735                     setPixelFormat(GL2.GL_RGBA);
736                     setPixelType(GL2.GL_FLOAT);
737                     this.alignment = 4;
738                     break;
739                 case GRAY_FLOAT:
740                     this.internalFormat = GL2.GL_LUMINANCE16F;
741                     setPixelFormat(GL2.GL_LUMINANCE);
742                     setPixelType(GL2.GL_FLOAT);
743                     this.alignment = 4;
744                     break;
745                 case RED_16:
746                     this.internalFormat = GL2.GL_RGB16;
747                     setPixelFormat(GL2.GL_RED);
748                     setPixelType(GL2.GL_UNSIGNED_SHORT);
749                     this.alignment = 2;
750                     break;
751                 case GREEN_16:
752                     this.internalFormat = GL2.GL_RGB16;
753                     setPixelFormat(GL2.GL_GREEN);
754                     setPixelType(GL2.GL_UNSIGNED_SHORT);
755                     this.alignment = 2;
756                     break;
757                 case BLUE_16:
758                     this.internalFormat = GL2.GL_RGB16;
759                     setPixelFormat(GL2.GL_BLUE);
760                     setPixelType(GL2.GL_UNSIGNED_SHORT);
761                     this.alignment = 2;
762                     break;
763                 case RED_FLOAT:
764                     this.internalFormat = GL2ES1.GL_RGB16F;
765                     setPixelFormat(GL2.GL_RED);
766                     setPixelType(GL2.GL_FLOAT);
767                     this.alignment = 4;
768                     break;
769                 case GREEN_FLOAT:
770                     this.internalFormat = GL2ES1.GL_RGB16F;
771                     setPixelFormat(GL2.GL_GREEN);
772                     setPixelType(GL2.GL_FLOAT);
773                     this.alignment = 4;
774                     break;
775                 case BLUE_FLOAT:
776                     this.internalFormat = GL2ES1.GL_RGB16F;
777                     setPixelFormat(GL2.GL_BLUE);
778                     setPixelType(GL2.GL_FLOAT);
779                     this.alignment = 4;
780                     break;
781                 case RGBA_BYTE:
782                     this.internalFormat = GL2.GL_RGBA;
783                     setPixelFormat(GL2.GL_RGBA);
784                     setPixelType(GL2.GL_UNSIGNED_BYTE);
785                     this.alignment = 1;
786                     break;
787             }
788         }
789
790         public JoGLTextureData(GLProfile glp, TextureDataProvider.ImageType type, ByteBuffer data, int width, int height) {
791             this(glp, type, data, width, height, 0, 0, width, height);
792         }
793
794         public ByteBuffer getBuffer() {
795             if (shift == 0) {
796                 return data;
797             } else {
798                 data.position(shift);
799                 ByteBuffer b = data.slice();
800                 data.rewind();
801
802                 return b;
803             }
804         }
805
806         public void setData(ByteBuffer data) {
807             this.data = data;
808         }
809
810         public void destroy() {
811             super.destroy();
812             this.data = null;
813         }
814     }
815 }