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