1 // SwiftShader Software Renderer
\r
3 // Copyright(c) 2005-2013 TransGaming Inc.
\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
\r
6 // transcribed, stored in a retrieval system, translated into any human or computer
\r
7 // language by any means, or disclosed to third parties without the explicit written
\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
\r
9 // or implied, including but not limited to any patent rights, are granted to you.
\r
12 // utilities.cpp: Conversion functions and other utility routines.
\r
14 #include "utilities.h"
\r
16 #include "mathutil.h"
\r
17 #include "Context.h"
\r
18 #include "common/debug.h"
\r
25 int UniformComponentCount(GLenum type)
\r
33 case GL_SAMPLER_CUBE:
\r
34 case GL_SAMPLER_EXTERNAL_OES:
\r
35 case GL_SAMPLER_3D_OES:
\r
61 GLenum UniformComponentType(GLenum type)
\r
80 case GL_SAMPLER_CUBE:
\r
81 case GL_SAMPLER_EXTERNAL_OES:
\r
82 case GL_SAMPLER_3D_OES:
\r
94 size_t UniformTypeSize(GLenum type)
\r
98 case GL_BOOL: return sizeof(GLboolean);
\r
99 case GL_FLOAT: return sizeof(GLfloat);
\r
100 case GL_INT: return sizeof(GLint);
\r
103 return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
\r
106 int VariableRowCount(GLenum type)
\r
116 case GL_FLOAT_VEC2:
\r
119 case GL_FLOAT_VEC3:
\r
122 case GL_FLOAT_VEC4:
\r
124 case GL_SAMPLER_2D:
\r
125 case GL_SAMPLER_CUBE:
\r
126 case GL_SAMPLER_EXTERNAL_OES:
\r
127 case GL_SAMPLER_3D_OES:
\r
129 case GL_FLOAT_MAT2:
\r
131 case GL_FLOAT_MAT3:
\r
133 case GL_FLOAT_MAT4:
\r
142 int VariableColumnCount(GLenum type)
\r
153 case GL_FLOAT_VEC2:
\r
155 case GL_FLOAT_MAT2:
\r
158 case GL_FLOAT_VEC3:
\r
160 case GL_FLOAT_MAT3:
\r
163 case GL_FLOAT_VEC4:
\r
165 case GL_FLOAT_MAT4:
\r
174 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
\r
176 ASSERT(allocationSize <= bitsSize);
\r
178 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
\r
180 for(unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
\r
182 if((*bits & mask) == 0)
\r
194 GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
\r
196 ASSERT(alignment > 0 && isPow2(alignment));
\r
198 GLsizei rawPitch = ComputePixelSize(format, type) * width;
\r
199 return (rawPitch + alignment - 1) & ~(alignment - 1);
\r
202 GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
\r
204 return ComputeCompressedSize(width, 1, format);
\r
207 GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
\r
211 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
\r
212 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
\r
213 case GL_ETC1_RGB8_OES:
\r
214 return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
\r
215 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
\r
216 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
\r
217 return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
\r
223 bool IsCompressed(GLenum format)
\r
225 return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
\r
226 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
\r
227 format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
\r
228 format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE ||
\r
229 format == GL_ETC1_RGB8_OES;
\r
232 bool IsDepthTexture(GLenum format)
\r
234 return format == GL_DEPTH_COMPONENT ||
\r
235 format == GL_DEPTH_STENCIL_OES;
\r
238 bool IsStencilTexture(GLenum format)
\r
240 return format == GL_STENCIL_INDEX_OES ||
\r
241 format == GL_DEPTH_STENCIL_OES;
\r
244 // Returns the size, in bytes, of a single texel in an Image
\r
245 int ComputePixelSize(GLenum format, GLenum type)
\r
249 case GL_UNSIGNED_BYTE:
\r
252 case GL_ALPHA: return sizeof(unsigned char);
\r
253 case GL_LUMINANCE: return sizeof(unsigned char);
\r
254 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
\r
255 case GL_RGB: return sizeof(unsigned char) * 3;
\r
256 case GL_RGBA: return sizeof(unsigned char) * 4;
\r
257 case GL_BGRA_EXT: return sizeof(unsigned char) * 4;
\r
258 default: UNREACHABLE();
\r
261 case GL_UNSIGNED_SHORT_4_4_4_4:
\r
262 case GL_UNSIGNED_SHORT_5_5_5_1:
\r
263 case GL_UNSIGNED_SHORT_5_6_5:
\r
264 case GL_UNSIGNED_SHORT:
\r
265 return sizeof(unsigned short);
\r
266 case GL_UNSIGNED_INT:
\r
267 case GL_UNSIGNED_INT_24_8_OES:
\r
268 return sizeof(unsigned int);
\r
272 case GL_ALPHA: return sizeof(float);
\r
273 case GL_LUMINANCE: return sizeof(float);
\r
274 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
\r
275 case GL_RGB: return sizeof(float) * 3;
\r
276 case GL_RGBA: return sizeof(float) * 4;
\r
277 default: UNREACHABLE();
\r
280 case GL_HALF_FLOAT_OES:
\r
283 case GL_ALPHA: return sizeof(unsigned short);
\r
284 case GL_LUMINANCE: return sizeof(unsigned short);
\r
285 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
\r
286 case GL_RGB: return sizeof(unsigned short) * 3;
\r
287 case GL_RGBA: return sizeof(unsigned short) * 4;
\r
288 default: UNREACHABLE();
\r
291 default: UNREACHABLE();
\r
297 bool IsCubemapTextureTarget(GLenum target)
\r
299 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
\r
302 int CubeFaceIndex(GLenum cubeFace)
\r
306 case GL_TEXTURE_CUBE_MAP:
\r
307 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;
\r
308 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;
\r
309 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;
\r
310 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;
\r
311 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;
\r
312 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;
\r
313 default: UNREACHABLE(); return 0;
\r
317 bool IsTextureTarget(GLenum target)
\r
319 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
\r
322 // Verify that format/type are one of the combinations from table 3.4.
\r
323 bool CheckTextureFormatType(GLenum format, GLenum type)
\r
327 case GL_UNSIGNED_BYTE:
\r
335 case GL_LUMINANCE_ALPHA:
\r
341 case GL_HALF_FLOAT_OES:
\r
348 case GL_LUMINANCE_ALPHA:
\r
353 case GL_UNSIGNED_SHORT_4_4_4_4:
\r
354 case GL_UNSIGNED_SHORT_5_5_5_1:
\r
355 return (format == GL_RGBA);
\r
356 case GL_UNSIGNED_SHORT_5_6_5:
\r
357 return (format == GL_RGB);
\r
358 case GL_UNSIGNED_INT:
\r
359 return (format == GL_DEPTH_COMPONENT);
\r
360 case GL_UNSIGNED_INT_24_8_OES:
\r
361 return (format == GL_DEPTH_STENCIL_OES);
\r
367 bool IsColorRenderable(GLenum internalformat)
\r
369 switch(internalformat)
\r
377 case GL_DEPTH_COMPONENT16:
\r
378 case GL_STENCIL_INDEX8:
\r
379 case GL_DEPTH24_STENCIL8_OES:
\r
388 bool IsDepthRenderable(GLenum internalformat)
\r
390 switch(internalformat)
\r
392 case GL_DEPTH_COMPONENT16:
\r
393 case GL_DEPTH24_STENCIL8_OES:
\r
395 case GL_STENCIL_INDEX8:
\r
409 bool IsStencilRenderable(GLenum internalformat)
\r
411 switch(internalformat)
\r
413 case GL_STENCIL_INDEX8:
\r
414 case GL_DEPTH24_STENCIL8_OES:
\r
421 case GL_DEPTH_COMPONENT16:
\r
433 sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
\r
437 case GL_NEVER: return sw::DEPTH_NEVER;
\r
438 case GL_ALWAYS: return sw::DEPTH_ALWAYS;
\r
439 case GL_LESS: return sw::DEPTH_LESS;
\r
440 case GL_LEQUAL: return sw::DEPTH_LESSEQUAL;
\r
441 case GL_EQUAL: return sw::DEPTH_EQUAL;
\r
442 case GL_GREATER: return sw::DEPTH_GREATER;
\r
443 case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL;
\r
444 case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
\r
445 default: UNREACHABLE();
\r
448 return sw::DEPTH_ALWAYS;
\r
451 sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
\r
455 case GL_NEVER: return sw::STENCIL_NEVER;
\r
456 case GL_ALWAYS: return sw::STENCIL_ALWAYS;
\r
457 case GL_LESS: return sw::STENCIL_LESS;
\r
458 case GL_LEQUAL: return sw::STENCIL_LESSEQUAL;
\r
459 case GL_EQUAL: return sw::STENCIL_EQUAL;
\r
460 case GL_GREATER: return sw::STENCIL_GREATER;
\r
461 case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL;
\r
462 case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
\r
463 default: UNREACHABLE();
\r
466 return sw::STENCIL_ALWAYS;
\r
469 sw::Color<float> ConvertColor(es2::Color color)
\r
471 return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
\r
474 sw::BlendFactor ConvertBlendFunc(GLenum blend)
\r
478 case GL_ZERO: return sw::BLEND_ZERO;
\r
479 case GL_ONE: return sw::BLEND_ONE;
\r
480 case GL_SRC_COLOR: return sw::BLEND_SOURCE;
\r
481 case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE;
\r
482 case GL_DST_COLOR: return sw::BLEND_DEST;
\r
483 case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST;
\r
484 case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA;
\r
485 case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA;
\r
486 case GL_DST_ALPHA: return sw::BLEND_DESTALPHA;
\r
487 case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA;
\r
488 case GL_CONSTANT_COLOR: return sw::BLEND_CONSTANT;
\r
489 case GL_ONE_MINUS_CONSTANT_COLOR: return sw::BLEND_INVCONSTANT;
\r
490 case GL_CONSTANT_ALPHA: return sw::BLEND_CONSTANTALPHA;
\r
491 case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::BLEND_INVCONSTANTALPHA;
\r
492 case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT;
\r
493 default: UNREACHABLE();
\r
496 return sw::BLEND_ZERO;
\r
499 sw::BlendOperation ConvertBlendOp(GLenum blendOp)
\r
503 case GL_FUNC_ADD: return sw::BLENDOP_ADD;
\r
504 case GL_FUNC_SUBTRACT: return sw::BLENDOP_SUB;
\r
505 case GL_FUNC_REVERSE_SUBTRACT: return sw::BLENDOP_INVSUB;
\r
506 case GL_MIN_EXT: return sw::BLENDOP_MIN;
\r
507 case GL_MAX_EXT: return sw::BLENDOP_MAX;
\r
508 default: UNREACHABLE();
\r
511 return sw::BLENDOP_ADD;
\r
514 sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
\r
518 case GL_ZERO: return sw::OPERATION_ZERO;
\r
519 case GL_KEEP: return sw::OPERATION_KEEP;
\r
520 case GL_REPLACE: return sw::OPERATION_REPLACE;
\r
521 case GL_INCR: return sw::OPERATION_INCRSAT;
\r
522 case GL_DECR: return sw::OPERATION_DECRSAT;
\r
523 case GL_INVERT: return sw::OPERATION_INVERT;
\r
524 case GL_INCR_WRAP: return sw::OPERATION_INCR;
\r
525 case GL_DECR_WRAP: return sw::OPERATION_DECR;
\r
526 default: UNREACHABLE();
\r
529 return sw::OPERATION_KEEP;
\r
532 sw::AddressingMode ConvertTextureWrap(GLenum wrap)
\r
536 case GL_REPEAT: return sw::ADDRESSING_WRAP;
\r
537 case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP;
\r
538 case GL_MIRRORED_REPEAT: return sw::ADDRESSING_MIRROR;
\r
539 default: UNREACHABLE();
\r
542 return sw::ADDRESSING_WRAP;
\r
545 sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
\r
550 return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
\r
552 return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
\r
553 case GL_FRONT_AND_BACK:
\r
554 return sw::CULL_NONE; // culling will be handled during draw
\r
555 default: UNREACHABLE();
\r
558 return sw::CULL_COUNTERCLOCKWISE;
\r
561 unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
\r
563 return (red ? 0x00000001 : 0) |
\r
564 (green ? 0x00000002 : 0) |
\r
565 (blue ? 0x00000004 : 0) |
\r
566 (alpha ? 0x00000008 : 0);
\r
569 sw::FilterType ConvertMagFilter(GLenum magFilter)
\r
573 case GL_NEAREST: return sw::FILTER_POINT;
\r
574 case GL_LINEAR: return sw::FILTER_LINEAR;
\r
575 default: UNREACHABLE();
\r
578 return sw::FILTER_POINT;
\r
581 void ConvertMinFilter(GLenum texFilter, sw::FilterType *minFilter, sw::MipmapType *mipFilter, float maxAnisotropy)
\r
586 *minFilter = sw::FILTER_POINT;
\r
587 *mipFilter = sw::MIPMAP_NONE;
\r
590 *minFilter = sw::FILTER_LINEAR;
\r
591 *mipFilter = sw::MIPMAP_NONE;
\r
593 case GL_NEAREST_MIPMAP_NEAREST:
\r
594 *minFilter = sw::FILTER_POINT;
\r
595 *mipFilter = sw::MIPMAP_POINT;
\r
597 case GL_LINEAR_MIPMAP_NEAREST:
\r
598 *minFilter = sw::FILTER_LINEAR;
\r
599 *mipFilter = sw::MIPMAP_POINT;
\r
601 case GL_NEAREST_MIPMAP_LINEAR:
\r
602 *minFilter = sw::FILTER_POINT;
\r
603 *mipFilter = sw::MIPMAP_LINEAR;
\r
605 case GL_LINEAR_MIPMAP_LINEAR:
\r
606 *minFilter = sw::FILTER_LINEAR;
\r
607 *mipFilter = sw::MIPMAP_LINEAR;
\r
610 *minFilter = sw::FILTER_POINT;
\r
611 *mipFilter = sw::MIPMAP_NONE;
\r
615 if(maxAnisotropy > 1.0f)
\r
617 *minFilter = sw::FILTER_ANISOTROPIC;
\r
621 bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, es2::PrimitiveType &swPrimitiveType, int &primitiveCount)
\r
623 switch(primitiveType)
\r
626 swPrimitiveType = es2::DRAW_POINTLIST;
\r
627 primitiveCount = elementCount;
\r
630 swPrimitiveType = es2::DRAW_LINELIST;
\r
631 primitiveCount = elementCount / 2;
\r
634 swPrimitiveType = es2::DRAW_LINELOOP;
\r
635 primitiveCount = elementCount;
\r
637 case GL_LINE_STRIP:
\r
638 swPrimitiveType = es2::DRAW_LINESTRIP;
\r
639 primitiveCount = elementCount - 1;
\r
642 swPrimitiveType = es2::DRAW_TRIANGLELIST;
\r
643 primitiveCount = elementCount / 3;
\r
645 case GL_TRIANGLE_STRIP:
\r
646 swPrimitiveType = es2::DRAW_TRIANGLESTRIP;
\r
647 primitiveCount = elementCount - 2;
\r
649 case GL_TRIANGLE_FAN:
\r
650 swPrimitiveType = es2::DRAW_TRIANGLEFAN;
\r
651 primitiveCount = elementCount - 2;
\r
660 sw::Format ConvertRenderbufferFormat(GLenum format)
\r
666 case GL_RGBA8_OES: return sw::FORMAT_A8R8G8B8;
\r
667 case GL_RGB565: return sw::FORMAT_R5G6B5;
\r
668 case GL_RGB8_OES: return sw::FORMAT_X8R8G8B8;
\r
669 case GL_DEPTH_COMPONENT16:
\r
670 case GL_STENCIL_INDEX8:
\r
671 case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;
\r
672 default: UNREACHABLE(); return sw::FORMAT_A8R8G8B8;
\r
679 unsigned int GetStencilSize(sw::Format stencilFormat)
\r
681 switch(stencilFormat)
\r
683 case sw::FORMAT_D24FS8:
\r
684 case sw::FORMAT_D24S8:
\r
685 case sw::FORMAT_D32FS8_TEXTURE:
\r
687 // case sw::FORMAT_D24X4S4:
\r
689 // case sw::FORMAT_D15S1:
\r
691 // case sw::FORMAT_D16_LOCKABLE:
\r
692 case sw::FORMAT_D32:
\r
693 case sw::FORMAT_D24X8:
\r
694 case sw::FORMAT_D32F_LOCKABLE:
\r
695 case sw::FORMAT_D16:
\r
697 // case sw::FORMAT_D32_LOCKABLE: return 0;
\r
698 // case sw::FORMAT_S8_LOCKABLE: return 8;
\r
704 unsigned int GetAlphaSize(sw::Format colorFormat)
\r
706 switch(colorFormat)
\r
708 case sw::FORMAT_A16B16G16R16F:
\r
710 case sw::FORMAT_A32B32G32R32F:
\r
712 case sw::FORMAT_A2R10G10B10:
\r
714 case sw::FORMAT_A8R8G8B8:
\r
716 case sw::FORMAT_A1R5G5B5:
\r
718 case sw::FORMAT_X8R8G8B8:
\r
719 case sw::FORMAT_R5G6B5:
\r
726 unsigned int GetRedSize(sw::Format colorFormat)
\r
728 switch(colorFormat)
\r
730 case sw::FORMAT_A16B16G16R16F:
\r
732 case sw::FORMAT_A32B32G32R32F:
\r
734 case sw::FORMAT_A2R10G10B10:
\r
736 case sw::FORMAT_A8R8G8B8:
\r
737 case sw::FORMAT_X8R8G8B8:
\r
739 case sw::FORMAT_A1R5G5B5:
\r
740 case sw::FORMAT_R5G6B5:
\r
747 unsigned int GetGreenSize(sw::Format colorFormat)
\r
749 switch(colorFormat)
\r
751 case sw::FORMAT_A16B16G16R16F:
\r
753 case sw::FORMAT_A32B32G32R32F:
\r
755 case sw::FORMAT_A2R10G10B10:
\r
757 case sw::FORMAT_A8R8G8B8:
\r
758 case sw::FORMAT_X8R8G8B8:
\r
760 case sw::FORMAT_A1R5G5B5:
\r
762 case sw::FORMAT_R5G6B5:
\r
769 unsigned int GetBlueSize(sw::Format colorFormat)
\r
771 switch(colorFormat)
\r
773 case sw::FORMAT_A16B16G16R16F:
\r
775 case sw::FORMAT_A32B32G32R32F:
\r
777 case sw::FORMAT_A2R10G10B10:
\r
779 case sw::FORMAT_A8R8G8B8:
\r
780 case sw::FORMAT_X8R8G8B8:
\r
782 case sw::FORMAT_A1R5G5B5:
\r
783 case sw::FORMAT_R5G6B5:
\r
790 unsigned int GetDepthSize(sw::Format depthFormat)
\r
792 switch(depthFormat)
\r
794 // case sw::FORMAT_D16_LOCKABLE: return 16;
\r
795 case sw::FORMAT_D32: return 32;
\r
796 // case sw::FORMAT_D15S1: return 15;
\r
797 case sw::FORMAT_D24S8: return 24;
\r
798 case sw::FORMAT_D24X8: return 24;
\r
799 // case sw::FORMAT_D24X4S4: return 24;
\r
800 case sw::FORMAT_D16: return 16;
\r
801 case sw::FORMAT_D32F_LOCKABLE: return 32;
\r
802 case sw::FORMAT_D24FS8: return 24;
\r
803 // case sw::FORMAT_D32_LOCKABLE: return 32;
\r
804 // case sw::FORMAT_S8_LOCKABLE: return 0;
\r
805 case sw::FORMAT_D32FS8_TEXTURE: return 32;
\r
810 GLenum ConvertBackBufferFormat(sw::Format format)
\r
814 case sw::FORMAT_A4R4G4B4: return GL_RGBA4;
\r
815 case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
\r
816 case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;
\r
817 case sw::FORMAT_R5G6B5: return GL_RGB565;
\r
818 case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
\r
826 GLenum ConvertDepthStencilFormat(sw::Format format)
\r
830 case sw::FORMAT_D16:
\r
831 case sw::FORMAT_D24X8:
\r
832 case sw::FORMAT_D32:
\r
833 return GL_DEPTH_COMPONENT16;
\r
834 case sw::FORMAT_D24S8:
\r
835 return GL_DEPTH24_STENCIL8_OES;
\r
840 return GL_DEPTH24_STENCIL8_OES;
\r