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
60 GLenum UniformComponentType(GLenum type)
\r
79 case GL_SAMPLER_CUBE:
\r
80 case GL_SAMPLER_EXTERNAL_OES:
\r
92 size_t UniformTypeSize(GLenum type)
\r
96 case GL_BOOL: return sizeof(GLboolean);
\r
97 case GL_FLOAT: return sizeof(GLfloat);
\r
98 case GL_INT: return sizeof(GLint);
\r
101 return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
\r
104 int VariableRowCount(GLenum type)
\r
114 case GL_FLOAT_VEC2:
\r
117 case GL_FLOAT_VEC3:
\r
120 case GL_FLOAT_VEC4:
\r
122 case GL_SAMPLER_2D:
\r
123 case GL_SAMPLER_CUBE:
\r
124 case GL_SAMPLER_EXTERNAL_OES:
\r
126 case GL_FLOAT_MAT2:
\r
128 case GL_FLOAT_MAT3:
\r
130 case GL_FLOAT_MAT4:
\r
139 int VariableColumnCount(GLenum type)
\r
150 case GL_FLOAT_VEC2:
\r
152 case GL_FLOAT_MAT2:
\r
155 case GL_FLOAT_VEC3:
\r
157 case GL_FLOAT_MAT3:
\r
160 case GL_FLOAT_VEC4:
\r
162 case GL_FLOAT_MAT4:
\r
171 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
\r
173 ASSERT(allocationSize <= bitsSize);
\r
175 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
\r
177 for(unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
\r
179 if((*bits & mask) == 0)
\r
191 GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
\r
193 ASSERT(alignment > 0 && isPow2(alignment));
\r
195 GLsizei rawPitch = ComputePixelSize(format, type) * width;
\r
196 return (rawPitch + alignment - 1) & ~(alignment - 1);
\r
199 GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
\r
201 return ComputeCompressedSize(width, 1, format);
\r
204 GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
\r
208 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
\r
209 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
\r
210 return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
\r
211 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
\r
212 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
\r
213 return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
\r
219 bool IsCompressed(GLenum format)
\r
221 if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
\r
222 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
\r
223 format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
\r
224 format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
\r
234 bool IsDepthTexture(GLenum format)
\r
236 if(format == GL_DEPTH_COMPONENT ||
\r
237 format == GL_DEPTH_STENCIL_OES)
\r
245 bool IsStencilTexture(GLenum format)
\r
247 if(format == GL_STENCIL_INDEX_OES ||
\r
248 format == GL_DEPTH_STENCIL_OES)
\r
256 // Returns the size, in bytes, of a single texel in an Image
\r
257 int ComputePixelSize(GLenum format, GLenum type)
\r
261 case GL_UNSIGNED_BYTE:
\r
264 case GL_ALPHA: return sizeof(unsigned char);
\r
265 case GL_LUMINANCE: return sizeof(unsigned char);
\r
266 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
\r
267 case GL_RGB: return sizeof(unsigned char) * 3;
\r
268 case GL_RGBA: return sizeof(unsigned char) * 4;
\r
269 case GL_BGRA_EXT: return sizeof(unsigned char) * 4;
\r
270 default: UNREACHABLE();
\r
273 case GL_UNSIGNED_SHORT_4_4_4_4:
\r
274 case GL_UNSIGNED_SHORT_5_5_5_1:
\r
275 case GL_UNSIGNED_SHORT_5_6_5:
\r
276 case GL_UNSIGNED_SHORT:
\r
277 return sizeof(unsigned short);
\r
278 case GL_UNSIGNED_INT:
\r
279 case GL_UNSIGNED_INT_24_8_OES:
\r
280 return sizeof(unsigned int);
\r
284 case GL_ALPHA: return sizeof(float);
\r
285 case GL_LUMINANCE: return sizeof(float);
\r
286 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
\r
287 case GL_RGB: return sizeof(float) * 3;
\r
288 case GL_RGBA: return sizeof(float) * 4;
\r
289 default: UNREACHABLE();
\r
292 case GL_HALF_FLOAT_OES:
\r
295 case GL_ALPHA: return sizeof(unsigned short);
\r
296 case GL_LUMINANCE: return sizeof(unsigned short);
\r
297 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
\r
298 case GL_RGB: return sizeof(unsigned short) * 3;
\r
299 case GL_RGBA: return sizeof(unsigned short) * 4;
\r
300 default: UNREACHABLE();
\r
303 default: UNREACHABLE();
\r
309 bool IsCubemapTextureTarget(GLenum target)
\r
311 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
\r
314 int CubeFaceIndex(GLenum cubeFace)
\r
318 case GL_TEXTURE_CUBE_MAP:
\r
319 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;
\r
320 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;
\r
321 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;
\r
322 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;
\r
323 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;
\r
324 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;
\r
325 default: UNREACHABLE(); return 0;
\r
329 bool IsTextureTarget(GLenum target)
\r
331 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
\r
334 // Verify that format/type are one of the combinations from table 3.4.
\r
335 bool CheckTextureFormatType(GLenum format, GLenum type)
\r
339 case GL_UNSIGNED_BYTE:
\r
347 case GL_LUMINANCE_ALPHA:
\r
353 case GL_HALF_FLOAT_OES:
\r
360 case GL_LUMINANCE_ALPHA:
\r
365 case GL_UNSIGNED_SHORT_4_4_4_4:
\r
366 case GL_UNSIGNED_SHORT_5_5_5_1:
\r
367 return (format == GL_RGBA);
\r
368 case GL_UNSIGNED_SHORT_5_6_5:
\r
369 return (format == GL_RGB);
\r
370 case GL_UNSIGNED_INT:
\r
371 return (format == GL_DEPTH_COMPONENT);
\r
372 case GL_UNSIGNED_INT_24_8_OES:
\r
373 return (format == GL_DEPTH_STENCIL_OES);
\r
379 bool IsColorRenderable(GLenum internalformat)
\r
381 switch(internalformat)
\r
389 case GL_DEPTH_COMPONENT16:
\r
390 case GL_STENCIL_INDEX8:
\r
391 case GL_DEPTH24_STENCIL8_OES:
\r
400 bool IsDepthRenderable(GLenum internalformat)
\r
402 switch(internalformat)
\r
404 case GL_DEPTH_COMPONENT16:
\r
405 case GL_DEPTH24_STENCIL8_OES:
\r
407 case GL_STENCIL_INDEX8:
\r
421 bool IsStencilRenderable(GLenum internalformat)
\r
423 switch(internalformat)
\r
425 case GL_STENCIL_INDEX8:
\r
426 case GL_DEPTH24_STENCIL8_OES:
\r
433 case GL_DEPTH_COMPONENT16:
\r
445 sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
\r
449 case GL_NEVER: return sw::DEPTH_NEVER;
\r
450 case GL_ALWAYS: return sw::DEPTH_ALWAYS;
\r
451 case GL_LESS: return sw::DEPTH_LESS;
\r
452 case GL_LEQUAL: return sw::DEPTH_LESSEQUAL;
\r
453 case GL_EQUAL: return sw::DEPTH_EQUAL;
\r
454 case GL_GREATER: return sw::DEPTH_GREATER;
\r
455 case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL;
\r
456 case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
\r
457 default: UNREACHABLE();
\r
460 return sw::DEPTH_ALWAYS;
\r
463 sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
\r
467 case GL_NEVER: return sw::STENCIL_NEVER;
\r
468 case GL_ALWAYS: return sw::STENCIL_ALWAYS;
\r
469 case GL_LESS: return sw::STENCIL_LESS;
\r
470 case GL_LEQUAL: return sw::STENCIL_LESSEQUAL;
\r
471 case GL_EQUAL: return sw::STENCIL_EQUAL;
\r
472 case GL_GREATER: return sw::STENCIL_GREATER;
\r
473 case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL;
\r
474 case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
\r
475 default: UNREACHABLE();
\r
478 return sw::STENCIL_ALWAYS;
\r
481 sw::Color<float> ConvertColor(es2::Color color)
\r
483 return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
\r
486 sw::BlendFactor ConvertBlendFunc(GLenum blend)
\r
490 case GL_ZERO: return sw::BLEND_ZERO;
\r
491 case GL_ONE: return sw::BLEND_ONE;
\r
492 case GL_SRC_COLOR: return sw::BLEND_SOURCE;
\r
493 case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE;
\r
494 case GL_DST_COLOR: return sw::BLEND_DEST;
\r
495 case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST;
\r
496 case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA;
\r
497 case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA;
\r
498 case GL_DST_ALPHA: return sw::BLEND_DESTALPHA;
\r
499 case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA;
\r
500 case GL_CONSTANT_COLOR: return sw::BLEND_CONSTANT;
\r
501 case GL_ONE_MINUS_CONSTANT_COLOR: return sw::BLEND_INVCONSTANT;
\r
502 case GL_CONSTANT_ALPHA: return sw::BLEND_CONSTANTALPHA;
\r
503 case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::BLEND_INVCONSTANTALPHA;
\r
504 case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT;
\r
505 default: UNREACHABLE();
\r
508 return sw::BLEND_ZERO;
\r
511 sw::BlendOperation ConvertBlendOp(GLenum blendOp)
\r
515 case GL_FUNC_ADD: return sw::BLENDOP_ADD;
\r
516 case GL_FUNC_SUBTRACT: return sw::BLENDOP_SUB;
\r
517 case GL_FUNC_REVERSE_SUBTRACT: return sw::BLENDOP_INVSUB;
\r
518 case GL_MIN_EXT: return sw::BLENDOP_MIN;
\r
519 case GL_MAX_EXT: return sw::BLENDOP_MAX;
\r
520 default: UNREACHABLE();
\r
523 return sw::BLENDOP_ADD;
\r
526 sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
\r
530 case GL_ZERO: return sw::OPERATION_ZERO;
\r
531 case GL_KEEP: return sw::OPERATION_KEEP;
\r
532 case GL_REPLACE: return sw::OPERATION_REPLACE;
\r
533 case GL_INCR: return sw::OPERATION_INCRSAT;
\r
534 case GL_DECR: return sw::OPERATION_DECRSAT;
\r
535 case GL_INVERT: return sw::OPERATION_INVERT;
\r
536 case GL_INCR_WRAP: return sw::OPERATION_INCR;
\r
537 case GL_DECR_WRAP: return sw::OPERATION_DECR;
\r
538 default: UNREACHABLE();
\r
541 return sw::OPERATION_KEEP;
\r
544 sw::AddressingMode ConvertTextureWrap(GLenum wrap)
\r
548 case GL_REPEAT: return sw::ADDRESSING_WRAP;
\r
549 case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP;
\r
550 case GL_MIRRORED_REPEAT: return sw::ADDRESSING_MIRROR;
\r
551 default: UNREACHABLE();
\r
554 return sw::ADDRESSING_WRAP;
\r
557 sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
\r
562 return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
\r
564 return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
\r
565 case GL_FRONT_AND_BACK:
\r
566 return sw::CULL_NONE; // culling will be handled during draw
\r
567 default: UNREACHABLE();
\r
570 return sw::CULL_COUNTERCLOCKWISE;
\r
573 unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
\r
575 return (red ? 0x00000001 : 0) |
\r
576 (green ? 0x00000002 : 0) |
\r
577 (blue ? 0x00000004 : 0) |
\r
578 (alpha ? 0x00000008 : 0);
\r
581 sw::FilterType ConvertMagFilter(GLenum magFilter)
\r
585 case GL_NEAREST: return sw::FILTER_POINT;
\r
586 case GL_LINEAR: return sw::FILTER_LINEAR;
\r
587 default: UNREACHABLE();
\r
590 return sw::FILTER_POINT;
\r
593 void ConvertMinFilter(GLenum texFilter, sw::FilterType *minFilter, sw::MipmapType *mipFilter, float maxAnisotropy)
\r
598 *minFilter = sw::FILTER_POINT;
\r
599 *mipFilter = sw::MIPMAP_NONE;
\r
602 *minFilter = sw::FILTER_LINEAR;
\r
603 *mipFilter = sw::MIPMAP_NONE;
\r
605 case GL_NEAREST_MIPMAP_NEAREST:
\r
606 *minFilter = sw::FILTER_POINT;
\r
607 *mipFilter = sw::MIPMAP_POINT;
\r
609 case GL_LINEAR_MIPMAP_NEAREST:
\r
610 *minFilter = sw::FILTER_LINEAR;
\r
611 *mipFilter = sw::MIPMAP_POINT;
\r
613 case GL_NEAREST_MIPMAP_LINEAR:
\r
614 *minFilter = sw::FILTER_POINT;
\r
615 *mipFilter = sw::MIPMAP_LINEAR;
\r
617 case GL_LINEAR_MIPMAP_LINEAR:
\r
618 *minFilter = sw::FILTER_LINEAR;
\r
619 *mipFilter = sw::MIPMAP_LINEAR;
\r
622 *minFilter = sw::FILTER_POINT;
\r
623 *mipFilter = sw::MIPMAP_NONE;
\r
627 if(maxAnisotropy > 1.0f)
\r
629 *minFilter = sw::FILTER_ANISOTROPIC;
\r
633 bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, es2::PrimitiveType &swPrimitiveType, int &primitiveCount)
\r
635 switch(primitiveType)
\r
638 swPrimitiveType = es2::DRAW_POINTLIST;
\r
639 primitiveCount = elementCount;
\r
642 swPrimitiveType = es2::DRAW_LINELIST;
\r
643 primitiveCount = elementCount / 2;
\r
646 swPrimitiveType = es2::DRAW_LINELOOP;
\r
647 primitiveCount = elementCount;
\r
649 case GL_LINE_STRIP:
\r
650 swPrimitiveType = es2::DRAW_LINESTRIP;
\r
651 primitiveCount = elementCount - 1;
\r
654 swPrimitiveType = es2::DRAW_TRIANGLELIST;
\r
655 primitiveCount = elementCount / 3;
\r
657 case GL_TRIANGLE_STRIP:
\r
658 swPrimitiveType = es2::DRAW_TRIANGLESTRIP;
\r
659 primitiveCount = elementCount - 2;
\r
661 case GL_TRIANGLE_FAN:
\r
662 swPrimitiveType = es2::DRAW_TRIANGLEFAN;
\r
663 primitiveCount = elementCount - 2;
\r
672 sw::Format ConvertRenderbufferFormat(GLenum format)
\r
678 case GL_RGBA8_OES: return sw::FORMAT_A8R8G8B8;
\r
679 case GL_RGB565: return sw::FORMAT_R5G6B5;
\r
680 case GL_RGB8_OES: return sw::FORMAT_X8R8G8B8;
\r
681 case GL_DEPTH_COMPONENT16:
\r
682 case GL_STENCIL_INDEX8:
\r
683 case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;
\r
684 default: UNREACHABLE(); return sw::FORMAT_A8R8G8B8;
\r
691 unsigned int GetStencilSize(sw::Format stencilFormat)
\r
693 switch(stencilFormat)
\r
695 case sw::FORMAT_D24FS8:
\r
696 case sw::FORMAT_D24S8:
\r
697 case sw::FORMAT_D32FS8_TEXTURE:
\r
699 // case sw::FORMAT_D24X4S4:
\r
701 // case sw::FORMAT_D15S1:
\r
703 // case sw::FORMAT_D16_LOCKABLE:
\r
704 case sw::FORMAT_D32:
\r
705 case sw::FORMAT_D24X8:
\r
706 case sw::FORMAT_D32F_LOCKABLE:
\r
707 case sw::FORMAT_D16:
\r
709 // case sw::FORMAT_D32_LOCKABLE: return 0;
\r
710 // case sw::FORMAT_S8_LOCKABLE: return 8;
\r
716 unsigned int GetAlphaSize(sw::Format colorFormat)
\r
718 switch(colorFormat)
\r
720 case sw::FORMAT_A16B16G16R16F:
\r
722 case sw::FORMAT_A32B32G32R32F:
\r
724 case sw::FORMAT_A2R10G10B10:
\r
726 case sw::FORMAT_A8R8G8B8:
\r
728 case sw::FORMAT_A1R5G5B5:
\r
730 case sw::FORMAT_X8R8G8B8:
\r
731 case sw::FORMAT_R5G6B5:
\r
738 unsigned int GetRedSize(sw::Format colorFormat)
\r
740 switch(colorFormat)
\r
742 case sw::FORMAT_A16B16G16R16F:
\r
744 case sw::FORMAT_A32B32G32R32F:
\r
746 case sw::FORMAT_A2R10G10B10:
\r
748 case sw::FORMAT_A8R8G8B8:
\r
749 case sw::FORMAT_X8R8G8B8:
\r
751 case sw::FORMAT_A1R5G5B5:
\r
752 case sw::FORMAT_R5G6B5:
\r
759 unsigned int GetGreenSize(sw::Format colorFormat)
\r
761 switch(colorFormat)
\r
763 case sw::FORMAT_A16B16G16R16F:
\r
765 case sw::FORMAT_A32B32G32R32F:
\r
767 case sw::FORMAT_A2R10G10B10:
\r
769 case sw::FORMAT_A8R8G8B8:
\r
770 case sw::FORMAT_X8R8G8B8:
\r
772 case sw::FORMAT_A1R5G5B5:
\r
774 case sw::FORMAT_R5G6B5:
\r
781 unsigned int GetBlueSize(sw::Format colorFormat)
\r
783 switch(colorFormat)
\r
785 case sw::FORMAT_A16B16G16R16F:
\r
787 case sw::FORMAT_A32B32G32R32F:
\r
789 case sw::FORMAT_A2R10G10B10:
\r
791 case sw::FORMAT_A8R8G8B8:
\r
792 case sw::FORMAT_X8R8G8B8:
\r
794 case sw::FORMAT_A1R5G5B5:
\r
795 case sw::FORMAT_R5G6B5:
\r
802 unsigned int GetDepthSize(sw::Format depthFormat)
\r
804 switch(depthFormat)
\r
806 // case sw::FORMAT_D16_LOCKABLE: return 16;
\r
807 case sw::FORMAT_D32: return 32;
\r
808 // case sw::FORMAT_D15S1: return 15;
\r
809 case sw::FORMAT_D24S8: return 24;
\r
810 case sw::FORMAT_D24X8: return 24;
\r
811 // case sw::FORMAT_D24X4S4: return 24;
\r
812 case sw::FORMAT_D16: return 16;
\r
813 case sw::FORMAT_D32F_LOCKABLE: return 32;
\r
814 case sw::FORMAT_D24FS8: return 24;
\r
815 // case sw::FORMAT_D32_LOCKABLE: return 32;
\r
816 // case sw::FORMAT_S8_LOCKABLE: return 0;
\r
817 case sw::FORMAT_D32FS8_TEXTURE: return 32;
\r
822 GLenum ConvertBackBufferFormat(sw::Format format)
\r
826 case sw::FORMAT_A4R4G4B4: return GL_RGBA4;
\r
827 case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
\r
828 case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;
\r
829 case sw::FORMAT_R5G6B5: return GL_RGB565;
\r
830 case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
\r
838 GLenum ConvertDepthStencilFormat(sw::Format format)
\r
842 case sw::FORMAT_D16:
\r
843 case sw::FORMAT_D24X8:
\r
844 case sw::FORMAT_D32:
\r
845 return GL_DEPTH_COMPONENT16;
\r
846 case sw::FORMAT_D24S8:
\r
847 return GL_DEPTH24_STENCIL8_OES;
\r
852 return GL_DEPTH24_STENCIL8_OES;
\r