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 33package com.jme3.renderer.lwjgl; 34 35import com.jme3.renderer.RendererException; 36import com.jme3.texture.Image; 37import com.jme3.texture.Image.Format; 38import java.nio.ByteBuffer; 39import static org.lwjgl.opengl.ATITextureCompression3DC.GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI; 40import static org.lwjgl.opengl.EXTTextureCompressionLATC.GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; 41import static org.lwjgl.opengl.EXTTextureCompressionLATC.GL_COMPRESSED_LUMINANCE_LATC1_EXT; 42import static org.lwjgl.opengl.EXTTextureCompressionS3TC.*; 43import static org.lwjgl.opengl.GL11.*; 44import static org.lwjgl.opengl.GL12.*; 45import static org.lwjgl.opengl.GL13.glCompressedTexImage2D; 46import static org.lwjgl.opengl.GL13.glCompressedTexImage3D; 47import static org.lwjgl.opengl.GL14.*; 48import org.lwjgl.opengl.*; 49 50public 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