1 // 2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // utilities.cpp: Conversion functions and other utility routines. 8 9 #include "libGLESv2/utilities.h" 10 11 #include <limits> 12 13 #include "common/debug.h" 14 15 #include "libGLESv2/mathutil.h" 16 #include "libGLESv2/Context.h" 17 18 namespace gl 19 { 20 21 int UniformComponentCount(GLenum type) 22 { 23 switch (type) 24 { 25 case GL_BOOL: 26 case GL_FLOAT: 27 case GL_INT: 28 case GL_SAMPLER_2D: 29 case GL_SAMPLER_CUBE: 30 return 1; 31 case GL_BOOL_VEC2: 32 case GL_FLOAT_VEC2: 33 case GL_INT_VEC2: 34 return 2; 35 case GL_INT_VEC3: 36 case GL_FLOAT_VEC3: 37 case GL_BOOL_VEC3: 38 return 3; 39 case GL_BOOL_VEC4: 40 case GL_FLOAT_VEC4: 41 case GL_INT_VEC4: 42 case GL_FLOAT_MAT2: 43 return 4; 44 case GL_FLOAT_MAT3: 45 return 9; 46 case GL_FLOAT_MAT4: 47 return 16; 48 default: 49 UNREACHABLE(); 50 } 51 52 return 0; 53 } 54 55 GLenum UniformComponentType(GLenum type) 56 { 57 switch(type) 58 { 59 case GL_BOOL: 60 case GL_BOOL_VEC2: 61 case GL_BOOL_VEC3: 62 case GL_BOOL_VEC4: 63 return GL_BOOL; 64 case GL_FLOAT: 65 case GL_FLOAT_VEC2: 66 case GL_FLOAT_VEC3: 67 case GL_FLOAT_VEC4: 68 case GL_FLOAT_MAT2: 69 case GL_FLOAT_MAT3: 70 case GL_FLOAT_MAT4: 71 return GL_FLOAT; 72 case GL_INT: 73 case GL_SAMPLER_2D: 74 case GL_SAMPLER_CUBE: 75 case GL_INT_VEC2: 76 case GL_INT_VEC3: 77 case GL_INT_VEC4: 78 return GL_INT; 79 default: 80 UNREACHABLE(); 81 } 82 83 return GL_NONE; 84 } 85 86 size_t UniformTypeSize(GLenum type) 87 { 88 switch(type) 89 { 90 case GL_BOOL: return sizeof(GLboolean); 91 case GL_FLOAT: return sizeof(GLfloat); 92 case GL_INT: return sizeof(GLint); 93 } 94 95 return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type); 96 } 97 98 int VariableRowCount(GLenum type) 99 { 100 switch (type) 101 { 102 case GL_NONE: 103 return 0; 104 case GL_BOOL: 105 case GL_FLOAT: 106 case GL_INT: 107 case GL_BOOL_VEC2: 108 case GL_FLOAT_VEC2: 109 case GL_INT_VEC2: 110 case GL_INT_VEC3: 111 case GL_FLOAT_VEC3: 112 case GL_BOOL_VEC3: 113 case GL_BOOL_VEC4: 114 case GL_FLOAT_VEC4: 115 case GL_INT_VEC4: 116 return 1; 117 case GL_FLOAT_MAT2: 118 return 2; 119 case GL_FLOAT_MAT3: 120 return 3; 121 case GL_FLOAT_MAT4: 122 return 4; 123 default: 124 UNREACHABLE(); 125 } 126 127 return 0; 128 } 129 130 int VariableColumnCount(GLenum type) 131 { 132 switch (type) 133 { 134 case GL_NONE: 135 return 0; 136 case GL_BOOL: 137 case GL_FLOAT: 138 case GL_INT: 139 return 1; 140 case GL_BOOL_VEC2: 141 case GL_FLOAT_VEC2: 142 case GL_INT_VEC2: 143 case GL_FLOAT_MAT2: 144 return 2; 145 case GL_INT_VEC3: 146 case GL_FLOAT_VEC3: 147 case GL_BOOL_VEC3: 148 case GL_FLOAT_MAT3: 149 return 3; 150 case GL_BOOL_VEC4: 151 case GL_FLOAT_VEC4: 152 case GL_INT_VEC4: 153 case GL_FLOAT_MAT4: 154 return 4; 155 default: 156 UNREACHABLE(); 157 } 158 159 return 0; 160 } 161 162 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize) 163 { 164 ASSERT(allocationSize <= bitsSize); 165 166 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize); 167 168 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++) 169 { 170 if ((*bits & mask) == 0) 171 { 172 *bits |= mask; 173 return i; 174 } 175 176 mask <<= 1; 177 } 178 179 return -1; 180 } 181 182 GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment) 183 { 184 ASSERT(alignment > 0 && isPow2(alignment)); 185 186 GLsizei rawPitch = ComputePixelSize(format, type) * width; 187 return (rawPitch + alignment - 1) & ~(alignment - 1); 188 } 189 190 GLsizei ComputeCompressedPitch(GLsizei width, GLenum format) 191 { 192 switch (format) 193 { 194 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 195 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 196 break; 197 default: 198 return 0; 199 } 200 201 ASSERT(width % 4 == 0); 202 203 return 8 * width / 4; 204 } 205 206 GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format) 207 { 208 switch (format) 209 { 210 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 211 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 212 break; 213 default: 214 return 0; 215 } 216 217 return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f); 218 } 219 220 bool IsCompressed(GLenum format) 221 { 222 if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || 223 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) 224 { 225 return true; 226 } 227 else 228 { 229 return false; 230 } 231 } 232 233 // Returns the size, in bytes, of a single texel in an Image 234 int ComputePixelSize(GLenum format, GLenum type) 235 { 236 switch (type) 237 { 238 case GL_UNSIGNED_BYTE: 239 switch (format) 240 { 241 case GL_ALPHA: return sizeof(unsigned char); 242 case GL_LUMINANCE: return sizeof(unsigned char); 243 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2; 244 case GL_RGB: return sizeof(unsigned char) * 3; 245 case GL_RGBA: return sizeof(unsigned char) * 4; 246 case GL_BGRA_EXT: return sizeof(unsigned char) * 4; 247 default: UNREACHABLE(); 248 } 249 break; 250 case GL_UNSIGNED_SHORT_4_4_4_4: 251 case GL_UNSIGNED_SHORT_5_5_5_1: 252 case GL_UNSIGNED_SHORT_5_6_5: 253 return sizeof(unsigned short); 254 case GL_FLOAT: 255 switch (format) 256 { 257 case GL_ALPHA: return sizeof(float); 258 case GL_LUMINANCE: return sizeof(float); 259 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2; 260 case GL_RGB: return sizeof(float) * 3; 261 case GL_RGBA: return sizeof(float) * 4; 262 default: UNREACHABLE(); 263 } 264 break; 265 case GL_HALF_FLOAT_OES: 266 switch (format) 267 { 268 case GL_ALPHA: return sizeof(unsigned short); 269 case GL_LUMINANCE: return sizeof(unsigned short); 270 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2; 271 case GL_RGB: return sizeof(unsigned short) * 3; 272 case GL_RGBA: return sizeof(unsigned short) * 4; 273 default: UNREACHABLE(); 274 } 275 break; 276 default: UNREACHABLE(); 277 } 278 279 return 0; 280 } 281 282 bool IsCubemapTextureTarget(GLenum target) 283 { 284 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); 285 } 286 287 bool IsTextureTarget(GLenum target) 288 { 289 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target); 290 } 291 292 // Verify that format/type are one of the combinations from table 3.4. 293 bool CheckTextureFormatType(GLenum format, GLenum type) 294 { 295 switch (type) 296 { 297 case GL_UNSIGNED_BYTE: 298 switch (format) 299 { 300 case GL_RGBA: 301 case GL_BGRA_EXT: 302 case GL_RGB: 303 case GL_ALPHA: 304 case GL_LUMINANCE: 305 case GL_LUMINANCE_ALPHA: 306 return true; 307 308 default: 309 return false; 310 } 311 312 case GL_FLOAT: 313 case GL_HALF_FLOAT_OES: 314 switch (format) 315 { 316 case GL_RGBA: 317 case GL_RGB: 318 case GL_ALPHA: 319 case GL_LUMINANCE: 320 case GL_LUMINANCE_ALPHA: 321 return true; 322 323 default: 324 return false; 325 } 326 327 case GL_UNSIGNED_SHORT_4_4_4_4: 328 case GL_UNSIGNED_SHORT_5_5_5_1: 329 return (format == GL_RGBA); 330 331 case GL_UNSIGNED_SHORT_5_6_5: 332 return (format == GL_RGB); 333 334 default: 335 return false; 336 } 337 } 338 339 bool IsColorRenderable(GLenum internalformat) 340 { 341 switch (internalformat) 342 { 343 case GL_RGBA4: 344 case GL_RGB5_A1: 345 case GL_RGB565: 346 case GL_RGB8_OES: 347 case GL_RGBA8_OES: 348 return true; 349 case GL_DEPTH_COMPONENT16: 350 case GL_STENCIL_INDEX8: 351 case GL_DEPTH24_STENCIL8_OES: 352 return false; 353 default: 354 UNIMPLEMENTED(); 355 } 356 357 return false; 358 } 359 360 bool IsDepthRenderable(GLenum internalformat) 361 { 362 switch (internalformat) 363 { 364 case GL_DEPTH_COMPONENT16: 365 case GL_DEPTH24_STENCIL8_OES: 366 return true; 367 case GL_STENCIL_INDEX8: 368 case GL_RGBA4: 369 case GL_RGB5_A1: 370 case GL_RGB565: 371 case GL_RGB8_OES: 372 case GL_RGBA8_OES: 373 return false; 374 default: 375 UNIMPLEMENTED(); 376 } 377 378 return false; 379 } 380 381 bool IsStencilRenderable(GLenum internalformat) 382 { 383 switch (internalformat) 384 { 385 case GL_STENCIL_INDEX8: 386 case GL_DEPTH24_STENCIL8_OES: 387 return true; 388 case GL_RGBA4: 389 case GL_RGB5_A1: 390 case GL_RGB565: 391 case GL_RGB8_OES: 392 case GL_RGBA8_OES: 393 case GL_DEPTH_COMPONENT16: 394 return false; 395 default: 396 UNIMPLEMENTED(); 397 } 398 399 return false; 400 } 401 402 } 403 404 namespace es2dx 405 { 406 407 D3DCMPFUNC ConvertComparison(GLenum comparison) 408 { 409 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; 410 switch (comparison) 411 { 412 case GL_NEVER: d3dComp = D3DCMP_NEVER; break; 413 case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; 414 case GL_LESS: d3dComp = D3DCMP_LESS; break; 415 case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; 416 case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; 417 case GL_GREATER: d3dComp = D3DCMP_GREATER; break; 418 case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; 419 case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; 420 default: UNREACHABLE(); 421 } 422 423 return d3dComp; 424 } 425 426 D3DCOLOR ConvertColor(gl::Color color) 427 { 428 return D3DCOLOR_RGBA(gl::unorm<8>(color.red), 429 gl::unorm<8>(color.green), 430 gl::unorm<8>(color.blue), 431 gl::unorm<8>(color.alpha)); 432 } 433 434 D3DBLEND ConvertBlendFunc(GLenum blend) 435 { 436 D3DBLEND d3dBlend = D3DBLEND_ZERO; 437 438 switch (blend) 439 { 440 case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; 441 case GL_ONE: d3dBlend = D3DBLEND_ONE; break; 442 case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; 443 case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; 444 case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; 445 case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; 446 case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; 447 case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; 448 case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; 449 case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; 450 case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; 451 case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; 452 case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; 453 case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; 454 case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; 455 default: UNREACHABLE(); 456 } 457 458 return d3dBlend; 459 } 460 461 D3DBLENDOP ConvertBlendOp(GLenum blendOp) 462 { 463 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; 464 465 switch (blendOp) 466 { 467 case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; 468 case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; 469 case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; 470 default: UNREACHABLE(); 471 } 472 473 return d3dBlendOp; 474 } 475 476 D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) 477 { 478 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; 479 480 switch (stencilOp) 481 { 482 case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; 483 case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; 484 case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; 485 case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; 486 case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; 487 case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; 488 case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; 489 case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; 490 default: UNREACHABLE(); 491 } 492 493 return d3dStencilOp; 494 } 495 496 D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) 497 { 498 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; 499 500 switch (wrap) 501 { 502 case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; 503 case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; 504 case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; 505 default: UNREACHABLE(); 506 } 507 508 return d3dWrap; 509 } 510 511 D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) 512 { 513 D3DCULL cull = D3DCULL_CCW; 514 switch (cullFace) 515 { 516 case GL_FRONT: 517 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); 518 break; 519 case GL_BACK: 520 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); 521 break; 522 case GL_FRONT_AND_BACK: 523 cull = D3DCULL_NONE; // culling will be handled during draw 524 break; 525 default: UNREACHABLE(); 526 } 527 528 return cull; 529 } 530 531 DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) 532 { 533 return (red ? D3DCOLORWRITEENABLE_RED : 0) | 534 (green ? D3DCOLORWRITEENABLE_GREEN : 0) | 535 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | 536 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); 537 } 538 539 D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter) 540 { 541 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; 542 switch (magFilter) 543 { 544 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; 545 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; 546 default: UNREACHABLE(); 547 } 548 549 return d3dMagFilter; 550 } 551 552 void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter) 553 { 554 switch (minFilter) 555 { 556 case GL_NEAREST: 557 *d3dMinFilter = D3DTEXF_POINT; 558 *d3dMipFilter = D3DTEXF_NONE; 559 break; 560 case GL_LINEAR: 561 *d3dMinFilter = D3DTEXF_LINEAR; 562 *d3dMipFilter = D3DTEXF_NONE; 563 break; 564 case GL_NEAREST_MIPMAP_NEAREST: 565 *d3dMinFilter = D3DTEXF_POINT; 566 *d3dMipFilter = D3DTEXF_POINT; 567 break; 568 case GL_LINEAR_MIPMAP_NEAREST: 569 *d3dMinFilter = D3DTEXF_LINEAR; 570 *d3dMipFilter = D3DTEXF_POINT; 571 break; 572 case GL_NEAREST_MIPMAP_LINEAR: 573 *d3dMinFilter = D3DTEXF_POINT; 574 *d3dMipFilter = D3DTEXF_LINEAR; 575 break; 576 case GL_LINEAR_MIPMAP_LINEAR: 577 *d3dMinFilter = D3DTEXF_LINEAR; 578 *d3dMipFilter = D3DTEXF_LINEAR; 579 break; 580 default: 581 *d3dMinFilter = D3DTEXF_POINT; 582 *d3dMipFilter = D3DTEXF_NONE; 583 UNREACHABLE(); 584 } 585 } 586 587 unsigned int GetStencilSize(D3DFORMAT stencilFormat) 588 { 589 switch(stencilFormat) 590 { 591 case D3DFMT_D24FS8: 592 case D3DFMT_D24S8: 593 return 8; 594 case D3DFMT_D24X4S4: 595 return 4; 596 case D3DFMT_D15S1: 597 return 1; 598 case D3DFMT_D16_LOCKABLE: 599 case D3DFMT_D32: 600 case D3DFMT_D24X8: 601 case D3DFMT_D32F_LOCKABLE: 602 case D3DFMT_D16: 603 return 0; 604 // case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only 605 // case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only 606 default: UNREACHABLE(); 607 } 608 return 0; 609 } 610 611 unsigned int GetAlphaSize(D3DFORMAT colorFormat) 612 { 613 switch (colorFormat) 614 { 615 case D3DFMT_A16B16G16R16F: 616 return 16; 617 case D3DFMT_A32B32G32R32F: 618 return 32; 619 case D3DFMT_A2R10G10B10: 620 return 2; 621 case D3DFMT_A8R8G8B8: 622 return 8; 623 case D3DFMT_A1R5G5B5: 624 return 1; 625 case D3DFMT_X8R8G8B8: 626 case D3DFMT_R5G6B5: 627 return 0; 628 default: UNREACHABLE(); 629 } 630 return 0; 631 } 632 633 unsigned int GetRedSize(D3DFORMAT colorFormat) 634 { 635 switch (colorFormat) 636 { 637 case D3DFMT_A16B16G16R16F: 638 return 16; 639 case D3DFMT_A32B32G32R32F: 640 return 32; 641 case D3DFMT_A2R10G10B10: 642 return 10; 643 case D3DFMT_A8R8G8B8: 644 case D3DFMT_X8R8G8B8: 645 return 8; 646 case D3DFMT_A1R5G5B5: 647 case D3DFMT_R5G6B5: 648 return 5; 649 default: UNREACHABLE(); 650 } 651 return 0; 652 } 653 654 unsigned int GetGreenSize(D3DFORMAT colorFormat) 655 { 656 switch (colorFormat) 657 { 658 case D3DFMT_A16B16G16R16F: 659 return 16; 660 case D3DFMT_A32B32G32R32F: 661 return 32; 662 case D3DFMT_A2R10G10B10: 663 return 10; 664 case D3DFMT_A8R8G8B8: 665 case D3DFMT_X8R8G8B8: 666 return 8; 667 case D3DFMT_A1R5G5B5: 668 return 5; 669 case D3DFMT_R5G6B5: 670 return 6; 671 default: UNREACHABLE(); 672 } 673 return 0; 674 } 675 676 unsigned int GetBlueSize(D3DFORMAT colorFormat) 677 { 678 switch (colorFormat) 679 { 680 case D3DFMT_A16B16G16R16F: 681 return 16; 682 case D3DFMT_A32B32G32R32F: 683 return 32; 684 case D3DFMT_A2R10G10B10: 685 return 10; 686 case D3DFMT_A8R8G8B8: 687 case D3DFMT_X8R8G8B8: 688 return 8; 689 case D3DFMT_A1R5G5B5: 690 case D3DFMT_R5G6B5: 691 return 5; 692 default: UNREACHABLE(); 693 } 694 return 0; 695 } 696 697 unsigned int GetDepthSize(D3DFORMAT depthFormat) 698 { 699 switch (depthFormat) 700 { 701 case D3DFMT_D16_LOCKABLE: return 16; 702 case D3DFMT_D32: return 32; 703 case D3DFMT_D15S1: return 15; 704 case D3DFMT_D24S8: return 24; 705 case D3DFMT_D24X8: return 24; 706 case D3DFMT_D24X4S4: return 24; 707 case D3DFMT_D16: return 16; 708 case D3DFMT_D32F_LOCKABLE: return 32; 709 case D3DFMT_D24FS8: return 24; 710 //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only 711 //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only 712 default: 713 UNREACHABLE(); 714 } 715 return 0; 716 } 717 718 bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, 719 D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount) 720 { 721 switch (primitiveType) 722 { 723 case GL_POINTS: 724 *d3dPrimitiveType = D3DPT_POINTLIST; 725 *d3dPrimitiveCount = elementCount; 726 break; 727 case GL_LINES: 728 *d3dPrimitiveType = D3DPT_LINELIST; 729 *d3dPrimitiveCount = elementCount / 2; 730 break; 731 case GL_LINE_LOOP: 732 *d3dPrimitiveType = D3DPT_LINESTRIP; 733 *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately 734 break; 735 case GL_LINE_STRIP: 736 *d3dPrimitiveType = D3DPT_LINESTRIP; 737 *d3dPrimitiveCount = elementCount - 1; 738 break; 739 case GL_TRIANGLES: 740 *d3dPrimitiveType = D3DPT_TRIANGLELIST; 741 *d3dPrimitiveCount = elementCount / 3; 742 break; 743 case GL_TRIANGLE_STRIP: 744 *d3dPrimitiveType = D3DPT_TRIANGLESTRIP; 745 *d3dPrimitiveCount = elementCount - 2; 746 break; 747 case GL_TRIANGLE_FAN: 748 *d3dPrimitiveType = D3DPT_TRIANGLEFAN; 749 *d3dPrimitiveCount = elementCount - 2; 750 break; 751 default: 752 return false; 753 } 754 755 return true; 756 } 757 758 D3DFORMAT ConvertRenderbufferFormat(GLenum format) 759 { 760 switch (format) 761 { 762 case GL_RGBA4: 763 case GL_RGB5_A1: 764 case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; 765 case GL_RGB565: return D3DFMT_R5G6B5; 766 case GL_RGB8_OES: return D3DFMT_X8R8G8B8; 767 case GL_DEPTH_COMPONENT16: 768 case GL_STENCIL_INDEX8: 769 case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; 770 default: UNREACHABLE(); return D3DFMT_A8R8G8B8; 771 } 772 } 773 774 GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) 775 { 776 if (type == D3DMULTISAMPLE_NONMASKABLE) 777 return 0; 778 else 779 return type; 780 } 781 782 D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) 783 { 784 if (samples <= 1) 785 return D3DMULTISAMPLE_NONE; 786 else 787 return (D3DMULTISAMPLE_TYPE)samples; 788 } 789 790 } 791 792 namespace dx2es 793 { 794 795 GLenum ConvertBackBufferFormat(D3DFORMAT format) 796 { 797 switch (format) 798 { 799 case D3DFMT_A4R4G4B4: return GL_RGBA4; 800 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; 801 case D3DFMT_A1R5G5B5: return GL_RGB5_A1; 802 case D3DFMT_R5G6B5: return GL_RGB565; 803 case D3DFMT_X8R8G8B8: return GL_RGB8_OES; 804 default: 805 UNREACHABLE(); 806 } 807 808 return GL_RGBA4; 809 } 810 811 GLenum ConvertDepthStencilFormat(D3DFORMAT format) 812 { 813 switch (format) 814 { 815 case D3DFMT_D16: 816 case D3DFMT_D24X8: 817 return GL_DEPTH_COMPONENT16; 818 case D3DFMT_D24S8: 819 return GL_DEPTH24_STENCIL8_OES; 820 default: 821 UNREACHABLE(); 822 } 823 824 return GL_DEPTH24_STENCIL8_OES; 825 } 826 827 } 828