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