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 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 IsDepthTexture(GLenum format)
36	{
37		return format == GL_DEPTH_STENCIL_OES;
38	}
39
40	bool IsStencilTexture(GLenum format)
41	{
42		return format == GL_DEPTH_STENCIL_OES;
43	}
44
45	bool IsCubemapTextureTarget(GLenum target)
46	{
47		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES);
48	}
49
50	int CubeFaceIndex(GLenum cubeFace)
51	{
52		switch(cubeFace)
53		{
54		case GL_TEXTURE_CUBE_MAP_OES:
55		case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0;
56		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1;
57		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2;
58		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3;
59		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4;
60		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5;
61		default: UNREACHABLE(cubeFace); return 0;
62		}
63	}
64
65	bool IsTextureTarget(GLenum target)
66	{
67		return target == GL_TEXTURE_2D;
68	}
69
70	// Verify that format/type are one of the combinations from table 3.4.
71	bool CheckTextureFormatType(GLenum format, GLenum type)
72	{
73		switch(type)
74		{
75		case GL_UNSIGNED_BYTE:
76			switch(format)
77			{
78			case GL_RGBA:
79			case GL_BGRA_EXT:
80			case GL_RGB:
81			case GL_ALPHA:
82			case GL_LUMINANCE:
83			case GL_LUMINANCE_ALPHA:
84				return true;
85			default:
86				return false;
87			}
88		case GL_FLOAT:
89		case GL_UNSIGNED_SHORT_4_4_4_4:
90		case GL_UNSIGNED_SHORT_5_5_5_1:
91			return (format == GL_RGBA);
92		case GL_UNSIGNED_SHORT_5_6_5:
93			return (format == GL_RGB);
94		case GL_UNSIGNED_INT_24_8_OES:
95			return (format == GL_DEPTH_STENCIL_OES);
96		default:
97			return false;
98		}
99	}
100
101	bool IsColorRenderable(GLenum internalformat)
102	{
103		switch(internalformat)
104		{
105		case GL_RGB:
106		case GL_RGBA:
107		case GL_RGBA4_OES:
108		case GL_RGB5_A1_OES:
109		case GL_RGB565_OES:
110		case GL_RGB8_OES:
111		case GL_RGBA8_OES:
112			return true;
113		case GL_DEPTH_COMPONENT16_OES:
114		case GL_STENCIL_INDEX8_OES:
115		case GL_DEPTH24_STENCIL8_OES:
116			return false;
117		default:
118			UNIMPLEMENTED();
119		}
120
121		return false;
122	}
123
124	bool IsDepthRenderable(GLenum internalformat)
125	{
126		switch(internalformat)
127		{
128		case GL_DEPTH_COMPONENT16_OES:
129		case GL_DEPTH24_STENCIL8_OES:
130			return true;
131		case GL_STENCIL_INDEX8_OES:
132		case GL_RGBA4_OES:
133		case GL_RGB5_A1_OES:
134		case GL_RGB565_OES:
135		case GL_RGB8_OES:
136		case GL_RGBA8_OES:
137			return false;
138		default:
139			UNIMPLEMENTED();
140		}
141
142		return false;
143	}
144
145	bool IsStencilRenderable(GLenum internalformat)
146	{
147		switch(internalformat)
148		{
149		case GL_STENCIL_INDEX8_OES:
150		case GL_DEPTH24_STENCIL8_OES:
151			return true;
152		case GL_RGBA4_OES:
153		case GL_RGB5_A1_OES:
154		case GL_RGB565_OES:
155		case GL_RGB8_OES:
156		case GL_RGBA8_OES:
157		case GL_DEPTH_COMPONENT16_OES:
158			return false;
159		default:
160			UNIMPLEMENTED();
161		}
162
163		return false;
164	}
165
166	bool IsAlpha(GLenum texFormat)
167	{
168		switch(texFormat)
169		{
170		case GL_ALPHA:
171			return true;
172		default:
173			return false;
174		}
175	}
176
177	bool IsRGB(GLenum texFormat)
178	{
179		switch(texFormat)
180		{
181		case GL_LUMINANCE:
182		case GL_RGB:
183		case GL_RGB565_OES:   // GL_OES_framebuffer_object
184		case GL_RGB8_OES:     // GL_OES_rgb8_rgba8
185		case SW_YV12_BT601:
186		case SW_YV12_BT709:
187		case SW_YV12_JFIF:
188			return true;
189		default:
190			return false;
191		}
192	}
193
194	bool IsRGBA(GLenum texFormat)
195	{
196		switch(texFormat)
197		{
198		case GL_LUMINANCE_ALPHA:
199		case GL_RGBA:
200		case GL_BGRA_EXT:      // GL_EXT_texture_format_BGRA8888
201		case GL_RGBA4_OES:     // GL_OES_framebuffer_object
202		case GL_RGB5_A1_OES:   // GL_OES_framebuffer_object
203		case GL_RGBA8_OES:     // GL_OES_rgb8_rgba8
204			return true;
205		default:
206			return false;
207		}
208	}
209}
210
211namespace es2sw
212{
213	sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
214	{
215		switch(comparison)
216		{
217		case GL_NEVER:    return sw::DEPTH_NEVER;
218		case GL_ALWAYS:   return sw::DEPTH_ALWAYS;
219		case GL_LESS:     return sw::DEPTH_LESS;
220		case GL_LEQUAL:   return sw::DEPTH_LESSEQUAL;
221		case GL_EQUAL:    return sw::DEPTH_EQUAL;
222		case GL_GREATER:  return sw::DEPTH_GREATER;
223		case GL_GEQUAL:   return sw::DEPTH_GREATEREQUAL;
224		case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
225		default: UNREACHABLE(comparison);
226		}
227
228		return sw::DEPTH_ALWAYS;
229	}
230
231	sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
232	{
233		switch(comparison)
234		{
235		case GL_NEVER:    return sw::STENCIL_NEVER;
236		case GL_ALWAYS:   return sw::STENCIL_ALWAYS;
237		case GL_LESS:     return sw::STENCIL_LESS;
238		case GL_LEQUAL:   return sw::STENCIL_LESSEQUAL;
239		case GL_EQUAL:    return sw::STENCIL_EQUAL;
240		case GL_GREATER:  return sw::STENCIL_GREATER;
241		case GL_GEQUAL:   return sw::STENCIL_GREATEREQUAL;
242		case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
243		default: UNREACHABLE(comparison);
244		}
245
246		return sw::STENCIL_ALWAYS;
247	}
248
249	sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison)
250	{
251		switch(comparison)
252		{
253		case GL_NEVER:    return sw::ALPHA_NEVER;
254		case GL_ALWAYS:   return sw::ALPHA_ALWAYS;
255		case GL_LESS:     return sw::ALPHA_LESS;
256		case GL_LEQUAL:   return sw::ALPHA_LESSEQUAL;
257		case GL_EQUAL:    return sw::ALPHA_EQUAL;
258		case GL_GREATER:  return sw::ALPHA_GREATER;
259		case GL_GEQUAL:   return sw::ALPHA_GREATEREQUAL;
260		case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL;
261		default: UNREACHABLE(comparison);
262		}
263
264		return sw::ALPHA_ALWAYS;
265	}
266
267	sw::Color<float> ConvertColor(es1::Color color)
268	{
269		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
270	}
271
272	sw::BlendFactor ConvertBlendFunc(GLenum blend)
273	{
274		switch(blend)
275		{
276		case GL_ZERO:                     return sw::BLEND_ZERO;
277		case GL_ONE:                      return sw::BLEND_ONE;
278		case GL_SRC_COLOR:                return sw::BLEND_SOURCE;
279		case GL_ONE_MINUS_SRC_COLOR:      return sw::BLEND_INVSOURCE;
280		case GL_DST_COLOR:                return sw::BLEND_DEST;
281		case GL_ONE_MINUS_DST_COLOR:      return sw::BLEND_INVDEST;
282		case GL_SRC_ALPHA:                return sw::BLEND_SOURCEALPHA;
283		case GL_ONE_MINUS_SRC_ALPHA:      return sw::BLEND_INVSOURCEALPHA;
284		case GL_DST_ALPHA:                return sw::BLEND_DESTALPHA;
285		case GL_ONE_MINUS_DST_ALPHA:      return sw::BLEND_INVDESTALPHA;
286		case GL_SRC_ALPHA_SATURATE:       return sw::BLEND_SRCALPHASAT;
287		default: UNREACHABLE(blend);
288		}
289
290		return sw::BLEND_ZERO;
291	}
292
293	sw::BlendOperation ConvertBlendOp(GLenum blendOp)
294	{
295		switch(blendOp)
296		{
297		case GL_FUNC_ADD_OES:              return sw::BLENDOP_ADD;
298		case GL_FUNC_SUBTRACT_OES:         return sw::BLENDOP_SUB;
299		case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB;
300		case GL_MIN_EXT:                   return sw::BLENDOP_MIN;
301		case GL_MAX_EXT:                   return sw::BLENDOP_MAX;
302		default: UNREACHABLE(blendOp);
303		}
304
305		return sw::BLENDOP_ADD;
306	}
307
308	sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation)
309	{
310		switch(logicalOperation)
311		{
312		case GL_CLEAR:         return sw::LOGICALOP_CLEAR;
313		case GL_SET:           return sw::LOGICALOP_SET;
314		case GL_COPY:          return sw::LOGICALOP_COPY;
315		case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED;
316		case GL_NOOP:          return sw::LOGICALOP_NOOP;
317		case GL_INVERT:        return sw::LOGICALOP_INVERT;
318		case GL_AND:           return sw::LOGICALOP_AND;
319		case GL_NAND:          return sw::LOGICALOP_NAND;
320		case GL_OR:            return sw::LOGICALOP_OR;
321		case GL_NOR:           return sw::LOGICALOP_NOR;
322		case GL_XOR:           return sw::LOGICALOP_XOR;
323		case GL_EQUIV:         return sw::LOGICALOP_EQUIV;
324		case GL_AND_REVERSE:   return sw::LOGICALOP_AND_REVERSE;
325		case GL_AND_INVERTED:  return sw::LOGICALOP_AND_INVERTED;
326		case GL_OR_REVERSE:    return sw::LOGICALOP_OR_REVERSE;
327		case GL_OR_INVERTED:   return sw::LOGICALOP_OR_INVERTED;
328		default: UNREACHABLE(logicalOperation);
329		}
330
331		return sw::LOGICALOP_COPY;
332	}
333
334	sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
335	{
336		switch(stencilOp)
337		{
338		case GL_ZERO:          return sw::OPERATION_ZERO;
339		case GL_KEEP:          return sw::OPERATION_KEEP;
340		case GL_REPLACE:       return sw::OPERATION_REPLACE;
341		case GL_INCR:          return sw::OPERATION_INCRSAT;
342		case GL_DECR:          return sw::OPERATION_DECRSAT;
343		case GL_INVERT:        return sw::OPERATION_INVERT;
344		case GL_INCR_WRAP_OES: return sw::OPERATION_INCR;
345		case GL_DECR_WRAP_OES: return sw::OPERATION_DECR;
346		default: UNREACHABLE(stencilOp);
347		}
348
349		return sw::OPERATION_KEEP;
350	}
351
352	sw::AddressingMode ConvertTextureWrap(GLenum wrap)
353	{
354		switch(wrap)
355		{
356		case GL_REPEAT:              return sw::ADDRESSING_WRAP;
357		case GL_CLAMP_TO_EDGE:       return sw::ADDRESSING_CLAMP;
358		case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR;
359		default: UNREACHABLE(wrap);
360		}
361
362		return sw::ADDRESSING_WRAP;
363	}
364
365	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
366	{
367		switch(cullFace)
368		{
369		case GL_FRONT:
370			return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
371		case GL_BACK:
372			return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
373		case GL_FRONT_AND_BACK:
374			return sw::CULL_NONE;   // culling will be handled during draw
375		default: UNREACHABLE(cullFace);
376		}
377
378		return sw::CULL_COUNTERCLOCKWISE;
379	}
380
381	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
382	{
383		return (red   ? 0x00000001 : 0) |
384			   (green ? 0x00000002 : 0) |
385			   (blue  ? 0x00000004 : 0) |
386			   (alpha ? 0x00000008 : 0);
387	}
388
389	sw::MipmapType ConvertMipMapFilter(GLenum minFilter)
390	{
391		switch(minFilter)
392		{
393		case GL_NEAREST:
394		case GL_LINEAR:
395			return sw::MIPMAP_NONE;
396			break;
397		case GL_NEAREST_MIPMAP_NEAREST:
398		case GL_LINEAR_MIPMAP_NEAREST:
399			return sw::MIPMAP_POINT;
400			break;
401		case GL_NEAREST_MIPMAP_LINEAR:
402		case GL_LINEAR_MIPMAP_LINEAR:
403			return sw::MIPMAP_LINEAR;
404			break;
405		default:
406			UNREACHABLE(minFilter);
407			return sw::MIPMAP_NONE;
408		}
409	}
410
411	sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
412	{
413		if(maxAnisotropy > 1.0f)
414		{
415			return sw::FILTER_ANISOTROPIC;
416		}
417
418		sw::FilterType magFilterType = sw::FILTER_POINT;
419		switch(magFilter)
420		{
421		case GL_NEAREST: magFilterType = sw::FILTER_POINT;  break;
422		case GL_LINEAR:  magFilterType = sw::FILTER_LINEAR; break;
423		default: UNREACHABLE(magFilter);
424		}
425
426		switch(minFilter)
427		{
428		case GL_NEAREST:
429		case GL_NEAREST_MIPMAP_NEAREST:
430		case GL_NEAREST_MIPMAP_LINEAR:
431			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
432		case GL_LINEAR:
433		case GL_LINEAR_MIPMAP_NEAREST:
434		case GL_LINEAR_MIPMAP_LINEAR:
435			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR;
436		default:
437			UNREACHABLE(minFilter);
438			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
439		}
440	}
441
442	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType,  sw::DrawType &drawType, int &primitiveCount)
443	{
444		switch(primitiveType)
445		{
446		case GL_POINTS:
447			drawType = sw::DRAW_POINTLIST;
448			primitiveCount = elementCount;
449			break;
450		case GL_LINES:
451			drawType = sw::DRAW_LINELIST;
452			primitiveCount = elementCount / 2;
453			break;
454		case GL_LINE_LOOP:
455			drawType = sw::DRAW_LINELOOP;
456			primitiveCount = elementCount;
457			break;
458		case GL_LINE_STRIP:
459			drawType = sw::DRAW_LINESTRIP;
460			primitiveCount = elementCount - 1;
461			break;
462		case GL_TRIANGLES:
463			drawType = sw::DRAW_TRIANGLELIST;
464			primitiveCount = elementCount / 3;
465			break;
466		case GL_TRIANGLE_STRIP:
467			drawType = sw::DRAW_TRIANGLESTRIP;
468			primitiveCount = elementCount - 2;
469			break;
470		case GL_TRIANGLE_FAN:
471			drawType = sw::DRAW_TRIANGLEFAN;
472			primitiveCount = elementCount - 2;
473			break;
474		default:
475			return false;
476		}
477
478		sw::DrawType elementSize;
479		switch(elementType)
480		{
481		case GL_NONE:           elementSize = sw::DRAW_NONINDEXED; break;
482		case GL_UNSIGNED_BYTE:  elementSize = sw::DRAW_INDEXED8;   break;
483		case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16;  break;
484		case GL_UNSIGNED_INT:   elementSize = sw::DRAW_INDEXED32;  break;
485		default: return false;
486		}
487
488		drawType = sw::DrawType(drawType | elementSize);
489
490		return true;
491	}
492
493	sw::Format ConvertRenderbufferFormat(GLenum format)
494	{
495		switch(format)
496		{
497		case GL_RGBA4_OES:
498		case GL_RGB5_A1_OES:
499		case GL_RGBA8_OES:            return sw::FORMAT_A8B8G8R8;
500		case GL_RGB565_OES:           return sw::FORMAT_R5G6B5;
501		case GL_RGB8_OES:             return sw::FORMAT_X8B8G8R8;
502		case GL_DEPTH_COMPONENT16_OES:
503		case GL_STENCIL_INDEX8_OES:
504		case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;
505		default: UNREACHABLE(format); return sw::FORMAT_A8B8G8R8;
506		}
507	}
508
509	sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation)
510	{
511		switch(operation)
512		{
513		case GL_REPLACE:        return sw::TextureStage::STAGE_SELECTARG1;
514		case GL_MODULATE:       return sw::TextureStage::STAGE_MODULATE;
515		case GL_ADD:            return sw::TextureStage::STAGE_ADD;
516		case GL_ADD_SIGNED:     return sw::TextureStage::STAGE_ADDSIGNED;
517		case GL_INTERPOLATE:    return sw::TextureStage::STAGE_LERP;
518		case GL_SUBTRACT:       return sw::TextureStage::STAGE_SUBTRACT;
519		case GL_DOT3_RGB:       return sw::TextureStage::STAGE_DOT3;
520		case GL_DOT3_RGBA:      return sw::TextureStage::STAGE_DOT3;
521		default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1;
522		}
523	}
524
525	sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument)
526	{
527		switch(argument)
528		{
529		case GL_TEXTURE:        return sw::TextureStage::SOURCE_TEXTURE;
530		case GL_CONSTANT:       return sw::TextureStage::SOURCE_CONSTANT;
531		case GL_PRIMARY_COLOR:  return sw::TextureStage::SOURCE_DIFFUSE;
532		case GL_PREVIOUS:       return sw::TextureStage::SOURCE_CURRENT;
533		default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT;
534		}
535	}
536
537	sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand)
538	{
539		switch(operand)
540		{
541		case GL_SRC_COLOR:           return sw::TextureStage::MODIFIER_COLOR;
542		case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR;
543		case GL_SRC_ALPHA:           return sw::TextureStage::MODIFIER_ALPHA;
544		case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA;
545		default: UNREACHABLE(operand);      return sw::TextureStage::MODIFIER_COLOR;
546		}
547	}
548}
549
550namespace sw2es
551{
552	unsigned int GetStencilSize(sw::Format stencilFormat)
553	{
554		switch(stencilFormat)
555		{
556		case sw::FORMAT_D24FS8:
557		case sw::FORMAT_D24S8:
558		case sw::FORMAT_D32FS8_TEXTURE:
559			return 8;
560	//	case sw::FORMAT_D24X4S4:
561	//		return 4;
562	//	case sw::FORMAT_D15S1:
563	//		return 1;
564	//	case sw::FORMAT_D16_LOCKABLE:
565		case sw::FORMAT_D32:
566		case sw::FORMAT_D24X8:
567		case sw::FORMAT_D32F_LOCKABLE:
568		case sw::FORMAT_D16:
569			return 0;
570	//	case sw::FORMAT_D32_LOCKABLE:  return 0;
571	//	case sw::FORMAT_S8_LOCKABLE:   return 8;
572		default:
573			return 0;
574		}
575	}
576
577	unsigned int GetAlphaSize(sw::Format colorFormat)
578	{
579		switch(colorFormat)
580		{
581		case sw::FORMAT_A16B16G16R16F:
582			return 16;
583		case sw::FORMAT_A32B32G32R32F:
584			return 32;
585		case sw::FORMAT_A2R10G10B10:
586			return 2;
587		case sw::FORMAT_A8R8G8B8:
588		case sw::FORMAT_A8B8G8R8:
589			return 8;
590		case sw::FORMAT_A1R5G5B5:
591			return 1;
592		case sw::FORMAT_X8R8G8B8:
593		case sw::FORMAT_X8B8G8R8:
594		case sw::FORMAT_R5G6B5:
595			return 0;
596		default:
597			return 0;
598		}
599	}
600
601	unsigned int GetRedSize(sw::Format colorFormat)
602	{
603		switch(colorFormat)
604		{
605		case sw::FORMAT_A16B16G16R16F:
606			return 16;
607		case sw::FORMAT_A32B32G32R32F:
608			return 32;
609		case sw::FORMAT_A2R10G10B10:
610			return 10;
611		case sw::FORMAT_A8R8G8B8:
612		case sw::FORMAT_A8B8G8R8:
613		case sw::FORMAT_X8R8G8B8:
614		case sw::FORMAT_X8B8G8R8:
615			return 8;
616		case sw::FORMAT_A1R5G5B5:
617		case sw::FORMAT_R5G6B5:
618			return 5;
619		default:
620			return 0;
621		}
622	}
623
624	unsigned int GetGreenSize(sw::Format colorFormat)
625	{
626		switch(colorFormat)
627		{
628		case sw::FORMAT_A16B16G16R16F:
629			return 16;
630		case sw::FORMAT_A32B32G32R32F:
631			return 32;
632		case sw::FORMAT_A2R10G10B10:
633			return 10;
634		case sw::FORMAT_A8R8G8B8:
635		case sw::FORMAT_A8B8G8R8:
636		case sw::FORMAT_X8R8G8B8:
637		case sw::FORMAT_X8B8G8R8:
638			return 8;
639		case sw::FORMAT_A1R5G5B5:
640			return 5;
641		case sw::FORMAT_R5G6B5:
642			return 6;
643		default:
644			return 0;
645		}
646	}
647
648	unsigned int GetBlueSize(sw::Format colorFormat)
649	{
650		switch(colorFormat)
651		{
652		case sw::FORMAT_A16B16G16R16F:
653			return 16;
654		case sw::FORMAT_A32B32G32R32F:
655			return 32;
656		case sw::FORMAT_A2R10G10B10:
657			return 10;
658		case sw::FORMAT_A8R8G8B8:
659		case sw::FORMAT_A8B8G8R8:
660		case sw::FORMAT_X8R8G8B8:
661		case sw::FORMAT_X8B8G8R8:
662			return 8;
663		case sw::FORMAT_A1R5G5B5:
664		case sw::FORMAT_R5G6B5:
665			return 5;
666		default:
667			return 0;
668		}
669	}
670
671	unsigned int GetDepthSize(sw::Format depthFormat)
672	{
673		switch(depthFormat)
674		{
675	//	case sw::FORMAT_D16_LOCKABLE:   return 16;
676		case sw::FORMAT_D32:            return 32;
677	//	case sw::FORMAT_D15S1:          return 15;
678		case sw::FORMAT_D24S8:          return 24;
679		case sw::FORMAT_D24X8:          return 24;
680	//	case sw::FORMAT_D24X4S4:        return 24;
681		case sw::FORMAT_D16:            return 16;
682		case sw::FORMAT_D32F_LOCKABLE:  return 32;
683		case sw::FORMAT_D24FS8:         return 24;
684	//	case sw::FORMAT_D32_LOCKABLE:   return 32;
685	//	case sw::FORMAT_S8_LOCKABLE:    return 0;
686		case sw::FORMAT_D32FS8_TEXTURE: return 32;
687		default:                        return 0;
688		}
689	}
690
691	GLenum ConvertBackBufferFormat(sw::Format format)
692	{
693		switch(format)
694		{
695		case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES;
696		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
697		case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES;
698		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES;
699		case sw::FORMAT_R5G6B5:   return GL_RGB565_OES;
700		case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
701		case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES;
702		default:
703			UNREACHABLE(format);
704		}
705
706		return GL_RGBA4_OES;
707	}
708
709	GLenum ConvertDepthStencilFormat(sw::Format format)
710	{
711		switch(format)
712		{
713		case sw::FORMAT_D16:
714		case sw::FORMAT_D24X8:
715		case sw::FORMAT_D32:
716			return GL_DEPTH_COMPONENT16_OES;
717		case sw::FORMAT_D24S8:
718			return GL_DEPTH24_STENCIL8_OES;
719		default:
720			UNREACHABLE(format);
721		}
722
723		return GL_DEPTH24_STENCIL8_OES;
724	}
725}
726