Home | History | Annotate | Download | only in lwjgl
      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 
     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 
     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 
     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 
    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