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