• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.jme3.renderer.lwjgl;
34 
35 import com.jme3.renderer.RendererException;
36 import com.jme3.texture.Image;
37 import com.jme3.texture.Image.Format;
38 import java.nio.ByteBuffer;
39 import static org.lwjgl.opengl.ATITextureCompression3DC.GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI;
40 import static org.lwjgl.opengl.EXTTextureCompressionLATC.GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
41 import static org.lwjgl.opengl.EXTTextureCompressionLATC.GL_COMPRESSED_LUMINANCE_LATC1_EXT;
42 import static org.lwjgl.opengl.EXTTextureCompressionS3TC.*;
43 import static org.lwjgl.opengl.GL11.*;
44 import static org.lwjgl.opengl.GL12.*;
45 import static org.lwjgl.opengl.GL13.glCompressedTexImage2D;
46 import static org.lwjgl.opengl.GL13.glCompressedTexImage3D;
47 import static org.lwjgl.opengl.GL14.*;
48 import org.lwjgl.opengl.*;
49 
50 public class TextureUtil {
51 
isFormatSupported(Format fmt, ContextCapabilities caps)52     private static boolean isFormatSupported(Format fmt, ContextCapabilities caps){
53         switch (fmt){
54             case ARGB4444:
55                 return false;
56             case BGR8:
57                 return caps.OpenGL12 || caps.GL_EXT_bgra;
58             case DXT1:
59             case DXT1A:
60             case DXT3:
61             case DXT5:
62                 return caps.GL_EXT_texture_compression_s3tc;
63             case Depth:
64             case Depth16:
65             case Depth24:
66             case Depth32:
67                 return caps.OpenGL14 || caps.GL_ARB_depth_texture;
68             case Depth32F:
69             case Luminance16F:
70             case Luminance16FAlpha16F:
71             case Luminance32F:
72             case RGBA16F:
73             case RGBA32F:
74                 return caps.OpenGL30 || caps.GL_ARB_texture_float;
75             case LATC:
76             case LTC:
77                 return caps.GL_EXT_texture_compression_latc;
78             case RGB9E5:
79             case RGB16F_to_RGB9E5:
80                 return caps.OpenGL30 || caps.GL_EXT_texture_shared_exponent;
81             case RGB111110F:
82             case RGB16F_to_RGB111110F:
83                 return caps.OpenGL30 || caps.GL_EXT_packed_float;
84             default:
85                 return true;
86         }
87     }
88 
checkFormatSupported(Format fmt)89     public static void checkFormatSupported(Format fmt) {
90         if (!isFormatSupported(fmt, GLContext.getCapabilities())) {
91             throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware.");
92         }
93     }
94 
convertTextureFormat(Format fmt)95     public static int convertTextureFormat(Format fmt){
96         switch (fmt){
97             case Alpha16:
98                 return GL_ALPHA16;
99             case Alpha8:
100                 return GL_ALPHA8;
101             case DXT1:
102                 return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
103             case DXT1A:
104                 return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
105             case DXT3:
106                 return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
107             case DXT5:
108                 return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
109             case LATC:
110                 return GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
111             case Depth:
112                 return GL_DEPTH_COMPONENT;
113             case Depth16:
114                 return GL_DEPTH_COMPONENT16;
115             case Depth24:
116                 return GL_DEPTH_COMPONENT24;
117             case Depth32:
118                 return GL_DEPTH_COMPONENT32;
119             case Depth32F:
120                 return ARBDepthBufferFloat.GL_DEPTH_COMPONENT32F;
121             case Luminance8Alpha8:
122                 return GL_LUMINANCE8_ALPHA8;
123             case Luminance16Alpha16:
124                 return GL_LUMINANCE16_ALPHA16;
125             case Luminance16FAlpha16F:
126                 return ARBTextureFloat.GL_LUMINANCE_ALPHA16F_ARB;
127             case Intensity8:
128                 return GL_INTENSITY8;
129             case Intensity16:
130                 return GL_INTENSITY16;
131             case Luminance8:
132                 return GL_LUMINANCE8;
133             case Luminance16:
134                 return GL_LUMINANCE16;
135             case Luminance16F:
136                 return ARBTextureFloat.GL_LUMINANCE16F_ARB;
137              case Luminance32F:
138                 return ARBTextureFloat.GL_LUMINANCE32F_ARB;
139             case RGB10:
140                 return GL_RGB10;
141             case RGB16:
142                 return GL_RGB16;
143             case RGB111110F:
144                 return EXTPackedFloat.GL_R11F_G11F_B10F_EXT;
145             case RGB9E5:
146                 return EXTTextureSharedExponent.GL_RGB9_E5_EXT;
147             case RGB16F:
148                 return ARBTextureFloat.GL_RGB16F_ARB;
149             case RGBA16F:
150                 return ARBTextureFloat.GL_RGBA16F_ARB;
151             case RGB32F:
152                 return ARBTextureFloat.GL_RGB32F_ARB;
153             case RGB5A1:
154                 return GL_RGB5_A1;
155             case BGR8:
156                 return GL_RGB8;
157             case RGB8:
158                 return GL_RGB8;
159             case RGBA16:
160                 return GL_RGBA16;
161             case RGBA8:
162                 return GL_RGBA8;
163             default:
164                 throw new UnsupportedOperationException("Unrecognized format: "+fmt);
165         }
166     }
167 
uploadTexture(Image img, int target, int index, int border, boolean tdc)168     public static void uploadTexture(Image img,
169                                      int target,
170                                      int index,
171                                      int border,
172                                      boolean tdc){
173         Image.Format fmt = img.getFormat();
174 
175         checkFormatSupported(fmt);
176 
177         ByteBuffer data;
178         if (index >= 0 && img.getData() != null && img.getData().size() > 0){
179             data = img.getData(index);
180         }else{
181             data = null;
182         }
183 
184         int width = img.getWidth();
185         int height = img.getHeight();
186         int depth = img.getDepth();
187 
188         boolean compress = false;
189         int internalFormat = -1;
190         int format = -1;
191         int dataType = -1;
192 
193         switch (fmt){
194             case Alpha16:
195                 internalFormat = GL_ALPHA16;
196                 format = GL_ALPHA;
197                 dataType = GL_UNSIGNED_BYTE;
198                 break;
199             case Alpha8:
200                 internalFormat = GL_ALPHA8;
201                 format = GL_ALPHA;
202                 dataType = GL_UNSIGNED_BYTE;
203                 break;
204             case DXT1:
205                 compress = true;
206                 internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
207                 format = GL_RGB;
208                 dataType = GL_UNSIGNED_BYTE;
209                 break;
210             case DXT1A:
211                 compress = true;
212                 internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
213                 format = GL_RGBA;
214                 dataType = GL_UNSIGNED_BYTE;
215                 break;
216             case DXT3:
217                 compress = true;
218                 internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
219                 format = GL_RGBA;
220                 dataType = GL_UNSIGNED_BYTE;
221                 break;
222             case DXT5:
223                 compress = true;
224                 internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
225                 format = GL_RGBA;
226                 dataType = GL_UNSIGNED_BYTE;
227                 break;
228             case LATC:
229                 compress = true;
230                 if (tdc){
231                     internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI;
232                 }else{
233                     internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
234                 }
235                 format = GL_LUMINANCE_ALPHA;
236                 dataType = GL_UNSIGNED_BYTE;
237                 break;
238             case LTC:
239                 compress = true;
240                 internalFormat = GL_COMPRESSED_LUMINANCE_LATC1_EXT;
241                 format = GL_LUMINANCE_ALPHA;
242                 dataType = GL_UNSIGNED_BYTE;
243                 break;
244             case Depth:
245                 internalFormat = GL_DEPTH_COMPONENT;
246                 format = GL_DEPTH_COMPONENT;
247                 dataType = GL_UNSIGNED_BYTE;
248                 break;
249             case Depth16:
250                 internalFormat = GL_DEPTH_COMPONENT16;
251                 format = GL_DEPTH_COMPONENT;
252                 dataType = GL_UNSIGNED_BYTE;
253                 break;
254             case Depth24:
255                 internalFormat = GL_DEPTH_COMPONENT24;
256                 format = GL_DEPTH_COMPONENT;
257                 dataType = GL_UNSIGNED_BYTE;
258                 break;
259             case Depth32:
260                 internalFormat = GL_DEPTH_COMPONENT32;
261                 format = GL_DEPTH_COMPONENT;
262                 dataType = GL_UNSIGNED_BYTE;
263                 break;
264             case Depth32F:
265                 internalFormat = NVDepthBufferFloat.GL_DEPTH_COMPONENT32F_NV;
266                 format = GL_DEPTH_COMPONENT;
267                 dataType = GL_FLOAT;
268                 break;
269             case Luminance16FAlpha16F:
270                 internalFormat = ARBTextureFloat.GL_LUMINANCE_ALPHA16F_ARB;
271                 format = GL_LUMINANCE_ALPHA;
272                 dataType = GL_UNSIGNED_BYTE;
273                 break;
274             case Intensity8:
275                 internalFormat = GL_INTENSITY8;
276                 format = GL_INTENSITY;
277                 dataType = GL_UNSIGNED_BYTE;
278                 break;
279             case Intensity16:
280                 internalFormat = GL_INTENSITY16;
281                 format = GL_INTENSITY;
282                 dataType = GL_UNSIGNED_BYTE;
283                 break;
284             case Luminance8:
285                 internalFormat = GL_LUMINANCE8;
286                 format = GL_LUMINANCE;
287                 dataType = GL_UNSIGNED_BYTE;
288                 break;
289             case Luminance8Alpha8:
290                 internalFormat = GL_LUMINANCE8_ALPHA8;
291                 format = GL_LUMINANCE_ALPHA;
292                 dataType = GL_UNSIGNED_BYTE;
293                 break;
294             case Luminance16Alpha16:
295                 internalFormat = GL_LUMINANCE16_ALPHA16;
296                 format = GL_LUMINANCE_ALPHA;
297                 dataType = GL_UNSIGNED_BYTE;
298                 break;
299             case Luminance16:
300                 internalFormat = GL_LUMINANCE16;
301                 format = GL_LUMINANCE;
302                 dataType = GL_UNSIGNED_BYTE;
303                 break;
304             case Luminance16F:
305                 internalFormat = ARBTextureFloat.GL_LUMINANCE16F_ARB;
306                 format = GL_LUMINANCE;
307                 dataType = ARBHalfFloatPixel.GL_HALF_FLOAT_ARB;
308                 break;
309             case Luminance32F:
310                 internalFormat = ARBTextureFloat.GL_LUMINANCE32F_ARB;
311                 format = GL_LUMINANCE;
312                 dataType = GL_FLOAT;
313                 break;
314             case RGB10:
315                 internalFormat = GL_RGB10;
316                 format = GL_RGB;
317                 dataType = GL_UNSIGNED_BYTE;
318                 break;
319             case RGB16:
320                 internalFormat = GL_RGB16;
321                 format = GL_RGB;
322                 dataType = GL_UNSIGNED_BYTE;
323                 break;
324             case RGB111110F:
325                 internalFormat = EXTPackedFloat.GL_R11F_G11F_B10F_EXT;
326                 format = GL_RGB;
327                 dataType = EXTPackedFloat.GL_UNSIGNED_INT_10F_11F_11F_REV_EXT;
328                 break;
329             case RGB16F_to_RGB111110F:
330                 internalFormat = EXTPackedFloat.GL_R11F_G11F_B10F_EXT;
331                 format = GL_RGB;
332                 dataType = ARBHalfFloatPixel.GL_HALF_FLOAT_ARB;
333                 break;
334             case RGB16F_to_RGB9E5:
335                 internalFormat = EXTTextureSharedExponent.GL_RGB9_E5_EXT;
336                 format = GL_RGB;
337                 dataType = ARBHalfFloatPixel.GL_HALF_FLOAT_ARB;
338                 break;
339             case RGB9E5:
340                 internalFormat = EXTTextureSharedExponent.GL_RGB9_E5_EXT;
341                 format = GL_RGB;
342                 dataType = EXTTextureSharedExponent.GL_UNSIGNED_INT_5_9_9_9_REV_EXT;
343                 break;
344             case RGB16F:
345                 internalFormat = ARBTextureFloat.GL_RGB16F_ARB;
346                 format = GL_RGB;
347                 dataType = ARBHalfFloatPixel.GL_HALF_FLOAT_ARB;
348                 break;
349             case RGBA16F:
350                 internalFormat = ARBTextureFloat.GL_RGBA16F_ARB;
351                 format = GL_RGBA;
352                 dataType = ARBHalfFloatPixel.GL_HALF_FLOAT_ARB;
353                 break;
354             case RGB32F:
355                 internalFormat = ARBTextureFloat.GL_RGB32F_ARB;
356                 format = GL_RGB;
357                 dataType = GL_FLOAT;
358                 break;
359             case RGBA32F:
360                 internalFormat = ARBTextureFloat.GL_RGBA32F_ARB;
361                 format = GL_RGBA;
362                 dataType = GL_FLOAT;
363                 break;
364             case RGB5A1:
365                 internalFormat = GL_RGB5_A1;
366                 format = GL_RGBA;
367                 dataType = GL_UNSIGNED_BYTE;
368                 break;
369             case RGB8:
370                 internalFormat = GL_RGB8;
371                 format = GL_RGB;
372                 dataType = GL_UNSIGNED_BYTE;
373                 break;
374             case BGR8:
375                 internalFormat = GL_RGB8;
376                 format = GL_BGR;
377                 dataType = GL_UNSIGNED_BYTE;
378                 break;
379             case RGBA16:
380                 internalFormat = GL_RGBA16;
381                 format = GL_RGBA;
382                 dataType = GL_UNSIGNED_BYTE;
383                 break;
384             case RGBA8:
385                 internalFormat = GL_RGBA8;
386                 format = GL_RGBA;
387                 dataType = GL_UNSIGNED_BYTE;
388                 break;
389             case ABGR8:
390                 internalFormat = GL_RGBA8;
391                 format = EXTAbgr.GL_ABGR_EXT;
392                 dataType = GL_UNSIGNED_BYTE;
393                 break;
394             default:
395                 throw new UnsupportedOperationException("Unrecognized format: "+fmt);
396         }
397 
398         if (data != null)
399             glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
400 
401         int[] mipSizes = img.getMipMapSizes();
402         int pos = 0;
403         // TODO: Remove unneccessary allocation
404         if (mipSizes == null){
405             if (data != null)
406                 mipSizes = new int[]{ data.capacity() };
407             else
408                 mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 };
409         }
410 
411         boolean subtex = false;
412         int samples = img.getMultiSamples();
413 
414         for (int i = 0; i < mipSizes.length; i++){
415             int mipWidth =  Math.max(1, width  >> i);
416             int mipHeight = Math.max(1, height >> i);
417             int mipDepth =  Math.max(1, depth  >> i);
418 
419             if (data != null){
420                 data.position(pos);
421                 data.limit(pos + mipSizes[i]);
422             }
423 
424             if (compress && data != null){
425                 if (target == GL_TEXTURE_3D){
426                     glCompressedTexImage3D(target,
427                                            i,
428                                            internalFormat,
429                                            mipWidth,
430                                            mipHeight,
431                                            mipDepth,
432                                            border,
433                                            data);
434                 }else{
435                     //all other targets use 2D: array, cubemap, 2d
436                     glCompressedTexImage2D(target,
437                                            i,
438                                            internalFormat,
439                                            mipWidth,
440                                            mipHeight,
441                                            border,
442                                            data);
443                 }
444             }else{
445                 if (target == GL_TEXTURE_3D){
446                     glTexImage3D(target,
447                                  i,
448                                  internalFormat,
449                                  mipWidth,
450                                  mipHeight,
451                                  mipDepth,
452                                  border,
453                                  format,
454                                  dataType,
455                                  data);
456                 }else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT){
457                     // prepare data for 2D array
458                     // or upload slice
459                     if (index == -1){
460                         glTexImage3D(target,
461                                      0,
462                                      internalFormat,
463                                      mipWidth,
464                                      mipHeight,
465                                      img.getData().size(), //# of slices
466                                      border,
467                                      format,
468                                      dataType,
469                                      data);
470                     }else{
471                         glTexSubImage3D(target,
472                                         i, // level
473                                         0, // xoffset
474                                         0, // yoffset
475                                         index, // zoffset
476                                         width, // width
477                                         height, // height
478                                         1, // depth
479                                         format,
480                                         dataType,
481                                         data);
482                     }
483                 }else{
484                     if (subtex){
485                         if (samples > 1)
486                             throw new IllegalStateException("Cannot update multisample textures");
487 
488                         glTexSubImage2D(target,
489                                         i,
490                                         0, 0,
491                                         mipWidth, mipHeight,
492                                         format,
493                                         dataType,
494                                         data);
495                     }else{
496                         if (samples > 1){
497                             ARBTextureMultisample.glTexImage2DMultisample(target,
498                                                                           samples,
499                                                                           internalFormat,
500                                                                           mipWidth,
501                                                                           mipHeight,
502                                                                           true);
503                         }else{
504                             glTexImage2D(target,
505                                          i,
506                                          internalFormat,
507                                          mipWidth,
508                                          mipHeight,
509                                          border,
510                                          format,
511                                          dataType,
512                                          data);
513                         }
514                     }
515                 }
516             }
517 
518             pos += mipSizes[i];
519         }
520     }
521 
522 }
523