Home | History | Annotate | Download | only in libGLES_CM
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // utilities.cpp: Conversion functions and other utility routines.
     16 
     17 #include "utilities.h"
     18 
     19 #include "mathutil.h"
     20 #include "Context.h"
     21 #include "common/debug.h"
     22 
     23 #include <limits>
     24 #include <stdio.h>
     25 
     26 namespace es1
     27 {
     28 	bool IsCompressed(GLenum format)
     29 	{
     30 		return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
     31 		       format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
     32                format == GL_ETC1_RGB8_OES;
     33 	}
     34 
     35 	bool IsSizedInternalFormat(GLint internalformat)
     36 	{
     37 		switch(internalformat)
     38 		{
     39 		case GL_ALPHA8_EXT:
     40 		case GL_LUMINANCE8_ALPHA8_EXT:
     41 		case GL_LUMINANCE8_EXT:
     42 		case GL_RGBA4_OES:
     43 		case GL_RGB5_A1_OES:
     44 		case GL_RGB565_OES:
     45 		case GL_RGB8_OES:
     46 		case GL_RGBA8_OES:
     47 		case GL_BGRA8_EXT:   // GL_APPLE_texture_format_BGRA8888
     48 		case GL_DEPTH_COMPONENT16_OES:
     49 		case GL_STENCIL_INDEX8_OES:
     50 		case GL_DEPTH24_STENCIL8_OES:
     51 			return true;
     52 		default:
     53 			return false;
     54 		}
     55 	}
     56 
     57 	GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset,
     58 	                              GLsizei width, GLsizei height, GLenum format, GLenum type, Texture *texture)
     59 	{
     60 		if(!texture)
     61 		{
     62 			return GL_INVALID_OPERATION;
     63 		}
     64 
     65 		GLenum sizedInternalFormat = texture->getFormat(target, level);
     66 
     67 		if(compressed)
     68 		{
     69 			if(format != sizedInternalFormat)
     70 			{
     71 				return GL_INVALID_OPERATION;
     72 			}
     73 		}
     74 		else if(!copy)   // CopyTexSubImage doesn't have format/type parameters.
     75 		{
     76 			GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, target);
     77 			if(validationError != GL_NO_ERROR)
     78 			{
     79 				return validationError;
     80 			}
     81 		}
     82 
     83 		if(compressed)
     84 		{
     85 			if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
     86 			   (height % 4 != 0 && height != texture->getHeight(target, 0)))
     87 			{
     88 				return GL_INVALID_OPERATION;
     89 			}
     90 		}
     91 
     92 		if(xoffset + width > texture->getWidth(target, level) ||
     93 		   yoffset + height > texture->getHeight(target, level))
     94 		{
     95 			return GL_INVALID_VALUE;
     96 		}
     97 
     98 		return GL_NO_ERROR;
     99 	}
    100 
    101 	bool IsDepthTexture(GLenum format)
    102 	{
    103 		return format == GL_DEPTH_STENCIL_OES;
    104 	}
    105 
    106 	bool IsStencilTexture(GLenum format)
    107 	{
    108 		return format == GL_DEPTH_STENCIL_OES;
    109 	}
    110 
    111 	bool IsCubemapTextureTarget(GLenum target)
    112 	{
    113 		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES);
    114 	}
    115 
    116 	int CubeFaceIndex(GLenum cubeFace)
    117 	{
    118 		switch(cubeFace)
    119 		{
    120 		case GL_TEXTURE_CUBE_MAP_OES:
    121 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0;
    122 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1;
    123 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2;
    124 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3;
    125 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4;
    126 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5;
    127 		default: UNREACHABLE(cubeFace); return 0;
    128 		}
    129 	}
    130 
    131 	bool IsTextureTarget(GLenum target)
    132 	{
    133 		return target == GL_TEXTURE_2D;
    134 	}
    135 
    136 	// Verify that format/type are one of the combinations from table 3.4.
    137 	GLenum ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLenum target)
    138 	{
    139 		switch(type)
    140 		{
    141 		case GL_UNSIGNED_BYTE:
    142 		case GL_UNSIGNED_SHORT_4_4_4_4:
    143 		case GL_UNSIGNED_SHORT_5_5_5_1:
    144 		case GL_UNSIGNED_SHORT_5_6_5:
    145 		case GL_UNSIGNED_INT_24_8_OES:   // GL_OES_packed_depth_stencil
    146 			break;
    147 		default:
    148 			return GL_INVALID_ENUM;
    149 		}
    150 
    151 		switch(format)
    152 		{
    153 		case GL_ALPHA:
    154 		case GL_RGB:
    155 		case GL_RGBA:
    156 		case GL_LUMINANCE:
    157 		case GL_LUMINANCE_ALPHA:
    158 		case GL_BGRA_EXT:            // GL_EXT_texture_format_BGRA8888
    159 			break;
    160 		case GL_DEPTH_STENCIL_OES:   // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES)
    161 			switch(target)
    162 			{
    163 			case GL_TEXTURE_2D:
    164 				break;
    165 			default:
    166 				return GL_INVALID_OPERATION;
    167 			}
    168 			break;
    169 		default:
    170 			return GL_INVALID_ENUM;
    171 		}
    172 
    173 		if((GLenum)internalformat != format)
    174 		{
    175 			if(gl::IsUnsizedInternalFormat(internalformat))
    176 			{
    177 				return GL_INVALID_OPERATION;
    178 			}
    179 
    180 			if(!IsSizedInternalFormat(internalformat))
    181 			{
    182 				return GL_INVALID_VALUE;
    183 			}
    184 		}
    185 
    186 		if((GLenum)internalformat == format)
    187 		{
    188 			// Validate format, type, and unsized internalformat combinations [OpenGL ES 1.1 Table 3.3]
    189 			switch(format)
    190 			{
    191 			case GL_RGBA:
    192 				switch(type)
    193 				{
    194 				case GL_UNSIGNED_BYTE:
    195 				case GL_UNSIGNED_SHORT_4_4_4_4:
    196 				case GL_UNSIGNED_SHORT_5_5_5_1:
    197 					break;
    198 				default:
    199 					return GL_INVALID_OPERATION;
    200 				}
    201 				break;
    202 			case GL_RGB:
    203 				switch(type)
    204 				{
    205 				case GL_UNSIGNED_BYTE:
    206 				case GL_UNSIGNED_SHORT_5_6_5:
    207 					break;
    208 				default:
    209 					return GL_INVALID_OPERATION;
    210 				}
    211 				break;
    212 			case GL_LUMINANCE_ALPHA:
    213 			case GL_LUMINANCE:
    214 			case GL_ALPHA:
    215 				switch(type)
    216 				{
    217 				case GL_UNSIGNED_BYTE:
    218 					break;
    219 				default:
    220 					return GL_INVALID_OPERATION;
    221 				}
    222 				break;
    223 			case GL_DEPTH_STENCIL_OES:
    224 				switch(type)
    225 				{
    226 				case GL_UNSIGNED_INT_24_8_OES:   // GL_OES_packed_depth_stencil
    227 					break;
    228 				default:
    229 					return GL_INVALID_OPERATION;
    230 				}
    231 				break;
    232 			case GL_BGRA_EXT:
    233 				if(type != GL_UNSIGNED_BYTE)   // GL_APPLE_texture_format_BGRA8888 / GL_EXT_texture_format_BGRA8888
    234 				{
    235 					return GL_INVALID_OPERATION;
    236 				}
    237 				break;
    238 			default:
    239 				UNREACHABLE(format);
    240 				return GL_INVALID_ENUM;
    241 			}
    242 
    243 			return GL_NO_ERROR;
    244 		}
    245 
    246 		// Validate format, type, and sized internalformat combinations [OpenGL ES 3.0 Table 3.2]
    247 		bool validSizedInternalformat = false;
    248 		#define VALIDATE_INTERNALFORMAT(...) { GLint validInternalformats[] = {__VA_ARGS__}; for(GLint v : validInternalformats) {if(internalformat == v) validSizedInternalformat = true;} } break;
    249 
    250 		switch(format)
    251 		{
    252 		case GL_RGBA:
    253 			switch(type)
    254 			{
    255 			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGBA8_OES, GL_RGB5_A1_OES, GL_RGBA4_OES)
    256 			case GL_UNSIGNED_SHORT_4_4_4_4:      VALIDATE_INTERNALFORMAT(GL_RGBA4_OES)
    257 			case GL_UNSIGNED_SHORT_5_5_5_1:      VALIDATE_INTERNALFORMAT(GL_RGB5_A1_OES)
    258 			default:                             return GL_INVALID_OPERATION;
    259 			}
    260 			break;
    261 		case GL_RGB:
    262 			switch(type)
    263 			{
    264 			case GL_UNSIGNED_BYTE:                VALIDATE_INTERNALFORMAT(GL_RGB8_OES, GL_RGB565_OES)
    265 			case GL_UNSIGNED_SHORT_5_6_5:         VALIDATE_INTERNALFORMAT(GL_RGB565_OES)
    266 			default:                              return GL_INVALID_OPERATION;
    267 			}
    268 			break;
    269 		case GL_DEPTH_STENCIL_OES:
    270 			switch(type)
    271 			{
    272 			case GL_UNSIGNED_INT_24_8_OES: VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8_OES)
    273 			default:                       return GL_INVALID_OPERATION;
    274 			}
    275 			break;
    276 		case GL_LUMINANCE_ALPHA:
    277 			switch(type)
    278 			{
    279 			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_ALPHA8_EXT)
    280 			default:
    281 				return GL_INVALID_OPERATION;
    282 			}
    283 			break;
    284 		case GL_LUMINANCE:
    285 			switch(type)
    286 			{
    287 			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_EXT)
    288 			default:
    289 				return GL_INVALID_OPERATION;
    290 			}
    291 			break;
    292 		case GL_ALPHA:
    293 			switch(type)
    294 			{
    295 			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_ALPHA8_EXT)
    296 			default:
    297 				return GL_INVALID_OPERATION;
    298 			}
    299 			break;
    300 		case GL_BGRA_EXT:   // GL_APPLE_texture_format_BGRA8888
    301 			switch(type)
    302 			{
    303 			case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_BGRA8_EXT)
    304 			default:               return GL_INVALID_OPERATION;
    305 			}
    306 			break;
    307 		default:
    308 			UNREACHABLE(format);
    309 			return GL_INVALID_ENUM;
    310 		}
    311 
    312 		#undef VALIDATE_INTERNALFORMAT
    313 
    314 		if(!validSizedInternalformat)
    315 		{
    316 			return GL_INVALID_OPERATION;
    317 		}
    318 
    319 		return GL_NO_ERROR;
    320 	}
    321 
    322 	bool IsColorRenderable(GLint internalformat)
    323 	{
    324 		switch(internalformat)
    325 		{
    326 		case GL_RGBA4_OES:
    327 		case GL_RGB5_A1_OES:
    328 		case GL_RGB565_OES:
    329 		case GL_RGB8_OES:
    330 		case GL_RGBA8_OES:
    331 			return true;
    332 		case GL_DEPTH_COMPONENT16_OES:
    333 		case GL_STENCIL_INDEX8_OES:
    334 		case GL_DEPTH24_STENCIL8_OES:
    335 			return false;
    336 		default:
    337 			UNIMPLEMENTED();
    338 		}
    339 
    340 		return false;
    341 	}
    342 
    343 	bool IsDepthRenderable(GLint internalformat)
    344 	{
    345 		switch(internalformat)
    346 		{
    347 		case GL_DEPTH_COMPONENT16_OES:
    348 		case GL_DEPTH24_STENCIL8_OES:
    349 			return true;
    350 		case GL_STENCIL_INDEX8_OES:
    351 		case GL_RGBA4_OES:
    352 		case GL_RGB5_A1_OES:
    353 		case GL_RGB565_OES:
    354 		case GL_RGB8_OES:
    355 		case GL_RGBA8_OES:
    356 			return false;
    357 		default:
    358 			UNIMPLEMENTED();
    359 		}
    360 
    361 		return false;
    362 	}
    363 
    364 	bool IsStencilRenderable(GLint internalformat)
    365 	{
    366 		switch(internalformat)
    367 		{
    368 		case GL_STENCIL_INDEX8_OES:
    369 		case GL_DEPTH24_STENCIL8_OES:
    370 			return true;
    371 		case GL_RGBA4_OES:
    372 		case GL_RGB5_A1_OES:
    373 		case GL_RGB565_OES:
    374 		case GL_RGB8_OES:
    375 		case GL_RGBA8_OES:
    376 		case GL_DEPTH_COMPONENT16_OES:
    377 			return false;
    378 		default:
    379 			UNIMPLEMENTED();
    380 		}
    381 
    382 		return false;
    383 	}
    384 
    385 	GLuint GetAlphaSize(GLint internalformat)
    386 	{
    387 		switch(internalformat)
    388 		{
    389 		case GL_NONE_OES:    return 0;
    390 		case GL_RGBA4_OES:   return 4;
    391 		case GL_RGB5_A1_OES: return 1;
    392 		case GL_RGB565_OES:  return 0;
    393 		case GL_RGB8_OES:    return 0;
    394 		case GL_RGBA8_OES:   return 8;
    395 		case GL_BGRA8_EXT:   return 8;
    396 		default:
    397 		//	UNREACHABLE(internalformat);
    398 			return 0;
    399 		}
    400 	}
    401 
    402 	GLuint GetRedSize(GLint internalformat)
    403 	{
    404 		switch(internalformat)
    405 		{
    406 		case GL_NONE_OES:    return 0;
    407 		case GL_RGBA4_OES:   return 4;
    408 		case GL_RGB5_A1_OES: return 5;
    409 		case GL_RGB565_OES:  return 5;
    410 		case GL_RGB8_OES:    return 8;
    411 		case GL_RGBA8_OES:   return 8;
    412 		case GL_BGRA8_EXT:   return 8;
    413 		default:
    414 		//	UNREACHABLE(internalformat);
    415 			return 0;
    416 		}
    417 	}
    418 
    419 	GLuint GetGreenSize(GLint internalformat)
    420 	{
    421 		switch(internalformat)
    422 		{
    423 		case GL_NONE_OES:    return 0;
    424 		case GL_RGBA4_OES:   return 4;
    425 		case GL_RGB5_A1_OES: return 5;
    426 		case GL_RGB565_OES:  return 6;
    427 		case GL_RGB8_OES:    return 8;
    428 		case GL_RGBA8_OES:   return 8;
    429 		case GL_BGRA8_EXT:   return 8;
    430 		default:
    431 		//	UNREACHABLE(internalformat);
    432 			return 0;
    433 		}
    434 	}
    435 
    436 	GLuint GetBlueSize(GLint internalformat)
    437 	{
    438 		switch(internalformat)
    439 		{
    440 		case GL_NONE_OES:    return 0;
    441 		case GL_RGBA4_OES:   return 4;
    442 		case GL_RGB5_A1_OES: return 5;
    443 		case GL_RGB565_OES:  return 5;
    444 		case GL_RGB8_OES:    return 8;
    445 		case GL_RGBA8_OES:   return 8;
    446 		case GL_BGRA8_EXT:   return 8;
    447 		default:
    448 		//	UNREACHABLE(internalformat);
    449 			return 0;
    450 		}
    451 	}
    452 
    453 	GLuint GetDepthSize(GLint internalformat)
    454 	{
    455 		switch(internalformat)
    456 		{
    457 		case GL_STENCIL_INDEX8_OES:    return 0;
    458 		case GL_DEPTH_COMPONENT16_OES: return 16;
    459 		case GL_DEPTH24_STENCIL8_OES:  return 24;
    460 		default:
    461 		//	UNREACHABLE(internalformat);
    462 			return 0;
    463 		}
    464 	}
    465 
    466 	GLuint GetStencilSize(GLint internalformat)
    467 	{
    468 		switch(internalformat)
    469 		{
    470 		case GL_STENCIL_INDEX8_OES:    return 8;
    471 		case GL_DEPTH_COMPONENT16_OES: return 0;
    472 		case GL_DEPTH24_STENCIL8_OES:  return 8;
    473 		default:
    474 		//	UNREACHABLE(internalformat);
    475 			return 0;
    476 		}
    477 	}
    478 
    479 	bool IsAlpha(GLint internalformat)
    480 	{
    481 		switch(internalformat)
    482 		{
    483 		case GL_ALPHA8_EXT:
    484 			return true;
    485 		default:
    486 			return false;
    487 		}
    488 	}
    489 
    490 	bool IsRGB(GLint internalformat)
    491 	{
    492 		switch(internalformat)
    493 		{
    494 		case GL_LUMINANCE8_EXT:
    495 		case GL_RGB565_OES:
    496 		case GL_RGB8_OES:
    497 		case SW_YV12_BT601:
    498 		case SW_YV12_BT709:
    499 		case SW_YV12_JFIF:
    500 			return true;
    501 		default:
    502 			return false;
    503 		}
    504 	}
    505 
    506 	bool IsRGBA(GLint internalformat)
    507 	{
    508 		switch(internalformat)
    509 		{
    510 		case GL_LUMINANCE8_ALPHA8_EXT:
    511 		case GL_RGBA:
    512 		case GL_BGRA8_EXT:     // GL_EXT_texture_format_BGRA8888
    513 		case GL_RGBA4_OES:
    514 		case GL_RGB5_A1_OES:
    515 		case GL_RGBA8_OES:
    516 			return true;
    517 		default:
    518 			return false;
    519 		}
    520 	}
    521 }
    522 
    523 namespace es2sw
    524 {
    525 	sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
    526 	{
    527 		switch(comparison)
    528 		{
    529 		case GL_NEVER:    return sw::DEPTH_NEVER;
    530 		case GL_ALWAYS:   return sw::DEPTH_ALWAYS;
    531 		case GL_LESS:     return sw::DEPTH_LESS;
    532 		case GL_LEQUAL:   return sw::DEPTH_LESSEQUAL;
    533 		case GL_EQUAL:    return sw::DEPTH_EQUAL;
    534 		case GL_GREATER:  return sw::DEPTH_GREATER;
    535 		case GL_GEQUAL:   return sw::DEPTH_GREATEREQUAL;
    536 		case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
    537 		default: UNREACHABLE(comparison);
    538 		}
    539 
    540 		return sw::DEPTH_ALWAYS;
    541 	}
    542 
    543 	sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
    544 	{
    545 		switch(comparison)
    546 		{
    547 		case GL_NEVER:    return sw::STENCIL_NEVER;
    548 		case GL_ALWAYS:   return sw::STENCIL_ALWAYS;
    549 		case GL_LESS:     return sw::STENCIL_LESS;
    550 		case GL_LEQUAL:   return sw::STENCIL_LESSEQUAL;
    551 		case GL_EQUAL:    return sw::STENCIL_EQUAL;
    552 		case GL_GREATER:  return sw::STENCIL_GREATER;
    553 		case GL_GEQUAL:   return sw::STENCIL_GREATEREQUAL;
    554 		case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
    555 		default: UNREACHABLE(comparison);
    556 		}
    557 
    558 		return sw::STENCIL_ALWAYS;
    559 	}
    560 
    561 	sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison)
    562 	{
    563 		switch(comparison)
    564 		{
    565 		case GL_NEVER:    return sw::ALPHA_NEVER;
    566 		case GL_ALWAYS:   return sw::ALPHA_ALWAYS;
    567 		case GL_LESS:     return sw::ALPHA_LESS;
    568 		case GL_LEQUAL:   return sw::ALPHA_LESSEQUAL;
    569 		case GL_EQUAL:    return sw::ALPHA_EQUAL;
    570 		case GL_GREATER:  return sw::ALPHA_GREATER;
    571 		case GL_GEQUAL:   return sw::ALPHA_GREATEREQUAL;
    572 		case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL;
    573 		default: UNREACHABLE(comparison);
    574 		}
    575 
    576 		return sw::ALPHA_ALWAYS;
    577 	}
    578 
    579 	sw::Color<float> ConvertColor(es1::Color color)
    580 	{
    581 		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
    582 	}
    583 
    584 	sw::BlendFactor ConvertBlendFunc(GLenum blend)
    585 	{
    586 		switch(blend)
    587 		{
    588 		case GL_ZERO:                     return sw::BLEND_ZERO;
    589 		case GL_ONE:                      return sw::BLEND_ONE;
    590 		case GL_SRC_COLOR:                return sw::BLEND_SOURCE;
    591 		case GL_ONE_MINUS_SRC_COLOR:      return sw::BLEND_INVSOURCE;
    592 		case GL_DST_COLOR:                return sw::BLEND_DEST;
    593 		case GL_ONE_MINUS_DST_COLOR:      return sw::BLEND_INVDEST;
    594 		case GL_SRC_ALPHA:                return sw::BLEND_SOURCEALPHA;
    595 		case GL_ONE_MINUS_SRC_ALPHA:      return sw::BLEND_INVSOURCEALPHA;
    596 		case GL_DST_ALPHA:                return sw::BLEND_DESTALPHA;
    597 		case GL_ONE_MINUS_DST_ALPHA:      return sw::BLEND_INVDESTALPHA;
    598 		case GL_SRC_ALPHA_SATURATE:       return sw::BLEND_SRCALPHASAT;
    599 		default: UNREACHABLE(blend);
    600 		}
    601 
    602 		return sw::BLEND_ZERO;
    603 	}
    604 
    605 	sw::BlendOperation ConvertBlendOp(GLenum blendOp)
    606 	{
    607 		switch(blendOp)
    608 		{
    609 		case GL_FUNC_ADD_OES:              return sw::BLENDOP_ADD;
    610 		case GL_FUNC_SUBTRACT_OES:         return sw::BLENDOP_SUB;
    611 		case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB;
    612 		case GL_MIN_EXT:                   return sw::BLENDOP_MIN;
    613 		case GL_MAX_EXT:                   return sw::BLENDOP_MAX;
    614 		default: UNREACHABLE(blendOp);
    615 		}
    616 
    617 		return sw::BLENDOP_ADD;
    618 	}
    619 
    620 	sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation)
    621 	{
    622 		switch(logicalOperation)
    623 		{
    624 		case GL_CLEAR:         return sw::LOGICALOP_CLEAR;
    625 		case GL_SET:           return sw::LOGICALOP_SET;
    626 		case GL_COPY:          return sw::LOGICALOP_COPY;
    627 		case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED;
    628 		case GL_NOOP:          return sw::LOGICALOP_NOOP;
    629 		case GL_INVERT:        return sw::LOGICALOP_INVERT;
    630 		case GL_AND:           return sw::LOGICALOP_AND;
    631 		case GL_NAND:          return sw::LOGICALOP_NAND;
    632 		case GL_OR:            return sw::LOGICALOP_OR;
    633 		case GL_NOR:           return sw::LOGICALOP_NOR;
    634 		case GL_XOR:           return sw::LOGICALOP_XOR;
    635 		case GL_EQUIV:         return sw::LOGICALOP_EQUIV;
    636 		case GL_AND_REVERSE:   return sw::LOGICALOP_AND_REVERSE;
    637 		case GL_AND_INVERTED:  return sw::LOGICALOP_AND_INVERTED;
    638 		case GL_OR_REVERSE:    return sw::LOGICALOP_OR_REVERSE;
    639 		case GL_OR_INVERTED:   return sw::LOGICALOP_OR_INVERTED;
    640 		default: UNREACHABLE(logicalOperation);
    641 		}
    642 
    643 		return sw::LOGICALOP_COPY;
    644 	}
    645 
    646 	sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
    647 	{
    648 		switch(stencilOp)
    649 		{
    650 		case GL_ZERO:          return sw::OPERATION_ZERO;
    651 		case GL_KEEP:          return sw::OPERATION_KEEP;
    652 		case GL_REPLACE:       return sw::OPERATION_REPLACE;
    653 		case GL_INCR:          return sw::OPERATION_INCRSAT;
    654 		case GL_DECR:          return sw::OPERATION_DECRSAT;
    655 		case GL_INVERT:        return sw::OPERATION_INVERT;
    656 		case GL_INCR_WRAP_OES: return sw::OPERATION_INCR;
    657 		case GL_DECR_WRAP_OES: return sw::OPERATION_DECR;
    658 		default: UNREACHABLE(stencilOp);
    659 		}
    660 
    661 		return sw::OPERATION_KEEP;
    662 	}
    663 
    664 	sw::AddressingMode ConvertTextureWrap(GLenum wrap)
    665 	{
    666 		switch(wrap)
    667 		{
    668 		case GL_REPEAT:              return sw::ADDRESSING_WRAP;
    669 		case GL_CLAMP_TO_EDGE:       return sw::ADDRESSING_CLAMP;
    670 		case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR;
    671 		default: UNREACHABLE(wrap);
    672 		}
    673 
    674 		return sw::ADDRESSING_WRAP;
    675 	}
    676 
    677 	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
    678 	{
    679 		switch(cullFace)
    680 		{
    681 		case GL_FRONT:
    682 			return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
    683 		case GL_BACK:
    684 			return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
    685 		case GL_FRONT_AND_BACK:
    686 			return sw::CULL_NONE;   // culling will be handled during draw
    687 		default: UNREACHABLE(cullFace);
    688 		}
    689 
    690 		return sw::CULL_COUNTERCLOCKWISE;
    691 	}
    692 
    693 	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
    694 	{
    695 		return (red   ? 0x00000001 : 0) |
    696 			   (green ? 0x00000002 : 0) |
    697 			   (blue  ? 0x00000004 : 0) |
    698 			   (alpha ? 0x00000008 : 0);
    699 	}
    700 
    701 	sw::MipmapType ConvertMipMapFilter(GLenum minFilter)
    702 	{
    703 		switch(minFilter)
    704 		{
    705 		case GL_NEAREST:
    706 		case GL_LINEAR:
    707 			return sw::MIPMAP_NONE;
    708 			break;
    709 		case GL_NEAREST_MIPMAP_NEAREST:
    710 		case GL_LINEAR_MIPMAP_NEAREST:
    711 			return sw::MIPMAP_POINT;
    712 			break;
    713 		case GL_NEAREST_MIPMAP_LINEAR:
    714 		case GL_LINEAR_MIPMAP_LINEAR:
    715 			return sw::MIPMAP_LINEAR;
    716 			break;
    717 		default:
    718 			UNREACHABLE(minFilter);
    719 			return sw::MIPMAP_NONE;
    720 		}
    721 	}
    722 
    723 	sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
    724 	{
    725 		if(maxAnisotropy > 1.0f)
    726 		{
    727 			return sw::FILTER_ANISOTROPIC;
    728 		}
    729 
    730 		sw::FilterType magFilterType = sw::FILTER_POINT;
    731 		switch(magFilter)
    732 		{
    733 		case GL_NEAREST: magFilterType = sw::FILTER_POINT;  break;
    734 		case GL_LINEAR:  magFilterType = sw::FILTER_LINEAR; break;
    735 		default: UNREACHABLE(magFilter);
    736 		}
    737 
    738 		switch(minFilter)
    739 		{
    740 		case GL_NEAREST:
    741 		case GL_NEAREST_MIPMAP_NEAREST:
    742 		case GL_NEAREST_MIPMAP_LINEAR:
    743 			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
    744 		case GL_LINEAR:
    745 		case GL_LINEAR_MIPMAP_NEAREST:
    746 		case GL_LINEAR_MIPMAP_LINEAR:
    747 			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR;
    748 		default:
    749 			UNREACHABLE(minFilter);
    750 			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
    751 		}
    752 	}
    753 
    754 	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType,  sw::DrawType &drawType, int &primitiveCount)
    755 	{
    756 		switch(primitiveType)
    757 		{
    758 		case GL_POINTS:
    759 			drawType = sw::DRAW_POINTLIST;
    760 			primitiveCount = elementCount;
    761 			break;
    762 		case GL_LINES:
    763 			drawType = sw::DRAW_LINELIST;
    764 			primitiveCount = elementCount / 2;
    765 			break;
    766 		case GL_LINE_LOOP:
    767 			drawType = sw::DRAW_LINELOOP;
    768 			primitiveCount = elementCount;
    769 			break;
    770 		case GL_LINE_STRIP:
    771 			drawType = sw::DRAW_LINESTRIP;
    772 			primitiveCount = elementCount - 1;
    773 			break;
    774 		case GL_TRIANGLES:
    775 			drawType = sw::DRAW_TRIANGLELIST;
    776 			primitiveCount = elementCount / 3;
    777 			break;
    778 		case GL_TRIANGLE_STRIP:
    779 			drawType = sw::DRAW_TRIANGLESTRIP;
    780 			primitiveCount = elementCount - 2;
    781 			break;
    782 		case GL_TRIANGLE_FAN:
    783 			drawType = sw::DRAW_TRIANGLEFAN;
    784 			primitiveCount = elementCount - 2;
    785 			break;
    786 		default:
    787 			return false;
    788 		}
    789 
    790 		sw::DrawType elementSize;
    791 		switch(elementType)
    792 		{
    793 		case GL_NONE_OES:       elementSize = sw::DRAW_NONINDEXED; break;
    794 		case GL_UNSIGNED_BYTE:  elementSize = sw::DRAW_INDEXED8;   break;
    795 		case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16;  break;
    796 		case GL_UNSIGNED_INT:   elementSize = sw::DRAW_INDEXED32;  break;
    797 		default: return false;
    798 		}
    799 
    800 		drawType = sw::DrawType(drawType | elementSize);
    801 
    802 		return true;
    803 	}
    804 
    805 	sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation)
    806 	{
    807 		switch(operation)
    808 		{
    809 		case GL_REPLACE:        return sw::TextureStage::STAGE_SELECTARG1;
    810 		case GL_MODULATE:       return sw::TextureStage::STAGE_MODULATE;
    811 		case GL_ADD:            return sw::TextureStage::STAGE_ADD;
    812 		case GL_ADD_SIGNED:     return sw::TextureStage::STAGE_ADDSIGNED;
    813 		case GL_INTERPOLATE:    return sw::TextureStage::STAGE_LERP;
    814 		case GL_SUBTRACT:       return sw::TextureStage::STAGE_SUBTRACT;
    815 		case GL_DOT3_RGB:       return sw::TextureStage::STAGE_DOT3;
    816 		case GL_DOT3_RGBA:      return sw::TextureStage::STAGE_DOT3;
    817 		default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1;
    818 		}
    819 	}
    820 
    821 	sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument)
    822 	{
    823 		switch(argument)
    824 		{
    825 		case GL_TEXTURE:        return sw::TextureStage::SOURCE_TEXTURE;
    826 		case GL_CONSTANT:       return sw::TextureStage::SOURCE_CONSTANT;
    827 		case GL_PRIMARY_COLOR:  return sw::TextureStage::SOURCE_DIFFUSE;
    828 		case GL_PREVIOUS:       return sw::TextureStage::SOURCE_CURRENT;
    829 		default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT;
    830 		}
    831 	}
    832 
    833 	sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand)
    834 	{
    835 		switch(operand)
    836 		{
    837 		case GL_SRC_COLOR:           return sw::TextureStage::MODIFIER_COLOR;
    838 		case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR;
    839 		case GL_SRC_ALPHA:           return sw::TextureStage::MODIFIER_ALPHA;
    840 		case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA;
    841 		default: UNREACHABLE(operand);      return sw::TextureStage::MODIFIER_COLOR;
    842 		}
    843 	}
    844 }
    845 
    846 namespace sw2es
    847 {
    848 	GLenum ConvertBackBufferFormat(sw::Format format)
    849 	{
    850 		switch(format)
    851 		{
    852 		case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES;
    853 		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
    854 		case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES;
    855 		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES;
    856 		case sw::FORMAT_R5G6B5:   return GL_RGB565_OES;
    857 		case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
    858 		case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES;
    859 		default:
    860 			UNREACHABLE(format);
    861 		}
    862 
    863 		return GL_RGBA4_OES;
    864 	}
    865 
    866 	GLenum ConvertDepthStencilFormat(sw::Format format)
    867 	{
    868 		switch(format)
    869 		{
    870 		case sw::FORMAT_D16:
    871 		case sw::FORMAT_D24X8:
    872 		case sw::FORMAT_D32:
    873 			return GL_DEPTH_COMPONENT16_OES;
    874 		case sw::FORMAT_D24S8:
    875 			return GL_DEPTH24_STENCIL8_OES;
    876 		default:
    877 			UNREACHABLE(format);
    878 		}
    879 
    880 		return GL_DEPTH24_STENCIL8_OES;
    881 	}
    882 }
    883