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 case GL_ETC1_RGB8_OES:
\r
211 return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
\r
212 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
\r
213 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
\r
214 return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
\r
220 bool IsCompressed(GLenum format)
\r
222 return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
\r
223 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
\r
224 format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
\r
225 format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE ||
\r
226 format == GL_ETC1_RGB8_OES;
\r
229 bool IsDepthTexture(GLenum format)
\r
231 return format == GL_DEPTH_COMPONENT ||
\r
232 format == GL_DEPTH_STENCIL_OES;
\r
235 bool IsStencilTexture(GLenum format)
\r
237 return format == GL_STENCIL_INDEX_OES ||
\r
238 format == GL_DEPTH_STENCIL_OES;
\r
241 // Returns the size, in bytes, of a single texel in an Image
\r
242 int ComputePixelSize(GLenum format, GLenum type)
\r
246 case GL_UNSIGNED_BYTE:
\r
249 case GL_ALPHA: return sizeof(unsigned char);
\r
250 case GL_LUMINANCE: return sizeof(unsigned char);
\r
251 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
\r
252 case GL_RGB: return sizeof(unsigned char) * 3;
\r
253 case GL_RGBA: return sizeof(unsigned char) * 4;
\r
254 case GL_BGRA_EXT: return sizeof(unsigned char) * 4;
\r
255 default: UNREACHABLE();
\r
258 case GL_UNSIGNED_SHORT_4_4_4_4:
\r
259 case GL_UNSIGNED_SHORT_5_5_5_1:
\r
260 case GL_UNSIGNED_SHORT_5_6_5:
\r
261 case GL_UNSIGNED_SHORT:
\r
262 return sizeof(unsigned short);
\r
263 case GL_UNSIGNED_INT:
\r
264 case GL_UNSIGNED_INT_24_8_OES:
\r
265 return sizeof(unsigned int);
\r
269 case GL_ALPHA: return sizeof(float);
\r
270 case GL_LUMINANCE: return sizeof(float);
\r
271 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
\r
272 case GL_RGB: return sizeof(float) * 3;
\r
273 case GL_RGBA: return sizeof(float) * 4;
\r
274 default: UNREACHABLE();
\r
277 case GL_HALF_FLOAT_OES:
\r
280 case GL_ALPHA: return sizeof(unsigned short);
\r
281 case GL_LUMINANCE: return sizeof(unsigned short);
\r
282 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
\r
283 case GL_RGB: return sizeof(unsigned short) * 3;
\r
284 case GL_RGBA: return sizeof(unsigned short) * 4;
\r
285 default: UNREACHABLE();
\r
288 default: UNREACHABLE();
\r
294 bool IsCubemapTextureTarget(GLenum target)
\r
296 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
\r
299 int CubeFaceIndex(GLenum cubeFace)
\r
303 case GL_TEXTURE_CUBE_MAP:
\r
304 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;
\r
305 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;
\r
306 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;
\r
307 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;
\r
308 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;
\r
309 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;
\r
310 default: UNREACHABLE(); return 0;
\r
314 bool IsTextureTarget(GLenum target)
\r
316 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
\r
319 // Verify that format/type are one of the combinations from table 3.4.
\r
320 bool CheckTextureFormatType(GLenum format, GLenum type)
\r
324 case GL_UNSIGNED_BYTE:
\r
332 case GL_LUMINANCE_ALPHA:
\r
338 case GL_HALF_FLOAT_OES:
\r
345 case GL_LUMINANCE_ALPHA:
\r
350 case GL_UNSIGNED_SHORT_4_4_4_4:
\r
351 case GL_UNSIGNED_SHORT_5_5_5_1:
\r
352 return (format == GL_RGBA);
\r
353 case GL_UNSIGNED_SHORT_5_6_5:
\r
354 return (format == GL_RGB);
\r
355 case GL_UNSIGNED_INT:
\r
356 return (format == GL_DEPTH_COMPONENT);
\r
357 case GL_UNSIGNED_INT_24_8_OES:
\r
358 return (format == GL_DEPTH_STENCIL_OES);
\r
364 bool IsColorRenderable(GLenum internalformat)
\r
366 switch(internalformat)
\r
374 case GL_DEPTH_COMPONENT16:
\r
375 case GL_STENCIL_INDEX8:
\r
376 case GL_DEPTH24_STENCIL8_OES:
\r
385 bool IsDepthRenderable(GLenum internalformat)
\r
387 switch(internalformat)
\r
389 case GL_DEPTH_COMPONENT16:
\r
390 case GL_DEPTH24_STENCIL8_OES:
\r
392 case GL_STENCIL_INDEX8:
\r
406 bool IsStencilRenderable(GLenum internalformat)
\r
408 switch(internalformat)
\r
410 case GL_STENCIL_INDEX8:
\r
411 case GL_DEPTH24_STENCIL8_OES:
\r
418 case GL_DEPTH_COMPONENT16:
\r
430 sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
\r
434 case GL_NEVER: return sw::DEPTH_NEVER;
\r
435 case GL_ALWAYS: return sw::DEPTH_ALWAYS;
\r
436 case GL_LESS: return sw::DEPTH_LESS;
\r
437 case GL_LEQUAL: return sw::DEPTH_LESSEQUAL;
\r
438 case GL_EQUAL: return sw::DEPTH_EQUAL;
\r
439 case GL_GREATER: return sw::DEPTH_GREATER;
\r
440 case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL;
\r
441 case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
\r
442 default: UNREACHABLE();
\r
445 return sw::DEPTH_ALWAYS;
\r
448 sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
\r
452 case GL_NEVER: return sw::STENCIL_NEVER;
\r
453 case GL_ALWAYS: return sw::STENCIL_ALWAYS;
\r
454 case GL_LESS: return sw::STENCIL_LESS;
\r
455 case GL_LEQUAL: return sw::STENCIL_LESSEQUAL;
\r
456 case GL_EQUAL: return sw::STENCIL_EQUAL;
\r
457 case GL_GREATER: return sw::STENCIL_GREATER;
\r
458 case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL;
\r
459 case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
\r
460 default: UNREACHABLE();
\r
463 return sw::STENCIL_ALWAYS;
\r
466 sw::Color<float> ConvertColor(es2::Color color)
\r
468 return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
\r
471 sw::BlendFactor ConvertBlendFunc(GLenum blend)
\r
475 case GL_ZERO: return sw::BLEND_ZERO;
\r
476 case GL_ONE: return sw::BLEND_ONE;
\r
477 case GL_SRC_COLOR: return sw::BLEND_SOURCE;
\r
478 case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE;
\r
479 case GL_DST_COLOR: return sw::BLEND_DEST;
\r
480 case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST;
\r
481 case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA;
\r
482 case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA;
\r
483 case GL_DST_ALPHA: return sw::BLEND_DESTALPHA;
\r
484 case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA;
\r
485 case GL_CONSTANT_COLOR: return sw::BLEND_CONSTANT;
\r
486 case GL_ONE_MINUS_CONSTANT_COLOR: return sw::BLEND_INVCONSTANT;
\r
487 case GL_CONSTANT_ALPHA: return sw::BLEND_CONSTANTALPHA;
\r
488 case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::BLEND_INVCONSTANTALPHA;
\r
489 case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT;
\r
490 default: UNREACHABLE();
\r
493 return sw::BLEND_ZERO;
\r
496 sw::BlendOperation ConvertBlendOp(GLenum blendOp)
\r
500 case GL_FUNC_ADD: return sw::BLENDOP_ADD;
\r
501 case GL_FUNC_SUBTRACT: return sw::BLENDOP_SUB;
\r
502 case GL_FUNC_REVERSE_SUBTRACT: return sw::BLENDOP_INVSUB;
\r
503 case GL_MIN_EXT: return sw::BLENDOP_MIN;
\r
504 case GL_MAX_EXT: return sw::BLENDOP_MAX;
\r
505 default: UNREACHABLE();
\r
508 return sw::BLENDOP_ADD;
\r
511 sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
\r
515 case GL_ZERO: return sw::OPERATION_ZERO;
\r
516 case GL_KEEP: return sw::OPERATION_KEEP;
\r
517 case GL_REPLACE: return sw::OPERATION_REPLACE;
\r
518 case GL_INCR: return sw::OPERATION_INCRSAT;
\r
519 case GL_DECR: return sw::OPERATION_DECRSAT;
\r
520 case GL_INVERT: return sw::OPERATION_INVERT;
\r
521 case GL_INCR_WRAP: return sw::OPERATION_INCR;
\r
522 case GL_DECR_WRAP: return sw::OPERATION_DECR;
\r
523 default: UNREACHABLE();
\r
526 return sw::OPERATION_KEEP;
\r
529 sw::AddressingMode ConvertTextureWrap(GLenum wrap)
\r
533 case GL_REPEAT: return sw::ADDRESSING_WRAP;
\r
534 case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP;
\r
535 case GL_MIRRORED_REPEAT: return sw::ADDRESSING_MIRROR;
\r
536 default: UNREACHABLE();
\r
539 return sw::ADDRESSING_WRAP;
\r
542 sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
\r
547 return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
\r
549 return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
\r
550 case GL_FRONT_AND_BACK:
\r
551 return sw::CULL_NONE; // culling will be handled during draw
\r
552 default: UNREACHABLE();
\r
555 return sw::CULL_COUNTERCLOCKWISE;
\r
558 unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
\r
560 return (red ? 0x00000001 : 0) |
\r
561 (green ? 0x00000002 : 0) |
\r
562 (blue ? 0x00000004 : 0) |
\r
563 (alpha ? 0x00000008 : 0);
\r
566 sw::FilterType ConvertMagFilter(GLenum magFilter)
\r
570 case GL_NEAREST: return sw::FILTER_POINT;
\r
571 case GL_LINEAR: return sw::FILTER_LINEAR;
\r
572 default: UNREACHABLE();
\r
575 return sw::FILTER_POINT;
\r
578 void ConvertMinFilter(GLenum texFilter, sw::FilterType *minFilter, sw::MipmapType *mipFilter, float maxAnisotropy)
\r
583 *minFilter = sw::FILTER_POINT;
\r
584 *mipFilter = sw::MIPMAP_NONE;
\r
587 *minFilter = sw::FILTER_LINEAR;
\r
588 *mipFilter = sw::MIPMAP_NONE;
\r
590 case GL_NEAREST_MIPMAP_NEAREST:
\r
591 *minFilter = sw::FILTER_POINT;
\r
592 *mipFilter = sw::MIPMAP_POINT;
\r
594 case GL_LINEAR_MIPMAP_NEAREST:
\r
595 *minFilter = sw::FILTER_LINEAR;
\r
596 *mipFilter = sw::MIPMAP_POINT;
\r
598 case GL_NEAREST_MIPMAP_LINEAR:
\r
599 *minFilter = sw::FILTER_POINT;
\r
600 *mipFilter = sw::MIPMAP_LINEAR;
\r
602 case GL_LINEAR_MIPMAP_LINEAR:
\r
603 *minFilter = sw::FILTER_LINEAR;
\r
604 *mipFilter = sw::MIPMAP_LINEAR;
\r
607 *minFilter = sw::FILTER_POINT;
\r
608 *mipFilter = sw::MIPMAP_NONE;
\r
612 if(maxAnisotropy > 1.0f)
\r
614 *minFilter = sw::FILTER_ANISOTROPIC;
\r
618 bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, es2::PrimitiveType &swPrimitiveType, int &primitiveCount)
\r
620 switch(primitiveType)
\r
623 swPrimitiveType = es2::DRAW_POINTLIST;
\r
624 primitiveCount = elementCount;
\r
627 swPrimitiveType = es2::DRAW_LINELIST;
\r
628 primitiveCount = elementCount / 2;
\r
631 swPrimitiveType = es2::DRAW_LINELOOP;
\r
632 primitiveCount = elementCount;
\r
634 case GL_LINE_STRIP:
\r
635 swPrimitiveType = es2::DRAW_LINESTRIP;
\r
636 primitiveCount = elementCount - 1;
\r
639 swPrimitiveType = es2::DRAW_TRIANGLELIST;
\r
640 primitiveCount = elementCount / 3;
\r
642 case GL_TRIANGLE_STRIP:
\r
643 swPrimitiveType = es2::DRAW_TRIANGLESTRIP;
\r
644 primitiveCount = elementCount - 2;
\r
646 case GL_TRIANGLE_FAN:
\r
647 swPrimitiveType = es2::DRAW_TRIANGLEFAN;
\r
648 primitiveCount = elementCount - 2;
\r
657 sw::Format ConvertRenderbufferFormat(GLenum format)
\r
663 case GL_RGBA8_OES: return sw::FORMAT_A8R8G8B8;
\r
664 case GL_RGB565: return sw::FORMAT_R5G6B5;
\r
665 case GL_RGB8_OES: return sw::FORMAT_X8R8G8B8;
\r
666 case GL_DEPTH_COMPONENT16:
\r
667 case GL_STENCIL_INDEX8:
\r
668 case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;
\r
669 default: UNREACHABLE(); return sw::FORMAT_A8R8G8B8;
\r
676 unsigned int GetStencilSize(sw::Format stencilFormat)
\r
678 switch(stencilFormat)
\r
680 case sw::FORMAT_D24FS8:
\r
681 case sw::FORMAT_D24S8:
\r
682 case sw::FORMAT_D32FS8_TEXTURE:
\r
684 // case sw::FORMAT_D24X4S4:
\r
686 // case sw::FORMAT_D15S1:
\r
688 // case sw::FORMAT_D16_LOCKABLE:
\r
689 case sw::FORMAT_D32:
\r
690 case sw::FORMAT_D24X8:
\r
691 case sw::FORMAT_D32F_LOCKABLE:
\r
692 case sw::FORMAT_D16:
\r
694 // case sw::FORMAT_D32_LOCKABLE: return 0;
\r
695 // case sw::FORMAT_S8_LOCKABLE: return 8;
\r
701 unsigned int GetAlphaSize(sw::Format colorFormat)
\r
703 switch(colorFormat)
\r
705 case sw::FORMAT_A16B16G16R16F:
\r
707 case sw::FORMAT_A32B32G32R32F:
\r
709 case sw::FORMAT_A2R10G10B10:
\r
711 case sw::FORMAT_A8R8G8B8:
\r
713 case sw::FORMAT_A1R5G5B5:
\r
715 case sw::FORMAT_X8R8G8B8:
\r
716 case sw::FORMAT_R5G6B5:
\r
723 unsigned int GetRedSize(sw::Format colorFormat)
\r
725 switch(colorFormat)
\r
727 case sw::FORMAT_A16B16G16R16F:
\r
729 case sw::FORMAT_A32B32G32R32F:
\r
731 case sw::FORMAT_A2R10G10B10:
\r
733 case sw::FORMAT_A8R8G8B8:
\r
734 case sw::FORMAT_X8R8G8B8:
\r
736 case sw::FORMAT_A1R5G5B5:
\r
737 case sw::FORMAT_R5G6B5:
\r
744 unsigned int GetGreenSize(sw::Format colorFormat)
\r
746 switch(colorFormat)
\r
748 case sw::FORMAT_A16B16G16R16F:
\r
750 case sw::FORMAT_A32B32G32R32F:
\r
752 case sw::FORMAT_A2R10G10B10:
\r
754 case sw::FORMAT_A8R8G8B8:
\r
755 case sw::FORMAT_X8R8G8B8:
\r
757 case sw::FORMAT_A1R5G5B5:
\r
759 case sw::FORMAT_R5G6B5:
\r
766 unsigned int GetBlueSize(sw::Format colorFormat)
\r
768 switch(colorFormat)
\r
770 case sw::FORMAT_A16B16G16R16F:
\r
772 case sw::FORMAT_A32B32G32R32F:
\r
774 case sw::FORMAT_A2R10G10B10:
\r
776 case sw::FORMAT_A8R8G8B8:
\r
777 case sw::FORMAT_X8R8G8B8:
\r
779 case sw::FORMAT_A1R5G5B5:
\r
780 case sw::FORMAT_R5G6B5:
\r
787 unsigned int GetDepthSize(sw::Format depthFormat)
\r
789 switch(depthFormat)
\r
791 // case sw::FORMAT_D16_LOCKABLE: return 16;
\r
792 case sw::FORMAT_D32: return 32;
\r
793 // case sw::FORMAT_D15S1: return 15;
\r
794 case sw::FORMAT_D24S8: return 24;
\r
795 case sw::FORMAT_D24X8: return 24;
\r
796 // case sw::FORMAT_D24X4S4: return 24;
\r
797 case sw::FORMAT_D16: return 16;
\r
798 case sw::FORMAT_D32F_LOCKABLE: return 32;
\r
799 case sw::FORMAT_D24FS8: return 24;
\r
800 // case sw::FORMAT_D32_LOCKABLE: return 32;
\r
801 // case sw::FORMAT_S8_LOCKABLE: return 0;
\r
802 case sw::FORMAT_D32FS8_TEXTURE: return 32;
\r
807 GLenum ConvertBackBufferFormat(sw::Format format)
\r
811 case sw::FORMAT_A4R4G4B4: return GL_RGBA4;
\r
812 case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
\r
813 case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;
\r
814 case sw::FORMAT_R5G6B5: return GL_RGB565;
\r
815 case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
\r
823 GLenum ConvertDepthStencilFormat(sw::Format format)
\r
827 case sw::FORMAT_D16:
\r
828 case sw::FORMAT_D24X8:
\r
829 case sw::FORMAT_D32:
\r
830 return GL_DEPTH_COMPONENT16;
\r
831 case sw::FORMAT_D24S8:
\r
832 return GL_DEPTH24_STENCIL8_OES;
\r
837 return GL_DEPTH24_STENCIL8_OES;
\r