| // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | // utilities.cpp: Conversion functions and other utility routines. | 
 |  | 
 | #include "utilities.h" | 
 |  | 
 | #include "mathutil.h" | 
 | #include "Context.h" | 
 | #include "common/debug.h" | 
 |  | 
 | #include <limits> | 
 | #include <stdio.h> | 
 |  | 
 | namespace es1 | 
 | { | 
 | 	bool IsCompressed(GLenum format) | 
 | 	{ | 
 | 		return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || | 
 | 		       format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || | 
 |                format == GL_ETC1_RGB8_OES; | 
 | 	} | 
 |  | 
 | 	bool IsSizedInternalFormat(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_ALPHA8_EXT: | 
 | 		case GL_LUMINANCE8_ALPHA8_EXT: | 
 | 		case GL_LUMINANCE8_EXT: | 
 | 		case GL_RGBA4_OES: | 
 | 		case GL_RGB5_A1_OES: | 
 | 		case GL_RGB565_OES: | 
 | 		case GL_RGB8_OES: | 
 | 		case GL_RGBA8_OES: | 
 | 		case GL_BGRA8_EXT:   // GL_APPLE_texture_format_BGRA8888 | 
 | 		case GL_DEPTH_COMPONENT16_OES: | 
 | 		case GL_STENCIL_INDEX8_OES: | 
 | 		case GL_DEPTH24_STENCIL8_OES: | 
 | 			return true; | 
 | 		default: | 
 | 			return false; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset, | 
 | 	                              GLsizei width, GLsizei height, GLenum format, GLenum type, Texture *texture) | 
 | 	{ | 
 | 		if(!texture) | 
 | 		{ | 
 | 			return GL_INVALID_OPERATION; | 
 | 		} | 
 |  | 
 | 		GLenum sizedInternalFormat = texture->getFormat(target, level); | 
 |  | 
 | 		if(compressed) | 
 | 		{ | 
 | 			if(format != sizedInternalFormat) | 
 | 			{ | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 | 		} | 
 | 		else if(!copy)   // CopyTexSubImage doesn't have format/type parameters. | 
 | 		{ | 
 | 			GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, target); | 
 | 			if(validationError != GL_NO_ERROR) | 
 | 			{ | 
 | 				return validationError; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if(compressed) | 
 | 		{ | 
 | 			if((width % 4 != 0 && width != texture->getWidth(target, 0)) || | 
 | 			   (height % 4 != 0 && height != texture->getHeight(target, 0))) | 
 | 			{ | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if(xoffset + width > texture->getWidth(target, level) || | 
 | 		   yoffset + height > texture->getHeight(target, level)) | 
 | 		{ | 
 | 			return GL_INVALID_VALUE; | 
 | 		} | 
 |  | 
 | 		return GL_NO_ERROR; | 
 | 	} | 
 |  | 
 | 	bool IsDepthTexture(GLenum format) | 
 | 	{ | 
 | 		return format == GL_DEPTH_STENCIL_OES; | 
 | 	} | 
 |  | 
 | 	bool IsStencilTexture(GLenum format) | 
 | 	{ | 
 | 		return format == GL_DEPTH_STENCIL_OES; | 
 | 	} | 
 |  | 
 | 	bool IsCubemapTextureTarget(GLenum target) | 
 | 	{ | 
 | 		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES); | 
 | 	} | 
 |  | 
 | 	int CubeFaceIndex(GLenum cubeFace) | 
 | 	{ | 
 | 		switch(cubeFace) | 
 | 		{ | 
 | 		case GL_TEXTURE_CUBE_MAP_OES: | 
 | 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0; | 
 | 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1; | 
 | 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2; | 
 | 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3; | 
 | 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4; | 
 | 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5; | 
 | 		default: UNREACHABLE(cubeFace); return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	bool IsTextureTarget(GLenum target) | 
 | 	{ | 
 | 		return target == GL_TEXTURE_2D; | 
 | 	} | 
 |  | 
 | 	// Verify that format/type are one of the combinations from table 3.4. | 
 | 	GLenum ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLenum target) | 
 | 	{ | 
 | 		switch(type) | 
 | 		{ | 
 | 		case GL_UNSIGNED_BYTE: | 
 | 		case GL_UNSIGNED_SHORT_4_4_4_4: | 
 | 		case GL_UNSIGNED_SHORT_5_5_5_1: | 
 | 		case GL_UNSIGNED_SHORT_5_6_5: | 
 | 		case GL_UNSIGNED_INT_24_8_OES:   // GL_OES_packed_depth_stencil | 
 | 			break; | 
 | 		default: | 
 | 			return GL_INVALID_ENUM; | 
 | 		} | 
 |  | 
 | 		switch(format) | 
 | 		{ | 
 | 		case GL_ALPHA: | 
 | 		case GL_RGB: | 
 | 		case GL_RGBA: | 
 | 		case GL_LUMINANCE: | 
 | 		case GL_LUMINANCE_ALPHA: | 
 | 		case GL_BGRA_EXT:            // GL_EXT_texture_format_BGRA8888 | 
 | 			break; | 
 | 		case GL_DEPTH_STENCIL_OES:   // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES) | 
 | 			switch(target) | 
 | 			{ | 
 | 			case GL_TEXTURE_2D: | 
 | 				break; | 
 | 			default: | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		default: | 
 | 			return GL_INVALID_ENUM; | 
 | 		} | 
 |  | 
 | 		if((GLenum)internalformat != format) | 
 | 		{ | 
 | 			if(gl::IsUnsizedInternalFormat(internalformat)) | 
 | 			{ | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 |  | 
 | 			if(!IsSizedInternalFormat(internalformat)) | 
 | 			{ | 
 | 				return GL_INVALID_VALUE; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if((GLenum)internalformat == format) | 
 | 		{ | 
 | 			// Validate format, type, and unsized internalformat combinations [OpenGL ES 1.1 Table 3.3] | 
 | 			switch(format) | 
 | 			{ | 
 | 			case GL_RGBA: | 
 | 				switch(type) | 
 | 				{ | 
 | 				case GL_UNSIGNED_BYTE: | 
 | 				case GL_UNSIGNED_SHORT_4_4_4_4: | 
 | 				case GL_UNSIGNED_SHORT_5_5_5_1: | 
 | 					break; | 
 | 				default: | 
 | 					return GL_INVALID_OPERATION; | 
 | 				} | 
 | 				break; | 
 | 			case GL_RGB: | 
 | 				switch(type) | 
 | 				{ | 
 | 				case GL_UNSIGNED_BYTE: | 
 | 				case GL_UNSIGNED_SHORT_5_6_5: | 
 | 					break; | 
 | 				default: | 
 | 					return GL_INVALID_OPERATION; | 
 | 				} | 
 | 				break; | 
 | 			case GL_LUMINANCE_ALPHA: | 
 | 			case GL_LUMINANCE: | 
 | 			case GL_ALPHA: | 
 | 				switch(type) | 
 | 				{ | 
 | 				case GL_UNSIGNED_BYTE: | 
 | 					break; | 
 | 				default: | 
 | 					return GL_INVALID_OPERATION; | 
 | 				} | 
 | 				break; | 
 | 			case GL_DEPTH_STENCIL_OES: | 
 | 				switch(type) | 
 | 				{ | 
 | 				case GL_UNSIGNED_INT_24_8_OES:   // GL_OES_packed_depth_stencil | 
 | 					break; | 
 | 				default: | 
 | 					return GL_INVALID_OPERATION; | 
 | 				} | 
 | 				break; | 
 | 			case GL_BGRA_EXT: | 
 | 				if(type != GL_UNSIGNED_BYTE)   // GL_APPLE_texture_format_BGRA8888 / GL_EXT_texture_format_BGRA8888 | 
 | 				{ | 
 | 					return GL_INVALID_OPERATION; | 
 | 				} | 
 | 				break; | 
 | 			default: | 
 | 				UNREACHABLE(format); | 
 | 				return GL_INVALID_ENUM; | 
 | 			} | 
 |  | 
 | 			return GL_NO_ERROR; | 
 | 		} | 
 |  | 
 | 		// Validate format, type, and sized internalformat combinations [OpenGL ES 3.0 Table 3.2] | 
 | 		bool validSizedInternalformat = false; | 
 | 		#define VALIDATE_INTERNALFORMAT(...) { GLint validInternalformats[] = {__VA_ARGS__}; for(GLint v : validInternalformats) {if(internalformat == v) validSizedInternalformat = true;} } break; | 
 |  | 
 | 		switch(format) | 
 | 		{ | 
 | 		case GL_RGBA: | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGBA8_OES, GL_RGB5_A1_OES, GL_RGBA4_OES) | 
 | 			case GL_UNSIGNED_SHORT_4_4_4_4:      VALIDATE_INTERNALFORMAT(GL_RGBA4_OES) | 
 | 			case GL_UNSIGNED_SHORT_5_5_5_1:      VALIDATE_INTERNALFORMAT(GL_RGB5_A1_OES) | 
 | 			default:                             return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		case GL_RGB: | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_BYTE:                VALIDATE_INTERNALFORMAT(GL_RGB8_OES, GL_RGB565_OES) | 
 | 			case GL_UNSIGNED_SHORT_5_6_5:         VALIDATE_INTERNALFORMAT(GL_RGB565_OES) | 
 | 			default:                              return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		case GL_DEPTH_STENCIL_OES: | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_INT_24_8_OES: VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8_OES) | 
 | 			default:                       return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		case GL_LUMINANCE_ALPHA: | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_ALPHA8_EXT) | 
 | 			default: | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		case GL_LUMINANCE: | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_EXT) | 
 | 			default: | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		case GL_ALPHA: | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_ALPHA8_EXT) | 
 | 			default: | 
 | 				return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		case GL_BGRA_EXT:   // GL_APPLE_texture_format_BGRA8888 | 
 | 			switch(type) | 
 | 			{ | 
 | 			case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_BGRA8_EXT) | 
 | 			default:               return GL_INVALID_OPERATION; | 
 | 			} | 
 | 			break; | 
 | 		default: | 
 | 			UNREACHABLE(format); | 
 | 			return GL_INVALID_ENUM; | 
 | 		} | 
 |  | 
 | 		#undef VALIDATE_INTERNALFORMAT | 
 |  | 
 | 		if(!validSizedInternalformat) | 
 | 		{ | 
 | 			return GL_INVALID_OPERATION; | 
 | 		} | 
 |  | 
 | 		return GL_NO_ERROR; | 
 | 	} | 
 |  | 
 | 	bool IsColorRenderable(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_RGBA4_OES: | 
 | 		case GL_RGB5_A1_OES: | 
 | 		case GL_RGB565_OES: | 
 | 		case GL_RGB8_OES: | 
 | 		case GL_RGBA8_OES: | 
 | 			return true; | 
 | 		case GL_DEPTH_COMPONENT16_OES: | 
 | 		case GL_STENCIL_INDEX8_OES: | 
 | 		case GL_DEPTH24_STENCIL8_OES: | 
 | 			return false; | 
 | 		default: | 
 | 			UNIMPLEMENTED(); | 
 | 		} | 
 |  | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	bool IsDepthRenderable(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_DEPTH_COMPONENT16_OES: | 
 | 		case GL_DEPTH24_STENCIL8_OES: | 
 | 			return true; | 
 | 		case GL_STENCIL_INDEX8_OES: | 
 | 		case GL_RGBA4_OES: | 
 | 		case GL_RGB5_A1_OES: | 
 | 		case GL_RGB565_OES: | 
 | 		case GL_RGB8_OES: | 
 | 		case GL_RGBA8_OES: | 
 | 			return false; | 
 | 		default: | 
 | 			UNIMPLEMENTED(); | 
 | 		} | 
 |  | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	bool IsStencilRenderable(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_STENCIL_INDEX8_OES: | 
 | 		case GL_DEPTH24_STENCIL8_OES: | 
 | 			return true; | 
 | 		case GL_RGBA4_OES: | 
 | 		case GL_RGB5_A1_OES: | 
 | 		case GL_RGB565_OES: | 
 | 		case GL_RGB8_OES: | 
 | 		case GL_RGBA8_OES: | 
 | 		case GL_DEPTH_COMPONENT16_OES: | 
 | 			return false; | 
 | 		default: | 
 | 			UNIMPLEMENTED(); | 
 | 		} | 
 |  | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	GLuint GetAlphaSize(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_NONE_OES:    return 0; | 
 | 		case GL_RGBA4_OES:   return 4; | 
 | 		case GL_RGB5_A1_OES: return 1; | 
 | 		case GL_RGB565_OES:  return 0; | 
 | 		case GL_RGB8_OES:    return 0; | 
 | 		case GL_RGBA8_OES:   return 8; | 
 | 		case GL_BGRA8_EXT:   return 8; | 
 | 		default: | 
 | 		//	UNREACHABLE(internalformat); | 
 | 			return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	GLuint GetRedSize(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_NONE_OES:    return 0; | 
 | 		case GL_RGBA4_OES:   return 4; | 
 | 		case GL_RGB5_A1_OES: return 5; | 
 | 		case GL_RGB565_OES:  return 5; | 
 | 		case GL_RGB8_OES:    return 8; | 
 | 		case GL_RGBA8_OES:   return 8; | 
 | 		case GL_BGRA8_EXT:   return 8; | 
 | 		default: | 
 | 		//	UNREACHABLE(internalformat); | 
 | 			return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	GLuint GetGreenSize(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_NONE_OES:    return 0; | 
 | 		case GL_RGBA4_OES:   return 4; | 
 | 		case GL_RGB5_A1_OES: return 5; | 
 | 		case GL_RGB565_OES:  return 6; | 
 | 		case GL_RGB8_OES:    return 8; | 
 | 		case GL_RGBA8_OES:   return 8; | 
 | 		case GL_BGRA8_EXT:   return 8; | 
 | 		default: | 
 | 		//	UNREACHABLE(internalformat); | 
 | 			return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	GLuint GetBlueSize(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_NONE_OES:    return 0; | 
 | 		case GL_RGBA4_OES:   return 4; | 
 | 		case GL_RGB5_A1_OES: return 5; | 
 | 		case GL_RGB565_OES:  return 5; | 
 | 		case GL_RGB8_OES:    return 8; | 
 | 		case GL_RGBA8_OES:   return 8; | 
 | 		case GL_BGRA8_EXT:   return 8; | 
 | 		default: | 
 | 		//	UNREACHABLE(internalformat); | 
 | 			return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	GLuint GetDepthSize(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_STENCIL_INDEX8_OES:    return 0; | 
 | 		case GL_DEPTH_COMPONENT16_OES: return 16; | 
 | 		case GL_DEPTH24_STENCIL8_OES:  return 24; | 
 | 		default: | 
 | 		//	UNREACHABLE(internalformat); | 
 | 			return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	GLuint GetStencilSize(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_STENCIL_INDEX8_OES:    return 8; | 
 | 		case GL_DEPTH_COMPONENT16_OES: return 0; | 
 | 		case GL_DEPTH24_STENCIL8_OES:  return 8; | 
 | 		default: | 
 | 		//	UNREACHABLE(internalformat); | 
 | 			return 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	bool IsAlpha(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_ALPHA8_EXT: | 
 | 			return true; | 
 | 		default: | 
 | 			return false; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	bool IsRGB(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_LUMINANCE8_EXT: | 
 | 		case GL_RGB565_OES: | 
 | 		case GL_RGB8_OES: | 
 | 		case SW_YV12_BT601: | 
 | 		case SW_YV12_BT709: | 
 | 		case SW_YV12_JFIF: | 
 | 			return true; | 
 | 		default: | 
 | 			return false; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	bool IsRGBA(GLint internalformat) | 
 | 	{ | 
 | 		switch(internalformat) | 
 | 		{ | 
 | 		case GL_LUMINANCE8_ALPHA8_EXT: | 
 | 		case GL_RGBA: | 
 | 		case GL_BGRA8_EXT:     // GL_EXT_texture_format_BGRA8888 | 
 | 		case GL_RGBA4_OES: | 
 | 		case GL_RGB5_A1_OES: | 
 | 		case GL_RGBA8_OES: | 
 | 			return true; | 
 | 		default: | 
 | 			return false; | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | namespace es2sw | 
 | { | 
 | 	sw::DepthCompareMode ConvertDepthComparison(GLenum comparison) | 
 | 	{ | 
 | 		switch(comparison) | 
 | 		{ | 
 | 		case GL_NEVER:    return sw::DEPTH_NEVER; | 
 | 		case GL_ALWAYS:   return sw::DEPTH_ALWAYS; | 
 | 		case GL_LESS:     return sw::DEPTH_LESS; | 
 | 		case GL_LEQUAL:   return sw::DEPTH_LESSEQUAL; | 
 | 		case GL_EQUAL:    return sw::DEPTH_EQUAL; | 
 | 		case GL_GREATER:  return sw::DEPTH_GREATER; | 
 | 		case GL_GEQUAL:   return sw::DEPTH_GREATEREQUAL; | 
 | 		case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL; | 
 | 		default: UNREACHABLE(comparison); | 
 | 		} | 
 |  | 
 | 		return sw::DEPTH_ALWAYS; | 
 | 	} | 
 |  | 
 | 	sw::StencilCompareMode ConvertStencilComparison(GLenum comparison) | 
 | 	{ | 
 | 		switch(comparison) | 
 | 		{ | 
 | 		case GL_NEVER:    return sw::STENCIL_NEVER; | 
 | 		case GL_ALWAYS:   return sw::STENCIL_ALWAYS; | 
 | 		case GL_LESS:     return sw::STENCIL_LESS; | 
 | 		case GL_LEQUAL:   return sw::STENCIL_LESSEQUAL; | 
 | 		case GL_EQUAL:    return sw::STENCIL_EQUAL; | 
 | 		case GL_GREATER:  return sw::STENCIL_GREATER; | 
 | 		case GL_GEQUAL:   return sw::STENCIL_GREATEREQUAL; | 
 | 		case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL; | 
 | 		default: UNREACHABLE(comparison); | 
 | 		} | 
 |  | 
 | 		return sw::STENCIL_ALWAYS; | 
 | 	} | 
 |  | 
 | 	sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison) | 
 | 	{ | 
 | 		switch(comparison) | 
 | 		{ | 
 | 		case GL_NEVER:    return sw::ALPHA_NEVER; | 
 | 		case GL_ALWAYS:   return sw::ALPHA_ALWAYS; | 
 | 		case GL_LESS:     return sw::ALPHA_LESS; | 
 | 		case GL_LEQUAL:   return sw::ALPHA_LESSEQUAL; | 
 | 		case GL_EQUAL:    return sw::ALPHA_EQUAL; | 
 | 		case GL_GREATER:  return sw::ALPHA_GREATER; | 
 | 		case GL_GEQUAL:   return sw::ALPHA_GREATEREQUAL; | 
 | 		case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL; | 
 | 		default: UNREACHABLE(comparison); | 
 | 		} | 
 |  | 
 | 		return sw::ALPHA_ALWAYS; | 
 | 	} | 
 |  | 
 | 	sw::Color<float> ConvertColor(es1::Color color) | 
 | 	{ | 
 | 		return sw::Color<float>(color.red, color.green, color.blue, color.alpha); | 
 | 	} | 
 |  | 
 | 	sw::BlendFactor ConvertBlendFunc(GLenum blend) | 
 | 	{ | 
 | 		switch(blend) | 
 | 		{ | 
 | 		case GL_ZERO:                     return sw::BLEND_ZERO; | 
 | 		case GL_ONE:                      return sw::BLEND_ONE; | 
 | 		case GL_SRC_COLOR:                return sw::BLEND_SOURCE; | 
 | 		case GL_ONE_MINUS_SRC_COLOR:      return sw::BLEND_INVSOURCE; | 
 | 		case GL_DST_COLOR:                return sw::BLEND_DEST; | 
 | 		case GL_ONE_MINUS_DST_COLOR:      return sw::BLEND_INVDEST; | 
 | 		case GL_SRC_ALPHA:                return sw::BLEND_SOURCEALPHA; | 
 | 		case GL_ONE_MINUS_SRC_ALPHA:      return sw::BLEND_INVSOURCEALPHA; | 
 | 		case GL_DST_ALPHA:                return sw::BLEND_DESTALPHA; | 
 | 		case GL_ONE_MINUS_DST_ALPHA:      return sw::BLEND_INVDESTALPHA; | 
 | 		case GL_SRC_ALPHA_SATURATE:       return sw::BLEND_SRCALPHASAT; | 
 | 		default: UNREACHABLE(blend); | 
 | 		} | 
 |  | 
 | 		return sw::BLEND_ZERO; | 
 | 	} | 
 |  | 
 | 	sw::BlendOperation ConvertBlendOp(GLenum blendOp) | 
 | 	{ | 
 | 		switch(blendOp) | 
 | 		{ | 
 | 		case GL_FUNC_ADD_OES:              return sw::BLENDOP_ADD; | 
 | 		case GL_FUNC_SUBTRACT_OES:         return sw::BLENDOP_SUB; | 
 | 		case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB; | 
 | 		case GL_MIN_EXT:                   return sw::BLENDOP_MIN; | 
 | 		case GL_MAX_EXT:                   return sw::BLENDOP_MAX; | 
 | 		default: UNREACHABLE(blendOp); | 
 | 		} | 
 |  | 
 | 		return sw::BLENDOP_ADD; | 
 | 	} | 
 |  | 
 | 	sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation) | 
 | 	{ | 
 | 		switch(logicalOperation) | 
 | 		{ | 
 | 		case GL_CLEAR:         return sw::LOGICALOP_CLEAR; | 
 | 		case GL_SET:           return sw::LOGICALOP_SET; | 
 | 		case GL_COPY:          return sw::LOGICALOP_COPY; | 
 | 		case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED; | 
 | 		case GL_NOOP:          return sw::LOGICALOP_NOOP; | 
 | 		case GL_INVERT:        return sw::LOGICALOP_INVERT; | 
 | 		case GL_AND:           return sw::LOGICALOP_AND; | 
 | 		case GL_NAND:          return sw::LOGICALOP_NAND; | 
 | 		case GL_OR:            return sw::LOGICALOP_OR; | 
 | 		case GL_NOR:           return sw::LOGICALOP_NOR; | 
 | 		case GL_XOR:           return sw::LOGICALOP_XOR; | 
 | 		case GL_EQUIV:         return sw::LOGICALOP_EQUIV; | 
 | 		case GL_AND_REVERSE:   return sw::LOGICALOP_AND_REVERSE; | 
 | 		case GL_AND_INVERTED:  return sw::LOGICALOP_AND_INVERTED; | 
 | 		case GL_OR_REVERSE:    return sw::LOGICALOP_OR_REVERSE; | 
 | 		case GL_OR_INVERTED:   return sw::LOGICALOP_OR_INVERTED; | 
 | 		default: UNREACHABLE(logicalOperation); | 
 | 		} | 
 |  | 
 | 		return sw::LOGICALOP_COPY; | 
 | 	} | 
 |  | 
 | 	sw::StencilOperation ConvertStencilOp(GLenum stencilOp) | 
 | 	{ | 
 | 		switch(stencilOp) | 
 | 		{ | 
 | 		case GL_ZERO:          return sw::OPERATION_ZERO; | 
 | 		case GL_KEEP:          return sw::OPERATION_KEEP; | 
 | 		case GL_REPLACE:       return sw::OPERATION_REPLACE; | 
 | 		case GL_INCR:          return sw::OPERATION_INCRSAT; | 
 | 		case GL_DECR:          return sw::OPERATION_DECRSAT; | 
 | 		case GL_INVERT:        return sw::OPERATION_INVERT; | 
 | 		case GL_INCR_WRAP_OES: return sw::OPERATION_INCR; | 
 | 		case GL_DECR_WRAP_OES: return sw::OPERATION_DECR; | 
 | 		default: UNREACHABLE(stencilOp); | 
 | 		} | 
 |  | 
 | 		return sw::OPERATION_KEEP; | 
 | 	} | 
 |  | 
 | 	sw::AddressingMode ConvertTextureWrap(GLenum wrap) | 
 | 	{ | 
 | 		switch(wrap) | 
 | 		{ | 
 | 		case GL_REPEAT:              return sw::ADDRESSING_WRAP; | 
 | 		case GL_CLAMP_TO_EDGE:       return sw::ADDRESSING_CLAMP; | 
 | 		case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR; | 
 | 		default: UNREACHABLE(wrap); | 
 | 		} | 
 |  | 
 | 		return sw::ADDRESSING_WRAP; | 
 | 	} | 
 |  | 
 | 	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace) | 
 | 	{ | 
 | 		switch(cullFace) | 
 | 		{ | 
 | 		case GL_FRONT: | 
 | 			return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE); | 
 | 		case GL_BACK: | 
 | 			return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE); | 
 | 		case GL_FRONT_AND_BACK: | 
 | 			return sw::CULL_NONE;   // culling will be handled during draw | 
 | 		default: UNREACHABLE(cullFace); | 
 | 		} | 
 |  | 
 | 		return sw::CULL_COUNTERCLOCKWISE; | 
 | 	} | 
 |  | 
 | 	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha) | 
 | 	{ | 
 | 		return (red   ? 0x00000001 : 0) | | 
 | 			   (green ? 0x00000002 : 0) | | 
 | 			   (blue  ? 0x00000004 : 0) | | 
 | 			   (alpha ? 0x00000008 : 0); | 
 | 	} | 
 |  | 
 | 	sw::MipmapType ConvertMipMapFilter(GLenum minFilter) | 
 | 	{ | 
 | 		switch(minFilter) | 
 | 		{ | 
 | 		case GL_NEAREST: | 
 | 		case GL_LINEAR: | 
 | 			return sw::MIPMAP_NONE; | 
 | 			break; | 
 | 		case GL_NEAREST_MIPMAP_NEAREST: | 
 | 		case GL_LINEAR_MIPMAP_NEAREST: | 
 | 			return sw::MIPMAP_POINT; | 
 | 			break; | 
 | 		case GL_NEAREST_MIPMAP_LINEAR: | 
 | 		case GL_LINEAR_MIPMAP_LINEAR: | 
 | 			return sw::MIPMAP_LINEAR; | 
 | 			break; | 
 | 		default: | 
 | 			UNREACHABLE(minFilter); | 
 | 			return sw::MIPMAP_NONE; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) | 
 | 	{ | 
 | 		if(maxAnisotropy > 1.0f) | 
 | 		{ | 
 | 			return sw::FILTER_ANISOTROPIC; | 
 | 		} | 
 |  | 
 | 		sw::FilterType magFilterType = sw::FILTER_POINT; | 
 | 		switch(magFilter) | 
 | 		{ | 
 | 		case GL_NEAREST: magFilterType = sw::FILTER_POINT;  break; | 
 | 		case GL_LINEAR:  magFilterType = sw::FILTER_LINEAR; break; | 
 | 		default: UNREACHABLE(magFilter); | 
 | 		} | 
 |  | 
 | 		switch(minFilter) | 
 | 		{ | 
 | 		case GL_NEAREST: | 
 | 		case GL_NEAREST_MIPMAP_NEAREST: | 
 | 		case GL_NEAREST_MIPMAP_LINEAR: | 
 | 			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; | 
 | 		case GL_LINEAR: | 
 | 		case GL_LINEAR_MIPMAP_NEAREST: | 
 | 		case GL_LINEAR_MIPMAP_LINEAR: | 
 | 			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR; | 
 | 		default: | 
 | 			UNREACHABLE(minFilter); | 
 | 			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType,  sw::DrawType &drawType, int &primitiveCount) | 
 | 	{ | 
 | 		switch(primitiveType) | 
 | 		{ | 
 | 		case GL_POINTS: | 
 | 			drawType = sw::DRAW_POINTLIST; | 
 | 			primitiveCount = elementCount; | 
 | 			break; | 
 | 		case GL_LINES: | 
 | 			drawType = sw::DRAW_LINELIST; | 
 | 			primitiveCount = elementCount / 2; | 
 | 			break; | 
 | 		case GL_LINE_LOOP: | 
 | 			drawType = sw::DRAW_LINELOOP; | 
 | 			primitiveCount = elementCount; | 
 | 			break; | 
 | 		case GL_LINE_STRIP: | 
 | 			drawType = sw::DRAW_LINESTRIP; | 
 | 			primitiveCount = elementCount - 1; | 
 | 			break; | 
 | 		case GL_TRIANGLES: | 
 | 			drawType = sw::DRAW_TRIANGLELIST; | 
 | 			primitiveCount = elementCount / 3; | 
 | 			break; | 
 | 		case GL_TRIANGLE_STRIP: | 
 | 			drawType = sw::DRAW_TRIANGLESTRIP; | 
 | 			primitiveCount = elementCount - 2; | 
 | 			break; | 
 | 		case GL_TRIANGLE_FAN: | 
 | 			drawType = sw::DRAW_TRIANGLEFAN; | 
 | 			primitiveCount = elementCount - 2; | 
 | 			break; | 
 | 		default: | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		sw::DrawType elementSize; | 
 | 		switch(elementType) | 
 | 		{ | 
 | 		case GL_NONE_OES:       elementSize = sw::DRAW_NONINDEXED; break; | 
 | 		case GL_UNSIGNED_BYTE:  elementSize = sw::DRAW_INDEXED8;   break; | 
 | 		case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16;  break; | 
 | 		case GL_UNSIGNED_INT:   elementSize = sw::DRAW_INDEXED32;  break; | 
 | 		default: return false; | 
 | 		} | 
 |  | 
 | 		drawType = sw::DrawType(drawType | elementSize); | 
 |  | 
 | 		return true; | 
 | 	} | 
 |  | 
 | 	sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation) | 
 | 	{ | 
 | 		switch(operation) | 
 | 		{ | 
 | 		case GL_REPLACE:        return sw::TextureStage::STAGE_SELECTARG1; | 
 | 		case GL_MODULATE:       return sw::TextureStage::STAGE_MODULATE; | 
 | 		case GL_ADD:            return sw::TextureStage::STAGE_ADD; | 
 | 		case GL_ADD_SIGNED:     return sw::TextureStage::STAGE_ADDSIGNED; | 
 | 		case GL_INTERPOLATE:    return sw::TextureStage::STAGE_LERP; | 
 | 		case GL_SUBTRACT:       return sw::TextureStage::STAGE_SUBTRACT; | 
 | 		case GL_DOT3_RGB:       return sw::TextureStage::STAGE_DOT3; | 
 | 		case GL_DOT3_RGBA:      return sw::TextureStage::STAGE_DOT3; | 
 | 		default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument) | 
 | 	{ | 
 | 		switch(argument) | 
 | 		{ | 
 | 		case GL_TEXTURE:        return sw::TextureStage::SOURCE_TEXTURE; | 
 | 		case GL_CONSTANT:       return sw::TextureStage::SOURCE_CONSTANT; | 
 | 		case GL_PRIMARY_COLOR:  return sw::TextureStage::SOURCE_DIFFUSE; | 
 | 		case GL_PREVIOUS:       return sw::TextureStage::SOURCE_CURRENT; | 
 | 		default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand) | 
 | 	{ | 
 | 		switch(operand) | 
 | 		{ | 
 | 		case GL_SRC_COLOR:           return sw::TextureStage::MODIFIER_COLOR; | 
 | 		case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR; | 
 | 		case GL_SRC_ALPHA:           return sw::TextureStage::MODIFIER_ALPHA; | 
 | 		case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA; | 
 | 		default: UNREACHABLE(operand);      return sw::TextureStage::MODIFIER_COLOR; | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | namespace sw2es | 
 | { | 
 | 	GLenum ConvertBackBufferFormat(sw::Format format) | 
 | 	{ | 
 | 		switch(format) | 
 | 		{ | 
 | 		case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES; | 
 | 		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES; | 
 | 		case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES; | 
 | 		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES; | 
 | 		case sw::FORMAT_R5G6B5:   return GL_RGB565_OES; | 
 | 		case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES; | 
 | 		case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES; | 
 | 		default: | 
 | 			UNREACHABLE(format); | 
 | 		} | 
 |  | 
 | 		return GL_RGBA4_OES; | 
 | 	} | 
 |  | 
 | 	GLenum ConvertDepthStencilFormat(sw::Format format) | 
 | 	{ | 
 | 		switch(format) | 
 | 		{ | 
 | 		case sw::FORMAT_D16: | 
 | 		case sw::FORMAT_D24X8: | 
 | 		case sw::FORMAT_D32: | 
 | 			return GL_DEPTH_COMPONENT16_OES; | 
 | 		case sw::FORMAT_D24S8: | 
 | 			return GL_DEPTH24_STENCIL8_OES; | 
 | 		default: | 
 | 			UNREACHABLE(format); | 
 | 		} | 
 |  | 
 | 		return GL_DEPTH24_STENCIL8_OES; | 
 | 	} | 
 | } |