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 {
IsCompressed(GLenum format)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 
IsSizedInternalFormat(GLint internalformat)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 
ValidateSubImageParams(bool compressed,bool copy,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,Texture * texture)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 
IsDepthTexture(GLenum format)101 	bool IsDepthTexture(GLenum format)
102 	{
103 		return format == GL_DEPTH_STENCIL_OES;
104 	}
105 
IsStencilTexture(GLenum format)106 	bool IsStencilTexture(GLenum format)
107 	{
108 		return format == GL_DEPTH_STENCIL_OES;
109 	}
110 
IsCubemapTextureTarget(GLenum target)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 
CubeFaceIndex(GLenum cubeFace)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 
IsTextureTarget(GLenum target)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.
ValidateTextureFormatType(GLenum format,GLenum type,GLint internalformat,GLenum target)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 
IsColorRenderable(GLint internalformat)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 
IsDepthRenderable(GLint internalformat)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 
IsStencilRenderable(GLint internalformat)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 
GetAlphaSize(GLint internalformat)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 
GetRedSize(GLint internalformat)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 
GetGreenSize(GLint internalformat)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 
GetBlueSize(GLint internalformat)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 
GetDepthSize(GLint internalformat)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 
GetStencilSize(GLint internalformat)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 
IsAlpha(GLint internalformat)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 
IsRGB(GLint internalformat)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 
IsRGBA(GLint internalformat)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 {
ConvertDepthComparison(GLenum comparison)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 
ConvertStencilComparison(GLenum comparison)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 
ConvertAlphaComparison(GLenum comparison)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 
ConvertColor(es1::Color color)579 	sw::Color<float> ConvertColor(es1::Color color)
580 	{
581 		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
582 	}
583 
ConvertBlendFunc(GLenum blend)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 
ConvertBlendOp(GLenum blendOp)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 
ConvertLogicalOperation(GLenum logicalOperation)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 
ConvertStencilOp(GLenum stencilOp)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 
ConvertTextureWrap(GLenum wrap)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 
ConvertCullMode(GLenum cullFace,GLenum frontFace)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 
ConvertColorMask(bool red,bool green,bool blue,bool alpha)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 
ConvertMipMapFilter(GLenum minFilter)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 
ConvertTextureFilter(GLenum minFilter,GLenum magFilter,float maxAnisotropy)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 
ConvertPrimitiveType(GLenum primitiveType,GLsizei elementCount,GLenum elementType,sw::DrawType & drawType,int & primitiveCount)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 
ConvertCombineOperation(GLenum operation)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 
ConvertSourceArgument(GLenum argument)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 
ConvertSourceOperand(GLenum operand)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 {
ConvertBackBufferFormat(sw::Format format)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 
ConvertDepthStencilFormat(sw::Format format)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