1 /*
2  * License Applicability. Except to the extent portions of this file are
3  * made subject to an alternative license as permitted in the SGI Free
4  * Software License B, Version 2.0 (the "License"), the contents of this
5  * file are subject only to the provisions of the License. You may not use
6  * this file except in compliance with the License. You may obtain a copy
7  * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8  * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9  *
10  * http://oss.sgi.com/projects/FreeB
11  *
12  * Note that, as provided in the License, the Software is distributed on an
13  * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14  * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15  * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17  *
18  * NOTE:  The Original Code (as defined below) has been licensed to Sun
19  * Microsystems, Inc. ("Sun") under the SGI Free Software License B
20  * (Version 1.1), shown above ("SGI License").   Pursuant to Section
21  * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
22  * you under an alternative license ("Alternative License").  This
23  * Alternative License includes all of the provisions of the SGI License
24  * except that Section 2.2 and 11 are omitted.  Any differences between
25  * the Alternative License and the SGI License are offered solely by Sun
26  * and not by SGI.
27  *
28  * Original Code. The Original Code is: OpenGL Sample Implementation,
29  * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
30  * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
31  * Copyright in any portions created by third parties is as indicated
32  * elsewhere herein. All Rights Reserved.
33  *
34  * Additional Notice Provisions: The application programming interfaces
35  * established by SGI in conjunction with the Original Code are The
36  * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
37  * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
38  * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
39  * Window System(R) (Version 1.3), released October 19, 1998. This software
40  * was created using the OpenGL(R) version 1.2.1 Sample Implementation
41  * published by SGI, but has not been independently verified as being
42  * compliant with the OpenGL(R) version 1.2.1 Specification.
43  */
44 
45 package jogamp.opengl.glu.mipmap;
46 
47 import com.jogamp.opengl.GL;
48 import com.jogamp.opengl.GL2;
49 import com.jogamp.opengl.GL2ES2;
50 import com.jogamp.opengl.GL2ES3;
51 import com.jogamp.opengl.GL2GL3;
52 import com.jogamp.opengl.GLContext;
53 import com.jogamp.opengl.glu.GLU;
54 import com.jogamp.opengl.GLException;
55 
56 import java.nio.*;
57 
58 import com.jogamp.common.nio.Buffers;
59 
60 /**
61  *
62  * @author  Administrator
63  */
64 public class Mipmap {
65 
66   /** Creates a new instance of Mipmap */
Mipmap()67   public Mipmap() {
68   }
69 
computeLog( int value )70   public static int computeLog( int value ) {
71     int i = 0;
72     // Error
73     if( value == 0 ) {
74       return( -1 );
75     }
76     for( ;; ) {
77       if( (value & 1) >= 1 ) {
78         if( value != 1 ) {
79           return( -1 );
80         }
81         return( i );
82       }
83       value = value >> 1;
84       i++;
85     }
86   }
87 
88   /* Compute the nearest power of 2 number.  This algorithm is a little strange
89    * but it works quite well.
90    */
nearestPower( int value )91   public static int nearestPower( int value ) {
92     int i = 1;
93     // Error!
94     if( value == 0 ) {
95       return( -1 );
96     }
97     for( ;; ) {
98       if( value == 1 ) {
99         return( i );
100       } else if( value == 3 ) {
101         return( i * 4 );
102       }
103       value = value >> 1;
104       i *= 2;
105     }
106   }
107 
GLU_SWAP_2_BYTES( short s )108   public static short GLU_SWAP_2_BYTES( short s ) {
109     byte b = 0;
110     b = (byte)( s >>> 8 );
111     s = (short)( s << 8 );
112     s = (short)( s | (0x00FF & b) );
113     return( s );
114   }
115 
GLU_SWAP_4_BYTES( final int i )116   public static int GLU_SWAP_4_BYTES( final int i ) {
117     int t = i << 24;
118     t |= 0x00FF0000 & ( i << 8 );
119     t |= 0x0000FF00 & ( i >>> 8 );
120     t |= 0x000000FF & ( i >>> 24 );
121     return( t );
122   }
123 
GLU_SWAP_4_BYTES( final float f )124   public static float GLU_SWAP_4_BYTES( final float f ) {
125     final int i = Float.floatToRawIntBits( f );
126     final float temp = Float.intBitsToFloat( i );
127     return( temp );
128   }
129 
checkMipmapArgs( final int internalFormat, final int format, final int type )130   public static int checkMipmapArgs( final int internalFormat, final int format, final int type ) {
131     if( !legalFormat( format ) || !legalType( type ) ) {
132       return( GLU.GLU_INVALID_ENUM );
133     }
134     if( format == GL2ES2.GL_STENCIL_INDEX ) {
135       return( GLU.GLU_INVALID_ENUM );
136     }
137     if( !isLegalFormatForPackedPixelType( format, type ) ) {
138       return( GLU.GLU_INVALID_OPERATION );
139     }
140     return( 0 );
141   }
142 
legalFormat( final int format )143   public static boolean legalFormat( final int format ) {
144     switch( format ) {
145       case( GL2.GL_COLOR_INDEX ):
146       case( GL2ES2.GL_STENCIL_INDEX ):
147       case( GL2ES2.GL_DEPTH_COMPONENT ):
148       case( GL2ES2.GL_RED ):
149       case( GL2ES3.GL_GREEN ):
150       case( GL2ES3.GL_BLUE ):
151       case( GL.GL_ALPHA ):
152       case( GL.GL_RGB ):
153       case( GL.GL_RGBA ):
154       case( GL.GL_LUMINANCE ):
155       case( GL.GL_LUMINANCE_ALPHA ):
156       case( GL2GL3.GL_BGR ):
157       case( GL.GL_BGRA ):
158         return( true );
159       default:
160         return( false );
161     }
162   }
163 
legalType( final int type )164   public static boolean legalType( final int type ) {
165     switch( type ) {
166       case( GL2.GL_BITMAP ):
167       case( GL.GL_BYTE ):
168       case( GL.GL_UNSIGNED_BYTE ):
169       case( GL.GL_SHORT ):
170       case( GL.GL_UNSIGNED_SHORT ):
171       case( GL2ES2.GL_INT ):
172       case( GL.GL_UNSIGNED_INT ):
173       case( GL.GL_FLOAT ):
174       case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
175       case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
176       case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
177       case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
178       case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
179       case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
180       case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
181       case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
182       case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
183       case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
184       case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
185       case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
186         return( true );
187       default:
188         return( false );
189     }
190   }
191 
isTypePackedPixel( final int type )192   public static boolean isTypePackedPixel( final int type ) {
193     assert( legalType( type ) );
194 
195     if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ||
196         type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
197         type == GL.GL_UNSIGNED_SHORT_5_6_5 ||
198         type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ||
199         type == GL.GL_UNSIGNED_SHORT_4_4_4_4 ||
200         type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
201         type == GL.GL_UNSIGNED_SHORT_5_5_5_1 ||
202         type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
203         type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
204         type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
205         type == GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ||
206         type == GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ) {
207           return( true );
208     }
209     return( false );
210   }
211 
isLegalFormatForPackedPixelType( final int format, final int type )212   public static boolean isLegalFormatForPackedPixelType( final int format, final int type ) {
213     // if not a packed pixel type then return true
214     if( isTypePackedPixel( type ) ) {
215       return( true );
216     }
217 
218     // 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB
219     if( (type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
220         type == GL.GL_UNSIGNED_SHORT_5_6_5 || type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV )
221         & format != GL.GL_RGB ) {
222           return( false );
223     }
224 
225     // 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV &
226     // 10_10_10_2/2_10_10_10_REV are only campatible with RGBA, BGRA & ARGB_EXT
227     if( ( type == GL.GL_UNSIGNED_SHORT_4_4_4_4 ||
228           type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
229           type == GL.GL_UNSIGNED_SHORT_5_5_5_1 ||
230           type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
231           type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
232           type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
233           type == GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ||
234           type == GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ) &&
235           (format != GL.GL_RGBA && format != GL.GL_BGRA) ) {
236             return( false );
237     }
238     return( true );
239   }
240 
isLegalLevels( final int userLevel, final int baseLevel, final int maxLevel, final int totalLevels )241   public static boolean isLegalLevels( final int userLevel, final int baseLevel, final int maxLevel,
242                                             final int totalLevels ) {
243     if( (baseLevel < 0) || (baseLevel < userLevel) || (maxLevel < baseLevel) ||
244                                                   (totalLevels < maxLevel) ) {
245       return( false );
246     }
247     return( true );
248   }
249 
250   /* Given user requested textures size, determine if it fits. If it doesn't then
251    * halve both sides and make the determination again until it does fit ( for
252    * IR only ).
253    * Note that proxy textures are not implemented in RE* even though they
254    * advertise the texture extension.
255    * Note that proxy textures are implemented but not according to spec in IMPACT*
256    */
closestFit( final GL gl, final int target, final int width, final int height, final int internalFormat, final int format, final int type, final int[] newWidth, final int[] newHeight )257   public static void closestFit( final GL gl, final int target, final int width, final int height, final int internalFormat,
258                                 final int format, final int type, final int[] newWidth, final int[] newHeight ) {
259     // Use proxy textures if OpenGL GL2/GL3 version >= 1.1
260     if( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_1) >= 0 ) {
261       int widthPowerOf2 = nearestPower( width );
262       int heightPowerOf2 = nearestPower( height );
263       final int[] proxyWidth = new int[1];
264       boolean noProxyTextures = false;
265 
266       // Some drivers (in particular, ATI's) seem to set a GL error
267       // when proxy textures are used even though this is in violation
268       // of the spec. Guard against this and interactions with the
269       // DebugGL by watching for GLException.
270       try {
271         do {
272           // compute level 1 width & height, clamping each at 1
273           final int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 );
274           final int heightAtLevelOne = ( ( height > 1 ) ? (heightPowerOf2 >> 1) : heightPowerOf2 );
275           int proxyTarget;
276 
277           assert( widthAtLevelOne > 0 );
278           assert( heightAtLevelOne > 0 );
279 
280           // does width x height at level 1 & all their mipmaps fit?
281           if( target == GL.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D ) {
282             proxyTarget = GL2GL3.GL_PROXY_TEXTURE_2D;
283             gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
284                              heightAtLevelOne, 0, format, type, null );
285           } else if( (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X) ||
286                      (target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) ||
287                      (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) ||
288                      (target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ||
289                      (target == GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) ||
290                      (target == GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ) {
291             proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP;
292             gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
293                              heightAtLevelOne, 0, format, type, null );
294           } else {
295             assert( target == GL2GL3.GL_TEXTURE_1D || target == GL2GL3.GL_PROXY_TEXTURE_1D );
296             proxyTarget = GL2GL3.GL_PROXY_TEXTURE_1D;
297             gl.getGL2GL3().glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne,
298                              0, format, type, null );
299           }
300           if(gl.isGL2GL3()) {
301             gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 );
302           } else {
303             proxyWidth[0] = 0;
304           }
305           // does it fit?
306           if( proxyWidth[0] == 0 ) { // nope, so try again with theses sizes
307             if( widthPowerOf2 == 1 && heightPowerOf2 == 1 ) {
308               /* A 1x1 texture couldn't fit for some reason so break out.  This
309                * should never happen.  But things happen.  The disadvantage with
310                * this if-statement is that we will never be aware of when this
311                * happens since it will silently branch out.
312                */
313               noProxyTextures = true;
314               break;
315             }
316             widthPowerOf2 = widthAtLevelOne;
317             heightPowerOf2 = heightAtLevelOne;
318           }
319           // else it does fit
320         } while( proxyWidth[0] == 0 );
321       } catch (final GLException e) {
322         noProxyTextures = true;
323       }
324       // loop must terminate
325       // return the width & height at level 0 that fits
326       if( !noProxyTextures ) {
327         newWidth[0] = widthPowerOf2;
328         newHeight[0] = heightPowerOf2;
329         return;
330       }
331     }
332     final int[] maxsize = new int[1];
333     gl.glGetIntegerv( GL.GL_MAX_TEXTURE_SIZE, maxsize , 0);
334     // clamp user's texture sizes to maximum sizes, if necessary
335     newWidth[0] = nearestPower( width );
336     if( newWidth[0] > maxsize[0] ) {
337       newWidth[0] = maxsize[0];
338     }
339     newHeight[0] = nearestPower( height );
340     if( newHeight[0] > maxsize[0] ) {
341       newHeight[0] = maxsize[0];
342     }
343   }
344 
closestFit3D( final GL gl, final int target, final int width, final int height, final int depth, final int internalFormat, final int format, final int type, final int[] newWidth, final int[] newHeight, final int[] newDepth )345   public static void closestFit3D( final GL gl, final int target, final int width, final int height, final int depth,
346           final int internalFormat, final int format, final int type, final int[] newWidth, final int[] newHeight,
347           final int[] newDepth ) {
348     int widthPowerOf2 = nearestPower( width );
349     int heightPowerOf2 = nearestPower( height );
350     int depthPowerOf2 = nearestPower( depth );
351     final int[] proxyWidth = new int[1];
352 
353     do {
354       // compute level 1 width & height & depth, clamping each at 1
355       final int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2;
356       final int heightAtLevelOne = (heightPowerOf2 > 1) ? heightPowerOf2 >> 1 : heightPowerOf2;
357       final int depthAtLevelOne = (depthPowerOf2 > 1) ? depthPowerOf2 >> 1 : depthPowerOf2;
358       int proxyTarget = 0;
359       assert( widthAtLevelOne > 0 );
360       assert( heightAtLevelOne > 0 );
361       assert( depthAtLevelOne > 0 );
362 
363       // does width x height x depth at level 1 & all their mipmaps fit?
364       if( target == GL2ES2.GL_TEXTURE_3D || target == GL2GL3.GL_PROXY_TEXTURE_3D ) {
365         proxyTarget = GL2GL3.GL_PROXY_TEXTURE_3D;
366         gl.getGL2GL3().glTexImage3D( proxyTarget, 1, internalFormat, widthAtLevelOne,
367                 heightAtLevelOne, depthAtLevelOne, 0, format, type, null );
368       }
369       if(gl.isGL2GL3()) {
370         gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 );
371       } else {
372         proxyWidth[0] = 0;
373       }
374       // does it fit
375       if( proxyWidth[0] == 0 ) {
376         if( widthPowerOf2 == 1 && heightPowerOf2 == 1 && depthPowerOf2 == 1 ) {
377           newWidth[0] = newHeight[0] = newDepth[0] = 1;
378           return;
379         }
380         widthPowerOf2 = widthAtLevelOne;
381         heightPowerOf2 = heightAtLevelOne;
382         depthPowerOf2 = depthAtLevelOne;
383       }
384     } while( proxyWidth[0] == 0 );
385     // loop must terminate
386 
387     // return the width & height at level 0 that fits
388     newWidth[0] = widthPowerOf2;
389     newHeight[0] = heightPowerOf2;
390     newDepth[0] = depthPowerOf2;
391   }
392 
elements_per_group( final int format, final int type )393   public static int elements_per_group( final int format, final int type ) {
394     // Return the number of elements per grtoup of a specified gromat
395 
396     // If the type is packedpixels then answer is 1
397     if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ||
398         type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
399         type == GL.GL_UNSIGNED_SHORT_5_6_5 ||
400         type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ||
401         type == GL.GL_UNSIGNED_SHORT_4_4_4_4 ||
402         type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
403         type == GL.GL_UNSIGNED_SHORT_5_5_5_1 ||
404         type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
405         type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
406         type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
407         type == GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ||
408         type == GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ) {
409           return( 1 );
410     }
411 
412     // Types are not packed pixels so get elements per group
413     switch( format ) {
414       case( GL.GL_RGB ):
415       case( GL2GL3.GL_BGR ):
416         return( 3 );
417       case( GL.GL_LUMINANCE_ALPHA ):
418         return( 2 );
419       case( GL.GL_RGBA ):
420       case( GL.GL_BGRA ):
421         return( 4 );
422       default:
423         return( 1 );
424     }
425   }
426 
bytes_per_element( final int type )427   public static int bytes_per_element( final int type ) {
428     // return the number of bytes per element, based on the element type
429 
430     switch( type ) {
431       case( GL2.GL_BITMAP ):
432       case( GL.GL_BYTE ):
433       case( GL.GL_UNSIGNED_BYTE ):
434       case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
435       case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
436         return( 1 );
437       case( GL.GL_SHORT ):
438       case( GL.GL_UNSIGNED_SHORT ):
439       case( GL.GL_UNSIGNED_SHORT_5_6_5 ):
440       case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
441       case( GL.GL_UNSIGNED_SHORT_4_4_4_4 ):
442       case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
443       case( GL.GL_UNSIGNED_SHORT_5_5_5_1 ):
444       case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
445         return( 2 );
446       case( GL2ES2.GL_INT ):
447       case( GL.GL_UNSIGNED_INT ):
448       case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
449       case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
450       case( GL2ES2.GL_UNSIGNED_INT_10_10_10_2 ):
451       case( GL2ES2.GL_UNSIGNED_INT_2_10_10_10_REV ):
452       case( GL.GL_FLOAT ):
453         return( 4 );
454       default:
455         return( 4 );
456     }
457   }
458 
is_index( final int format )459   public static boolean is_index( final int format ) {
460     return( format == GL2.GL_COLOR_INDEX || format == GL2ES2.GL_STENCIL_INDEX );
461   }
462 
463   /* Compute memory required for internal packed array of data of given type and format. */
464 
image_size( final int width, final int height, final int format, final int type )465   public static int image_size( final int width, final int height, final int format, final int type ) {
466     int bytes_per_row;
467     int components;
468 
469     assert( width > 0 );
470     assert( height > 0 );
471     components = elements_per_group( format, type );
472     if( type == GL2.GL_BITMAP ) {
473       bytes_per_row = (width + 7) / 8;
474     } else {
475       bytes_per_row = bytes_per_element( type ) * width;
476     }
477     return( bytes_per_row * height * components );
478   }
479 
imageSize3D( final int width, final int height, final int depth, final int format, final int type )480   public static int imageSize3D( final int width, final int height, final int depth, final int format, final int type ) {
481     final int components = elements_per_group( format, type );
482     final int bytes_per_row = bytes_per_element( type ) * width;
483 
484     assert( width > 0 && height > 0 && depth > 0 );
485     assert( type != GL2.GL_BITMAP );
486 
487     return( bytes_per_row * height * depth * components );
488   }
489 
retrieveStoreModes( final GL gl, final PixelStorageModes psm )490   public static void retrieveStoreModes( final GL gl, final PixelStorageModes psm ) {
491     final int[] a = new int[1];
492     gl.glGetIntegerv( GL.GL_UNPACK_ALIGNMENT, a, 0);
493     psm.setUnpackAlignment( a[0] );
494     gl.glGetIntegerv( GL2ES2.GL_UNPACK_ROW_LENGTH, a, 0);
495     psm.setUnpackRowLength( a[0] );
496     gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_ROWS, a, 0);
497     psm.setUnpackSkipRows( a[0] );
498     gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_PIXELS, a, 0);
499     psm.setUnpackSkipPixels( a[0] );
500     gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0);
501     psm.setUnpackLsbFirst( ( a[0] == 1 ) );
502     gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0);
503     psm.setUnpackSwapBytes( ( a[0] == 1 ) );
504 
505     gl.glGetIntegerv( GL.GL_PACK_ALIGNMENT, a, 0);
506     psm.setPackAlignment( a[0] );
507     gl.glGetIntegerv( GL2ES3.GL_PACK_ROW_LENGTH, a, 0);
508     psm.setPackRowLength( a[0] );
509     gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_ROWS, a, 0);
510     psm.setPackSkipRows( a[0] );
511     gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_PIXELS, a, 0);
512     psm.setPackSkipPixels( a[0] );
513     gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0);
514     psm.setPackLsbFirst( ( a[0] == 1 ) );
515     gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0);
516     psm.setPackSwapBytes( ( a[0] == 1 ) );
517   }
518 
retrieveStoreModes3D( final GL gl, final PixelStorageModes psm )519   public static void retrieveStoreModes3D( final GL gl, final PixelStorageModes psm ) {
520     final int[] a = new int[1];
521     gl.glGetIntegerv( GL.GL_UNPACK_ALIGNMENT, a, 0);
522     psm.setUnpackAlignment( a[0] );
523     gl.glGetIntegerv( GL2ES2.GL_UNPACK_ROW_LENGTH, a, 0);
524     psm.setUnpackRowLength( a[0] );
525     gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_ROWS, a, 0);
526     psm.setUnpackSkipRows( a[0] );
527     gl.glGetIntegerv( GL2ES2.GL_UNPACK_SKIP_PIXELS, a, 0);
528     psm.setUnpackSkipPixels( a[0] );
529     gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0);
530     psm.setUnpackLsbFirst( ( a[0] == 1 ) );
531     gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0);
532     psm.setUnpackSwapBytes( ( a[0] == 1 ) );
533     gl.glGetIntegerv( GL2ES3.GL_UNPACK_SKIP_IMAGES, a, 0);
534     psm.setUnpackSkipImages( a[0] );
535     gl.glGetIntegerv( GL2ES3.GL_UNPACK_IMAGE_HEIGHT, a, 0);
536     psm.setUnpackImageHeight( a[0] );
537 
538     gl.glGetIntegerv( GL.GL_PACK_ALIGNMENT, a, 0);
539     psm.setPackAlignment( a[0] );
540     gl.glGetIntegerv( GL2ES3.GL_PACK_ROW_LENGTH, a, 0);
541     psm.setPackRowLength( a[0] );
542     gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_ROWS, a, 0);
543     psm.setPackSkipRows( a[0] );
544     gl.glGetIntegerv( GL2ES3.GL_PACK_SKIP_PIXELS, a, 0 );
545     psm.setPackSkipPixels( a[0] );
546     gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0 );
547     psm.setPackLsbFirst( ( a[0] == 1 ) );
548     gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0 );
549     psm.setPackSwapBytes( ( a[0] == 1 ) );
550     gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_IMAGES, a, 0 );
551     psm.setPackSkipImages( a[0] );
552     gl.glGetIntegerv( GL2GL3.GL_PACK_IMAGE_HEIGHT, a, 0 );
553     psm.setPackImageHeight( a[0] );
554   }
555 
gluScaleImage( final GL gl, final int format, final int widthin, final int heightin, final int typein, final ByteBuffer datain, final int widthout, final int heightout, final int typeout, final ByteBuffer dataout )556   public static int gluScaleImage( final GL gl, final int format, final int widthin, final int heightin,
557           final int typein, final ByteBuffer datain, final int widthout, final int heightout,
558           final int typeout, final ByteBuffer dataout ) {
559     final int datainPos = datain.position();
560     final int dataoutPos = dataout.position();
561     try {
562 
563       int components;
564       ByteBuffer beforeimage;
565       ByteBuffer afterimage;
566       final PixelStorageModes psm = new PixelStorageModes();
567 
568       if( (widthin == 0)  || (heightin == 0) || (widthout == 0) || (heightout == 0) ) {
569         return( 0 );
570       }
571       if( (widthin < 0) || (heightin < 0) || (widthout < 0) || (heightout < 0) ) {
572         return( GLU.GLU_INVALID_VALUE );
573       }
574       if( !legalFormat( format ) || !legalType( typein ) || !legalType( typeout ) ) {
575         return( GLU.GLU_INVALID_ENUM );
576       }
577       if( !isLegalFormatForPackedPixelType( format, typein ) ) {
578         return( GLU.GLU_INVALID_OPERATION );
579       }
580       if( !isLegalFormatForPackedPixelType( format, typeout ) ) {
581         return( GLU.GLU_INVALID_OPERATION );
582       }
583       beforeimage = Buffers.newDirectByteBuffer( image_size( widthin, heightin, format, GL.GL_UNSIGNED_SHORT ) );
584       afterimage = Buffers.newDirectByteBuffer( image_size( widthout, heightout, format, GL.GL_UNSIGNED_SHORT ) );
585       if( beforeimage == null || afterimage == null ) {
586         return( GLU.GLU_OUT_OF_MEMORY );
587       }
588 
589       retrieveStoreModes( gl, psm );
590       Image.fill_image( psm, widthin, heightin, format, typein, is_index( format ), datain, beforeimage.asShortBuffer() );
591       components = elements_per_group( format, 0 );
592       ScaleInternal.scale_internal( components, widthin, heightin, beforeimage.asShortBuffer(), widthout, heightout, afterimage.asShortBuffer() );
593       Image.empty_image( psm, widthout, heightout, format, typeout, is_index( format ), afterimage.asShortBuffer(), dataout );
594 
595       return( 0 );
596     } finally {
597       datain.position(datainPos);
598       dataout.position(dataoutPos);
599     }
600   }
601 
gluBuild1DMipmapLevels( final GL gl, final int target, final int internalFormat, final int width, final int format, final int type, final int userLevel, final int baseLevel, final int maxLevel, final ByteBuffer data )602   public static int gluBuild1DMipmapLevels( final GL gl, final int target, final int internalFormat,
603                           final int width, final int format, final int type, final int userLevel, final int baseLevel,
604                           final int maxLevel, final ByteBuffer data ) {
605     final int dataPos = data.position();
606     try {
607 
608       int levels;
609 
610       final int rc = checkMipmapArgs( internalFormat, format, type );
611       if( rc != 0 ) {
612         return( rc );
613       }
614 
615       if( width < 1 ) {
616         return( GLU.GLU_INVALID_VALUE );
617       }
618 
619       levels = computeLog( width );
620 
621       levels += userLevel;
622       if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
623         return( GLU.GLU_INVALID_VALUE );
624       }
625 
626       return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, width,
627               width, format, type, userLevel, baseLevel, maxLevel, data ) );
628     } finally {
629       data.position(dataPos);
630     }
631   }
632 
gluBuild1DMipmaps( final GL gl, final int target, final int internalFormat, final int width, final int format, final int type, final ByteBuffer data )633   public static int gluBuild1DMipmaps( final GL gl, final int target, final int internalFormat, final int width,
634               final int format, final int type, final ByteBuffer data ) {
635     final int dataPos = data.position();
636 
637     try {
638       final int[] widthPowerOf2 = new int[1];
639       int levels;
640       final int[] dummy = new int[1];
641 
642       final int rc = checkMipmapArgs( internalFormat, format, type );
643       if( rc != 0 ) {
644         return( rc );
645       }
646 
647       if( width < 1 ) {
648         return( GLU.GLU_INVALID_VALUE );
649       }
650 
651       closestFit( gl, target, width, 1, internalFormat, format, type, widthPowerOf2, dummy );
652       levels = computeLog( widthPowerOf2[0] );
653 
654       return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat,
655                     width, widthPowerOf2[0], format, type, 0, 0, levels, data ) );
656     } finally {
657       data.position(dataPos);
658     }
659   }
660 
661 
gluBuild2DMipmapLevels( final GL gl, final int target, final int internalFormat, final int width, final int height, final int format, final int type, final int userLevel, final int baseLevel, final int maxLevel, final Object data )662   public static int gluBuild2DMipmapLevels( final GL gl, final int target, final int internalFormat,
663           final int width, final int height, final int format, final int type, final int userLevel,
664           final int baseLevel, final int maxLevel, final Object data ) {
665     int level, levels;
666 
667     final int rc = checkMipmapArgs( internalFormat, format, type );
668     if( rc != 0 ) {
669       return( rc );
670     }
671 
672     if( width < 1 || height < 1 ) {
673       return( GLU.GLU_INVALID_VALUE );
674     }
675 
676     levels = computeLog( width );
677     level = computeLog( height );
678     if( level > levels ) {
679       levels = level;
680     }
681 
682     levels += userLevel;
683     if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
684       return( GLU.GLU_INVALID_VALUE );
685     }
686 
687     //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data );
688     final ByteBuffer buffer;
689     if( data instanceof ByteBuffer ) {
690         buffer = (ByteBuffer)data;
691     } else if( data instanceof byte[] ) {
692         final byte[] array = (byte[])data;
693         buffer = ByteBuffer.allocateDirect(array.length);
694         buffer.put(array);
695         buffer.flip();
696     } else if( data instanceof short[] ) {
697         final short[] array = (short[])data;
698         buffer = ByteBuffer.allocateDirect( array.length * 2 );
699         final ShortBuffer sb = buffer.asShortBuffer();
700         sb.put( array );
701     } else if( data instanceof int[] ) {
702         final int[] array = (int[])data;
703         buffer = ByteBuffer.allocateDirect( array.length * 4 );
704         final IntBuffer ib = buffer.asIntBuffer();
705         ib.put( array );
706     } else if( data instanceof float[] ) {
707         final float[] array = (float[])data;
708         buffer = ByteBuffer.allocateDirect( array.length * 4 );
709         final FloatBuffer fb = buffer.asFloatBuffer();
710         fb.put( array );
711     } else {
712         throw new IllegalArgumentException("Unhandled data type: "+data.getClass().getName());
713     }
714 
715     final int dataPos = buffer.position();
716     try {
717       return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
718               width, height, width, height, format, type, userLevel, baseLevel,
719               maxLevel, buffer ) );
720     } finally {
721       buffer.position(dataPos);
722     }
723   }
724 
725 
gluBuild2DMipmaps( final GL gl, final int target, final int internalFormat, final int width, final int height, final int format, final int type, final Object data )726   public static int gluBuild2DMipmaps( final GL gl, final int target, final int internalFormat,
727           final int width, final int height, final int format, final int type, final Object data ) {
728     final int[] widthPowerOf2 = new int[1];
729     final int[] heightPowerOf2 = new int[1];
730     int level, levels;
731 
732     final int rc = checkMipmapArgs( internalFormat, format, type );
733     if( rc != 0 ) {
734       return( rc );
735     }
736 
737     if( width < 1 || height < 1 ) {
738       return( GLU.GLU_INVALID_VALUE );
739     }
740 
741     closestFit( gl, target, width, height, internalFormat, format, type,
742             widthPowerOf2, heightPowerOf2 );
743 
744     levels = computeLog( widthPowerOf2[0] );
745     level = computeLog( heightPowerOf2[0] );
746     if( level > levels ) {
747       levels = level;
748     }
749 
750     //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data );
751     final ByteBuffer buffer;
752     if( data instanceof ByteBuffer ) {
753         buffer = (ByteBuffer)data;
754     } else if( data instanceof byte[] ) {
755         final byte[] array = (byte[])data;
756         buffer = ByteBuffer.allocateDirect(array.length);
757         buffer.put(array);
758         buffer.flip();
759     } else if( data instanceof short[] ) {
760         final short[] array = (short[])data;
761         buffer = ByteBuffer.allocateDirect( array.length * 2 );
762         final ShortBuffer sb = buffer.asShortBuffer();
763         sb.put( array );
764     } else if( data instanceof int[] ) {
765         final int[] array = (int[])data;
766         buffer = ByteBuffer.allocateDirect( array.length * 4 );
767         final IntBuffer ib = buffer.asIntBuffer();
768         ib.put( array );
769     } else if( data instanceof float[] ) {
770         final float[] array = (float[])data;
771         buffer = ByteBuffer.allocateDirect( array.length * 4 );
772         final FloatBuffer fb = buffer.asFloatBuffer();
773         fb.put( array );
774     } else {
775         throw new IllegalArgumentException("Unhandled data type: "+data.getClass().getName());
776     }
777 
778     final int dataPos = buffer.position();
779     try {
780       return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
781               width, height, widthPowerOf2[0], heightPowerOf2[0], format, type, 0,
782               0, levels, buffer ) );
783     } finally {
784       buffer.position(dataPos);
785     }
786   }
787 
788 
gluBuild3DMipmaps( final GL gl, final int target, final int internalFormat, final int width, final int height, final int depth, final int format, final int type, final ByteBuffer data )789   public static int gluBuild3DMipmaps( final GL gl, final int target, final int internalFormat,
790           final int width, final int height, final int depth, final int format, final int type, final ByteBuffer data ) {
791     final int dataPos = data.position();
792     try {
793 
794       final int[] widthPowerOf2 = new int[1];
795       final int[] heightPowerOf2 = new int[1];
796       final int[] depthPowerOf2 = new int[1];
797       int level, levels;
798 
799       final int rc = checkMipmapArgs( internalFormat, format, type );
800       if( rc != 0 ) {
801         return( rc );
802       }
803 
804       if( width < 1 || height < 1 || depth < 1 ) {
805         return( GLU.GLU_INVALID_VALUE );
806       }
807 
808       if( type == GL2.GL_BITMAP ) {
809         return( GLU.GLU_INVALID_ENUM );
810       }
811 
812       closestFit3D( gl, target, width, height, depth, internalFormat, format,
813                     type, widthPowerOf2, heightPowerOf2, depthPowerOf2 );
814 
815       levels = computeLog( widthPowerOf2[0] );
816       level = computeLog( heightPowerOf2[0] );
817       if( level > levels ) {
818         levels = level;
819       }
820       level = computeLog( depthPowerOf2[0] );
821       if( level > levels ) {
822         levels = level;
823       }
824 
825       return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width,
826               height, depth, widthPowerOf2[0], heightPowerOf2[0], depthPowerOf2[0],
827               format, type, 0, 0, levels, data ) );
828     } finally {
829       data.position(dataPos);
830     }
831   }
832 
gluBuild3DMipmapLevels( final GL gl, final int target, final int internalFormat, final int width, final int height, final int depth, final int format, final int type, final int userLevel, final int baseLevel, final int maxLevel, final ByteBuffer data )833   public static int gluBuild3DMipmapLevels( final GL gl, final int target, final int internalFormat,
834           final int width, final int height, final int depth, final int format, final int type, final int userLevel,
835           final int baseLevel, final int maxLevel, final ByteBuffer data ) {
836     final int dataPos = data.position();
837     try {
838       int level, levels;
839 
840       final int rc = checkMipmapArgs( internalFormat, format, type );
841       if( rc != 0 ) {
842         return( rc );
843       }
844 
845       if( width < 1 || height < 1 || depth < 1 ) {
846         return( GLU.GLU_INVALID_VALUE );
847       }
848 
849       if( type == GL2.GL_BITMAP ) {
850         return( GLU.GLU_INVALID_ENUM );
851       }
852 
853       levels = computeLog( width );
854       level = computeLog( height );
855       if( level > levels ) {
856         levels = level;
857       }
858       level = computeLog( depth );
859       if( level > levels ) {
860         levels = level;
861       }
862 
863       levels += userLevel;
864       if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
865         return( GLU.GLU_INVALID_VALUE );
866       }
867 
868       return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width,
869               height, depth, width, height, depth, format, type, userLevel,
870               baseLevel, maxLevel, data ) );
871     } finally {
872       data.position(dataPos);
873     }
874   }
875 }
876