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
26namespace gl
27{
28	unsigned int UniformComponentCount(GLenum type)
29	{
30		switch(type)
31		{
32		case GL_BOOL:
33		case GL_FLOAT:
34		case GL_INT:
35		case GL_SAMPLER_2D:
36		case GL_SAMPLER_CUBE:
37			return 1;
38		case GL_BOOL_VEC2:
39		case GL_FLOAT_VEC2:
40		case GL_INT_VEC2:
41			return 2;
42		case GL_INT_VEC3:
43		case GL_FLOAT_VEC3:
44		case GL_BOOL_VEC3:
45			return 3;
46		case GL_BOOL_VEC4:
47		case GL_FLOAT_VEC4:
48		case GL_INT_VEC4:
49		case GL_FLOAT_MAT2:
50			return 4;
51		case GL_FLOAT_MAT3:
52			return 9;
53		case GL_FLOAT_MAT4:
54			return 16;
55		default:
56			UNREACHABLE(type);
57		}
58
59		return 0;
60	}
61
62	GLenum UniformComponentType(GLenum type)
63	{
64		switch(type)
65		{
66		case GL_BOOL:
67		case GL_BOOL_VEC2:
68		case GL_BOOL_VEC3:
69		case GL_BOOL_VEC4:
70			return GL_BOOL;
71		case GL_FLOAT:
72		case GL_FLOAT_VEC2:
73		case GL_FLOAT_VEC3:
74		case GL_FLOAT_VEC4:
75		case GL_FLOAT_MAT2:
76		case GL_FLOAT_MAT3:
77		case GL_FLOAT_MAT4:
78			return GL_FLOAT;
79		case GL_INT:
80		case GL_SAMPLER_2D:
81		case GL_SAMPLER_CUBE:
82		case GL_INT_VEC2:
83		case GL_INT_VEC3:
84		case GL_INT_VEC4:
85			return GL_INT;
86		default:
87			UNREACHABLE(type);
88		}
89
90		return GL_NONE;
91	}
92
93	size_t UniformTypeSize(GLenum type)
94	{
95		switch(type)
96		{
97		case GL_BOOL:  return sizeof(GLboolean);
98		case GL_FLOAT: return sizeof(GLfloat);
99		case GL_INT:   return sizeof(GLint);
100		}
101
102		return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
103	}
104
105	int VariableRowCount(GLenum type)
106	{
107		switch(type)
108		{
109		case GL_NONE:
110			return 0;
111		case GL_BOOL:
112		case GL_FLOAT:
113		case GL_INT:
114		case GL_BOOL_VEC2:
115		case GL_FLOAT_VEC2:
116		case GL_INT_VEC2:
117		case GL_INT_VEC3:
118		case GL_FLOAT_VEC3:
119		case GL_BOOL_VEC3:
120		case GL_BOOL_VEC4:
121		case GL_FLOAT_VEC4:
122		case GL_INT_VEC4:
123		case GL_SAMPLER_2D:
124		case GL_SAMPLER_CUBE:
125			return 1;
126		case GL_FLOAT_MAT2:
127			return 2;
128		case GL_FLOAT_MAT3:
129			return 3;
130		case GL_FLOAT_MAT4:
131			return 4;
132		default:
133			UNREACHABLE(type);
134		}
135
136		return 0;
137	}
138
139	int VariableColumnCount(GLenum type)
140	{
141		switch(type)
142		{
143		case GL_NONE:
144			return 0;
145		case GL_BOOL:
146		case GL_FLOAT:
147		case GL_INT:
148			return 1;
149		case GL_BOOL_VEC2:
150		case GL_FLOAT_VEC2:
151		case GL_INT_VEC2:
152		case GL_FLOAT_MAT2:
153			return 2;
154		case GL_INT_VEC3:
155		case GL_FLOAT_VEC3:
156		case GL_BOOL_VEC3:
157		case GL_FLOAT_MAT3:
158			return 3;
159		case GL_BOOL_VEC4:
160		case GL_FLOAT_VEC4:
161		case GL_INT_VEC4:
162		case GL_FLOAT_MAT4:
163			return 4;
164		default:
165			UNREACHABLE(type);
166		}
167
168		return 0;
169	}
170
171	int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
172	{
173		ASSERT(allocationSize <= bitsSize);
174
175		unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
176
177		for(unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
178		{
179			if((*bits & mask) == 0)
180			{
181				*bits |= mask;
182				return i;
183			}
184
185			mask <<= 1;
186		}
187
188		return -1;
189	}
190
191	GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
192	{
193		ASSERT(alignment > 0 && isPow2(alignment));
194
195		GLsizei rawPitch = ComputePixelSize(format, type) * width;
196		return (rawPitch + alignment - 1) & ~(alignment - 1);
197	}
198
199	GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
200	{
201		return ComputeCompressedSize(width, 1, format);
202	}
203
204	GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
205	{
206		switch(format)
207		{
208		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
209		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
210			return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
211		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
212		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
213			return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
214		default:
215			return 0;
216		}
217	}
218
219	bool IsCompressed(GLenum format)
220	{
221		return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
222		       format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
223		       format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
224		       format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
225	}
226
227	bool IsDepthTexture(GLenum format)
228	{
229		return format == GL_DEPTH_COMPONENT ||
230		       format == GL_DEPTH_STENCIL_EXT;
231	}
232
233	bool IsStencilTexture(GLenum format)
234	{
235		return format == GL_STENCIL_INDEX ||
236		       format == GL_DEPTH_STENCIL_EXT;
237	}
238
239	// Returns the size, in bytes, of a single texel in an Image
240	int ComputePixelSize(GLenum format, GLenum type)
241	{
242		switch(type)
243		{
244		case GL_UNSIGNED_BYTE:
245			switch(format)
246			{
247			case GL_ALPHA:           return sizeof(unsigned char);
248			case GL_LUMINANCE:       return sizeof(unsigned char);
249			case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
250			case GL_RGB:             return sizeof(unsigned char) * 3;
251			case GL_RGBA:            return sizeof(unsigned char) * 4;
252			case GL_BGRA_EXT:        return sizeof(unsigned char) * 4;
253			default: UNREACHABLE(format);
254			}
255			break;
256		case GL_UNSIGNED_SHORT_4_4_4_4:
257		case GL_UNSIGNED_SHORT_5_5_5_1:
258		case GL_UNSIGNED_SHORT_5_6_5:
259		case GL_UNSIGNED_SHORT:
260			return sizeof(unsigned short);
261		case GL_UNSIGNED_INT:
262		case GL_UNSIGNED_INT_24_8_EXT:
263		case GL_UNSIGNED_INT_8_8_8_8_REV:
264			return sizeof(unsigned int);
265		case GL_FLOAT:
266			switch(format)
267			{
268			case GL_ALPHA:           return sizeof(float);
269			case GL_LUMINANCE:       return sizeof(float);
270			case GL_DEPTH_COMPONENT: return sizeof(float);
271			case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
272			case GL_RGB:             return sizeof(float) * 3;
273			case GL_RGBA:            return sizeof(float) * 4;
274			default: UNREACHABLE(format);
275			}
276			break;
277		case GL_HALF_FLOAT:
278			switch(format)
279			{
280			case GL_ALPHA:           return sizeof(unsigned short);
281			case GL_LUMINANCE:       return sizeof(unsigned short);
282			case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
283			case GL_RGB:             return sizeof(unsigned short) * 3;
284			case GL_RGBA:            return sizeof(unsigned short) * 4;
285			default: UNREACHABLE(format);
286			}
287			break;
288		default: UNREACHABLE(type);
289		}
290
291		return 0;
292	}
293
294	bool IsCubemapTextureTarget(GLenum target)
295	{
296		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
297	}
298
299	int CubeFaceIndex(GLenum cubeFace)
300	{
301		switch(cubeFace)
302		{
303		case GL_TEXTURE_CUBE_MAP:
304		case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;
305		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;
306		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;
307		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;
308		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;
309		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;
310		default: UNREACHABLE(cubeFace); return 0;
311		}
312	}
313
314	bool IsTextureTarget(GLenum target)
315	{
316		return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
317	}
318
319	// Verify that format/type are one of the combinations from table 3.4.
320	bool CheckTextureFormatType(GLenum format, GLenum type)
321	{
322		switch(type)
323		{
324		case GL_UNSIGNED_BYTE:
325			switch(format)
326			{
327			case GL_RGBA:
328			case GL_BGRA_EXT:
329			case GL_RGB:
330			case GL_ALPHA:
331			case GL_LUMINANCE:
332			case GL_LUMINANCE_ALPHA:
333				return true;
334			default:
335				return false;
336			}
337		case GL_FLOAT:
338		case GL_HALF_FLOAT:
339			switch(format)
340			{
341			case GL_RGBA:
342			case GL_RGB:
343			case GL_ALPHA:
344			case GL_LUMINANCE:
345			case GL_LUMINANCE_ALPHA:
346				return true;
347			default:
348				return false;
349			}
350		case GL_UNSIGNED_SHORT_4_4_4_4:
351		case GL_UNSIGNED_SHORT_5_5_5_1:
352			return (format == GL_RGBA);
353		case GL_UNSIGNED_SHORT_5_6_5:
354			return (format == GL_RGB);
355		case GL_UNSIGNED_INT:
356			return (format == GL_DEPTH_COMPONENT);
357		case GL_UNSIGNED_INT_24_8_EXT:
358			return (format == GL_DEPTH_STENCIL_EXT);
359		case GL_UNSIGNED_INT_8_8_8_8_REV:
360			return (format == GL_BGRA);
361		default:
362			return false;
363		}
364	}
365
366	bool IsColorRenderable(GLenum internalformat)
367	{
368		switch(internalformat)
369		{
370		case GL_RGBA4:
371		case GL_RGB5_A1:
372		case GL_RGB565:
373		case GL_RGB8_EXT:
374		case GL_RGBA8_EXT:
375			return true;
376		case GL_DEPTH_COMPONENT16:
377		case GL_DEPTH_COMPONENT24:
378		case GL_STENCIL_INDEX8:
379		case GL_DEPTH24_STENCIL8_EXT:
380			return false;
381		default:
382			UNIMPLEMENTED();
383		}
384
385		return false;
386	}
387
388	bool IsDepthRenderable(GLenum internalformat)
389	{
390		switch(internalformat)
391		{
392		case GL_DEPTH_COMPONENT16:
393		case GL_DEPTH_COMPONENT24:
394		case GL_DEPTH24_STENCIL8_EXT:
395			return true;
396		case GL_STENCIL_INDEX8:
397		case GL_RGBA4:
398		case GL_RGB5_A1:
399		case GL_RGB565:
400		case GL_RGB8_EXT:
401		case GL_RGBA8_EXT:
402			return false;
403		default:
404			UNIMPLEMENTED();
405		}
406
407		return false;
408	}
409
410	bool IsStencilRenderable(GLenum internalformat)
411	{
412		switch(internalformat)
413		{
414		case GL_STENCIL_INDEX8:
415		case GL_DEPTH24_STENCIL8_EXT:
416			return true;
417		case GL_RGBA4:
418		case GL_RGB5_A1:
419		case GL_RGB565:
420		case GL_RGB8_EXT:
421		case GL_RGBA8_EXT:
422		case GL_DEPTH_COMPONENT16:
423		case GL_DEPTH_COMPONENT24:
424			return false;
425		default:
426			UNIMPLEMENTED();
427		}
428
429		return false;
430	}
431}
432
433namespace es2sw
434{
435	sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
436	{
437		switch(comparison)
438		{
439		case GL_NEVER:    return sw::DEPTH_NEVER;
440		case GL_ALWAYS:   return sw::DEPTH_ALWAYS;
441		case GL_LESS:     return sw::DEPTH_LESS;
442		case GL_LEQUAL:   return sw::DEPTH_LESSEQUAL;
443		case GL_EQUAL:    return sw::DEPTH_EQUAL;
444		case GL_GREATER:  return sw::DEPTH_GREATER;
445		case GL_GEQUAL:   return sw::DEPTH_GREATEREQUAL;
446		case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
447		default: UNREACHABLE(comparison);
448		}
449
450		return sw::DEPTH_ALWAYS;
451	}
452
453	sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
454	{
455		switch(comparison)
456		{
457		case GL_NEVER:    return sw::STENCIL_NEVER;
458		case GL_ALWAYS:   return sw::STENCIL_ALWAYS;
459		case GL_LESS:     return sw::STENCIL_LESS;
460		case GL_LEQUAL:   return sw::STENCIL_LESSEQUAL;
461		case GL_EQUAL:    return sw::STENCIL_EQUAL;
462		case GL_GREATER:  return sw::STENCIL_GREATER;
463		case GL_GEQUAL:   return sw::STENCIL_GREATEREQUAL;
464		case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
465		default: UNREACHABLE(comparison);
466		}
467
468		return sw::STENCIL_ALWAYS;
469	}
470
471	sw::Color<float> ConvertColor(gl::Color color)
472	{
473		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
474	}
475
476	sw::BlendFactor ConvertBlendFunc(GLenum blend)
477	{
478		switch(blend)
479		{
480		case GL_ZERO:                     return sw::BLEND_ZERO;
481		case GL_ONE:                      return sw::BLEND_ONE;
482		case GL_SRC_COLOR:                return sw::BLEND_SOURCE;
483		case GL_ONE_MINUS_SRC_COLOR:      return sw::BLEND_INVSOURCE;
484		case GL_DST_COLOR:                return sw::BLEND_DEST;
485		case GL_ONE_MINUS_DST_COLOR:      return sw::BLEND_INVDEST;
486		case GL_SRC_ALPHA:                return sw::BLEND_SOURCEALPHA;
487		case GL_ONE_MINUS_SRC_ALPHA:      return sw::BLEND_INVSOURCEALPHA;
488		case GL_DST_ALPHA:                return sw::BLEND_DESTALPHA;
489		case GL_ONE_MINUS_DST_ALPHA:      return sw::BLEND_INVDESTALPHA;
490		case GL_CONSTANT_COLOR:           return sw::BLEND_CONSTANT;
491		case GL_ONE_MINUS_CONSTANT_COLOR: return sw::BLEND_INVCONSTANT;
492		case GL_CONSTANT_ALPHA:           return sw::BLEND_CONSTANTALPHA;
493		case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::BLEND_INVCONSTANTALPHA;
494		case GL_SRC_ALPHA_SATURATE:       return sw::BLEND_SRCALPHASAT;
495		default: UNREACHABLE(blend);
496		}
497
498		return sw::BLEND_ZERO;
499	}
500
501	sw::BlendOperation ConvertBlendOp(GLenum blendOp)
502	{
503		switch(blendOp)
504		{
505		case GL_FUNC_ADD:              return sw::BLENDOP_ADD;
506		case GL_FUNC_SUBTRACT:         return sw::BLENDOP_SUB;
507		case GL_FUNC_REVERSE_SUBTRACT: return sw::BLENDOP_INVSUB;
508		case GL_MIN_EXT:               return sw::BLENDOP_MIN;
509		case GL_MAX_EXT:               return sw::BLENDOP_MAX;
510		default: UNREACHABLE(blendOp);
511		}
512
513		return sw::BLENDOP_ADD;
514	}
515
516	sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation)
517	{
518		switch(logicalOperation)
519		{
520		case GL_CLEAR:         return sw::LOGICALOP_CLEAR;
521		case GL_SET:           return sw::LOGICALOP_SET;
522		case GL_COPY:          return sw::LOGICALOP_COPY;
523		case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED;
524		case GL_NOOP:          return sw::LOGICALOP_NOOP;
525		case GL_INVERT:        return sw::LOGICALOP_INVERT;
526		case GL_AND:           return sw::LOGICALOP_AND;
527		case GL_NAND:          return sw::LOGICALOP_NAND;
528		case GL_OR:            return sw::LOGICALOP_OR;
529		case GL_NOR:           return sw::LOGICALOP_NOR;
530		case GL_XOR:           return sw::LOGICALOP_XOR;
531		case GL_EQUIV:         return sw::LOGICALOP_EQUIV;
532		case GL_AND_REVERSE:   return sw::LOGICALOP_AND_REVERSE;
533		case GL_AND_INVERTED:  return sw::LOGICALOP_AND_INVERTED;
534		case GL_OR_REVERSE:    return sw::LOGICALOP_OR_REVERSE;
535		case GL_OR_INVERTED:   return sw::LOGICALOP_OR_INVERTED;
536		default: UNREACHABLE(logicalOperation);
537		}
538
539		return sw::LOGICALOP_COPY;
540	}
541
542	sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
543	{
544		switch(stencilOp)
545		{
546		case GL_ZERO:      return sw::OPERATION_ZERO;
547		case GL_KEEP:      return sw::OPERATION_KEEP;
548		case GL_REPLACE:   return sw::OPERATION_REPLACE;
549		case GL_INCR:      return sw::OPERATION_INCRSAT;
550		case GL_DECR:      return sw::OPERATION_DECRSAT;
551		case GL_INVERT:    return sw::OPERATION_INVERT;
552		case GL_INCR_WRAP: return sw::OPERATION_INCR;
553		case GL_DECR_WRAP: return sw::OPERATION_DECR;
554		default: UNREACHABLE(stencilOp);
555		}
556
557		return sw::OPERATION_KEEP;
558	}
559
560	sw::AddressingMode ConvertTextureWrap(GLenum wrap)
561	{
562		switch(wrap)
563		{
564		case GL_CLAMP:             return sw::ADDRESSING_CLAMP;
565		case GL_REPEAT:            return sw::ADDRESSING_WRAP;
566		case GL_CLAMP_TO_EDGE:     return sw::ADDRESSING_CLAMP;
567		case GL_MIRRORED_REPEAT:   return sw::ADDRESSING_MIRROR;
568		default: UNREACHABLE(wrap);
569		}
570
571		return sw::ADDRESSING_WRAP;
572	}
573
574	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
575	{
576		switch(cullFace)
577		{
578		case GL_FRONT:
579			return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
580		case GL_BACK:
581			return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
582		case GL_FRONT_AND_BACK:
583			return sw::CULL_NONE;   // culling will be handled during draw
584		default: UNREACHABLE(cullFace);
585		}
586
587		return sw::CULL_COUNTERCLOCKWISE;
588	}
589
590	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
591	{
592		return (red   ? 0x00000001 : 0) |
593			   (green ? 0x00000002 : 0) |
594			   (blue  ? 0x00000004 : 0) |
595			   (alpha ? 0x00000008 : 0);
596	}
597
598	sw::MipmapType ConvertMipMapFilter(GLenum minFilter)
599	{
600		switch(minFilter)
601		{
602		case GL_NEAREST:
603		case GL_LINEAR:
604			return sw::MIPMAP_NONE;
605			break;
606		case GL_NEAREST_MIPMAP_NEAREST:
607		case GL_LINEAR_MIPMAP_NEAREST:
608			return sw::MIPMAP_POINT;
609			break;
610		case GL_NEAREST_MIPMAP_LINEAR:
611		case GL_LINEAR_MIPMAP_LINEAR:
612			return sw::MIPMAP_LINEAR;
613			break;
614		default:
615			UNREACHABLE(minFilter);
616			return sw::MIPMAP_NONE;
617		}
618	}
619
620	sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
621	{
622		if(maxAnisotropy > 1.0f)
623		{
624			return sw::FILTER_ANISOTROPIC;
625		}
626
627		switch(minFilter)
628		{
629		case GL_NEAREST:
630		case GL_NEAREST_MIPMAP_NEAREST:
631		case GL_NEAREST_MIPMAP_LINEAR:
632			return (magFilter == GL_NEAREST) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
633		case GL_LINEAR:
634		case GL_LINEAR_MIPMAP_NEAREST:
635		case GL_LINEAR_MIPMAP_LINEAR:
636			return (magFilter == GL_NEAREST) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR;
637		default:
638			UNREACHABLE(minFilter);
639			return sw::FILTER_LINEAR;
640		}
641	}
642
643	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,  gl::PrimitiveType &swPrimitiveType, int &primitiveCount)
644	{
645		switch(primitiveType)
646		{
647		case GL_POINTS:
648			swPrimitiveType = gl::DRAW_POINTLIST;
649			primitiveCount = elementCount;
650			break;
651		case GL_LINES:
652			swPrimitiveType = gl::DRAW_LINELIST;
653			primitiveCount = elementCount / 2;
654			break;
655		case GL_LINE_LOOP:
656			swPrimitiveType = gl::DRAW_LINELOOP;
657			primitiveCount = elementCount;
658			break;
659		case GL_LINE_STRIP:
660			swPrimitiveType = gl::DRAW_LINESTRIP;
661			primitiveCount = elementCount - 1;
662			break;
663		case GL_TRIANGLES:
664			swPrimitiveType = gl::DRAW_TRIANGLELIST;
665			primitiveCount = elementCount / 3;
666			break;
667		case GL_TRIANGLE_STRIP:
668			swPrimitiveType = gl::DRAW_TRIANGLESTRIP;
669			primitiveCount = elementCount - 2;
670			break;
671		case GL_TRIANGLE_FAN:
672			swPrimitiveType = gl::DRAW_TRIANGLEFAN;
673			primitiveCount = elementCount - 2;
674			break;
675		case GL_QUADS:
676			swPrimitiveType = gl::DRAW_QUADLIST;
677			primitiveCount = (elementCount / 4) * 2;
678			break;
679		default:
680			return false;
681		}
682
683		return true;
684	}
685
686	sw::Format ConvertRenderbufferFormat(GLenum format)
687	{
688		switch(format)
689		{
690		case GL_RGBA4:
691		case GL_RGB5_A1:
692		case GL_RGBA8_EXT:            return sw::FORMAT_A8R8G8B8;
693		case GL_RGB565:               return sw::FORMAT_R5G6B5;
694		case GL_RGB8_EXT:             return sw::FORMAT_X8R8G8B8;
695		case GL_DEPTH_COMPONENT16:
696		case GL_DEPTH_COMPONENT24:
697		case GL_STENCIL_INDEX8:
698		case GL_DEPTH24_STENCIL8_EXT: return sw::FORMAT_D24S8;
699		default: UNREACHABLE(format); return sw::FORMAT_A8R8G8B8;
700		}
701	}
702}
703
704namespace sw2es
705{
706	unsigned int GetStencilSize(sw::Format stencilFormat)
707	{
708		switch(stencilFormat)
709		{
710		case sw::FORMAT_D24FS8:
711		case sw::FORMAT_D24S8:
712		case sw::FORMAT_D32FS8_TEXTURE:
713			return 8;
714	//	case sw::FORMAT_D24X4S4:
715	//		return 4;
716	//	case sw::FORMAT_D15S1:
717	//		return 1;
718	//	case sw::FORMAT_D16_LOCKABLE:
719		case sw::FORMAT_D32:
720		case sw::FORMAT_D24X8:
721		case sw::FORMAT_D32F_LOCKABLE:
722		case sw::FORMAT_D16:
723			return 0;
724	//	case sw::FORMAT_D32_LOCKABLE:  return 0;
725	//	case sw::FORMAT_S8_LOCKABLE:   return 8;
726		default:
727			return 0;
728		}
729	}
730
731	unsigned int GetAlphaSize(sw::Format colorFormat)
732	{
733		switch(colorFormat)
734		{
735		case sw::FORMAT_A16B16G16R16F:
736			return 16;
737		case sw::FORMAT_A32B32G32R32F:
738			return 32;
739		case sw::FORMAT_A2R10G10B10:
740			return 2;
741		case sw::FORMAT_A8R8G8B8:
742			return 8;
743		case sw::FORMAT_A1R5G5B5:
744			return 1;
745		case sw::FORMAT_X8R8G8B8:
746		case sw::FORMAT_R5G6B5:
747			return 0;
748		default:
749			return 0;
750		}
751	}
752
753	unsigned int GetRedSize(sw::Format colorFormat)
754	{
755		switch(colorFormat)
756		{
757		case sw::FORMAT_A16B16G16R16F:
758			return 16;
759		case sw::FORMAT_A32B32G32R32F:
760			return 32;
761		case sw::FORMAT_A2R10G10B10:
762			return 10;
763		case sw::FORMAT_A8R8G8B8:
764		case sw::FORMAT_X8R8G8B8:
765			return 8;
766		case sw::FORMAT_A1R5G5B5:
767		case sw::FORMAT_R5G6B5:
768			return 5;
769		default:
770			return 0;
771		}
772	}
773
774	unsigned int GetGreenSize(sw::Format colorFormat)
775	{
776		switch(colorFormat)
777		{
778		case sw::FORMAT_A16B16G16R16F:
779			return 16;
780		case sw::FORMAT_A32B32G32R32F:
781			return 32;
782		case sw::FORMAT_A2R10G10B10:
783			return 10;
784		case sw::FORMAT_A8R8G8B8:
785		case sw::FORMAT_X8R8G8B8:
786			return 8;
787		case sw::FORMAT_A1R5G5B5:
788			return 5;
789		case sw::FORMAT_R5G6B5:
790			return 6;
791		default:
792			return 0;
793		}
794	}
795
796	unsigned int GetBlueSize(sw::Format colorFormat)
797	{
798		switch(colorFormat)
799		{
800		case sw::FORMAT_A16B16G16R16F:
801			return 16;
802		case sw::FORMAT_A32B32G32R32F:
803			return 32;
804		case sw::FORMAT_A2R10G10B10:
805			return 10;
806		case sw::FORMAT_A8R8G8B8:
807		case sw::FORMAT_X8R8G8B8:
808			return 8;
809		case sw::FORMAT_A1R5G5B5:
810		case sw::FORMAT_R5G6B5:
811			return 5;
812		default:
813			return 0;
814		}
815	}
816
817	unsigned int GetDepthSize(sw::Format depthFormat)
818	{
819		switch(depthFormat)
820		{
821	//	case sw::FORMAT_D16_LOCKABLE:   return 16;
822		case sw::FORMAT_D32:            return 32;
823	//	case sw::FORMAT_D15S1:          return 15;
824		case sw::FORMAT_D24S8:          return 24;
825		case sw::FORMAT_D24X8:          return 24;
826	//	case sw::FORMAT_D24X4S4:        return 24;
827		case sw::FORMAT_D16:            return 16;
828		case sw::FORMAT_D32F_LOCKABLE:  return 32;
829		case sw::FORMAT_D24FS8:         return 24;
830	//	case sw::FORMAT_D32_LOCKABLE:   return 32;
831	//	case sw::FORMAT_S8_LOCKABLE:    return 0;
832		case sw::FORMAT_D32FS8_TEXTURE: return 32;
833		default:                        return 0;
834		}
835	}
836
837	GLenum ConvertBackBufferFormat(sw::Format format)
838	{
839		switch(format)
840		{
841		case sw::FORMAT_A4R4G4B4: return GL_RGBA4;
842		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_EXT;
843		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;
844		case sw::FORMAT_R5G6B5:   return GL_RGB565;
845		case sw::FORMAT_X8R8G8B8: return GL_RGB8_EXT;
846		default:
847			UNREACHABLE(format);
848		}
849
850		return GL_RGBA4;
851	}
852
853	GLenum ConvertDepthStencilFormat(sw::Format format)
854	{
855		switch(format)
856		{
857		case sw::FORMAT_D16:
858			return GL_DEPTH_COMPONENT16;
859		case sw::FORMAT_D32:
860			return GL_DEPTH_COMPONENT32;
861		case sw::FORMAT_D24X8:
862			return GL_DEPTH_COMPONENT24;
863		case sw::FORMAT_D24S8:
864			return GL_DEPTH24_STENCIL8_EXT;
865		default:
866			UNREACHABLE(format);
867		}
868
869		return GL_DEPTH24_STENCIL8_EXT;
870	}
871}
872