1 /+ 2 The MIT License (MIT) 3 4 Copyright (c) <2013> <Oleg Butko (deviator), Anton Akzhigitov (Akzwar)> 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 +/ 24 25 module des.gl.base.texture; 26 27 import std.string; 28 29 public import derelict.opengl3.gl3; 30 31 import des.gl.base.type; 32 33 import des.il; 34 35 import std.algorithm; 36 import des.util.stdext.algorithm; 37 38 /// 39 class GLTextureException : DesGLException 40 { 41 /// 42 this( string msg, string file=__FILE__, size_t line=__LINE__ ) @safe pure nothrow 43 { super( msg, file, line ); } 44 } 45 46 /// 47 class GLTexture : DesObject 48 { 49 mixin DES; 50 mixin ClassLogger; 51 private: 52 uint _id; 53 54 protected: 55 /// 56 texsize_t img_size; 57 58 override void selfDestroy() 59 { 60 unbind(); 61 checkGLCall!glDeleteTextures( 1, &_id ); 62 } 63 64 /// 65 Target _target; 66 67 /// 68 nothrow @property GLenum gltype() const { return cast(GLenum)_target; } 69 70 /// 71 InternalFormat liformat; 72 /// 73 Format lformat; 74 /// 75 Type ltype; 76 77 public: 78 79 alias SizeVector!3 texsize_t; 80 81 /// 82 @property Target target() const { return _target; } 83 84 /// 85 enum Target 86 { 87 T1D = GL_TEXTURE_1D, /// `GL_TEXTURE_1D` 88 T2D = GL_TEXTURE_2D, /// `GL_TEXTURE_2D` 89 T3D = GL_TEXTURE_3D, /// `GL_TEXTURE_3D` 90 T1D_ARRAY = GL_TEXTURE_1D_ARRAY, /// `GL_TEXTURE_1D_ARRAY` 91 T2D_ARRAY = GL_TEXTURE_2D_ARRAY, /// `GL_TEXTURE_2D_ARRAY` 92 RECTANGLE = GL_TEXTURE_RECTANGLE, /// `GL_TEXTURE_RECTANGLE` 93 CUBE_MAP = GL_TEXTURE_CUBE_MAP, /// `GL_TEXTURE_CUBE_MAP` 94 CUBE_MAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY, /// `GL_TEXTURE_CUBE_MAP_ARRAY` 95 96 BUFFER = GL_TEXTURE_BUFFER, /// `GL_TEXTURE_BUFFER` 97 T2D_MULTISAMPLE = GL_TEXTURE_2D_MULTISAMPLE, /// `GL_TEXTURE_2D_MULTISAMPLE` 98 T2D_MULTISAMPLE_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY, /// `GL_TEXTURE_2D_MULTISAMPLE_ARRAY` 99 100 CUBE_MAP_POSITIVE_X = GL_TEXTURE_CUBE_MAP_POSITIVE_X, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_X` 101 CUBE_MAP_NEGATIVE_X = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_X` 102 CUBE_MAP_POSITIVE_Y = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_Y` 103 CUBE_MAP_NEGATIVE_Y = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_Y` 104 CUBE_MAP_POSITIVE_Z = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_Z` 105 CUBE_MAP_NEGATIVE_Z = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_Z` 106 } 107 108 /// 109 enum Parameter 110 { 111 DEPTH_STENCIL_TEXTURE_MODE = GL_DEPTH_STENCIL_TEXTURE_MODE, /// `GL_DEPTH_STENCIL_TEXTURE_MODE` 112 BASE_LEVEL = GL_TEXTURE_BASE_LEVEL, /// `GL_TEXTURE_BASE_LEVEL` 113 BORDER_COLOR = GL_TEXTURE_BORDER_COLOR, /// `GL_TEXTURE_BORDER_COLOR` 114 COMPARE_FUNC = GL_TEXTURE_COMPARE_FUNC, /// `GL_TEXTURE_COMPARE_FUNC` 115 COMPARE_MODE = GL_TEXTURE_COMPARE_MODE, /// `GL_TEXTURE_COMPARE_MODE` 116 LOD_BIAS = GL_TEXTURE_LOD_BIAS, /// `GL_TEXTURE_LOD_BIAS` 117 MIN_FILTER = GL_TEXTURE_MIN_FILTER, /// `GL_TEXTURE_MIN_FILTER` 118 MAG_FILTER = GL_TEXTURE_MAG_FILTER, /// `GL_TEXTURE_MAG_FILTER` 119 MIN_LOD = GL_TEXTURE_MIN_LOD, /// `GL_TEXTURE_MIN_LOD` 120 MAX_LOD = GL_TEXTURE_MAX_LOD, /// `GL_TEXTURE_MAX_LOD` 121 MAX_LEVEL = GL_TEXTURE_MAX_LEVEL, /// `GL_TEXTURE_MAX_LEVEL` 122 SWIZZLE_R = GL_TEXTURE_SWIZZLE_R, /// `GL_TEXTURE_SWIZZLE_R` 123 SWIZZLE_G = GL_TEXTURE_SWIZZLE_G, /// `GL_TEXTURE_SWIZZLE_G` 124 SWIZZLE_B = GL_TEXTURE_SWIZZLE_B, /// `GL_TEXTURE_SWIZZLE_B` 125 SWIZZLE_A = GL_TEXTURE_SWIZZLE_A, /// `GL_TEXTURE_SWIZZLE_A` 126 SWIZZLE_RGBA = GL_TEXTURE_SWIZZLE_RGBA, /// `GL_TEXTURE_SWIZZLE_RGBA` 127 WRAP_S = GL_TEXTURE_WRAP_S, /// `GL_TEXTURE_WRAP_S` 128 WRAP_T = GL_TEXTURE_WRAP_T, /// `GL_TEXTURE_WRAP_T` 129 WRAP_R = GL_TEXTURE_WRAP_R /// `GL_TEXTURE_WRAP_R` 130 } 131 132 /// 133 enum DepthStencilTextureMode 134 { 135 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 136 STENCIL = GL_STENCIL_COMPONENTS /// `GL_STENCIL_COMPONENTS` 137 } 138 139 /// 140 enum CompareFunc 141 { 142 LEQUAL = GL_LEQUAL, /// `GL_LEQUAL` 143 GEQUAL = GL_GEQUAL, /// `GL_GEQUAL` 144 LESS = GL_LESS, /// `GL_LESS` 145 GREATER = GL_GREATER, /// `GL_GREATER` 146 EQUAL = GL_EQUAL, /// `GL_EQUAL` 147 NOTEQUAL = GL_NOTEQUAL, /// `GL_NOTEQUAL` 148 ALWAYS = GL_ALWAYS, /// `GL_ALWAYS` 149 NEVER = GL_NEVER /// `GL_NEVER` 150 } 151 152 /// 153 enum CompareMode 154 { 155 REF_TO_TEXTURE = GL_COMPARE_REF_TO_TEXTURE, /// `GL_COMPARE_REF_TO_TEXTURE` 156 NONE = GL_NONE /// `GL_NONE` 157 } 158 159 /// 160 enum Filter 161 { 162 NEAREST = GL_NEAREST, /// `GL_NEAREST` 163 LINEAR = GL_LINEAR, /// `GL_LINEAR` 164 NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, /// `GL_NEAREST_MIPMAP_NEAREST` 165 LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, /// `GL_LINEAR_MIPMAP_NEAREST` 166 NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, /// `GL_NEAREST_MIPMAP_LINEAR` 167 LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR /// `GL_LINEAR_MIPMAP_LINEAR` 168 } 169 170 /// 171 enum Swizzle 172 { 173 RED = GL_RED, /// `GL_RED` 174 GREEN = GL_GREEN,/// `GL_GREEN` 175 BLUE = GL_BLUE, /// `GL_BLUE` 176 ALPHA = GL_ALPHA,/// `GL_ALPHA` 177 ZERO = GL_ZERO /// `GL_ZERO` 178 } 179 180 /// 181 enum Wrap 182 { 183 CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, /// `GL_CLAMP_TO_EDGE` 184 CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER, /// `GL_CLAMP_TO_BORDER` 185 MIRRORED_REPEAT = GL_MIRRORED_REPEAT, /// `GL_MIRRORED_REPEAT` 186 REPEAT = GL_REPEAT /// `GL_REPEAT` 187 } 188 189 /// 190 enum InternalFormat 191 { 192 COMPRESSED_RED = GL_COMPRESSED_RED, /// `GL_COMPRESSED_RED` 193 COMPRESSED_RG = GL_COMPRESSED_RG, /// `GL_COMPRESSED_RG` 194 COMPRESSED_RGB = GL_COMPRESSED_RGB, /// `GL_COMPRESSED_RGB` 195 COMPRESSED_RGBA = GL_COMPRESSED_RGBA, /// `GL_COMPRESSED_RGBA` 196 COMPRESSED_SRGB = GL_COMPRESSED_SRGB, /// `GL_COMPRESSED_SRGB` 197 COMPRESSED_SRGB_ALPHA = GL_COMPRESSED_SRGB_ALPHA, /// `GL_COMPRESSED_SRGB_ALPHA` 198 DEPTH_COMPONENT = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 199 DEPTH_COMPONENT16 = GL_DEPTH_COMPONENT16, /// `GL_DEPTH_COMPONENT16` 200 DEPTH_COMPONENT24 = GL_DEPTH_COMPONENT24, /// `GL_DEPTH_COMPONENT24` 201 DEPTH_COMPONENT32 = GL_DEPTH_COMPONENT32, /// `GL_DEPTH_COMPONENT32` 202 DEPTH_COMPONENT32F = GL_DEPTH_COMPONENT32F, /// `GL_DEPTH_COMPONENT32F` 203 R3_G3_B2 = GL_R3_G3_B2, /// `GL_R3_G3_B2` 204 RED = GL_RED, /// `GL_RED` 205 RG = GL_RG, /// `GL_RG` 206 RGB = GL_RGB, /// `GL_RGB` 207 RGB4 = GL_RGB4, /// `GL_RGB4` 208 RGB5 = GL_RGB5, /// `GL_RGB5` 209 RGB8 = GL_RGB8, /// `GL_RGB8` 210 RGB10 = GL_RGB10, /// `GL_RGB10` 211 RGB12 = GL_RGB12, /// `GL_RGB12` 212 RGB16 = GL_RGB16, /// `GL_RGB16` 213 RGBA = GL_RGBA, /// `GL_RGBA` 214 RGBA2 = GL_RGBA2, /// `GL_RGBA2` 215 RGBA4 = GL_RGBA4, /// `GL_RGBA4` 216 RGB5_A1 = GL_RGB5_A1, /// `GL_RGB5_A1` 217 RGBA8 = GL_RGBA8, /// `GL_RGBA8` 218 RGB10_A2 = GL_RGB10_A2, /// `GL_RGB10_A2` 219 RGBA12 = GL_RGBA12, /// `GL_RGBA12` 220 RGBA16 = GL_RGBA16, /// `GL_RGBA16` 221 SRGB = GL_SRGB, /// `GL_SRGB` 222 SRGB8 = GL_SRGB8, /// `GL_SRGB8` 223 SRGB_ALPHA = GL_SRGB_ALPHA, /// `GL_SRGB_ALPHA` 224 SRGB8_ALPHA8 = GL_SRGB8_ALPHA8 /// `GL_SRGB8_ALPHA8` 225 } 226 227 /// 228 enum Format 229 { 230 RED = GL_RED, /// `GL_RED` 231 RG = GL_RG, /// `GL_RG` 232 RGB = GL_RGB, /// `GL_RGB` 233 RGBA = GL_RGBA, /// `GL_RGBA` 234 235 BGR = GL_BGR, /// `GL_BGR` 236 BGRA = GL_BGRA, /// `GL_BGRA` 237 238 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 239 DEPTH_STENCIL = GL_DEPTH_STENCIL /// `GL_DEPTH_STENCIL` 240 } 241 242 /// 243 enum Type 244 { 245 UNSIGNED_BYTE = GL_UNSIGNED_BYTE, /// `GL_UNSIGNED_BYTE` 246 BYTE = GL_BYTE, /// `GL_BYTE` 247 UNSIGNED_SHORT = GL_UNSIGNED_SHORT, /// `GL_UNSIGNED_SHORT` 248 SHORT = GL_SHORT, /// `GL_SHORT` 249 UNSIGNED_INT = GL_UNSIGNED_INT, /// `GL_UNSIGNED_INT` 250 INT = GL_INT, /// `GL_INT` 251 HALF_FLOAT = GL_HALF_FLOAT, /// `GL_HALF_FLOAT` 252 FLOAT = GL_FLOAT, /// `GL_FLOAT` 253 254 UNSIGNED_BYTE_3_3_2 = GL_UNSIGNED_BYTE_3_3_2, /// `GL_UNSIGNED_BYTE_3_3_2` 255 UNSIGNED_BYTE_2_3_3_REV = GL_UNSIGNED_BYTE_2_3_3_REV, /// `GL_UNSIGNED_BYTE_2_3_3_REV` 256 UNSIGNED_SHORT_5_6_5 = GL_UNSIGNED_SHORT_5_6_5, /// `GL_UNSIGNED_SHORT_5_6_5` 257 UNSIGNED_SHORT_5_6_5_REV = GL_UNSIGNED_SHORT_5_6_5_REV, /// `GL_UNSIGNED_SHORT_5_6_5_REV` 258 UNSIGNED_SHORT_4_4_4_4 = GL_UNSIGNED_SHORT_4_4_4_4, /// `GL_UNSIGNED_SHORT_4_4_4_4` 259 UNSIGNED_SHORT_4_4_4_4_REV = GL_UNSIGNED_SHORT_4_4_4_4_REV, /// `GL_UNSIGNED_SHORT_4_4_4_4_REV` 260 UNSIGNED_SHORT_5_5_5_1 = GL_UNSIGNED_SHORT_5_5_5_1, /// `GL_UNSIGNED_SHORT_5_5_5_1` 261 UNSIGNED_SHORT_1_5_5_5_REV = GL_UNSIGNED_SHORT_1_5_5_5_REV, /// `GL_UNSIGNED_SHORT_1_5_5_5_REV` 262 UNSIGNED_INT_8_8_8_8 = GL_UNSIGNED_INT_8_8_8_8, /// `GL_UNSIGNED_INT_8_8_8_8` 263 UNSIGNED_INT_8_8_8_8_REV = GL_UNSIGNED_INT_8_8_8_8_REV, /// `GL_UNSIGNED_INT_8_8_8_8_REV` 264 UNSIGNED_INT_10_10_10_2 = GL_UNSIGNED_INT_10_10_10_2, /// `GL_UNSIGNED_INT_10_10_10_2` 265 UNSIGNED_INT_2_10_10_10_REV = GL_UNSIGNED_INT_2_10_10_10_REV, /// `GL_UNSIGNED_INT_2_10_10_10_REV` 266 UNSIGNED_INT_24_8 = GL_UNSIGNED_INT_24_8, /// `GL_UNSIGNED_INT_24_8` 267 UNSIGNED_INT_10F_11F_11F_REV = GL_UNSIGNED_INT_10F_11F_11F_REV, /// `GL_UNSIGNED_INT_10F_11F_11F_REV` 268 UNSIGNED_INT_5_9_9_9_REV = GL_UNSIGNED_INT_5_9_9_9_REV, /// `GL_UNSIGNED_INT_5_9_9_9_REV` 269 FLOAT_32_UNSIGNED_INT_24_8_REV = GL_FLOAT_32_UNSIGNED_INT_24_8_REV /// `GL_FLOAT_32_UNSIGNED_INT_24_8_REV` 270 } 271 272 /// 273 this( Target tg ) 274 in { assert( isBase(tg) ); } body 275 { 276 checkGLCall!glGenTextures( 1, &_id ); 277 logger = new InstanceLogger( this, format( "%d", _id ) ); 278 _target = tg; 279 logger.Debug( "with target [%s]", _target ); 280 } 281 282 /// 283 final pure const @property uint id() { return _id; } 284 285 /// bind, glGenerateMipmap 286 void genMipmap() 287 in { assert( isMipmapable(_target) ); } body 288 { 289 bind(); 290 checkGLCall!glGenerateMipmap(gltype); 291 logger.Debug( "with target [%s]", _target ); 292 } 293 294 /// 295 void setParameter(T)( Parameter pname, T[] val... ) 296 if( is(T==int) || is(T==float) || isParameterEnum!T ) 297 in 298 { 299 assert( val.length > 0 ); 300 assert( isParametric(_target) ); 301 static if( !is(T==float) ) 302 assert( checkPosibleIntParamValues( pname, amap!(a=>cast(int)(a))(val) ) ); 303 else 304 assert( checkPosibleFloatParamValues( pname, val ) ); 305 } 306 body 307 { 308 bind(); 309 enum ts = is(T==float) ? "f" : "i"; 310 enum cs = is(T==float) ? "float" : "int"; 311 if( val.length == 1 ) 312 mixin( format("glTexParameter%s( gltype, cast(GLenum)pname, cast(%s)val[0] );", ts, cs) ); 313 else 314 mixin( format("glTexParameter%sv( gltype, cast(GLenum)pname, cast(%s*)val.ptr );", ts, cs) ); 315 316 debug checkGL; 317 logger.Debug( "[%s]: %s", pname, val ); 318 } 319 320 final nothrow 321 { 322 /// glActiveTexture, glBindTexture 323 void bind( ubyte n=0 ) 324 { 325 ntCheckGLCall!glActiveTexture( GL_TEXTURE0 + n ); 326 ntCheckGLCall!glBindTexture( gltype, _id ); 327 debug logger.trace( "pass" ); 328 } 329 330 /// 331 void unbind() 332 { 333 ntCheckGLCall!glBindTexture( gltype, 0 ); 334 debug logger.trace( "pass" ); 335 } 336 337 /// 338 texsize_t size() const { return img_size; } 339 } 340 341 /// 342 void resize(T)( in T sz ) 343 if( isCompatibleVector!(1,size_t,T) || isCompatibleVector!(2,size_t,T) || isCompatibleVector!(3,size_t,T) ) 344 { image( sz, liformat, lformat, ltype ); } 345 346 /// set image 347 void image(T)( in T sz, InternalFormat internal_format, 348 Format data_format, Type data_type, in void* data=null ) 349 if( isCompatibleVector!(1,size_t,T) || isCompatibleVector!(2,size_t,T) || isCompatibleVector!(3,size_t,T) ) 350 { 351 enum N = sz.length; 352 img_size = texsize_t( sz, [1,1][0 .. 3-N] ); 353 354 liformat = internal_format; 355 lformat = data_format; 356 ltype = data_type; 357 358 bind(); 359 mixin( format(` 360 glTexImage%1dD( gltype, 0, cast(int)internal_format, %s, 0, 361 cast(GLenum)data_format, cast(GLenum)data_type, data ); 362 `, N, accessVecFields!(sz) ) ); 363 364 debug checkGL; 365 debug logger.trace( "[%d]: size %s, internal format [%s], format [%s], type [%s], with data [%s]", 366 _id, sz.data.dup, internal_format, data_format, data_type, data?true:false ); 367 } 368 369 /// ditto 370 final void image(size_t N)( in Image!N img ) if( N >= 1 && N <= 3 ) 371 in 372 { 373 switch( N ) 374 { 375 case 1: assert( target == Target.T1D ); break; 376 case 2: assert( target == Target.T2D ); break; 377 case 3: assert( target == Target.T3D ); break; 378 default: assert(0); 379 } 380 } 381 body 382 { 383 Type type = typeFromImageDataType( img.info.comp ); 384 auto fmt = formatFromImageChanelsCount( img.info.channels ); 385 image( img.size, fmt[0], fmt[1], type, img.data.ptr ); 386 } 387 388 /// 389 final void getImage( ref Image!2 img ) 390 in { assert( _target == Target.T2D ); } body 391 { getImage( img, ltype ); } 392 393 /// 394 final void getImage( ref Image!2 img, Type type ) 395 in { assert( _target == Target.T2D ); } body 396 { 397 enum uint level = 0; 398 399 bind(); 400 debug checkGL; 401 int w, h; 402 glGetTexLevelParameteriv( GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &(w)); 403 debug checkGL; 404 glGetTexLevelParameteriv( GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &(h)); 405 debug checkGL; 406 407 auto elemSize = formatElemCount(lformat) * sizeofType(type); 408 409 auto dsize = w * h * elemSize; 410 411 if( img.size != SizeVector!2(w,h) || img.info.bpe != elemSize ) 412 { 413 img.size = ivec2( w, h ); 414 img.info = imageElemInfo( lformat, type ); 415 } 416 417 glGetTexImage( GL_TEXTURE_2D, level, cast(GLenum)lformat, cast(GLenum)type, img.data.ptr ); 418 debug checkGL; 419 unbind(); 420 debug checkGL; 421 debug logger.trace( "[%d] size [%d,%d], format [%s], type [%s]", _id, w,h, lformat, type ); 422 } 423 424 protected static 425 { 426 /// 427 bool isBase( Target trg ) 428 { 429 switch(trg) 430 { 431 case Target.T1D: 432 case Target.T2D: 433 case Target.T3D: 434 case Target.T1D_ARRAY: 435 case Target.T2D_ARRAY: 436 case Target.RECTANGLE: 437 case Target.CUBE_MAP: 438 case Target.CUBE_MAP_ARRAY: return true; 439 default: return false; 440 } 441 } 442 443 /// 444 bool isParametric( Target trg ) 445 { 446 switch(trg) 447 { 448 case Target.T1D: 449 case Target.T2D: 450 case Target.T3D: 451 case Target.T1D_ARRAY: 452 case Target.T2D_ARRAY: 453 case Target.RECTANGLE: 454 case Target.CUBE_MAP: return true; 455 default: return false; 456 } 457 } 458 459 /// 460 bool isMipmapable( Target trg ) 461 { 462 switch(trg) 463 { 464 case Target.T1D: 465 case Target.T2D: 466 case Target.T3D: 467 case Target.T1D_ARRAY: 468 case Target.T2D_ARRAY: 469 case Target.CUBE_MAP: return true; 470 default: return false; 471 } 472 } 473 474 /// 475 bool checkPosibleIntParamValues( Parameter pname, int[] valbuf... ) 476 { 477 if( valbuf.length == 0 ) return false; 478 479 size_t count = valbuf.length; 480 bool single = count == 1; 481 auto val = valbuf[0]; 482 483 final switch(pname) 484 { 485 case Parameter.DEPTH_STENCIL_TEXTURE_MODE: return single && oneOf!DepthStencilTextureMode(val); 486 case Parameter.BASE_LEVEL: return single && val >= 0; 487 case Parameter.BORDER_COLOR: return count == 4 && all!(a=>a>=0)(valbuf); 488 case Parameter.COMPARE_FUNC: return single && oneOf!CompareFunc(val); 489 case Parameter.COMPARE_MODE: return single && oneOf!CompareMode(val); 490 case Parameter.LOD_BIAS: return false; // is float 491 case Parameter.MIN_FILTER: return single && oneOf!Filter(val); 492 case Parameter.MAG_FILTER: return single && oneOf( [Filter.NEAREST,Filter.LINEAR], val ); 493 case Parameter.MIN_LOD: return false; // is float 494 case Parameter.MAX_LOD: return false; // is float 495 case Parameter.MAX_LEVEL: return single; // initial is 1000, no info in documentation 496 497 case Parameter.SWIZZLE_R: 498 case Parameter.SWIZZLE_G: 499 case Parameter.SWIZZLE_B: 500 case Parameter.SWIZZLE_A: 501 return single && oneOf!Swizzle(val); 502 503 case Parameter.SWIZZLE_RGBA: return count == 4 && all!(a=>oneOf!Swizzle(a))(valbuf); 504 505 case Parameter.WRAP_S: 506 case Parameter.WRAP_T: 507 case Parameter.WRAP_R: 508 return single && oneOf!Wrap(val); 509 } 510 } 511 512 /// 513 bool checkPosibleFloatParamValues( Parameter pname, float[] valbuf... ) 514 { 515 if( valbuf.length == 0 ) return false; 516 517 size_t count = valbuf.length; 518 bool single = count == 1; 519 auto val = valbuf[0]; 520 521 switch(pname) 522 { 523 case Parameter.LOD_BIAS: 524 case Parameter.MIN_LOD: 525 case Parameter.MAX_LOD: 526 return single; 527 case Parameter.BORDER_COLOR: return count == 4; 528 default: return false; // is integer; 529 } 530 } 531 532 /// 533 size_t formatElemCount( Format fmt ) 534 { 535 final switch(fmt) 536 { 537 case Format.RED: return 1; 538 case Format.RG: return 2; 539 540 case Format.RGB: 541 case Format.BGR: 542 return 3; 543 544 case Format.RGBA: 545 case Format.BGRA: 546 return 4; 547 548 case Format.DEPTH: 549 return 1; 550 551 case Format.DEPTH_STENCIL: 552 return 2; 553 } 554 } 555 556 /// 557 size_t sizeofType( Type type ) 558 { 559 final switch(type) 560 { 561 case Type.BYTE: 562 case Type.UNSIGNED_BYTE: 563 case Type.UNSIGNED_BYTE_3_3_2: 564 case Type.UNSIGNED_BYTE_2_3_3_REV: 565 return byte.sizeof; 566 567 case Type.SHORT: 568 case Type.UNSIGNED_SHORT: 569 case Type.UNSIGNED_SHORT_5_6_5: 570 case Type.UNSIGNED_SHORT_5_6_5_REV: 571 case Type.UNSIGNED_SHORT_4_4_4_4: 572 case Type.UNSIGNED_SHORT_4_4_4_4_REV: 573 case Type.UNSIGNED_SHORT_5_5_5_1: 574 case Type.UNSIGNED_SHORT_1_5_5_5_REV: 575 return short.sizeof; 576 577 case Type.INT: 578 case Type.UNSIGNED_INT: 579 case Type.UNSIGNED_INT_8_8_8_8: 580 case Type.UNSIGNED_INT_8_8_8_8_REV: 581 case Type.UNSIGNED_INT_10_10_10_2: 582 case Type.UNSIGNED_INT_2_10_10_10_REV: 583 case Type.UNSIGNED_INT_24_8: 584 case Type.UNSIGNED_INT_10F_11F_11F_REV: 585 case Type.UNSIGNED_INT_5_9_9_9_REV: 586 case Type.FLOAT_32_UNSIGNED_INT_24_8_REV: 587 return int.sizeof; 588 589 case Type.HALF_FLOAT: return float.sizeof / 2; 590 case Type.FLOAT: return float.sizeof; 591 } 592 } 593 594 /// 595 auto imageElemInfo( Format fmt, Type type ) 596 { 597 auto cnt = formatElemCount(fmt); 598 auto ict = imageDataType(type); 599 if( ict == DataType.RAWBYTE ) 600 return ElemInfo( sizeofType(type) * cnt ); 601 else 602 return ElemInfo( ict, cnt ); 603 } 604 605 /// 606 DataType imageDataType( Type type ) 607 { 608 switch( type ) 609 { 610 case Type.BYTE: return DataType.BYTE; 611 case Type.UNSIGNED_BYTE: return DataType.UBYTE; 612 case Type.SHORT: return DataType.SHORT; 613 case Type.UNSIGNED_SHORT: return DataType.USHORT; 614 case Type.INT: return DataType.INT; 615 case Type.UNSIGNED_INT: return DataType.UINT; 616 case Type.FLOAT: return DataType.FLOAT; 617 default: return DataType.RAWBYTE; 618 } 619 } 620 621 /// 622 @property bool isParameterEnum(T)() 623 { 624 return is(T==DepthStencilTextureMode) || 625 is(T==CompareFunc) || 626 is(T==CompareMode) || 627 is(T==Filter) || 628 is(T==Swizzle) || 629 is(T==Wrap); 630 } 631 632 /// 633 Type typeFromImageDataType( DataType ctype ) 634 { 635 switch( ctype ) 636 { 637 case DataType.BYTE: return Type.BYTE; 638 case DataType.UBYTE: 639 case DataType.RAWBYTE: return Type.UNSIGNED_BYTE; 640 case DataType.SHORT: return Type.SHORT; 641 case DataType.USHORT: return Type.UNSIGNED_SHORT; 642 case DataType.INT: return Type.INT; 643 case DataType.UINT: return Type.UNSIGNED_INT; 644 case DataType.NORM_FIXED: return Type.INT; 645 case DataType.UNORM_FIXED: return Type.UNSIGNED_INT; 646 case DataType.FLOAT: return Type.FLOAT; 647 default: 648 throw new GLTextureException( "uncompatible image component type" ); 649 } 650 } 651 652 /// 653 auto formatFromImageChanelsCount( size_t channels ) 654 { 655 switch( channels ) 656 { 657 case 1: return tuple(InternalFormat.RED, Format.RED ); 658 case 2: return tuple(InternalFormat.RG, Format.RG ); 659 case 3: return tuple(InternalFormat.RGB, Format.RGB ); 660 case 4: return tuple(InternalFormat.RGBA, Format.RGBA ); 661 default: 662 throw new GLTextureException( "uncompatible image chanels count" ); 663 } 664 } 665 } 666 } 667 668 private @property string accessVecFields(alias T)() 669 { 670 string[] ret; 671 foreach( i; 0 .. T.length ) 672 ret ~= format( "cast(int)(%s[%d])", T.stringof, i ); 673 return ret.join(","); 674 }