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// libGLES_CM.cpp: Implements the exported OpenGL ES 1.1 functions.
16
17#include "main.h"
18#include "mathutil.h"
19#include "utilities.h"
20#include "Buffer.h"
21#include "Context.h"
22#include "Framebuffer.h"
23#include "Renderbuffer.h"
24#include "Texture.h"
25#include "common/debug.h"
26#include "Common/SharedLibrary.hpp"
27#include "Common/Version.h"
28
29#include <EGL/egl.h>
30#include <EGL/eglext.h>
31
32#include <GLES/gl.h>
33#include <GLES/glext.h>
34
35#include <algorithm>
36#include <limits>
37
38namespace es1
39{
40
41static bool validImageSize(GLint level, GLsizei width, GLsizei height)
42{
43	if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
44	{
45		return false;
46	}
47
48	return true;
49}
50
51void ActiveTexture(GLenum texture)
52{
53	TRACE("(GLenum texture = 0x%X)", texture);
54
55	es1::Context *context = es1::getContext();
56
57	if(context)
58	{
59		if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es1::MAX_TEXTURE_UNITS - 1)
60		{
61			return error(GL_INVALID_ENUM);
62		}
63
64		context->setActiveSampler(texture - GL_TEXTURE0);
65	}
66}
67
68void AlphaFunc(GLenum func, GLclampf ref)
69{
70	TRACE("(GLenum func = 0x%X, GLclampf ref = %f)", func, ref);
71
72	switch(func)
73	{
74	case GL_NEVER:
75	case GL_ALWAYS:
76	case GL_LESS:
77	case GL_LEQUAL:
78	case GL_EQUAL:
79	case GL_GEQUAL:
80	case GL_GREATER:
81	case GL_NOTEQUAL:
82		break;
83	default:
84		return error(GL_INVALID_ENUM);
85	}
86
87	es1::Context *context = es1::getContext();
88
89	if(context)
90	{
91		context->setAlphaFunc(func, clamp01(ref));
92	}
93}
94
95void AlphaFuncx(GLenum func, GLclampx ref)
96{
97	AlphaFunc(func, (float)ref / 0x10000);
98}
99
100void BindBuffer(GLenum target, GLuint buffer)
101{
102	TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
103
104	es1::Context *context = es1::getContext();
105
106	if(context)
107	{
108		switch(target)
109		{
110		case GL_ARRAY_BUFFER:
111			context->bindArrayBuffer(buffer);
112			return;
113		case GL_ELEMENT_ARRAY_BUFFER:
114			context->bindElementArrayBuffer(buffer);
115			return;
116		default:
117			return error(GL_INVALID_ENUM);
118		}
119	}
120}
121
122void BindFramebuffer(GLenum target, GLuint framebuffer)
123{
124	TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
125
126	if(target != GL_FRAMEBUFFER_OES)
127	{
128		return error(GL_INVALID_ENUM);
129	}
130
131	es1::Context *context = es1::getContext();
132
133	if(context)
134	{
135		context->bindFramebuffer(framebuffer);
136	}
137}
138
139void BindFramebufferOES(GLenum target, GLuint framebuffer)
140{
141	TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
142
143	if(target != GL_FRAMEBUFFER_OES)
144	{
145		return error(GL_INVALID_ENUM);
146	}
147
148	es1::Context *context = es1::getContext();
149
150	if(context)
151	{
152		context->bindFramebuffer(framebuffer);
153	}
154}
155
156void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
157{
158	TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
159
160	if(target != GL_RENDERBUFFER_OES)
161	{
162		return error(GL_INVALID_ENUM);
163	}
164
165	es1::Context *context = es1::getContext();
166
167	if(context)
168	{
169		// [GL_EXT_framebuffer_object]
170		// If <renderbuffer> is not zero, then the resulting renderbuffer object
171		// is a new state vector, initialized with a zero-sized memory buffer
172		context->bindRenderbuffer(renderbuffer);
173	}
174}
175
176void BindTexture(GLenum target, GLuint texture)
177{
178	TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
179
180	es1::Context *context = es1::getContext();
181
182	if(context)
183	{
184		es1::Texture *textureObject = context->getTexture(texture);
185
186		if(textureObject && textureObject->getTarget() != target && texture != 0)
187		{
188			return error(GL_INVALID_OPERATION);
189		}
190
191		switch(target)
192		{
193		case GL_TEXTURE_2D:
194			context->bindTexture(TEXTURE_2D, texture);
195			break;
196		case GL_TEXTURE_EXTERNAL_OES:
197			context->bindTexture(TEXTURE_EXTERNAL, texture);
198			break;
199		default:
200			return error(GL_INVALID_ENUM);
201		}
202	}
203}
204
205void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha);
206
207void BlendEquationOES(GLenum mode)
208{
209	BlendEquationSeparateOES(mode, mode);
210}
211
212void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha)
213{
214	TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
215
216	switch(modeRGB)
217	{
218	case GL_FUNC_ADD_OES:
219	case GL_FUNC_SUBTRACT_OES:
220	case GL_FUNC_REVERSE_SUBTRACT_OES:
221	case GL_MIN_EXT:
222	case GL_MAX_EXT:
223		break;
224	default:
225		return error(GL_INVALID_ENUM);
226	}
227
228	switch(modeAlpha)
229	{
230	case GL_FUNC_ADD_OES:
231	case GL_FUNC_SUBTRACT_OES:
232	case GL_FUNC_REVERSE_SUBTRACT_OES:
233	case GL_MIN_EXT:
234	case GL_MAX_EXT:
235		break;
236	default:
237		return error(GL_INVALID_ENUM);
238	}
239
240	es1::Context *context = es1::getContext();
241
242	if(context)
243	{
244		context->setBlendEquation(modeRGB, modeAlpha);
245	}
246}
247
248void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
249
250void BlendFunc(GLenum sfactor, GLenum dfactor)
251{
252	BlendFuncSeparateOES(sfactor, dfactor, sfactor, dfactor);
253}
254
255void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
256{
257	TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
258		  srcRGB, dstRGB, srcAlpha, dstAlpha);
259
260	switch(srcRGB)
261	{
262	case GL_ZERO:
263	case GL_ONE:
264	case GL_SRC_COLOR:
265	case GL_ONE_MINUS_SRC_COLOR:
266	case GL_DST_COLOR:
267	case GL_ONE_MINUS_DST_COLOR:
268	case GL_SRC_ALPHA:
269	case GL_ONE_MINUS_SRC_ALPHA:
270	case GL_DST_ALPHA:
271	case GL_ONE_MINUS_DST_ALPHA:
272	case GL_SRC_ALPHA_SATURATE:
273		break;
274	default:
275		return error(GL_INVALID_ENUM);
276	}
277
278	switch(dstRGB)
279	{
280	case GL_ZERO:
281	case GL_ONE:
282	case GL_SRC_COLOR:
283	case GL_ONE_MINUS_SRC_COLOR:
284	case GL_DST_COLOR:
285	case GL_ONE_MINUS_DST_COLOR:
286	case GL_SRC_ALPHA:
287	case GL_ONE_MINUS_SRC_ALPHA:
288	case GL_DST_ALPHA:
289	case GL_ONE_MINUS_DST_ALPHA:
290		break;
291	default:
292		return error(GL_INVALID_ENUM);
293	}
294
295	switch(srcAlpha)
296	{
297	case GL_ZERO:
298	case GL_ONE:
299	case GL_SRC_COLOR:
300	case GL_ONE_MINUS_SRC_COLOR:
301	case GL_DST_COLOR:
302	case GL_ONE_MINUS_DST_COLOR:
303	case GL_SRC_ALPHA:
304	case GL_ONE_MINUS_SRC_ALPHA:
305	case GL_DST_ALPHA:
306	case GL_ONE_MINUS_DST_ALPHA:
307	case GL_SRC_ALPHA_SATURATE:
308		break;
309	default:
310		return error(GL_INVALID_ENUM);
311	}
312
313	switch(dstAlpha)
314	{
315	case GL_ZERO:
316	case GL_ONE:
317	case GL_SRC_COLOR:
318	case GL_ONE_MINUS_SRC_COLOR:
319	case GL_DST_COLOR:
320	case GL_ONE_MINUS_DST_COLOR:
321	case GL_SRC_ALPHA:
322	case GL_ONE_MINUS_SRC_ALPHA:
323	case GL_DST_ALPHA:
324	case GL_ONE_MINUS_DST_ALPHA:
325		break;
326	default:
327		return error(GL_INVALID_ENUM);
328	}
329
330	es1::Context *context = es1::getContext();
331
332	if(context)
333	{
334		context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
335	}
336}
337
338void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
339{
340	size = static_cast<GLint>(size);   // Work around issues with some 64-bit applications
341
342	TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
343	      target, size, data, usage);
344
345	if(size < 0)
346	{
347		return error(GL_INVALID_VALUE);
348	}
349
350	switch(usage)
351	{
352	case GL_STATIC_DRAW:
353	case GL_DYNAMIC_DRAW:
354		break;
355	default:
356		return error(GL_INVALID_ENUM);
357	}
358
359	es1::Context *context = es1::getContext();
360
361	if(context)
362	{
363		es1::Buffer *buffer;
364
365		switch(target)
366		{
367		case GL_ARRAY_BUFFER:
368			buffer = context->getArrayBuffer();
369			break;
370		case GL_ELEMENT_ARRAY_BUFFER:
371			buffer = context->getElementArrayBuffer();
372			break;
373		default:
374			return error(GL_INVALID_ENUM);
375		}
376
377		if(!buffer)
378		{
379			return error(GL_INVALID_OPERATION);
380		}
381
382		buffer->bufferData(data, size, usage);
383	}
384}
385
386void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
387{
388	size = static_cast<GLint>(size);   // Work around issues with some 64-bit applications
389	offset = static_cast<GLint>(offset);
390
391	TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
392	      target, offset, size, data);
393
394	if(size < 0 || offset < 0)
395	{
396		return error(GL_INVALID_VALUE);
397	}
398
399	if(!data)
400	{
401		return;
402	}
403
404	es1::Context *context = es1::getContext();
405
406	if(context)
407	{
408		es1::Buffer *buffer;
409
410		switch(target)
411		{
412		case GL_ARRAY_BUFFER:
413			buffer = context->getArrayBuffer();
414			break;
415		case GL_ELEMENT_ARRAY_BUFFER:
416			buffer = context->getElementArrayBuffer();
417			break;
418		default:
419			return error(GL_INVALID_ENUM);
420		}
421
422		if(!buffer)
423		{
424			return error(GL_INVALID_OPERATION);
425		}
426
427		if((size_t)size + offset > buffer->size())
428		{
429			return error(GL_INVALID_VALUE);
430		}
431
432		buffer->bufferSubData(data, size, offset);
433	}
434}
435
436GLenum CheckFramebufferStatusOES(GLenum target)
437{
438	TRACE("(GLenum target = 0x%X)", target);
439
440	if(target != GL_FRAMEBUFFER_OES)
441	{
442		return error(GL_INVALID_ENUM, 0);
443	}
444
445	es1::Context *context = es1::getContext();
446
447	if(context)
448	{
449		es1::Framebuffer *framebuffer = context->getFramebuffer();
450
451		if(!framebuffer)
452		{
453			return GL_FRAMEBUFFER_UNDEFINED_OES;
454		}
455
456		return framebuffer->completeness();
457	}
458
459	return 0;
460}
461
462void Clear(GLbitfield mask)
463{
464	TRACE("(GLbitfield mask = %X)", mask);
465
466	if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
467	{
468		return error(GL_INVALID_VALUE);
469	}
470
471	es1::Context *context = es1::getContext();
472
473	if(context)
474	{
475		context->clear(mask);
476	}
477}
478
479void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
480{
481	TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
482	      red, green, blue, alpha);
483
484	es1::Context *context = es1::getContext();
485
486	if(context)
487	{
488		context->setClearColor(red, green, blue, alpha);
489	}
490}
491
492void ClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
493{
494	ClearColor((float)red / 0x10000, (float)green / 0x10000, (float)blue / 0x10000, (float)alpha / 0x10000);
495}
496
497void ClearDepthf(GLclampf depth)
498{
499	TRACE("(GLclampf depth = %f)", depth);
500
501	es1::Context *context = es1::getContext();
502
503	if(context)
504	{
505		context->setClearDepth(depth);
506	}
507}
508
509void ClearDepthx(GLclampx depth)
510{
511	ClearDepthf((float)depth / 0x10000);
512}
513
514void ClearStencil(GLint s)
515{
516	TRACE("(GLint s = %d)", s);
517
518	es1::Context *context = es1::getContext();
519
520	if(context)
521	{
522		context->setClearStencil(s);
523	}
524}
525
526void ClientActiveTexture(GLenum texture)
527{
528	TRACE("(GLenum texture = 0x%X)", texture);
529
530	switch(texture)
531	{
532	case GL_TEXTURE0:
533	case GL_TEXTURE1:
534		break;
535	default:
536		return error(GL_INVALID_ENUM);
537	}
538
539	es1::Context *context = es1::getContext();
540
541	if(context)
542	{
543		context->clientActiveTexture(texture);
544	}
545}
546
547void ClipPlanef(GLenum plane, const GLfloat *equation)
548{
549	TRACE("(GLenum plane = 0x%X, const GLfloat *equation)", plane);
550
551	int index = plane - GL_CLIP_PLANE0;
552
553	if(index < 0 || index >= MAX_CLIP_PLANES)
554	{
555		return error(GL_INVALID_ENUM);
556	}
557
558	es1::Context *context = es1::getContext();
559
560	if(context)
561	{
562		context->setClipPlane(index, equation);
563	}
564}
565
566void ClipPlanex(GLenum plane, const GLfixed *equation)
567{
568	GLfloat equationf[4] =
569	{
570		(float)equation[0] / 0x10000,
571		(float)equation[1] / 0x10000,
572		(float)equation[2] / 0x10000,
573		(float)equation[3] / 0x10000,
574	};
575
576	ClipPlanef(plane, equationf);
577}
578
579void Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
580{
581	TRACE("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red, green, blue, alpha);
582
583	es1::Context *context = es1::getContext();
584
585	if(context)
586	{
587		context->setVertexAttrib(sw::Color0, red, green, blue, alpha);
588	}
589}
590
591void Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
592{
593	Color4f((float)red / 0xFF, (float)green / 0xFF, (float)blue / 0xFF, (float)alpha / 0xFF);
594}
595
596void Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
597{
598	Color4f((float)red / 0x10000, (float)green / 0x10000, (float)blue / 0x10000, (float)alpha / 0x10000);
599}
600
601void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
602{
603	TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
604	      red, green, blue, alpha);
605
606	es1::Context *context = es1::getContext();
607
608	if(context)
609	{
610		context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
611	}
612}
613
614void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
615{
616	TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
617	      "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
618	      index, size, type, normalized, stride, ptr);
619
620	if(index >= es1::MAX_VERTEX_ATTRIBS)
621	{
622		return error(GL_INVALID_VALUE);
623	}
624
625	if(size < 1 || size > 4)
626	{
627		return error(GL_INVALID_VALUE);
628	}
629
630	switch(type)
631	{
632	case GL_BYTE:
633	case GL_UNSIGNED_BYTE:
634	case GL_SHORT:
635	case GL_UNSIGNED_SHORT:
636	case GL_FIXED:
637	case GL_FLOAT:
638		break;
639	default:
640		return error(GL_INVALID_ENUM);
641	}
642
643	if(stride < 0)
644	{
645		return error(GL_INVALID_VALUE);
646	}
647
648	es1::Context *context = es1::getContext();
649
650	if(context)
651	{
652		context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
653	}
654}
655
656void ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
657{
658	TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer);
659
660	if(size != 4)
661	{
662		return error(GL_INVALID_VALUE);
663	}
664
665	VertexAttribPointer(sw::Color0, size, type, true, stride, pointer);
666}
667
668void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
669                          GLint border, GLsizei imageSize, const GLvoid* data)
670{
671	TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
672	      "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
673	      target, level, internalformat, width, height, border, imageSize, data);
674
675	if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
676	{
677		return error(GL_INVALID_VALUE);
678	}
679
680	if(!validImageSize(level, width, height) || imageSize < 0)
681	{
682		return error(GL_INVALID_VALUE);
683	}
684
685	switch(internalformat)
686	{
687	case GL_ETC1_RGB8_OES:
688	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
689	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
690		break;
691	case GL_DEPTH_COMPONENT16_OES:
692	case GL_DEPTH_STENCIL_OES:
693	case GL_DEPTH24_STENCIL8_OES:
694		return error(GL_INVALID_OPERATION);
695	default:
696		return error(GL_INVALID_ENUM);
697	}
698
699	if(border != 0)
700	{
701		return error(GL_INVALID_VALUE);
702	}
703
704	es1::Context *context = es1::getContext();
705
706	if(context)
707	{
708		switch(target)
709		{
710		case GL_TEXTURE_2D:
711			if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
712			   height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
713			{
714				return error(GL_INVALID_VALUE);
715			}
716			break;
717		default:
718			return error(GL_INVALID_ENUM);
719		}
720
721		if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
722		{
723			return error(GL_INVALID_VALUE);
724		}
725
726		if(target == GL_TEXTURE_2D)
727		{
728			es1::Texture2D *texture = context->getTexture2D();
729
730			if(!texture)
731			{
732				return error(GL_INVALID_OPERATION);
733			}
734
735			texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
736		}
737		else UNREACHABLE(target);
738	}
739}
740
741void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
742                             GLenum format, GLsizei imageSize, const GLvoid* data)
743{
744	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
745	      "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
746	      "GLsizei imageSize = %d, const GLvoid* data = %p)",
747	      target, level, xoffset, yoffset, width, height, format, imageSize, data);
748
749	if(!es1::IsTextureTarget(target))
750	{
751		return error(GL_INVALID_ENUM);
752	}
753
754	if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
755	{
756		return error(GL_INVALID_VALUE);
757	}
758
759	if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
760	{
761		return error(GL_INVALID_VALUE);
762	}
763
764	switch(format)
765	{
766	case GL_ETC1_RGB8_OES:
767	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
768	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
769		break;
770	default:
771		return error(GL_INVALID_ENUM);
772	}
773
774	if(width == 0 || height == 0 || !data)
775	{
776		return;
777	}
778
779	es1::Context *context = es1::getContext();
780
781	if(context)
782	{
783		if(imageSize != gl::ComputeCompressedSize(width, height, format))
784		{
785			return error(GL_INVALID_VALUE);
786		}
787
788		if(xoffset % 4 != 0 || yoffset % 4 != 0)
789		{
790			// We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
791			return error(GL_INVALID_OPERATION);
792		}
793
794		if(target == GL_TEXTURE_2D)
795		{
796			es1::Texture2D *texture = context->getTexture2D();
797
798			GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE_OES, texture);
799			if(validationError != GL_NO_ERROR)
800			{
801				return error(validationError);
802			}
803
804			texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
805		}
806		else UNREACHABLE(target);
807	}
808}
809
810void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
811{
812	TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
813	      "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
814	      target, level, internalformat, x, y, width, height, border);
815
816	if(!validImageSize(level, width, height))
817	{
818		return error(GL_INVALID_VALUE);
819	}
820
821	if(border != 0)
822	{
823		return error(GL_INVALID_VALUE);
824	}
825
826	es1::Context *context = es1::getContext();
827
828	if(context)
829	{
830		switch(target)
831		{
832		case GL_TEXTURE_2D:
833			if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
834			   height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
835			{
836				return error(GL_INVALID_VALUE);
837			}
838			break;
839		default:
840			return error(GL_INVALID_ENUM);
841		}
842
843		es1::Framebuffer *framebuffer = context->getFramebuffer();
844
845		if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES))
846		{
847			return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES);
848		}
849
850		es1::Renderbuffer *source = framebuffer->getColorbuffer();
851
852		if(!source || source->getSamples() > 1)
853		{
854			return error(GL_INVALID_OPERATION);
855		}
856
857		GLenum colorbufferFormat = source->getFormat();
858
859		// [OpenGL ES 1.1.12] table 3.9
860		switch(internalformat)
861		{
862		case GL_ALPHA:
863			if(colorbufferFormat != GL_ALPHA &&
864			   colorbufferFormat != GL_RGBA &&
865			   colorbufferFormat != GL_RGBA4_OES &&
866			   colorbufferFormat != GL_RGB5_A1_OES &&
867			   colorbufferFormat != GL_RGBA8_OES)
868			{
869				return error(GL_INVALID_OPERATION);
870			}
871			break;
872		case GL_LUMINANCE:
873		case GL_RGB:
874			if(colorbufferFormat != GL_RGB &&
875			   colorbufferFormat != GL_RGB565_OES &&
876			   colorbufferFormat != GL_RGB8_OES &&
877			   colorbufferFormat != GL_RGBA &&
878			   colorbufferFormat != GL_RGBA4_OES &&
879			   colorbufferFormat != GL_RGB5_A1_OES &&
880			   colorbufferFormat != GL_RGBA8_OES)
881			{
882				return error(GL_INVALID_OPERATION);
883			}
884			break;
885		case GL_LUMINANCE_ALPHA:
886		case GL_RGBA:
887			if(colorbufferFormat != GL_RGBA &&
888			   colorbufferFormat != GL_RGBA4_OES &&
889			   colorbufferFormat != GL_RGB5_A1_OES &&
890			   colorbufferFormat != GL_RGBA8_OES &&
891			   colorbufferFormat != GL_BGRA_EXT &&  // GL_EXT_texture_format_BGRA8888
892			   colorbufferFormat != GL_BGRA8_EXT)   // GL_EXT_texture_format_BGRA8888
893			{
894				return error(GL_INVALID_OPERATION);
895			}
896			break;
897		case GL_ETC1_RGB8_OES:
898		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
899		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
900			return error(GL_INVALID_OPERATION);
901		case GL_BGRA_EXT:   // GL_EXT_texture_format_BGRA8888 doesn't mention the format to be accepted by glCopyTexImage2D.
902		default:
903			return error(GL_INVALID_ENUM);
904		}
905
906		// Determine the sized internal format.
907		if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
908		{
909			internalformat = colorbufferFormat;
910		}
911		else if(GetRedSize(colorbufferFormat) <= 8)
912		{
913			internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
914		}
915		else
916		{
917			UNIMPLEMENTED();
918
919			return error(GL_INVALID_OPERATION);
920		}
921
922		if(target == GL_TEXTURE_2D)
923		{
924			es1::Texture2D *texture = context->getTexture2D();
925
926			if(!texture)
927			{
928				return error(GL_INVALID_OPERATION);
929			}
930
931			texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
932		}
933		else UNREACHABLE(target);
934	}
935}
936
937void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
938{
939	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
940	      "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
941	      target, level, xoffset, yoffset, x, y, width, height);
942
943	if(!es1::IsTextureTarget(target))
944	{
945		return error(GL_INVALID_ENUM);
946	}
947
948	if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
949	{
950		return error(GL_INVALID_VALUE);
951	}
952
953	if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
954	{
955		return error(GL_INVALID_VALUE);
956	}
957
958	if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
959	{
960		return error(GL_INVALID_VALUE);
961	}
962
963	if(width == 0 || height == 0)
964	{
965		return;
966	}
967
968	es1::Context *context = es1::getContext();
969
970	if(context)
971	{
972		es1::Framebuffer *framebuffer = context->getFramebuffer();
973
974		if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES))
975		{
976			return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES);
977		}
978
979		es1::Renderbuffer *source = framebuffer->getColorbuffer();
980
981		if(context->getFramebufferName() != 0 && (!source || source->getSamples() > 1))
982		{
983			return error(GL_INVALID_OPERATION);
984		}
985
986		es1::Texture *texture = nullptr;
987
988		if(target == GL_TEXTURE_2D)
989		{
990			texture = context->getTexture2D();
991		}
992		else UNREACHABLE(target);
993
994		GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE_OES, GL_NONE_OES, texture);
995		if(validationError != GL_NO_ERROR)
996		{
997			return error(validationError);
998		}
999
1000		texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
1001	}
1002}
1003
1004void CullFace(GLenum mode)
1005{
1006	TRACE("(GLenum mode = 0x%X)", mode);
1007
1008	switch(mode)
1009	{
1010	case GL_FRONT:
1011	case GL_BACK:
1012	case GL_FRONT_AND_BACK:
1013		{
1014			es1::Context *context = es1::getContext();
1015
1016			if(context)
1017			{
1018				context->setCullMode(mode);
1019			}
1020		}
1021		break;
1022	default:
1023		return error(GL_INVALID_ENUM);
1024	}
1025}
1026
1027void DeleteBuffers(GLsizei n, const GLuint* buffers)
1028{
1029	TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1030
1031	if(n < 0)
1032	{
1033		return error(GL_INVALID_VALUE);
1034	}
1035
1036	es1::Context *context = es1::getContext();
1037
1038	if(context)
1039	{
1040		for(int i = 0; i < n; i++)
1041		{
1042			context->deleteBuffer(buffers[i]);
1043		}
1044	}
1045}
1046
1047void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
1048{
1049	TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1050
1051	if(n < 0)
1052	{
1053		return error(GL_INVALID_VALUE);
1054	}
1055
1056	es1::Context *context = es1::getContext();
1057
1058	if(context)
1059	{
1060		for(int i = 0; i < n; i++)
1061		{
1062			if(framebuffers[i] != 0)
1063			{
1064				context->deleteFramebuffer(framebuffers[i]);
1065			}
1066		}
1067	}
1068}
1069
1070void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
1071{
1072	TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1073
1074	if(n < 0)
1075	{
1076		return error(GL_INVALID_VALUE);
1077	}
1078
1079	es1::Context *context = es1::getContext();
1080
1081	if(context)
1082	{
1083		for(int i = 0; i < n; i++)
1084		{
1085			context->deleteRenderbuffer(renderbuffers[i]);
1086		}
1087	}
1088}
1089
1090void DeleteTextures(GLsizei n, const GLuint* textures)
1091{
1092	TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1093
1094	if(n < 0)
1095	{
1096		return error(GL_INVALID_VALUE);
1097	}
1098
1099	es1::Context *context = es1::getContext();
1100
1101	if(context)
1102	{
1103		for(int i = 0; i < n; i++)
1104		{
1105			if(textures[i] != 0)
1106			{
1107				context->deleteTexture(textures[i]);
1108			}
1109		}
1110	}
1111}
1112
1113void DepthFunc(GLenum func)
1114{
1115	TRACE("(GLenum func = 0x%X)", func);
1116
1117	switch(func)
1118	{
1119	case GL_NEVER:
1120	case GL_ALWAYS:
1121	case GL_LESS:
1122	case GL_LEQUAL:
1123	case GL_EQUAL:
1124	case GL_GREATER:
1125	case GL_GEQUAL:
1126	case GL_NOTEQUAL:
1127		break;
1128	default:
1129		return error(GL_INVALID_ENUM);
1130	}
1131
1132	es1::Context *context = es1::getContext();
1133
1134	if(context)
1135	{
1136		context->setDepthFunc(func);
1137	}
1138}
1139
1140void DepthMask(GLboolean flag)
1141{
1142	TRACE("(GLboolean flag = %d)", flag);
1143
1144	es1::Context *context = es1::getContext();
1145
1146	if(context)
1147	{
1148		context->setDepthMask(flag != GL_FALSE);
1149	}
1150}
1151
1152void DepthRangef(GLclampf zNear, GLclampf zFar)
1153{
1154	TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1155
1156	es1::Context *context = es1::getContext();
1157
1158	if(context)
1159	{
1160		context->setDepthRange(zNear, zFar);
1161	}
1162}
1163
1164void DepthRangex(GLclampx zNear, GLclampx zFar)
1165{
1166	DepthRangef((float)zNear / 0x10000, (float)zFar / 0x10000);
1167}
1168
1169void Disable(GLenum cap)
1170{
1171	TRACE("(GLenum cap = 0x%X)", cap);
1172
1173	es1::Context *context = es1::getContext();
1174
1175	if(context)
1176	{
1177		switch(cap)
1178		{
1179		case GL_CULL_FACE:                context->setCullFaceEnabled(false);              break;
1180		case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFillEnabled(false);     break;
1181		case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1182		case GL_SAMPLE_COVERAGE:          context->setSampleCoverageEnabled(false);        break;
1183		case GL_SCISSOR_TEST:             context->setScissorTestEnabled(false);           break;
1184		case GL_STENCIL_TEST:             context->setStencilTestEnabled(false);           break;
1185		case GL_DEPTH_TEST:               context->setDepthTestEnabled(false);             break;
1186		case GL_BLEND:                    context->setBlendEnabled(false);                 break;
1187		case GL_DITHER:                   context->setDitherEnabled(false);                break;
1188		case GL_LIGHTING:                 context->setLightingEnabled(false);              break;
1189		case GL_LIGHT0:                   context->setLightEnabled(0, false);              break;
1190		case GL_LIGHT1:                   context->setLightEnabled(1, false);              break;
1191		case GL_LIGHT2:                   context->setLightEnabled(2, false);              break;
1192		case GL_LIGHT3:                   context->setLightEnabled(3, false);              break;
1193		case GL_LIGHT4:                   context->setLightEnabled(4, false);              break;
1194		case GL_LIGHT5:                   context->setLightEnabled(5, false);              break;
1195		case GL_LIGHT6:                   context->setLightEnabled(6, false);              break;
1196		case GL_LIGHT7:                   context->setLightEnabled(7, false);              break;
1197		case GL_FOG:                      context->setFogEnabled(false);                   break;
1198		case GL_TEXTURE_2D:               context->setTexture2Denabled(false);             break;
1199		case GL_TEXTURE_EXTERNAL_OES:     context->setTextureExternalEnabled(false);       break;
1200		case GL_ALPHA_TEST:               context->setAlphaTestEnabled(false);             break;
1201		case GL_COLOR_LOGIC_OP:           context->setColorLogicOpEnabled(false);          break;
1202		case GL_POINT_SMOOTH:             context->setPointSmoothEnabled(false);           break;
1203		case GL_LINE_SMOOTH:              context->setLineSmoothEnabled(false);            break;
1204		case GL_COLOR_MATERIAL:           context->setColorMaterialEnabled(false);         break;
1205		case GL_NORMALIZE:                context->setNormalizeEnabled(false);             break;
1206		case GL_RESCALE_NORMAL:           context->setRescaleNormalEnabled(false);         break;
1207		case GL_VERTEX_ARRAY:             context->setVertexArrayEnabled(false);           break;
1208		case GL_NORMAL_ARRAY:             context->setNormalArrayEnabled(false);           break;
1209		case GL_COLOR_ARRAY:              context->setColorArrayEnabled(false);            break;
1210		case GL_POINT_SIZE_ARRAY_OES:     context->setPointSizeArrayEnabled(false);        break;
1211		case GL_TEXTURE_COORD_ARRAY:      context->setTextureCoordArrayEnabled(false);     break;
1212		case GL_MULTISAMPLE:              context->setMultisampleEnabled(false);           break;
1213		case GL_SAMPLE_ALPHA_TO_ONE:      context->setSampleAlphaToOneEnabled(false);      break;
1214		case GL_CLIP_PLANE0:              context->setClipPlaneEnabled(0, false);          break;
1215		case GL_CLIP_PLANE1:              context->setClipPlaneEnabled(1, false);          break;
1216		case GL_CLIP_PLANE2:              context->setClipPlaneEnabled(2, false);          break;
1217		case GL_CLIP_PLANE3:              context->setClipPlaneEnabled(3, false);          break;
1218		case GL_CLIP_PLANE4:              context->setClipPlaneEnabled(4, false);          break;
1219		case GL_CLIP_PLANE5:              context->setClipPlaneEnabled(5, false);          break;
1220		case GL_POINT_SPRITE_OES:         context->setPointSpriteEnabled(false);           break;
1221		default:
1222			return error(GL_INVALID_ENUM);
1223		}
1224	}
1225}
1226
1227void DisableClientState(GLenum array)
1228{
1229	TRACE("(GLenum array = 0x%X)", array);
1230
1231	switch(array)
1232	{
1233	case GL_VERTEX_ARRAY:
1234	case GL_NORMAL_ARRAY:
1235	case GL_COLOR_ARRAY:
1236	case GL_POINT_SIZE_ARRAY_OES:
1237	case GL_TEXTURE_COORD_ARRAY:
1238		break;
1239	default:
1240		return error(GL_INVALID_ENUM);
1241	}
1242
1243	es1::Context *context = es1::getContext();
1244
1245	if(context)
1246	{
1247		GLenum texture = context->getClientActiveTexture();
1248
1249		switch(array)
1250		{
1251		case GL_VERTEX_ARRAY:         context->setVertexAttribArrayEnabled(sw::Position, false);                            break;
1252		case GL_NORMAL_ARRAY:         context->setVertexAttribArrayEnabled(sw::Normal, false);                              break;
1253		case GL_COLOR_ARRAY:          context->setVertexAttribArrayEnabled(sw::Color0, false);                              break;
1254		case GL_POINT_SIZE_ARRAY_OES: context->setVertexAttribArrayEnabled(sw::PointSize, false);                           break;
1255		case GL_TEXTURE_COORD_ARRAY:  context->setVertexAttribArrayEnabled(sw::TexCoord0 + (texture - GL_TEXTURE0), false); break;
1256		default:                      UNREACHABLE(array);
1257		}
1258	}
1259}
1260
1261void DrawArrays(GLenum mode, GLint first, GLsizei count)
1262{
1263	TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1264
1265	if(count < 0 || first < 0)
1266	{
1267		return error(GL_INVALID_VALUE);
1268	}
1269
1270	es1::Context *context = es1::getContext();
1271
1272	if(context)
1273	{
1274		context->drawArrays(mode, first, count);
1275	}
1276}
1277
1278void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1279{
1280	TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1281	      mode, count, type, indices);
1282
1283	if(count < 0)
1284	{
1285		return error(GL_INVALID_VALUE);
1286	}
1287
1288	es1::Context *context = es1::getContext();
1289
1290	if(context)
1291	{
1292		switch(type)
1293		{
1294		case GL_UNSIGNED_BYTE:
1295		case GL_UNSIGNED_SHORT:
1296		case GL_UNSIGNED_INT:
1297			break;
1298		default:
1299			return error(GL_INVALID_ENUM);
1300		}
1301
1302		context->drawElements(mode, count, type, indices);
1303	}
1304}
1305
1306void Enable(GLenum cap)
1307{
1308	TRACE("(GLenum cap = 0x%X)", cap);
1309
1310	es1::Context *context = es1::getContext();
1311
1312	if(context)
1313	{
1314		switch(cap)
1315		{
1316		case GL_CULL_FACE:                context->setCullFaceEnabled(true);              break;
1317		case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFillEnabled(true);     break;
1318		case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1319		case GL_SAMPLE_COVERAGE:          context->setSampleCoverageEnabled(true);        break;
1320		case GL_SCISSOR_TEST:             context->setScissorTestEnabled(true);           break;
1321		case GL_STENCIL_TEST:             context->setStencilTestEnabled(true);           break;
1322		case GL_DEPTH_TEST:               context->setDepthTestEnabled(true);             break;
1323		case GL_BLEND:                    context->setBlendEnabled(true);                 break;
1324		case GL_DITHER:                   context->setDitherEnabled(true);                break;
1325		case GL_LIGHTING:                 context->setLightingEnabled(true);              break;
1326		case GL_LIGHT0:                   context->setLightEnabled(0, true);              break;
1327		case GL_LIGHT1:                   context->setLightEnabled(1, true);              break;
1328		case GL_LIGHT2:                   context->setLightEnabled(2, true);              break;
1329		case GL_LIGHT3:                   context->setLightEnabled(3, true);              break;
1330		case GL_LIGHT4:                   context->setLightEnabled(4, true);              break;
1331		case GL_LIGHT5:                   context->setLightEnabled(5, true);              break;
1332		case GL_LIGHT6:                   context->setLightEnabled(6, true);              break;
1333		case GL_LIGHT7:                   context->setLightEnabled(7, true);              break;
1334		case GL_FOG:                      context->setFogEnabled(true);                   break;
1335		case GL_TEXTURE_2D:               context->setTexture2Denabled(true);             break;
1336		case GL_TEXTURE_EXTERNAL_OES:     context->setTextureExternalEnabled(true);       break;
1337		case GL_ALPHA_TEST:               context->setAlphaTestEnabled(true);             break;
1338		case GL_COLOR_LOGIC_OP:           context->setColorLogicOpEnabled(true);          break;
1339		case GL_POINT_SMOOTH:             context->setPointSmoothEnabled(true);           break;
1340		case GL_LINE_SMOOTH:              context->setLineSmoothEnabled(true);            break;
1341		case GL_COLOR_MATERIAL:           context->setColorMaterialEnabled(true);         break;
1342		case GL_NORMALIZE:                context->setNormalizeEnabled(true);             break;
1343		case GL_RESCALE_NORMAL:           context->setRescaleNormalEnabled(true);         break;
1344		case GL_VERTEX_ARRAY:             context->setVertexArrayEnabled(true);           break;
1345		case GL_NORMAL_ARRAY:             context->setNormalArrayEnabled(true);           break;
1346		case GL_COLOR_ARRAY:              context->setColorArrayEnabled(true);            break;
1347		case GL_POINT_SIZE_ARRAY_OES:     context->setPointSizeArrayEnabled(true);        break;
1348		case GL_TEXTURE_COORD_ARRAY:      context->setTextureCoordArrayEnabled(true);     break;
1349		case GL_MULTISAMPLE:              context->setMultisampleEnabled(true);           break;
1350		case GL_SAMPLE_ALPHA_TO_ONE:      context->setSampleAlphaToOneEnabled(true);      break;
1351		case GL_CLIP_PLANE0:              context->setClipPlaneEnabled(0, true);          break;
1352		case GL_CLIP_PLANE1:              context->setClipPlaneEnabled(1, true);          break;
1353		case GL_CLIP_PLANE2:              context->setClipPlaneEnabled(2, true);          break;
1354		case GL_CLIP_PLANE3:              context->setClipPlaneEnabled(3, true);          break;
1355		case GL_CLIP_PLANE4:              context->setClipPlaneEnabled(4, true);          break;
1356		case GL_CLIP_PLANE5:              context->setClipPlaneEnabled(5, true);          break;
1357		case GL_POINT_SPRITE_OES:         context->setPointSpriteEnabled(true);           break;
1358		default:
1359			return error(GL_INVALID_ENUM);
1360		}
1361	}
1362}
1363
1364void EnableClientState(GLenum array)
1365{
1366	TRACE("(GLenum array = 0x%X)", array);
1367
1368	switch(array)
1369	{
1370	case GL_VERTEX_ARRAY:
1371	case GL_NORMAL_ARRAY:
1372	case GL_COLOR_ARRAY:
1373	case GL_POINT_SIZE_ARRAY_OES:
1374	case GL_TEXTURE_COORD_ARRAY:
1375		break;
1376	default:
1377		return error(GL_INVALID_ENUM);
1378	}
1379
1380	es1::Context *context = es1::getContext();
1381
1382	if(context)
1383	{
1384		GLenum texture = context->getClientActiveTexture();
1385
1386		switch(array)
1387		{
1388		case GL_VERTEX_ARRAY:         context->setVertexAttribArrayEnabled(sw::Position, true);                            break;
1389		case GL_NORMAL_ARRAY:         context->setVertexAttribArrayEnabled(sw::Normal, true);                              break;
1390		case GL_COLOR_ARRAY:          context->setVertexAttribArrayEnabled(sw::Color0, true);                              break;
1391		case GL_POINT_SIZE_ARRAY_OES: context->setVertexAttribArrayEnabled(sw::PointSize, true);                           break;
1392		case GL_TEXTURE_COORD_ARRAY:  context->setVertexAttribArrayEnabled(sw::TexCoord0 + (texture - GL_TEXTURE0), true); break;
1393		default:                      UNREACHABLE(array);
1394		}
1395	}
1396}
1397
1398void Finish(void)
1399{
1400	TRACE("()");
1401
1402	es1::Context *context = es1::getContext();
1403
1404	if(context)
1405	{
1406		context->finish();
1407	}
1408}
1409
1410void Flush(void)
1411{
1412	TRACE("()");
1413
1414	es1::Context *context = es1::getContext();
1415
1416	if(context)
1417	{
1418		context->flush();
1419	}
1420}
1421
1422void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1423{
1424	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1425	      "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1426
1427	if(target != GL_FRAMEBUFFER_OES || (renderbuffertarget != GL_RENDERBUFFER_OES && renderbuffer != 0))
1428	{
1429		return error(GL_INVALID_ENUM);
1430	}
1431
1432	es1::Context *context = es1::getContext();
1433
1434	if(context)
1435	{
1436		es1::Framebuffer *framebuffer = context->getFramebuffer();
1437		GLuint framebufferName = context->getFramebufferName();
1438
1439		if(!framebuffer || (framebufferName == 0 && renderbuffer != 0))
1440		{
1441			return error(GL_INVALID_OPERATION);
1442		}
1443
1444		switch(attachment)
1445		{
1446		case GL_COLOR_ATTACHMENT0_OES:
1447			framebuffer->setColorbuffer(GL_RENDERBUFFER_OES, renderbuffer);
1448			break;
1449		case GL_DEPTH_ATTACHMENT_OES:
1450			framebuffer->setDepthbuffer(GL_RENDERBUFFER_OES, renderbuffer);
1451			break;
1452		case GL_STENCIL_ATTACHMENT_OES:
1453			framebuffer->setStencilbuffer(GL_RENDERBUFFER_OES, renderbuffer);
1454			break;
1455		default:
1456			return error(GL_INVALID_ENUM);
1457		}
1458	}
1459}
1460
1461void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1462{
1463	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1464	      "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1465
1466	if(target != GL_FRAMEBUFFER_OES)
1467	{
1468		return error(GL_INVALID_ENUM);
1469	}
1470
1471	switch(attachment)
1472	{
1473	case GL_COLOR_ATTACHMENT0_OES:
1474	case GL_DEPTH_ATTACHMENT_OES:
1475	case GL_STENCIL_ATTACHMENT_OES:
1476		break;
1477	default:
1478		return error(GL_INVALID_ENUM);
1479	}
1480
1481	es1::Context *context = es1::getContext();
1482
1483	if(context)
1484	{
1485		if(texture == 0)
1486		{
1487			textarget = GL_NONE_OES;
1488		}
1489		else
1490		{
1491			es1::Texture *tex = context->getTexture(texture);
1492
1493			if(!tex)
1494			{
1495				return error(GL_INVALID_OPERATION);
1496			}
1497
1498			switch(textarget)
1499			{
1500			case GL_TEXTURE_2D:
1501				if(tex->getTarget() != GL_TEXTURE_2D)
1502				{
1503					return error(GL_INVALID_OPERATION);
1504				}
1505				break;
1506			default:
1507				return error(GL_INVALID_ENUM);
1508			}
1509
1510			if(level != 0)
1511			{
1512				return error(GL_INVALID_VALUE);
1513			}
1514
1515			if(tex->isCompressed(textarget, level))
1516			{
1517				return error(GL_INVALID_OPERATION);
1518			}
1519		}
1520
1521		es1::Framebuffer *framebuffer = context->getFramebuffer();
1522		GLuint framebufferName = context->getFramebufferName();
1523
1524		if(framebufferName == 0 || !framebuffer)
1525		{
1526			return error(GL_INVALID_OPERATION);
1527		}
1528
1529		switch(attachment)
1530		{
1531		case GL_COLOR_ATTACHMENT0_OES:  framebuffer->setColorbuffer(textarget, texture);   break;
1532		case GL_DEPTH_ATTACHMENT_OES:   framebuffer->setDepthbuffer(textarget, texture);   break;
1533		case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture); break;
1534		}
1535	}
1536}
1537
1538void Fogf(GLenum pname, GLfloat param)
1539{
1540	TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param);
1541
1542	es1::Context *context = es1::getContext();
1543
1544	if(context)
1545	{
1546		switch(pname)
1547		{
1548		case GL_FOG_MODE:
1549			switch((GLenum)param)
1550			{
1551			case GL_LINEAR:
1552			case GL_EXP:
1553			case GL_EXP2:
1554				context->setFogMode((GLenum)param);
1555				break;
1556			default:
1557				return error(GL_INVALID_ENUM);
1558			}
1559			break;
1560		case GL_FOG_DENSITY:
1561			if(param < 0)
1562			{
1563				return error(GL_INVALID_VALUE);
1564			}
1565			context->setFogDensity(param);
1566			break;
1567		case GL_FOG_START:
1568			context->setFogStart(param);
1569			break;
1570		case GL_FOG_END:
1571			context->setFogEnd(param);
1572			break;
1573		case GL_FOG_COLOR:
1574			return error(GL_INVALID_ENUM);   // Need four values, should call glFogfv() instead
1575		default:
1576			return error(GL_INVALID_ENUM);
1577		}
1578	}
1579}
1580
1581void Fogfv(GLenum pname, const GLfloat *params)
1582{
1583	TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname);
1584
1585	es1::Context *context = es1::getContext();
1586
1587	if(context)
1588	{
1589		switch(pname)
1590		{
1591		case GL_FOG_MODE:
1592			switch((GLenum)params[0])
1593			{
1594			case GL_LINEAR:
1595			case GL_EXP:
1596			case GL_EXP2:
1597				context->setFogMode((GLenum)params[0]);
1598				break;
1599			default:
1600				return error(GL_INVALID_ENUM);
1601			}
1602			break;
1603		case GL_FOG_DENSITY:
1604			if(params[0] < 0)
1605			{
1606				return error(GL_INVALID_VALUE);
1607			}
1608			context->setFogDensity(params[0]);
1609			break;
1610		case GL_FOG_START:
1611			context->setFogStart(params[0]);
1612			break;
1613		case GL_FOG_END:
1614			context->setFogEnd(params[0]);
1615			break;
1616		case GL_FOG_COLOR:
1617			context->setFogColor(params[0], params[1], params[2], params[3]);
1618			break;
1619		default:
1620			return error(GL_INVALID_ENUM);
1621		}
1622	}
1623}
1624
1625void Fogx(GLenum pname, GLfixed param)
1626{
1627	TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param);
1628
1629	es1::Context *context = es1::getContext();
1630
1631	if(context)
1632	{
1633		switch(pname)
1634		{
1635		case GL_FOG_MODE:
1636			switch((GLenum)param)
1637			{
1638			case GL_LINEAR:
1639			case GL_EXP:
1640			case GL_EXP2:
1641				context->setFogMode((GLenum)param);
1642				break;
1643			default:
1644				return error(GL_INVALID_ENUM);
1645			}
1646			break;
1647		case GL_FOG_DENSITY:
1648			if(param < 0)
1649			{
1650				return error(GL_INVALID_VALUE);
1651			}
1652			context->setFogDensity((float)param / 0x10000);
1653			break;
1654		case GL_FOG_START:
1655			context->setFogStart((float)param / 0x10000);
1656			break;
1657		case GL_FOG_END:
1658			context->setFogEnd((float)param / 0x10000);
1659			break;
1660		case GL_FOG_COLOR:
1661			return error(GL_INVALID_ENUM);   // Need four values, should call glFogxv() instead
1662		default:
1663			return error(GL_INVALID_ENUM);
1664		}
1665	}
1666}
1667
1668void Fogxv(GLenum pname, const GLfixed *params)
1669{
1670	UNIMPLEMENTED();
1671}
1672
1673void FrontFace(GLenum mode)
1674{
1675	TRACE("(GLenum mode = 0x%X)", mode);
1676
1677	switch(mode)
1678	{
1679	case GL_CW:
1680	case GL_CCW:
1681		{
1682			es1::Context *context = es1::getContext();
1683
1684			if(context)
1685			{
1686				context->setFrontFace(mode);
1687			}
1688		}
1689		break;
1690	default:
1691		return error(GL_INVALID_ENUM);
1692	}
1693}
1694
1695void Frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
1696{
1697	TRACE("(GLfloat left = %f, GLfloat right = %f, GLfloat bottom = %f, GLfloat top = %f, GLfloat zNear = %f, GLfloat zFar = %f)", left, right, bottom, top, zNear, zFar);
1698
1699	if(zNear <= 0.0f || zFar <= 0.0f || left == right || bottom == top || zNear == zFar)
1700	{
1701		return error(GL_INVALID_VALUE);
1702	}
1703
1704	es1::Context *context = es1::getContext();
1705
1706	if(context)
1707	{
1708		context->frustum(left, right, bottom, top, zNear, zFar);
1709	}
1710}
1711
1712void Frustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
1713{
1714	Frustumf((float)left / 0x10000, (float)right / 0x10000, (float)bottom / 0x10000, (float)top / 0x10000, (float)zNear / 0x10000, (float)zFar / 0x10000);
1715}
1716
1717void GenerateMipmapOES(GLenum target)
1718{
1719	TRACE("(GLenum target = 0x%X)", target);
1720
1721	es1::Context *context = es1::getContext();
1722
1723	if(context)
1724	{
1725		es1::Texture *texture;
1726
1727		switch(target)
1728		{
1729		case GL_TEXTURE_2D:
1730			texture = context->getTexture2D();
1731			break;
1732		default:
1733			return error(GL_INVALID_ENUM);
1734		}
1735
1736		if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))
1737		{
1738			return error(GL_INVALID_OPERATION);
1739		}
1740
1741		texture->generateMipmaps();
1742	}
1743}
1744
1745void GenBuffers(GLsizei n, GLuint* buffers)
1746{
1747	TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
1748
1749	if(n < 0)
1750	{
1751		return error(GL_INVALID_VALUE);
1752	}
1753
1754	es1::Context *context = es1::getContext();
1755
1756	if(context)
1757	{
1758		for(int i = 0; i < n; i++)
1759		{
1760			buffers[i] = context->createBuffer();
1761		}
1762	}
1763}
1764
1765void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
1766{
1767	TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
1768
1769	if(n < 0)
1770	{
1771		return error(GL_INVALID_VALUE);
1772	}
1773
1774	es1::Context *context = es1::getContext();
1775
1776	if(context)
1777	{
1778		for(int i = 0; i < n; i++)
1779		{
1780			framebuffers[i] = context->createFramebuffer();
1781		}
1782	}
1783}
1784
1785void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
1786{
1787	TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
1788
1789	if(n < 0)
1790	{
1791		return error(GL_INVALID_VALUE);
1792	}
1793
1794	es1::Context *context = es1::getContext();
1795
1796	if(context)
1797	{
1798		for(int i = 0; i < n; i++)
1799		{
1800			renderbuffers[i] = context->createRenderbuffer();
1801		}
1802	}
1803}
1804
1805void GenTextures(GLsizei n, GLuint* textures)
1806{
1807	TRACE("(GLsizei n = %d, GLuint* textures =  %p)", n, textures);
1808
1809	if(n < 0)
1810	{
1811		return error(GL_INVALID_VALUE);
1812	}
1813
1814	es1::Context *context = es1::getContext();
1815
1816	if(context)
1817	{
1818		for(int i = 0; i < n; i++)
1819		{
1820			textures[i] = context->createTexture();
1821		}
1822	}
1823}
1824
1825void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
1826{
1827	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
1828
1829	es1::Context *context = es1::getContext();
1830
1831	if(context)
1832	{
1833		if(target != GL_RENDERBUFFER_OES)
1834		{
1835			return error(GL_INVALID_ENUM);
1836		}
1837
1838		if(context->getRenderbufferName() == 0)
1839		{
1840			return error(GL_INVALID_OPERATION);
1841		}
1842
1843		es1::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
1844
1845		switch(pname)
1846		{
1847		case GL_RENDERBUFFER_WIDTH_OES:           *params = renderbuffer->getWidth();       break;
1848		case GL_RENDERBUFFER_HEIGHT_OES:          *params = renderbuffer->getHeight();      break;
1849		case GL_RENDERBUFFER_INTERNAL_FORMAT_OES:
1850			{
1851				GLint internalformat = renderbuffer->getFormat();
1852				*params = (internalformat == GL_NONE_OES) ? GL_RGBA4_OES : internalformat;
1853			}
1854			break;
1855		case GL_RENDERBUFFER_RED_SIZE_OES:        *params = renderbuffer->getRedSize();     break;
1856		case GL_RENDERBUFFER_GREEN_SIZE_OES:      *params = renderbuffer->getGreenSize();   break;
1857		case GL_RENDERBUFFER_BLUE_SIZE_OES:       *params = renderbuffer->getBlueSize();    break;
1858		case GL_RENDERBUFFER_ALPHA_SIZE_OES:      *params = renderbuffer->getAlphaSize();   break;
1859		case GL_RENDERBUFFER_DEPTH_SIZE_OES:      *params = renderbuffer->getDepthSize();   break;
1860		case GL_RENDERBUFFER_STENCIL_SIZE_OES:    *params = renderbuffer->getStencilSize(); break;
1861		default:
1862			return error(GL_INVALID_ENUM);
1863		}
1864	}
1865}
1866
1867void GetBooleanv(GLenum pname, GLboolean* params)
1868{
1869	TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)",  pname, params);
1870
1871	es1::Context *context = es1::getContext();
1872
1873	if(context)
1874	{
1875		if(!(context->getBooleanv(pname, params)))
1876		{
1877			int numParams = context->getQueryParameterNum(pname);
1878
1879			if(numParams < 0)
1880			{
1881				return error(GL_INVALID_ENUM);
1882			}
1883
1884			if(numParams == 0)
1885			{
1886				return;
1887			}
1888
1889			if(context->isQueryParameterFloat(pname))
1890			{
1891				GLfloat *floatParams = nullptr;
1892				floatParams = new GLfloat[numParams];
1893
1894				context->getFloatv(pname, floatParams);
1895
1896				for(int i = 0; i < numParams; ++i)
1897				{
1898					if(floatParams[i] == 0.0f)
1899						params[i] = GL_FALSE;
1900					else
1901						params[i] = GL_TRUE;
1902				}
1903
1904				delete [] floatParams;
1905			}
1906			else if(context->isQueryParameterInt(pname))
1907			{
1908				GLint *intParams = nullptr;
1909				intParams = new GLint[numParams];
1910
1911				context->getIntegerv(pname, intParams);
1912
1913				for(int i = 0; i < numParams; ++i)
1914				{
1915					if(intParams[i] == 0)
1916						params[i] = GL_FALSE;
1917					else
1918						params[i] = GL_TRUE;
1919				}
1920
1921				delete [] intParams;
1922			}
1923			else UNREACHABLE(pname);
1924		}
1925	}
1926}
1927
1928void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
1929{
1930	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
1931
1932	es1::Context *context = es1::getContext();
1933
1934	if(context)
1935	{
1936		es1::Buffer *buffer;
1937
1938		switch(target)
1939		{
1940		case GL_ARRAY_BUFFER:
1941			buffer = context->getArrayBuffer();
1942			break;
1943		case GL_ELEMENT_ARRAY_BUFFER:
1944			buffer = context->getElementArrayBuffer();
1945			break;
1946		default:
1947			return error(GL_INVALID_ENUM);
1948		}
1949
1950		if(!buffer)
1951		{
1952			// A null buffer means that "0" is bound to the requested buffer target
1953			return error(GL_INVALID_OPERATION);
1954		}
1955
1956		switch(pname)
1957		{
1958		case GL_BUFFER_USAGE:
1959			*params = buffer->usage();
1960			break;
1961		case GL_BUFFER_SIZE:
1962			*params = (GLint)buffer->size();
1963			break;
1964		default:
1965			return error(GL_INVALID_ENUM);
1966		}
1967	}
1968}
1969
1970void GetClipPlanef(GLenum pname, GLfloat eqn[4])
1971{
1972	UNIMPLEMENTED();
1973}
1974
1975void GetClipPlanex(GLenum pname, GLfixed eqn[4])
1976{
1977	UNIMPLEMENTED();
1978}
1979
1980GLenum GetError(void)
1981{
1982	TRACE("()");
1983
1984	es1::Context *context = es1::getContext();
1985
1986	if(context)
1987	{
1988		return context->getError();
1989	}
1990
1991	return GL_NO_ERROR;
1992}
1993
1994void GetFixedv(GLenum pname, GLfixed *params)
1995{
1996	UNIMPLEMENTED();
1997}
1998
1999void GetFloatv(GLenum pname, GLfloat* params)
2000{
2001	TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2002
2003	es1::Context *context = es1::getContext();
2004
2005	if(context)
2006	{
2007		if(!(context->getFloatv(pname, params)))
2008		{
2009			int numParams = context->getQueryParameterNum(pname);
2010
2011			if(numParams < 0)
2012			{
2013				return error(GL_INVALID_ENUM);
2014			}
2015
2016			if(numParams == 0)
2017			{
2018				return;
2019			}
2020
2021			if(context->isQueryParameterBool(pname))
2022			{
2023				GLboolean *boolParams = nullptr;
2024				boolParams = new GLboolean[numParams];
2025
2026				context->getBooleanv(pname, boolParams);
2027
2028				for(int i = 0; i < numParams; ++i)
2029				{
2030					if(boolParams[i] == GL_FALSE)
2031						params[i] = 0.0f;
2032					else
2033						params[i] = 1.0f;
2034				}
2035
2036				delete [] boolParams;
2037			}
2038			else if(context->isQueryParameterInt(pname))
2039			{
2040				GLint *intParams = nullptr;
2041				intParams = new GLint[numParams];
2042
2043				context->getIntegerv(pname, intParams);
2044
2045				for(int i = 0; i < numParams; ++i)
2046				{
2047					params[i] = (GLfloat)intParams[i];
2048				}
2049
2050				delete [] intParams;
2051			}
2052			else UNREACHABLE(pname);
2053		}
2054	}
2055}
2056
2057void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2058{
2059	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2060	      target, attachment, pname, params);
2061
2062	es1::Context *context = es1::getContext();
2063
2064	if(context)
2065	{
2066		if(target != GL_FRAMEBUFFER_OES)
2067		{
2068			return error(GL_INVALID_ENUM);
2069		}
2070
2071		if(context->getFramebufferName() == 0)
2072		{
2073			return error(GL_INVALID_OPERATION);
2074		}
2075
2076		es1::Framebuffer *framebuffer = context->getFramebuffer();
2077
2078		if(!framebuffer)
2079		{
2080			return error(GL_INVALID_OPERATION);
2081		}
2082
2083		GLenum attachmentType;
2084		GLuint attachmentHandle;
2085		switch(attachment)
2086		{
2087		case GL_COLOR_ATTACHMENT0_OES:
2088			attachmentType = framebuffer->getColorbufferType();
2089			attachmentHandle = framebuffer->getColorbufferName();
2090			break;
2091		case GL_DEPTH_ATTACHMENT_OES:
2092			attachmentType = framebuffer->getDepthbufferType();
2093			attachmentHandle = framebuffer->getDepthbufferName();
2094			break;
2095		case GL_STENCIL_ATTACHMENT_OES:
2096			attachmentType = framebuffer->getStencilbufferType();
2097			attachmentHandle = framebuffer->getStencilbufferName();
2098			break;
2099		default:
2100			return error(GL_INVALID_ENUM);
2101		}
2102
2103		GLenum attachmentObjectType;   // Type category
2104		if(attachmentType == GL_NONE_OES || attachmentType == GL_RENDERBUFFER_OES)
2105		{
2106			attachmentObjectType = attachmentType;
2107		}
2108		else if(es1::IsTextureTarget(attachmentType))
2109		{
2110			attachmentObjectType = GL_TEXTURE;
2111		}
2112		else UNREACHABLE(attachmentType);
2113
2114		switch(pname)
2115		{
2116		case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES:
2117			*params = attachmentObjectType;
2118			break;
2119		case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES:
2120			if(attachmentObjectType == GL_RENDERBUFFER_OES || attachmentObjectType == GL_TEXTURE)
2121			{
2122				*params = attachmentHandle;
2123			}
2124			else
2125			{
2126				return error(GL_INVALID_ENUM);
2127			}
2128			break;
2129		case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES:
2130			if(attachmentObjectType == GL_TEXTURE)
2131			{
2132				*params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
2133			}
2134			else
2135			{
2136				return error(GL_INVALID_ENUM);
2137			}
2138			break;
2139		default:
2140			return error(GL_INVALID_ENUM);
2141		}
2142	}
2143}
2144
2145void GetIntegerv(GLenum pname, GLint* params)
2146{
2147	TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2148
2149	es1::Context *context = es1::getContext();
2150
2151	if(context)
2152	{
2153		if(!(context->getIntegerv(pname, params)))
2154		{
2155			int numParams = context->getQueryParameterNum(pname);
2156
2157			if(numParams < 0)
2158			{
2159				return error(GL_INVALID_ENUM);
2160			}
2161
2162			if(numParams == 0)
2163			{
2164				return;
2165			}
2166
2167			if(context->isQueryParameterBool(pname))
2168			{
2169				GLboolean *boolParams = nullptr;
2170				boolParams = new GLboolean[numParams];
2171
2172				context->getBooleanv(pname, boolParams);
2173
2174				for(int i = 0; i < numParams; ++i)
2175				{
2176					if(boolParams[i] == GL_FALSE)
2177						params[i] = 0;
2178					else
2179						params[i] = 1;
2180				}
2181
2182				delete [] boolParams;
2183			}
2184			else if(context->isQueryParameterFloat(pname))
2185			{
2186				GLfloat *floatParams = nullptr;
2187				floatParams = new GLfloat[numParams];
2188
2189				context->getFloatv(pname, floatParams);
2190
2191				for(int i = 0; i < numParams; ++i)
2192				{
2193					if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE)
2194					{
2195						params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);
2196					}
2197					else
2198					{
2199						params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2200					}
2201				}
2202
2203				delete [] floatParams;
2204			}
2205			else UNREACHABLE(pname);
2206		}
2207	}
2208}
2209
2210void GetLightfv(GLenum light, GLenum pname, GLfloat *params)
2211{
2212	UNIMPLEMENTED();
2213}
2214
2215void GetLightxv(GLenum light, GLenum pname, GLfixed *params)
2216{
2217	UNIMPLEMENTED();
2218}
2219
2220void GetMaterialfv(GLenum face, GLenum pname, GLfloat *params)
2221{
2222	UNIMPLEMENTED();
2223}
2224
2225void GetMaterialxv(GLenum face, GLenum pname, GLfixed *params)
2226{
2227	UNIMPLEMENTED();
2228}
2229
2230void GetPointerv(GLenum pname, GLvoid **params)
2231{
2232	TRACE("(GLenum pname = 0x%X, GLvoid **params = %p)", pname, params);
2233
2234	es1::Context *context = es1::getContext();
2235
2236	if(context)
2237	{
2238		if(!(context->getPointerv(pname, const_cast<const GLvoid**>(params))))
2239		{
2240			return error(GL_INVALID_ENUM);
2241		}
2242	}
2243}
2244
2245const GLubyte* GetString(GLenum name)
2246{
2247	TRACE("(GLenum name = 0x%X)", name);
2248
2249	switch(name)
2250	{
2251	case GL_VENDOR:
2252		return (GLubyte*)"Google Inc.";
2253	case GL_RENDERER:
2254		return (GLubyte*)"Google SwiftShader " VERSION_STRING;
2255	case GL_VERSION:
2256		return (GLubyte*)"OpenGL ES-CM 1.1";
2257	case GL_EXTENSIONS:
2258		// Keep list sorted in following order:
2259		// OES extensions
2260		// EXT extensions
2261		// Vendor extensions
2262		return (GLubyte*)
2263			"GL_OES_blend_equation_separate "
2264			"GL_OES_blend_func_separate "
2265			"GL_OES_blend_subtract "
2266			"GL_OES_compressed_ETC1_RGB8_texture "
2267			"GL_OES_EGL_image "
2268			"GL_OES_EGL_image_external "
2269			"GL_OES_EGL_sync "
2270			"GL_OES_element_index_uint "
2271			"GL_OES_framebuffer_object "
2272			"GL_OES_packed_depth_stencil "
2273			"GL_OES_read_format "
2274			"GL_OES_rgb8_rgba8 "
2275			"GL_OES_stencil8 "
2276			"GL_OES_stencil_wrap "
2277			"GL_OES_surfaceless_context "
2278			"GL_OES_texture_mirrored_repeat "
2279			"GL_OES_texture_npot "
2280			"GL_EXT_blend_minmax "
2281			"GL_EXT_read_format_bgra "
2282			"GL_EXT_texture_compression_dxt1 "
2283			"GL_ANGLE_texture_compression_dxt3 "
2284			"GL_ANGLE_texture_compression_dxt5 "
2285			"GL_EXT_texture_filter_anisotropic "
2286			"GL_EXT_texture_format_BGRA8888";
2287	default:
2288		return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
2289	}
2290}
2291
2292void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
2293{
2294	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
2295
2296	es1::Context *context = es1::getContext();
2297
2298	if(context)
2299	{
2300		es1::Texture *texture;
2301
2302		switch(target)
2303		{
2304		case GL_TEXTURE_2D:
2305			texture = context->getTexture2D();
2306			break;
2307		case GL_TEXTURE_EXTERNAL_OES:
2308			texture = context->getTextureExternal();
2309			break;
2310		default:
2311			return error(GL_INVALID_ENUM);
2312		}
2313
2314		switch(pname)
2315		{
2316		case GL_TEXTURE_MAG_FILTER:
2317			*params = (GLfloat)texture->getMagFilter();
2318			break;
2319		case GL_TEXTURE_MIN_FILTER:
2320			*params = (GLfloat)texture->getMinFilter();
2321			break;
2322		case GL_TEXTURE_WRAP_S:
2323			*params = (GLfloat)texture->getWrapS();
2324			break;
2325		case GL_TEXTURE_WRAP_T:
2326			*params = (GLfloat)texture->getWrapT();
2327			break;
2328		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
2329			*params = texture->getMaxAnisotropy();
2330			break;
2331		case GL_GENERATE_MIPMAP:
2332			*params = (GLfloat)texture->getGenerateMipmap();
2333			break;
2334		case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2335			*params = (GLfloat)1;
2336			break;
2337		default:
2338			return error(GL_INVALID_ENUM);
2339		}
2340	}
2341}
2342
2343void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
2344{
2345	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2346
2347	es1::Context *context = es1::getContext();
2348
2349	if(context)
2350	{
2351		es1::Texture *texture;
2352
2353		switch(target)
2354		{
2355		case GL_TEXTURE_2D:
2356			texture = context->getTexture2D();
2357			break;
2358		case GL_TEXTURE_EXTERNAL_OES:
2359			texture = context->getTextureExternal();
2360			break;
2361		default:
2362			return error(GL_INVALID_ENUM);
2363		}
2364
2365		switch(pname)
2366		{
2367		case GL_TEXTURE_MAG_FILTER:
2368			*params = texture->getMagFilter();
2369			break;
2370		case GL_TEXTURE_MIN_FILTER:
2371			*params = texture->getMinFilter();
2372			break;
2373		case GL_TEXTURE_WRAP_S:
2374			*params = texture->getWrapS();
2375			break;
2376		case GL_TEXTURE_WRAP_T:
2377			*params = texture->getWrapT();
2378			break;
2379		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
2380			*params = (GLint)texture->getMaxAnisotropy();
2381			break;
2382		case GL_GENERATE_MIPMAP:
2383			*params = (GLint)texture->getGenerateMipmap();
2384			break;
2385		case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2386			*params = 1;
2387			break;
2388		default:
2389			return error(GL_INVALID_ENUM);
2390		}
2391	}
2392}
2393
2394void GetTexEnvfv(GLenum env, GLenum pname, GLfloat *params)
2395{
2396	UNIMPLEMENTED();
2397}
2398
2399void GetTexEnviv(GLenum env, GLenum pname, GLint *params)
2400{
2401	UNIMPLEMENTED();
2402}
2403
2404void GetTexEnvxv(GLenum env, GLenum pname, GLfixed *params)
2405{
2406	UNIMPLEMENTED();
2407}
2408
2409void GetTexParameterxv(GLenum target, GLenum pname, GLfixed *params)
2410{
2411	UNIMPLEMENTED();
2412}
2413
2414void Hint(GLenum target, GLenum mode)
2415{
2416	TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
2417
2418	switch(mode)
2419	{
2420	case GL_FASTEST:
2421	case GL_NICEST:
2422	case GL_DONT_CARE:
2423		break;
2424	default:
2425		return error(GL_INVALID_ENUM);
2426	}
2427
2428	es1::Context *context = es1::getContext();
2429
2430	if(context)
2431	{
2432		switch(target)
2433		{
2434		case GL_GENERATE_MIPMAP_HINT:
2435			context->setGenerateMipmapHint(mode);
2436			break;
2437		case GL_PERSPECTIVE_CORRECTION_HINT:
2438			context->setPerspectiveCorrectionHint(mode);
2439			break;
2440		case GL_FOG_HINT:
2441			context->setFogHint(mode);
2442			break;
2443		default:
2444			return error(GL_INVALID_ENUM);
2445		}
2446	}
2447}
2448
2449GLboolean IsBuffer(GLuint buffer)
2450{
2451	TRACE("(GLuint buffer = %d)", buffer);
2452
2453	es1::Context *context = es1::getContext();
2454
2455	if(context && buffer)
2456	{
2457		es1::Buffer *bufferObject = context->getBuffer(buffer);
2458
2459		if(bufferObject)
2460		{
2461			return GL_TRUE;
2462		}
2463	}
2464
2465	return GL_FALSE;
2466}
2467
2468GLboolean IsEnabled(GLenum cap)
2469{
2470	TRACE("(GLenum cap = 0x%X)", cap);
2471
2472	es1::Context *context = es1::getContext();
2473
2474	if(context)
2475	{
2476		switch(cap)
2477		{
2478		case GL_CULL_FACE:                return context->isCullFaceEnabled();              break;
2479		case GL_POLYGON_OFFSET_FILL:      return context->isPolygonOffsetFillEnabled();     break;
2480		case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled(); break;
2481		case GL_SAMPLE_COVERAGE:          return context->isSampleCoverageEnabled();        break;
2482		case GL_SCISSOR_TEST:             return context->isScissorTestEnabled();           break;
2483		case GL_STENCIL_TEST:             return context->isStencilTestEnabled();           break;
2484		case GL_DEPTH_TEST:               return context->isDepthTestEnabled();             break;
2485		case GL_BLEND:                    return context->isBlendEnabled();                 break;
2486		case GL_DITHER:                   return context->isDitherEnabled();                break;
2487		case GL_LIGHTING:                 return context->isLightingEnabled();              break;
2488		case GL_LIGHT0:                   return context->isLightEnabled(0);                break;
2489		case GL_LIGHT1:                   return context->isLightEnabled(1);                break;
2490		case GL_LIGHT2:                   return context->isLightEnabled(2);                break;
2491		case GL_LIGHT3:                   return context->isLightEnabled(3);                break;
2492		case GL_LIGHT4:                   return context->isLightEnabled(4);                break;
2493		case GL_LIGHT5:                   return context->isLightEnabled(5);                break;
2494		case GL_LIGHT6:                   return context->isLightEnabled(6);                break;
2495		case GL_LIGHT7:                   return context->isLightEnabled(7);                break;
2496		case GL_FOG:                      return context->isFogEnabled();                   break;
2497		case GL_TEXTURE_2D:               return context->isTexture2Denabled();             break;
2498		case GL_TEXTURE_EXTERNAL_OES:     return context->isTextureExternalEnabled();       break;
2499		case GL_ALPHA_TEST:               return context->isAlphaTestEnabled();             break;
2500		case GL_COLOR_LOGIC_OP:           return context->isColorLogicOpEnabled();          break;
2501		case GL_POINT_SMOOTH:             return context->isPointSmoothEnabled();           break;
2502		case GL_LINE_SMOOTH:              return context->isLineSmoothEnabled();            break;
2503		case GL_COLOR_MATERIAL:           return context->isColorMaterialEnabled();         break;
2504		case GL_NORMALIZE:                return context->isNormalizeEnabled();             break;
2505		case GL_RESCALE_NORMAL:           return context->isRescaleNormalEnabled();         break;
2506		case GL_VERTEX_ARRAY:             return context->isVertexArrayEnabled();           break;
2507		case GL_NORMAL_ARRAY:             return context->isNormalArrayEnabled();           break;
2508		case GL_COLOR_ARRAY:              return context->isColorArrayEnabled();            break;
2509		case GL_POINT_SIZE_ARRAY_OES:     return context->isPointSizeArrayEnabled();        break;
2510		case GL_TEXTURE_COORD_ARRAY:      return context->isTextureCoordArrayEnabled();     break;
2511		case GL_MULTISAMPLE:              return context->isMultisampleEnabled();           break;
2512		case GL_SAMPLE_ALPHA_TO_ONE:      return context->isSampleAlphaToOneEnabled();      break;
2513		case GL_CLIP_PLANE0:              return context->isClipPlaneEnabled(0);            break;
2514		case GL_CLIP_PLANE1:              return context->isClipPlaneEnabled(1);            break;
2515		case GL_CLIP_PLANE2:              return context->isClipPlaneEnabled(2);            break;
2516		case GL_CLIP_PLANE3:              return context->isClipPlaneEnabled(3);            break;
2517		case GL_CLIP_PLANE4:              return context->isClipPlaneEnabled(4);            break;
2518		case GL_CLIP_PLANE5:              return context->isClipPlaneEnabled(5);            break;
2519		case GL_POINT_SPRITE_OES:         return context->isPointSpriteEnabled();           break;
2520		default:
2521			return error(GL_INVALID_ENUM, GL_FALSE);
2522		}
2523	}
2524
2525	return GL_FALSE;
2526}
2527
2528GLboolean IsFramebufferOES(GLuint framebuffer)
2529{
2530	TRACE("(GLuint framebuffer = %d)", framebuffer);
2531
2532	es1::Context *context = es1::getContext();
2533
2534	if(context && framebuffer)
2535	{
2536		es1::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
2537
2538		if(framebufferObject)
2539		{
2540			return GL_TRUE;
2541		}
2542	}
2543
2544	return GL_FALSE;
2545}
2546
2547GLboolean IsTexture(GLuint texture)
2548{
2549	TRACE("(GLuint texture = %d)", texture);
2550
2551	es1::Context *context = es1::getContext();
2552
2553	if(context && texture)
2554	{
2555		es1::Texture *textureObject = context->getTexture(texture);
2556
2557		if(textureObject)
2558		{
2559			return GL_TRUE;
2560		}
2561	}
2562
2563	return GL_FALSE;
2564}
2565
2566GLboolean IsRenderbufferOES(GLuint renderbuffer)
2567{
2568	TRACE("(GLuint renderbuffer = %d)", renderbuffer);
2569
2570	es1::Context *context = es1::getContext();
2571
2572	if(context && renderbuffer)
2573	{
2574		es1::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
2575
2576		if(renderbufferObject)
2577		{
2578			return GL_TRUE;
2579		}
2580	}
2581
2582	return GL_FALSE;
2583}
2584
2585void LightModelf(GLenum pname, GLfloat param)
2586{
2587	TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param);
2588
2589	es1::Context *context = es1::getContext();
2590
2591	if(context)
2592	{
2593		switch(pname)
2594		{
2595		case GL_LIGHT_MODEL_TWO_SIDE:
2596			context->setLightModelTwoSide(param != 0.0f);
2597			break;
2598		case GL_LIGHT_MODEL_AMBIENT:
2599			return error(GL_INVALID_ENUM);   // Need four values, should call glLightModelfv() instead
2600		default:
2601			return error(GL_INVALID_ENUM);
2602		}
2603	}
2604}
2605
2606void LightModelfv(GLenum pname, const GLfloat *params)
2607{
2608	TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname);
2609
2610	es1::Context *context = es1::getContext();
2611
2612	if(context)
2613	{
2614		switch(pname)
2615		{
2616		case GL_LIGHT_MODEL_AMBIENT:
2617			context->setGlobalAmbient(params[0], params[1], params[2], params[3]);
2618			break;
2619		case GL_LIGHT_MODEL_TWO_SIDE:
2620			context->setLightModelTwoSide(params[0] != 0.0f);
2621			break;
2622		default:
2623			return error(GL_INVALID_ENUM);
2624		}
2625	}
2626}
2627
2628void LightModelx(GLenum pname, GLfixed param)
2629{
2630	TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param);
2631
2632	es1::Context *context = es1::getContext();
2633
2634	if(context)
2635	{
2636		switch(pname)
2637		{
2638		case GL_LIGHT_MODEL_TWO_SIDE:
2639			context->setLightModelTwoSide(param != 0);
2640			break;
2641		case GL_LIGHT_MODEL_AMBIENT:
2642			return error(GL_INVALID_ENUM);   // Need four values, should call glLightModelxv() instead
2643		default:
2644			return error(GL_INVALID_ENUM);
2645		}
2646	}
2647}
2648
2649void LightModelxv(GLenum pname, const GLfixed *params)
2650{
2651	TRACE("(GLenum pname = 0x%X, const GLfixed *params)", pname);
2652
2653	es1::Context *context = es1::getContext();
2654
2655	if(context)
2656	{
2657		switch(pname)
2658		{
2659		case GL_LIGHT_MODEL_AMBIENT:
2660			context->setGlobalAmbient((float)params[0] / 0x10000, (float)params[1] / 0x10000, (float)params[2] / 0x10000, (float)params[3] / 0x10000);
2661			break;
2662		case GL_LIGHT_MODEL_TWO_SIDE:
2663			context->setLightModelTwoSide(params[0] != 0);
2664			break;
2665		default:
2666			return error(GL_INVALID_ENUM);
2667		}
2668	}
2669}
2670
2671void Lightf(GLenum light, GLenum pname, GLfloat param)
2672{
2673	TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", light, pname, param);
2674
2675	int index = light - GL_LIGHT0;
2676
2677	if(index < 0 || index >= es1::MAX_LIGHTS)
2678	{
2679		return error(GL_INVALID_ENUM);
2680	}
2681
2682	es1::Context *context = es1::getContext();
2683
2684	if(context)
2685	{
2686		switch(pname)
2687		{
2688		case GL_SPOT_EXPONENT:
2689			if(param < 0.0f || param > 128.0f)
2690			{
2691				return error(GL_INVALID_VALUE);
2692			}
2693			context->setSpotLightExponent(index, param);
2694			break;
2695		case GL_SPOT_CUTOFF:
2696			if((param < 0.0f || param > 90.0f) && param != 180.0f)
2697			{
2698				return error(GL_INVALID_VALUE);
2699			}
2700			context->setSpotLightCutoff(index, param);
2701			break;
2702		case GL_CONSTANT_ATTENUATION:
2703			if(param < 0.0f)
2704			{
2705				return error(GL_INVALID_VALUE);
2706			}
2707			context->setLightAttenuationConstant(index, param);
2708			break;
2709		case GL_LINEAR_ATTENUATION:
2710			if(param < 0.0f)
2711			{
2712				return error(GL_INVALID_VALUE);
2713			}
2714			context->setLightAttenuationLinear(index, param);
2715			break;
2716		case GL_QUADRATIC_ATTENUATION:
2717			if(param < 0.0f)
2718			{
2719				return error(GL_INVALID_VALUE);
2720			}
2721			context->setLightAttenuationQuadratic(index, param);
2722			break;
2723		case GL_AMBIENT:
2724		case GL_DIFFUSE:
2725		case GL_SPECULAR:
2726		case GL_POSITION:
2727		case GL_SPOT_DIRECTION:
2728			return error(GL_INVALID_ENUM);   // Need four values, should call glLightfv() instead
2729		default:
2730			return error(GL_INVALID_ENUM);
2731		}
2732	}
2733}
2734
2735void Lightfv(GLenum light, GLenum pname, const GLfloat *params)
2736{
2737	TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, const GLint *params)", light, pname);
2738
2739	es1::Context *context = es1::getContext();
2740
2741	if(context)
2742	{
2743		int index = light - GL_LIGHT0;
2744
2745		if(index < 0 || index > es1::MAX_LIGHTS)
2746		{
2747			return error(GL_INVALID_ENUM);
2748		}
2749
2750		switch(pname)
2751		{
2752		case GL_AMBIENT:               context->setLightAmbient(index, params[0], params[1], params[2], params[3]);  break;
2753		case GL_DIFFUSE:               context->setLightDiffuse(index, params[0], params[1], params[2], params[3]);  break;
2754		case GL_SPECULAR:              context->setLightSpecular(index, params[0], params[1], params[2], params[3]); break;
2755		case GL_POSITION:              context->setLightPosition(index, params[0], params[1], params[2], params[3]); break;
2756		case GL_SPOT_DIRECTION:        context->setLightDirection(index, params[0], params[1], params[2]);           break;
2757		case GL_SPOT_EXPONENT:
2758			if(params[0] < 0.0f || params[0] > 128.0f)
2759			{
2760				return error(GL_INVALID_VALUE);
2761			}
2762			context->setSpotLightExponent(index, params[0]);
2763			break;
2764		case GL_SPOT_CUTOFF:
2765			if((params[0] < 0.0f || params[0] > 90.0f) && params[0] != 180.0f)
2766			{
2767				return error(GL_INVALID_VALUE);
2768			}
2769			context->setSpotLightCutoff(index, params[0]);
2770			break;
2771		case GL_CONSTANT_ATTENUATION:
2772			if(params[0] < 0.0f)
2773			{
2774				return error(GL_INVALID_VALUE);
2775			}
2776			context->setLightAttenuationConstant(index, params[0]);
2777			break;
2778		case GL_LINEAR_ATTENUATION:
2779			if(params[0] < 0.0f)
2780			{
2781				return error(GL_INVALID_VALUE);
2782			}
2783			context->setLightAttenuationLinear(index, params[0]);
2784			break;
2785		case GL_QUADRATIC_ATTENUATION:
2786			if(params[0] < 0.0f)
2787			{
2788				return error(GL_INVALID_VALUE);
2789			}
2790			context->setLightAttenuationQuadratic(index, params[0]);
2791			break;
2792		default:
2793			return error(GL_INVALID_ENUM);
2794		}
2795	}
2796}
2797
2798void Lightx(GLenum light, GLenum pname, GLfixed param)
2799{
2800	UNIMPLEMENTED();
2801}
2802
2803void Lightxv(GLenum light, GLenum pname, const GLfixed *params)
2804{
2805	UNIMPLEMENTED();
2806}
2807
2808void LineWidth(GLfloat width)
2809{
2810	TRACE("(GLfloat width = %f)", width);
2811
2812	if(width <= 0.0f)
2813	{
2814		return error(GL_INVALID_VALUE);
2815	}
2816
2817	es1::Context *context = es1::getContext();
2818
2819	if(context)
2820	{
2821		context->setLineWidth(width);
2822	}
2823}
2824
2825void LineWidthx(GLfixed width)
2826{
2827	LineWidth((float)width / 0x10000);
2828}
2829
2830void LoadIdentity(void)
2831{
2832	TRACE("()");
2833
2834	es1::Context *context = es1::getContext();
2835
2836	if(context)
2837	{
2838		context->loadIdentity();
2839	}
2840}
2841
2842void LoadMatrixf(const GLfloat *m)
2843{
2844	TRACE("(const GLfloat *m)");
2845
2846	es1::Context *context = es1::getContext();
2847
2848	if(context)
2849	{
2850		context->load(m);
2851	}
2852}
2853
2854void LoadMatrixx(const GLfixed *m)
2855{
2856	GLfloat matrix[16] =
2857	{
2858		(float)m[0] / 0x10000,  (float)m[1] / 0x10000,  (float)m[2] / 0x10000,  (float)m[3] / 0x10000,
2859		(float)m[4] / 0x10000,  (float)m[5] / 0x10000,  (float)m[6] / 0x10000,  (float)m[7] / 0x10000,
2860		(float)m[8] / 0x10000,  (float)m[9] / 0x10000,  (float)m[10] / 0x10000, (float)m[11] / 0x10000,
2861		(float)m[12] / 0x10000, (float)m[13] / 0x10000, (float)m[14] / 0x10000, (float)m[15] / 0x10000
2862	};
2863
2864	LoadMatrixf(matrix);
2865}
2866
2867void LogicOp(GLenum opcode)
2868{
2869	TRACE("(GLenum opcode = 0x%X)", opcode);
2870
2871	switch(opcode)
2872	{
2873	case GL_CLEAR:
2874	case GL_SET:
2875	case GL_COPY:
2876	case GL_COPY_INVERTED:
2877	case GL_NOOP:
2878	case GL_INVERT:
2879	case GL_AND:
2880	case GL_NAND:
2881	case GL_OR:
2882	case GL_NOR:
2883	case GL_XOR:
2884	case GL_EQUIV:
2885	case GL_AND_REVERSE:
2886	case GL_AND_INVERTED:
2887	case GL_OR_REVERSE:
2888	case GL_OR_INVERTED:
2889		break;
2890	default:
2891		return error(GL_INVALID_ENUM);
2892	}
2893
2894	es1::Context *context = es1::getContext();
2895
2896	if(context)
2897	{
2898		context->setLogicalOperation(opcode);
2899	}
2900}
2901
2902void Materialf(GLenum face, GLenum pname, GLfloat param)
2903{
2904	TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", face, pname, param);
2905
2906	if(face != GL_FRONT_AND_BACK)
2907	{
2908		return error(GL_INVALID_ENUM);
2909	}
2910
2911	es1::Context *context = es1::getContext();
2912
2913	if(context)
2914	{
2915		switch(pname)
2916		{
2917		case GL_SHININESS:
2918			if(param < 0.0f || param > 128.0f)
2919			{
2920				return error(GL_INVALID_VALUE);
2921			}
2922			context->setMaterialShininess(param);
2923			break;
2924		case GL_AMBIENT:
2925		case GL_DIFFUSE:
2926		case GL_AMBIENT_AND_DIFFUSE:
2927		case GL_SPECULAR:
2928		case GL_EMISSION:
2929			return error(GL_INVALID_ENUM);   // Need four values, should call glMaterialfv() instead
2930		default:
2931			return error(GL_INVALID_ENUM);
2932		}
2933	}
2934}
2935
2936void Materialfv(GLenum face, GLenum pname, const GLfloat *params)
2937{
2938	TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat params)", face, pname);
2939
2940	if(face != GL_FRONT_AND_BACK)
2941	{
2942		return error(GL_INVALID_ENUM);
2943	}
2944
2945	es1::Context *context = es1::getContext();
2946
2947	if(context)
2948	{
2949		switch(pname)
2950		{
2951		case GL_AMBIENT:
2952			context->setMaterialAmbient(params[0], params[1], params[2], params[3]);
2953			break;
2954		case GL_DIFFUSE:
2955			context->setMaterialDiffuse(params[0], params[1], params[2], params[3]);
2956			break;
2957		case GL_AMBIENT_AND_DIFFUSE:
2958			context->setMaterialAmbient(params[0], params[1], params[2], params[3]);
2959			context->setMaterialDiffuse(params[0], params[1], params[2], params[3]);
2960			break;
2961		case GL_SPECULAR:
2962			context->setMaterialSpecular(params[0], params[1], params[2], params[3]);
2963			break;
2964		case GL_EMISSION:
2965			context->setMaterialEmission(params[0], params[1], params[2], params[3]);
2966			break;
2967		case GL_SHININESS:
2968			context->setMaterialShininess(params[0]);
2969			break;
2970		default:
2971			return error(GL_INVALID_ENUM);
2972		}
2973	}
2974}
2975
2976void Materialx(GLenum face, GLenum pname, GLfixed param)
2977{
2978	UNIMPLEMENTED();
2979}
2980
2981void Materialxv(GLenum face, GLenum pname, const GLfixed *params)
2982{
2983	UNIMPLEMENTED();
2984}
2985
2986void MatrixMode(GLenum mode)
2987{
2988	TRACE("(GLenum mode = 0x%X)", mode);
2989
2990	es1::Context *context = es1::getContext();
2991
2992	if(context)
2993	{
2994		context->setMatrixMode(mode);
2995	}
2996}
2997
2998void MultMatrixf(const GLfloat *m)
2999{
3000	TRACE("(const GLfloat *m)");
3001
3002	es1::Context *context = es1::getContext();
3003
3004	if(context)
3005	{
3006		context->multiply(m);
3007	}
3008}
3009
3010void MultMatrixx(const GLfixed *m)
3011{
3012	GLfloat matrix[16] =
3013	{
3014		(float)m[0] / 0x10000,  (float)m[1] / 0x10000,  (float)m[2] / 0x10000,  (float)m[3] / 0x10000,
3015		(float)m[4] / 0x10000,  (float)m[5] / 0x10000,  (float)m[6] / 0x10000,  (float)m[7] / 0x10000,
3016		(float)m[8] / 0x10000,  (float)m[9] / 0x10000,  (float)m[10] / 0x10000, (float)m[11] / 0x10000,
3017		(float)m[12] / 0x10000, (float)m[13] / 0x10000, (float)m[14] / 0x10000, (float)m[15] / 0x10000
3018	};
3019
3020	MultMatrixf(matrix);
3021}
3022
3023void MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
3024{
3025	TRACE("(GLenum target = 0x%X, GLfloat s = %f, GLfloat t = %f, GLfloat r = %f, GLfloat q = %f)", target, s, t, r, q);
3026
3027	switch(target)
3028	{
3029	case GL_TEXTURE0:
3030	case GL_TEXTURE1:
3031		break;
3032	default:
3033		return error(GL_INVALID_ENUM);
3034	}
3035
3036	es1::Context *context = es1::getContext();
3037
3038	if(context)
3039	{
3040		context->setVertexAttrib(sw::TexCoord0 + (target - GL_TEXTURE0), s, t, r, q);
3041	}
3042}
3043
3044void MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
3045{
3046	UNIMPLEMENTED();
3047}
3048
3049void Normal3f(GLfloat nx, GLfloat ny, GLfloat nz)
3050{
3051	TRACE("(GLfloat nx, GLfloat ny, GLfloat nz)", nx, ny, nz);
3052
3053	es1::Context *context = es1::getContext();
3054
3055	if(context)
3056	{
3057		context->setVertexAttrib(sw::Normal, nx, ny, nz, 0);
3058	}
3059}
3060
3061void Normal3x(GLfixed nx, GLfixed ny, GLfixed nz)
3062{
3063	UNIMPLEMENTED();
3064}
3065
3066void NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
3067{
3068	TRACE("(GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", type, stride, pointer);
3069
3070	VertexAttribPointer(sw::Normal, 3, type, true, stride, pointer);
3071}
3072
3073void Orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
3074{
3075	TRACE("(GLfloat left = %f, GLfloat right = %f, GLfloat bottom = %f, GLfloat top = %f, GLfloat zNear = %f, GLfloat zFar = %f)", left, right, bottom, top, zNear, zFar);
3076
3077	if(left == right || bottom == top || zNear == zFar)
3078	{
3079		return error(GL_INVALID_VALUE);
3080	}
3081
3082	es1::Context *context = es1::getContext();
3083
3084	if(context)
3085	{
3086		context->ortho(left, right, bottom, top, zNear, zFar);
3087	}
3088}
3089
3090void Orthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
3091{
3092	Orthof((float)left / 0x10000, (float)right / 0x10000, (float)bottom / 0x10000, (float)top / 0x10000, (float)zNear / 0x10000, (float)zFar / 0x10000);
3093}
3094
3095void PixelStorei(GLenum pname, GLint param)
3096{
3097	TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
3098
3099	es1::Context *context = es1::getContext();
3100
3101	if(context)
3102	{
3103		switch(pname)
3104		{
3105		case GL_UNPACK_ALIGNMENT:
3106			if(param != 1 && param != 2 && param != 4 && param != 8)
3107			{
3108				return error(GL_INVALID_VALUE);
3109			}
3110
3111			context->setUnpackAlignment(param);
3112			break;
3113		case GL_PACK_ALIGNMENT:
3114			if(param != 1 && param != 2 && param != 4 && param != 8)
3115			{
3116				return error(GL_INVALID_VALUE);
3117			}
3118
3119			context->setPackAlignment(param);
3120			break;
3121		default:
3122			return error(GL_INVALID_ENUM);
3123		}
3124	}
3125}
3126
3127void PointParameterf(GLenum pname, GLfloat param)
3128{
3129	TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param);
3130
3131	es1::Context *context = es1::getContext();
3132
3133	if(context)
3134	{
3135		switch(pname)
3136		{
3137		case GL_POINT_SIZE_MIN:
3138			if(param < 0.0f)
3139			{
3140				return error(GL_INVALID_VALUE);
3141			}
3142			context->setPointSizeMin(param);
3143			break;
3144		case GL_POINT_SIZE_MAX:
3145			if(param < 0.0f)
3146			{
3147				return error(GL_INVALID_VALUE);
3148			}
3149			context->setPointSizeMax(param);
3150			break;
3151		case GL_POINT_FADE_THRESHOLD_SIZE:
3152			if(param < 0.0f)
3153			{
3154				return error(GL_INVALID_VALUE);
3155			}
3156			context->setPointFadeThresholdSize(param);
3157			break;
3158		case GL_POINT_DISTANCE_ATTENUATION:
3159			return error(GL_INVALID_ENUM);   // Needs three values, should call glPointParameterfv() instead
3160		default:
3161			return error(GL_INVALID_ENUM);
3162		}
3163	}
3164}
3165
3166void PointParameterfv(GLenum pname, const GLfloat *params)
3167{
3168	TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname);
3169
3170	es1::Context *context = es1::getContext();
3171
3172	if(context)
3173	{
3174		switch(pname)
3175		{
3176		case GL_POINT_SIZE_MIN:
3177			if(params[0] < 0.0f)
3178			{
3179				return error(GL_INVALID_VALUE);
3180			}
3181			context->setPointSizeMin(params[0]);
3182			break;
3183		case GL_POINT_SIZE_MAX:
3184			if(params[0] < 0.0f)
3185			{
3186				return error(GL_INVALID_VALUE);
3187			}
3188			context->setPointSizeMax(params[0]);
3189			break;
3190		case GL_POINT_DISTANCE_ATTENUATION:
3191			context->setPointDistanceAttenuation(params[0], params[1], params[2]);
3192			break;
3193		case GL_POINT_FADE_THRESHOLD_SIZE:
3194			if(params[0] < 0.0f)
3195			{
3196				return error(GL_INVALID_VALUE);
3197			}
3198			context->setPointFadeThresholdSize(params[0]);
3199			break;
3200		default:
3201			return error(GL_INVALID_ENUM);
3202		}
3203	}
3204}
3205
3206void PointParameterx(GLenum pname, GLfixed param)
3207{
3208	TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param);
3209
3210	es1::Context *context = es1::getContext();
3211
3212	if(context)
3213	{
3214		switch(pname)
3215		{
3216		case GL_POINT_SIZE_MIN:
3217			if(param < 0)
3218			{
3219				return error(GL_INVALID_VALUE);
3220			}
3221			context->setPointSizeMin((float)param / 0x10000);
3222			break;
3223		case GL_POINT_SIZE_MAX:
3224			if(param < 0)
3225			{
3226				return error(GL_INVALID_VALUE);
3227			}
3228			context->setPointSizeMax((float)param / 0x10000);
3229			break;
3230		case GL_POINT_FADE_THRESHOLD_SIZE:
3231			if(param < 0)
3232			{
3233				return error(GL_INVALID_VALUE);
3234			}
3235			context->setPointFadeThresholdSize((float)param / 0x10000);
3236			break;
3237		case GL_POINT_DISTANCE_ATTENUATION:
3238			return error(GL_INVALID_ENUM);   // Needs three parameters, should call glPointParameterxv() instead
3239		default:
3240			return error(GL_INVALID_ENUM);
3241		}
3242	}
3243}
3244
3245void PointParameterxv(GLenum pname, const GLfixed *params)
3246{
3247	TRACE("(GLenum pname = 0x%X, const GLfixed *params)", pname);
3248
3249	es1::Context *context = es1::getContext();
3250
3251	if(context)
3252	{
3253		switch(pname)
3254		{
3255		case GL_POINT_SIZE_MIN:
3256			if(params[0] < 0)
3257			{
3258				return error(GL_INVALID_VALUE);
3259			}
3260			context->setPointSizeMin((float)params[0] / 0x10000);
3261			break;
3262		case GL_POINT_SIZE_MAX:
3263			if(params[0] < 0)
3264			{
3265				return error(GL_INVALID_VALUE);
3266			}
3267			context->setPointSizeMax((float)params[0] / 0x10000);
3268			break;
3269		case GL_POINT_DISTANCE_ATTENUATION:
3270			context->setPointDistanceAttenuation((float)params[0] / 0x10000, (float)params[1] / 0x10000, (float)params[2] / 0x10000);
3271			break;
3272		case GL_POINT_FADE_THRESHOLD_SIZE:
3273			if(params[0] < 0)
3274			{
3275				return error(GL_INVALID_VALUE);
3276			}
3277			context->setPointFadeThresholdSize((float)params[0] / 0x10000);
3278			break;
3279		default:
3280			return error(GL_INVALID_ENUM);
3281		}
3282	}
3283}
3284
3285void PointSize(GLfloat size)
3286{
3287	TRACE("(GLfloat size = %f)", size);
3288
3289	if(size <= 0)
3290	{
3291		return error(GL_INVALID_VALUE);
3292	}
3293
3294	es1::Context *context = es1::getContext();
3295
3296	if(context)
3297	{
3298		context->setVertexAttrib(sw::PointSize, size, size, size, size);
3299	}
3300}
3301
3302void PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer)
3303{
3304	TRACE("(GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", type, stride, pointer);
3305
3306	switch(type)
3307	{
3308	case GL_FIXED:
3309	case GL_FLOAT:
3310		break;
3311	default:
3312		return error(GL_INVALID_ENUM);
3313	}
3314
3315	VertexAttribPointer(sw::PointSize, 1, type, true, stride, pointer);
3316}
3317
3318void PointSizex(GLfixed size)
3319{
3320	PointSize((float)size / 0x10000);
3321}
3322
3323void PolygonOffset(GLfloat factor, GLfloat units)
3324{
3325	TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
3326
3327	es1::Context *context = es1::getContext();
3328
3329	if(context)
3330	{
3331		context->setPolygonOffsetParams(factor, units);
3332	}
3333}
3334
3335void PolygonOffsetx(GLfixed factor, GLfixed units)
3336{
3337	PolygonOffset((float)factor / 0x10000, (float)units / 0x10000);
3338}
3339
3340void PopMatrix(void)
3341{
3342	TRACE("()");
3343
3344	es1::Context *context = es1::getContext();
3345
3346	if(context)
3347	{
3348		context->popMatrix();
3349	}
3350}
3351
3352void PushMatrix(void)
3353{
3354	TRACE("()");
3355
3356	es1::Context *context = es1::getContext();
3357
3358	if(context)
3359	{
3360		context->pushMatrix();
3361	}
3362}
3363
3364void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
3365{
3366	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
3367	      "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
3368	      x, y, width, height, format, type,  pixels);
3369
3370	if(width < 0 || height < 0)
3371	{
3372		return error(GL_INVALID_VALUE);
3373	}
3374
3375	es1::Context *context = es1::getContext();
3376
3377	if(context)
3378	{
3379		context->readPixels(x, y, width, height, format, type, nullptr, pixels);
3380	}
3381}
3382
3383void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
3384{
3385	TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
3386	      target, internalformat, width, height);
3387
3388	switch(target)
3389	{
3390	case GL_RENDERBUFFER_OES:
3391		break;
3392	default:
3393		return error(GL_INVALID_ENUM);
3394	}
3395
3396	if(!es1::IsColorRenderable(internalformat) && !es1::IsDepthRenderable(internalformat) && !es1::IsStencilRenderable(internalformat))
3397	{
3398		return error(GL_INVALID_ENUM);
3399	}
3400
3401	if(width < 0 || height < 0)
3402	{
3403		return error(GL_INVALID_VALUE);
3404	}
3405
3406	es1::Context *context = es1::getContext();
3407
3408	if(context)
3409	{
3410		if(width > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
3411		   height > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
3412		{
3413			return error(GL_INVALID_VALUE);
3414		}
3415
3416		GLuint handle = context->getRenderbufferName();
3417		if(handle == 0)
3418		{
3419			return error(GL_INVALID_OPERATION);
3420		}
3421
3422		switch(internalformat)
3423		{
3424		case GL_RGBA4_OES:
3425		case GL_RGB5_A1_OES:
3426		case GL_RGB565_OES:
3427		case GL_RGB8_OES:
3428		case GL_RGBA8_OES:
3429			context->setRenderbufferStorage(new es1::Colorbuffer(width, height, internalformat, 0));
3430			break;
3431		case GL_DEPTH_COMPONENT16_OES:
3432			context->setRenderbufferStorage(new es1::Depthbuffer(width, height, internalformat,  0));
3433			break;
3434		case GL_STENCIL_INDEX8_OES:
3435			context->setRenderbufferStorage(new es1::Stencilbuffer(width, height, 0));
3436			break;
3437		case GL_DEPTH24_STENCIL8_OES:
3438			context->setRenderbufferStorage(new es1::DepthStencilbuffer(width, height, internalformat, 0));
3439			break;
3440		default:
3441			return error(GL_INVALID_ENUM);
3442		}
3443	}
3444}
3445
3446void Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
3447{
3448	TRACE("(GLfloat angle = %f, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", angle, x, y, z);
3449
3450	es1::Context *context = es1::getContext();
3451
3452	if(context)
3453	{
3454		context->rotate(angle, x, y, z);
3455	}
3456}
3457
3458void Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
3459{
3460	Rotatef((float)angle / 0x10000, (float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000);
3461}
3462
3463void SampleCoverage(GLclampf value, GLboolean invert)
3464{
3465	TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
3466
3467	es1::Context* context = es1::getContext();
3468
3469	if(context)
3470	{
3471		context->setSampleCoverageParams(es1::clamp01(value), invert == GL_TRUE);
3472	}
3473}
3474
3475void SampleCoveragex(GLclampx value, GLboolean invert)
3476{
3477	SampleCoverage((float)value / 0x10000, invert);
3478}
3479
3480void Scalef(GLfloat x, GLfloat y, GLfloat z)
3481{
3482	TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", x, y, z);
3483
3484	es1::Context *context = es1::getContext();
3485
3486	if(context)
3487	{
3488		context->scale(x, y, z);
3489	}
3490}
3491
3492void Scalex(GLfixed x, GLfixed y, GLfixed z)
3493{
3494	Scalef((float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000);
3495}
3496
3497void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
3498{
3499	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
3500
3501	if(width < 0 || height < 0)
3502	{
3503		return error(GL_INVALID_VALUE);
3504	}
3505
3506	es1::Context* context = es1::getContext();
3507
3508	if(context)
3509	{
3510		context->setScissorParams(x, y, width, height);
3511	}
3512}
3513
3514void ShadeModel(GLenum mode)
3515{
3516	switch(mode)
3517	{
3518	case GL_FLAT:
3519	case GL_SMOOTH:
3520		break;
3521	default:
3522		return error(GL_INVALID_ENUM);
3523	}
3524
3525	es1::Context *context = es1::getContext();
3526
3527	if(context)
3528	{
3529		context->setShadeModel(mode);
3530	}
3531}
3532
3533void StencilFunc(GLenum func, GLint ref, GLuint mask)
3534{
3535	TRACE("(GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)",  func, ref, mask);
3536
3537	switch(func)
3538	{
3539	case GL_NEVER:
3540	case GL_ALWAYS:
3541	case GL_LESS:
3542	case GL_LEQUAL:
3543	case GL_EQUAL:
3544	case GL_GEQUAL:
3545	case GL_GREATER:
3546	case GL_NOTEQUAL:
3547		break;
3548	default:
3549		return error(GL_INVALID_ENUM);
3550	}
3551
3552	es1::Context *context = es1::getContext();
3553
3554	if(context)
3555	{
3556		context->setStencilParams(func, ref, mask);
3557	}
3558}
3559
3560void StencilMask(GLuint mask)
3561{
3562	TRACE("(GLuint mask = %d)", mask);
3563
3564	es1::Context *context = es1::getContext();
3565
3566	if(context)
3567	{
3568		context->setStencilWritemask(mask);
3569	}
3570}
3571
3572void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
3573{
3574	TRACE("(GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", fail, zfail, zpass);
3575
3576	switch(fail)
3577	{
3578	case GL_ZERO:
3579	case GL_KEEP:
3580	case GL_REPLACE:
3581	case GL_INCR:
3582	case GL_DECR:
3583	case GL_INVERT:
3584	case GL_INCR_WRAP_OES:
3585	case GL_DECR_WRAP_OES:
3586		break;
3587	default:
3588		return error(GL_INVALID_ENUM);
3589	}
3590
3591	switch(zfail)
3592	{
3593	case GL_ZERO:
3594	case GL_KEEP:
3595	case GL_REPLACE:
3596	case GL_INCR:
3597	case GL_DECR:
3598	case GL_INVERT:
3599	case GL_INCR_WRAP_OES:
3600	case GL_DECR_WRAP_OES:
3601		break;
3602	default:
3603		return error(GL_INVALID_ENUM);
3604	}
3605
3606	switch(zpass)
3607	{
3608	case GL_ZERO:
3609	case GL_KEEP:
3610	case GL_REPLACE:
3611	case GL_INCR:
3612	case GL_DECR:
3613	case GL_INVERT:
3614	case GL_INCR_WRAP_OES:
3615	case GL_DECR_WRAP_OES:
3616		break;
3617	default:
3618		return error(GL_INVALID_ENUM);
3619	}
3620
3621	es1::Context *context = es1::getContext();
3622
3623	if(context)
3624	{
3625		context->setStencilOperations(fail, zfail, zpass);
3626	}
3627}
3628
3629void TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
3630{
3631	TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer);
3632
3633	if(size < 2 || size > 4)
3634	{
3635		return error(GL_INVALID_VALUE);
3636	}
3637
3638	es1::Context *context = es1::getContext();
3639
3640	if(context)
3641	{
3642		GLenum texture = context->getClientActiveTexture();
3643		VertexAttribPointer(sw::TexCoord0 + (texture - GL_TEXTURE0), size, type, false, stride, pointer);
3644	}
3645}
3646
3647void TexEnvi(GLenum target, GLenum pname, GLint param);
3648
3649void TexEnvf(GLenum target, GLenum pname, GLfloat param)
3650{
3651	TexEnvi(target, pname, (GLint)param);
3652}
3653
3654void TexEnvfv(GLenum target, GLenum pname, const GLfloat *params)
3655{
3656	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat *params)", target, pname);
3657
3658	es1::Context *context = es1::getContext();
3659
3660	if(context)
3661	{
3662		GLint iParam = (GLint)roundf(params[0]);
3663
3664		switch(target)
3665		{
3666		case GL_POINT_SPRITE_OES:
3667			UNIMPLEMENTED();
3668			break;
3669		case GL_TEXTURE_ENV:
3670			switch(pname)
3671			{
3672			case GL_TEXTURE_ENV_MODE:
3673				switch(iParam)
3674				{
3675				case GL_REPLACE:
3676				case GL_MODULATE:
3677				case GL_DECAL:
3678				case GL_BLEND:
3679				case GL_ADD:
3680				case GL_COMBINE:
3681					break;
3682				default:
3683					error(GL_INVALID_ENUM);
3684				}
3685
3686				context->setTextureEnvMode(iParam);
3687				break;
3688			case GL_TEXTURE_ENV_COLOR:
3689				context->setTextureEnvColor(clamp01(params[0]), clamp01(params[1]), clamp01(params[2]), clamp01(params[3]));
3690				break;
3691			case GL_COMBINE_RGB:
3692				switch(iParam)
3693				{
3694				case GL_REPLACE:
3695				case GL_MODULATE:
3696				case GL_ADD:
3697				case GL_ADD_SIGNED:
3698				case GL_INTERPOLATE:
3699				case GL_SUBTRACT:
3700				case GL_DOT3_RGB:
3701				case GL_DOT3_RGBA:
3702					break;
3703				default:
3704					error(GL_INVALID_ENUM);
3705				}
3706
3707				context->setCombineRGB(iParam);
3708				break;
3709			case GL_COMBINE_ALPHA:
3710				switch(iParam)
3711				{
3712				case GL_REPLACE:
3713				case GL_MODULATE:
3714				case GL_ADD:
3715				case GL_ADD_SIGNED:
3716				case GL_INTERPOLATE:
3717				case GL_SUBTRACT:
3718					break;
3719				default:
3720					error(GL_INVALID_ENUM);
3721				}
3722
3723				context->setCombineAlpha(iParam);
3724				break;
3725			case GL_RGB_SCALE:
3726				if(iParam != 1 && iParam != 2 && iParam != 4)
3727				{
3728					return error(GL_INVALID_VALUE);
3729				}
3730				if(iParam != 1) UNIMPLEMENTED();
3731				break;
3732			case GL_ALPHA_SCALE:
3733				if(iParam != 1 && iParam != 2 && iParam != 4)
3734				{
3735					return error(GL_INVALID_VALUE);
3736				}
3737				if(iParam != 1) UNIMPLEMENTED();
3738				break;
3739			case GL_OPERAND0_RGB:
3740				switch(iParam)
3741				{
3742				case GL_SRC_COLOR:
3743				case GL_ONE_MINUS_SRC_COLOR:
3744				case GL_SRC_ALPHA:
3745				case GL_ONE_MINUS_SRC_ALPHA:
3746					break;
3747				default:
3748					error(GL_INVALID_ENUM);
3749				}
3750
3751				context->setOperand0RGB(iParam);
3752				break;
3753			case GL_OPERAND1_RGB:
3754				switch(iParam)
3755				{
3756				case GL_SRC_COLOR:
3757				case GL_ONE_MINUS_SRC_COLOR:
3758				case GL_SRC_ALPHA:
3759				case GL_ONE_MINUS_SRC_ALPHA:
3760					break;
3761				default:
3762					error(GL_INVALID_ENUM);
3763				}
3764
3765				context->setOperand1RGB(iParam);
3766				break;
3767			case GL_OPERAND2_RGB:
3768				switch(iParam)
3769				{
3770				case GL_SRC_COLOR:
3771				case GL_ONE_MINUS_SRC_COLOR:
3772				case GL_SRC_ALPHA:
3773				case GL_ONE_MINUS_SRC_ALPHA:
3774					break;
3775				default:
3776					error(GL_INVALID_ENUM);
3777				}
3778
3779				context->setOperand2RGB(iParam);
3780				break;
3781			case GL_OPERAND0_ALPHA:
3782				switch(iParam)
3783				{
3784				case GL_SRC_ALPHA:
3785				case GL_ONE_MINUS_SRC_ALPHA:
3786					break;
3787				default:
3788					error(GL_INVALID_ENUM);
3789				}
3790
3791				context->setOperand0Alpha(iParam);
3792				break;
3793			case GL_OPERAND1_ALPHA:
3794				switch(iParam)
3795				{
3796				case GL_SRC_ALPHA:
3797				case GL_ONE_MINUS_SRC_ALPHA:
3798					break;
3799				default:
3800					error(GL_INVALID_ENUM);
3801				}
3802
3803				context->setOperand1Alpha(iParam);
3804				break;
3805			case GL_OPERAND2_ALPHA:
3806				switch(iParam)
3807				{
3808				case GL_SRC_ALPHA:
3809				case GL_ONE_MINUS_SRC_ALPHA:
3810					break;
3811				default:
3812					error(GL_INVALID_ENUM);
3813				}
3814
3815				context->setOperand2Alpha(iParam);
3816				break;
3817			case GL_SRC0_RGB:
3818				switch(iParam)
3819				{
3820				case GL_TEXTURE:
3821				case GL_CONSTANT:
3822				case GL_PRIMARY_COLOR:
3823				case GL_PREVIOUS:
3824					break;
3825				default:
3826					error(GL_INVALID_ENUM);
3827				}
3828
3829				context->setSrc0RGB(iParam);
3830				break;
3831			case GL_SRC1_RGB:
3832				switch(iParam)
3833				{
3834				case GL_TEXTURE:
3835				case GL_CONSTANT:
3836				case GL_PRIMARY_COLOR:
3837				case GL_PREVIOUS:
3838					break;
3839				default:
3840					error(GL_INVALID_ENUM);
3841				}
3842
3843				context->setSrc1RGB(iParam);
3844				break;
3845			case GL_SRC2_RGB:
3846				switch(iParam)
3847				{
3848				case GL_TEXTURE:
3849				case GL_CONSTANT:
3850				case GL_PRIMARY_COLOR:
3851				case GL_PREVIOUS:
3852					break;
3853				default:
3854					error(GL_INVALID_ENUM);
3855				}
3856
3857				context->setSrc2RGB(iParam);
3858				break;
3859			case GL_SRC0_ALPHA:
3860				switch(iParam)
3861				{
3862				case GL_TEXTURE:
3863				case GL_CONSTANT:
3864				case GL_PRIMARY_COLOR:
3865				case GL_PREVIOUS:
3866					break;
3867				default:
3868					error(GL_INVALID_ENUM);
3869				}
3870
3871				context->setSrc0Alpha(iParam);
3872				break;
3873			case GL_SRC1_ALPHA:
3874				switch(iParam)
3875				{
3876				case GL_TEXTURE:
3877				case GL_CONSTANT:
3878				case GL_PRIMARY_COLOR:
3879				case GL_PREVIOUS:
3880					break;
3881				default:
3882					error(GL_INVALID_ENUM);
3883				}
3884
3885				context->setSrc1Alpha(iParam);
3886				break;
3887			case GL_SRC2_ALPHA:
3888				switch(iParam)
3889				{
3890				case GL_TEXTURE:
3891				case GL_CONSTANT:
3892				case GL_PRIMARY_COLOR:
3893				case GL_PREVIOUS:
3894					break;
3895				default:
3896					error(GL_INVALID_ENUM);
3897				}
3898
3899				context->setSrc2Alpha(iParam);
3900				break;
3901			default:
3902				return error(GL_INVALID_ENUM);
3903			}
3904			break;
3905		default:
3906			return error(GL_INVALID_ENUM);
3907		}
3908	}
3909}
3910
3911void TexEnvi(GLenum target, GLenum pname, GLint param)
3912{
3913	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
3914
3915	es1::Context *context = es1::getContext();
3916
3917	if(context)
3918	{
3919		switch(target)
3920		{
3921		case GL_POINT_SPRITE_OES:
3922			UNIMPLEMENTED();
3923			break;
3924		case GL_TEXTURE_ENV:
3925			switch(pname)
3926			{
3927			case GL_TEXTURE_ENV_MODE:
3928				switch((GLenum)param)
3929				{
3930				case GL_REPLACE:
3931				case GL_MODULATE:
3932				case GL_DECAL:
3933				case GL_BLEND:
3934				case GL_ADD:
3935				case GL_COMBINE:
3936					break;
3937				default:
3938					error(GL_INVALID_ENUM);
3939				}
3940
3941				context->setTextureEnvMode((GLenum)param);
3942				break;
3943			case GL_TEXTURE_ENV_COLOR:
3944				return error(GL_INVALID_ENUM);   // Needs four values, should call glTexEnviv() instead
3945				break;
3946			case GL_COMBINE_RGB:
3947				switch((GLenum)param)
3948				{
3949				case GL_REPLACE:
3950				case GL_MODULATE:
3951				case GL_ADD:
3952				case GL_ADD_SIGNED:
3953				case GL_INTERPOLATE:
3954				case GL_SUBTRACT:
3955				case GL_DOT3_RGB:
3956				case GL_DOT3_RGBA:
3957					break;
3958				default:
3959					error(GL_INVALID_ENUM);
3960				}
3961
3962				context->setCombineRGB((GLenum)param);
3963				break;
3964			case GL_COMBINE_ALPHA:
3965				switch((GLenum)param)
3966				{
3967				case GL_REPLACE:
3968				case GL_MODULATE:
3969				case GL_ADD:
3970				case GL_ADD_SIGNED:
3971				case GL_INTERPOLATE:
3972				case GL_SUBTRACT:
3973					break;
3974				default:
3975					error(GL_INVALID_ENUM);
3976				}
3977
3978				context->setCombineAlpha((GLenum)param);
3979				break;
3980			case GL_RGB_SCALE:
3981				if(param != 1 && param != 2 && param != 4)
3982				{
3983					return error(GL_INVALID_VALUE);
3984				}
3985				if(param != 1) UNIMPLEMENTED();
3986				break;
3987			case GL_ALPHA_SCALE:
3988				if(param != 1 && param != 2 && param != 4)
3989				{
3990					return error(GL_INVALID_VALUE);
3991				}
3992				if(param != 1) UNIMPLEMENTED();
3993				break;
3994			case GL_OPERAND0_RGB:
3995				switch((GLenum)param)
3996				{
3997				case GL_SRC_COLOR:
3998				case GL_ONE_MINUS_SRC_COLOR:
3999				case GL_SRC_ALPHA:
4000				case GL_ONE_MINUS_SRC_ALPHA:
4001					break;
4002				default:
4003					error(GL_INVALID_ENUM);
4004				}
4005
4006				context->setOperand0RGB((GLenum)param);
4007				break;
4008			case GL_OPERAND1_RGB:
4009				switch((GLenum)param)
4010				{
4011				case GL_SRC_COLOR:
4012				case GL_ONE_MINUS_SRC_COLOR:
4013				case GL_SRC_ALPHA:
4014				case GL_ONE_MINUS_SRC_ALPHA:
4015					break;
4016				default:
4017					error(GL_INVALID_ENUM);
4018				}
4019
4020				context->setOperand1RGB((GLenum)param);
4021				break;
4022			case GL_OPERAND2_RGB:
4023				switch((GLenum)param)
4024				{
4025				case GL_SRC_COLOR:
4026				case GL_ONE_MINUS_SRC_COLOR:
4027				case GL_SRC_ALPHA:
4028				case GL_ONE_MINUS_SRC_ALPHA:
4029					break;
4030				default:
4031					error(GL_INVALID_ENUM);
4032				}
4033
4034				context->setOperand2RGB((GLenum)param);
4035				break;
4036			case GL_OPERAND0_ALPHA:
4037				switch((GLenum)param)
4038				{
4039				case GL_SRC_ALPHA:
4040				case GL_ONE_MINUS_SRC_ALPHA:
4041					break;
4042				default:
4043					error(GL_INVALID_ENUM);
4044				}
4045
4046				context->setOperand0Alpha((GLenum)param);
4047				break;
4048			case GL_OPERAND1_ALPHA:
4049				switch((GLenum)param)
4050				{
4051				case GL_SRC_ALPHA:
4052				case GL_ONE_MINUS_SRC_ALPHA:
4053					break;
4054				default:
4055					error(GL_INVALID_ENUM);
4056				}
4057
4058				context->setOperand1Alpha((GLenum)param);
4059				break;
4060			case GL_OPERAND2_ALPHA:
4061				switch((GLenum)param)
4062				{
4063				case GL_SRC_ALPHA:
4064				case GL_ONE_MINUS_SRC_ALPHA:
4065					break;
4066				default:
4067					error(GL_INVALID_ENUM);
4068				}
4069
4070				context->setOperand2Alpha((GLenum)param);
4071				break;
4072			case GL_SRC0_RGB:
4073				switch((GLenum)param)
4074				{
4075				case GL_TEXTURE:
4076				case GL_CONSTANT:
4077				case GL_PRIMARY_COLOR:
4078				case GL_PREVIOUS:
4079					break;
4080				default:
4081					error(GL_INVALID_ENUM);
4082				}
4083
4084				context->setSrc0RGB((GLenum)param);
4085				break;
4086			case GL_SRC1_RGB:
4087				switch((GLenum)param)
4088				{
4089				case GL_TEXTURE:
4090				case GL_CONSTANT:
4091				case GL_PRIMARY_COLOR:
4092				case GL_PREVIOUS:
4093					break;
4094				default:
4095					error(GL_INVALID_ENUM);
4096				}
4097
4098				context->setSrc1RGB((GLenum)param);
4099				break;
4100			case GL_SRC2_RGB:
4101				switch((GLenum)param)
4102				{
4103				case GL_TEXTURE:
4104				case GL_CONSTANT:
4105				case GL_PRIMARY_COLOR:
4106				case GL_PREVIOUS:
4107					break;
4108				default:
4109					error(GL_INVALID_ENUM);
4110				}
4111
4112				context->setSrc2RGB((GLenum)param);
4113				break;
4114			case GL_SRC0_ALPHA:
4115				switch((GLenum)param)
4116				{
4117				case GL_TEXTURE:
4118				case GL_CONSTANT:
4119				case GL_PRIMARY_COLOR:
4120				case GL_PREVIOUS:
4121					break;
4122				default:
4123					error(GL_INVALID_ENUM);
4124				}
4125
4126				context->setSrc0Alpha((GLenum)param);
4127				break;
4128			case GL_SRC1_ALPHA:
4129				switch((GLenum)param)
4130				{
4131				case GL_TEXTURE:
4132				case GL_CONSTANT:
4133				case GL_PRIMARY_COLOR:
4134				case GL_PREVIOUS:
4135					break;
4136				default:
4137					error(GL_INVALID_ENUM);
4138				}
4139
4140				context->setSrc1Alpha((GLenum)param);
4141				break;
4142			case GL_SRC2_ALPHA:
4143				switch((GLenum)param)
4144				{
4145				case GL_TEXTURE:
4146				case GL_CONSTANT:
4147				case GL_PRIMARY_COLOR:
4148				case GL_PREVIOUS:
4149					break;
4150				default:
4151					error(GL_INVALID_ENUM);
4152				}
4153
4154				context->setSrc2Alpha((GLenum)param);
4155				break;
4156			default:
4157				return error(GL_INVALID_ENUM);
4158			}
4159			break;
4160		default:
4161			return error(GL_INVALID_ENUM);
4162		}
4163	}
4164}
4165
4166void TexEnvx(GLenum target, GLenum pname, GLfixed param)
4167{
4168	TexEnvi(target, pname, (GLint)param);
4169}
4170
4171void TexEnviv(GLenum target, GLenum pname, const GLint *params)
4172{
4173	UNIMPLEMENTED();
4174}
4175
4176void TexEnvxv(GLenum target, GLenum pname, const GLfixed *params)
4177{
4178	UNIMPLEMENTED();
4179}
4180
4181void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
4182                GLint border, GLenum format, GLenum type, const GLvoid* pixels)
4183{
4184	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
4185	      "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels =  %p)",
4186	      target, level, internalformat, width, height, border, format, type, pixels);
4187
4188	if(!validImageSize(level, width, height))
4189	{
4190		return error(GL_INVALID_VALUE);
4191	}
4192
4193	if(internalformat != (GLint)format)
4194	{
4195		return error(GL_INVALID_OPERATION);
4196	}
4197
4198	switch(format)
4199	{
4200	case GL_ALPHA:
4201	case GL_LUMINANCE:
4202	case GL_LUMINANCE_ALPHA:
4203		switch(type)
4204		{
4205		case GL_UNSIGNED_BYTE:
4206			break;
4207		default:
4208			return error(GL_INVALID_ENUM);
4209		}
4210		break;
4211	case GL_RGB:
4212		switch(type)
4213		{
4214		case GL_UNSIGNED_BYTE:
4215		case GL_UNSIGNED_SHORT_5_6_5:
4216			break;
4217		default:
4218			return error(GL_INVALID_ENUM);
4219		}
4220		break;
4221	case GL_RGBA:
4222		switch(type)
4223		{
4224		case GL_UNSIGNED_BYTE:
4225		case GL_UNSIGNED_SHORT_4_4_4_4:
4226		case GL_UNSIGNED_SHORT_5_5_5_1:
4227			break;
4228		default:
4229			return error(GL_INVALID_ENUM);
4230		}
4231		break;
4232	case GL_BGRA_EXT:
4233		switch(type)
4234		{
4235		case GL_UNSIGNED_BYTE:
4236			break;
4237		default:
4238			return error(GL_INVALID_ENUM);
4239		}
4240		break;
4241	case GL_ETC1_RGB8_OES:
4242	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
4243	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
4244		return error(GL_INVALID_OPERATION);
4245	case GL_DEPTH_STENCIL_OES:
4246		switch(type)
4247		{
4248		case GL_UNSIGNED_INT_24_8_OES:
4249			break;
4250		default:
4251			return error(GL_INVALID_ENUM);
4252		}
4253		break;
4254	default:
4255		return error(GL_INVALID_VALUE);
4256	}
4257
4258	if(border != 0)
4259	{
4260		return error(GL_INVALID_VALUE);
4261	}
4262
4263	GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4264
4265	es1::Context *context = es1::getContext();
4266
4267	if(context)
4268	{
4269		switch(target)
4270		{
4271		case GL_TEXTURE_2D:
4272			if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4273			   height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4274			{
4275				return error(GL_INVALID_VALUE);
4276			}
4277			break;
4278		default:
4279			return error(GL_INVALID_ENUM);
4280		}
4281
4282		if(target == GL_TEXTURE_2D)
4283		{
4284			es1::Texture2D *texture = context->getTexture2D();
4285
4286			if(!texture)
4287			{
4288				return error(GL_INVALID_OPERATION);
4289			}
4290
4291			texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackAlignment(), pixels);
4292		}
4293		else UNREACHABLE(target);
4294	}
4295}
4296
4297void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4298{
4299	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4300
4301	es1::Context *context = es1::getContext();
4302
4303	if(context)
4304	{
4305		es1::Texture *texture;
4306
4307		switch(target)
4308		{
4309		case GL_TEXTURE_2D:
4310			texture = context->getTexture2D();
4311			break;
4312		case GL_TEXTURE_EXTERNAL_OES:
4313			texture = context->getTextureExternal();
4314			break;
4315		default:
4316			return error(GL_INVALID_ENUM);
4317		}
4318
4319		switch(pname)
4320		{
4321		case GL_TEXTURE_WRAP_S:
4322			if(!texture->setWrapS((GLenum)param))
4323			{
4324				return error(GL_INVALID_ENUM);
4325			}
4326			break;
4327		case GL_TEXTURE_WRAP_T:
4328			if(!texture->setWrapT((GLenum)param))
4329			{
4330				return error(GL_INVALID_ENUM);
4331			}
4332			break;
4333		case GL_TEXTURE_MIN_FILTER:
4334			if(!texture->setMinFilter((GLenum)param))
4335			{
4336				return error(GL_INVALID_ENUM);
4337			}
4338			break;
4339		case GL_TEXTURE_MAG_FILTER:
4340			if(!texture->setMagFilter((GLenum)param))
4341			{
4342				return error(GL_INVALID_ENUM);
4343			}
4344			break;
4345		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4346			if(!texture->setMaxAnisotropy(param))
4347			{
4348				return error(GL_INVALID_VALUE);
4349			}
4350			break;
4351		case GL_GENERATE_MIPMAP:
4352			texture->setGenerateMipmap((GLboolean)param);
4353			break;
4354		case GL_TEXTURE_CROP_RECT_OES:
4355			return error(GL_INVALID_ENUM);   // Needs four values, should call glTexParameterfv() instead
4356		default:
4357			return error(GL_INVALID_ENUM);
4358		}
4359	}
4360}
4361
4362void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4363{
4364	TexParameterf(target, pname, *params);
4365}
4366
4367void TexParameteri(GLenum target, GLenum pname, GLint param)
4368{
4369	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4370
4371	es1::Context *context = es1::getContext();
4372
4373	if(context)
4374	{
4375		es1::Texture *texture;
4376
4377		switch(target)
4378		{
4379		case GL_TEXTURE_2D:
4380			texture = context->getTexture2D();
4381			break;
4382		case GL_TEXTURE_EXTERNAL_OES:
4383			texture = context->getTextureExternal();
4384			break;
4385		default:
4386			return error(GL_INVALID_ENUM);
4387		}
4388
4389		switch(pname)
4390		{
4391		case GL_TEXTURE_WRAP_S:
4392			if(!texture->setWrapS((GLenum)param))
4393			{
4394				return error(GL_INVALID_ENUM);
4395			}
4396			break;
4397		case GL_TEXTURE_WRAP_T:
4398			if(!texture->setWrapT((GLenum)param))
4399			{
4400				return error(GL_INVALID_ENUM);
4401			}
4402			break;
4403		case GL_TEXTURE_MIN_FILTER:
4404			if(!texture->setMinFilter((GLenum)param))
4405			{
4406				return error(GL_INVALID_ENUM);
4407			}
4408			break;
4409		case GL_TEXTURE_MAG_FILTER:
4410			if(!texture->setMagFilter((GLenum)param))
4411			{
4412				return error(GL_INVALID_ENUM);
4413			}
4414			break;
4415		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4416			if(!texture->setMaxAnisotropy((GLfloat)param))
4417			{
4418				return error(GL_INVALID_VALUE);
4419			}
4420			break;
4421		case GL_GENERATE_MIPMAP:
4422			texture->setGenerateMipmap((GLboolean)param);
4423			break;
4424		case GL_TEXTURE_CROP_RECT_OES:
4425			return error(GL_INVALID_ENUM);   // Needs four values, should call glTexParameteriv() instead
4426		default:
4427			return error(GL_INVALID_ENUM);
4428		}
4429	}
4430}
4431
4432void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4433{
4434	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %p)", target, pname, params);
4435
4436	switch(pname)
4437	{
4438	case GL_TEXTURE_CROP_RECT_OES:
4439		break;
4440	default:
4441		return TexParameteri(target, pname, params[0]);
4442	}
4443
4444	es1::Context *context = es1::getContext();
4445
4446	if(context)
4447	{
4448		es1::Texture *texture;
4449
4450		switch(target)
4451		{
4452		case GL_TEXTURE_2D:
4453			texture = context->getTexture2D();
4454			break;
4455		default:
4456			return error(GL_INVALID_ENUM);
4457		}
4458
4459		switch(pname)
4460		{
4461		case GL_TEXTURE_CROP_RECT_OES:
4462			texture->setCropRect(params[0], params[1], params[2], params[3]);
4463			break;
4464		default:
4465			return error(GL_INVALID_ENUM);
4466		}
4467	}
4468}
4469
4470void TexParameterx(GLenum target, GLenum pname, GLfixed param)
4471{
4472	TexParameteri(target, pname, (GLint)param);
4473}
4474
4475void TexParameterxv(GLenum target, GLenum pname, const GLfixed *params)
4476{
4477	UNIMPLEMENTED();
4478}
4479
4480void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
4481                   GLenum format, GLenum type, const GLvoid* pixels)
4482{
4483	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4484	      "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
4485	      "const GLvoid* pixels = %p)",
4486	      target, level, xoffset, yoffset, width, height, format, type, pixels);
4487
4488	if(!es1::IsTextureTarget(target))
4489	{
4490		return error(GL_INVALID_ENUM);
4491	}
4492
4493	if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4494	{
4495		return error(GL_INVALID_VALUE);
4496	}
4497
4498	if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4499	{
4500		return error(GL_INVALID_VALUE);
4501	}
4502
4503	if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4504	{
4505		return error(GL_INVALID_VALUE);
4506	}
4507
4508	if(width == 0 || height == 0 || !pixels)
4509	{
4510		return;
4511	}
4512
4513	es1::Context *context = es1::getContext();
4514
4515	if(context)
4516	{
4517		if(target == GL_TEXTURE_2D)
4518		{
4519			es1::Texture2D *texture = context->getTexture2D();
4520
4521			GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
4522			if(validationError != GL_NO_ERROR)
4523			{
4524				return error(validationError);
4525			}
4526
4527			texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
4528		}
4529		else UNREACHABLE(target);
4530	}
4531}
4532
4533void Translatef(GLfloat x, GLfloat y, GLfloat z)
4534{
4535	TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", x, y, z);
4536
4537	es1::Context *context = es1::getContext();
4538
4539	if(context)
4540	{
4541		context->translate(x, y, z);
4542	}
4543}
4544
4545void Translatex(GLfixed x, GLfixed y, GLfixed z)
4546{
4547	Translatef((float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000);
4548}
4549
4550void VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
4551{
4552	TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer);
4553
4554	if(size < 2 || size > 4)
4555	{
4556		return error(GL_INVALID_VALUE);
4557	}
4558
4559	VertexAttribPointer(sw::Position, size, type, false, stride, pointer);
4560}
4561
4562void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
4563{
4564	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4565
4566	if(width < 0 || height < 0)
4567	{
4568		return error(GL_INVALID_VALUE);
4569	}
4570
4571	es1::Context *context = es1::getContext();
4572
4573	if(context)
4574	{
4575		context->setViewportParams(x, y, width, height);
4576	}
4577}
4578
4579void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
4580{
4581	TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
4582
4583	switch(target)
4584	{
4585	case GL_TEXTURE_2D:
4586	case GL_TEXTURE_EXTERNAL_OES:
4587		break;
4588	default:
4589		return error(GL_INVALID_ENUM);
4590	}
4591
4592	es1::Context *context = es1::getContext();
4593
4594	if(context)
4595	{
4596		es1::Texture2D *texture = nullptr;
4597
4598		switch(target)
4599		{
4600		case GL_TEXTURE_2D:           texture = context->getTexture2D();       break;
4601		case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4602		default:                      UNREACHABLE(target);
4603		}
4604
4605		if(!texture)
4606		{
4607			return error(GL_INVALID_OPERATION);
4608		}
4609
4610		egl::Image *eglImage = context->getSharedImage(image);
4611
4612		if(!eglImage)
4613		{
4614			return error(GL_INVALID_OPERATION);
4615		}
4616
4617		texture->setSharedImage(eglImage);
4618	}
4619}
4620
4621void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
4622{
4623	TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
4624
4625	UNIMPLEMENTED();
4626}
4627
4628void DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
4629{
4630	UNIMPLEMENTED();
4631}
4632
4633void DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
4634{
4635	TRACE("(GLint x = %d, GLint y = %d, GLint z = %d, GLint width = %d, GLint height = %d)", x, y, z, width, height);
4636
4637	if(width <= 0 || height <= 0)
4638	{
4639		return error(GL_INVALID_VALUE);
4640	}
4641
4642	es1::Context *context = es1::getContext();
4643
4644	if(context)
4645	{
4646		context->drawTexture((GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)width, (GLfloat)height);
4647	}
4648}
4649
4650void DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
4651{
4652	UNIMPLEMENTED();
4653}
4654
4655void DrawTexsvOES(const GLshort *coords)
4656{
4657	UNIMPLEMENTED();
4658}
4659
4660void DrawTexivOES(const GLint *coords)
4661{
4662	UNIMPLEMENTED();
4663}
4664
4665void DrawTexxvOES(const GLfixed *coords)
4666{
4667	UNIMPLEMENTED();
4668}
4669
4670void DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
4671{
4672	TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat width = %f, GLfloat height = %f)", x, y, z, width, height);
4673
4674	if(width <= 0 || height <= 0)
4675	{
4676		return error(GL_INVALID_VALUE);
4677	}
4678
4679	es1::Context *context = es1::getContext();
4680
4681	if(context)
4682	{
4683		context->drawTexture(x, y, z, width, height);
4684	}
4685}
4686
4687void DrawTexfvOES(const GLfloat *coords)
4688{
4689	UNIMPLEMENTED();
4690}
4691
4692}
4693
4694extern "C" __eglMustCastToProperFunctionPointerType es1GetProcAddress(const char *procname)
4695{
4696	struct Function
4697	{
4698		const char *name;
4699		__eglMustCastToProperFunctionPointerType address;
4700	};
4701
4702	struct CompareFunctor
4703	{
4704		bool operator()(const Function &a, const Function &b) const
4705		{
4706			return strcmp(a.name, b.name) < 0;
4707		}
4708	};
4709
4710	// This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
4711	// The Unix command "LC_COLLATE=C sort" will generate the correct order.
4712	static const Function glFunctions[] =
4713	{
4714		#define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
4715
4716		FUNCTION(glActiveTexture),
4717		FUNCTION(glAlphaFunc),
4718		FUNCTION(glAlphaFuncx),
4719		FUNCTION(glBindBuffer),
4720		FUNCTION(glBindFramebufferOES),
4721		FUNCTION(glBindRenderbufferOES),
4722		FUNCTION(glBindTexture),
4723		FUNCTION(glBlendEquationOES),
4724		FUNCTION(glBlendEquationSeparateOES),
4725		FUNCTION(glBlendFunc),
4726		FUNCTION(glBlendFuncSeparateOES),
4727		FUNCTION(glBufferData),
4728		FUNCTION(glBufferSubData),
4729		FUNCTION(glCheckFramebufferStatusOES),
4730		FUNCTION(glClear),
4731		FUNCTION(glClearColor),
4732		FUNCTION(glClearColorx),
4733		FUNCTION(glClearDepthf),
4734		FUNCTION(glClearDepthx),
4735		FUNCTION(glClearStencil),
4736		FUNCTION(glClientActiveTexture),
4737		FUNCTION(glClipPlanef),
4738		FUNCTION(glClipPlanex),
4739		FUNCTION(glColor4f),
4740		FUNCTION(glColor4ub),
4741		FUNCTION(glColor4x),
4742		FUNCTION(glColorMask),
4743		FUNCTION(glColorPointer),
4744		FUNCTION(glCompressedTexImage2D),
4745		FUNCTION(glCompressedTexSubImage2D),
4746		FUNCTION(glCopyTexImage2D),
4747		FUNCTION(glCopyTexSubImage2D),
4748		FUNCTION(glCullFace),
4749		FUNCTION(glDeleteBuffers),
4750		FUNCTION(glDeleteFramebuffersOES),
4751		FUNCTION(glDeleteRenderbuffersOES),
4752		FUNCTION(glDeleteTextures),
4753		FUNCTION(glDepthFunc),
4754		FUNCTION(glDepthMask),
4755		FUNCTION(glDepthRangef),
4756		FUNCTION(glDepthRangex),
4757		FUNCTION(glDisable),
4758		FUNCTION(glDisableClientState),
4759		FUNCTION(glDrawArrays),
4760		FUNCTION(glDrawElements),
4761		FUNCTION(glDrawTexfOES),
4762		FUNCTION(glDrawTexfvOES),
4763		FUNCTION(glDrawTexiOES),
4764		FUNCTION(glDrawTexivOES),
4765		FUNCTION(glDrawTexsOES),
4766		FUNCTION(glDrawTexsvOES),
4767		FUNCTION(glDrawTexxOES),
4768		FUNCTION(glDrawTexxvOES),
4769		FUNCTION(glEGLImageTargetRenderbufferStorageOES),
4770		FUNCTION(glEGLImageTargetTexture2DOES),
4771		FUNCTION(glEnable),
4772		FUNCTION(glEnableClientState),
4773		FUNCTION(glFinish),
4774		FUNCTION(glFlush),
4775		FUNCTION(glFogf),
4776		FUNCTION(glFogfv),
4777		FUNCTION(glFogx),
4778		FUNCTION(glFogxv),
4779		FUNCTION(glFramebufferRenderbufferOES),
4780		FUNCTION(glFramebufferTexture2DOES),
4781		FUNCTION(glFrontFace),
4782		FUNCTION(glFrustumf),
4783		FUNCTION(glFrustumx),
4784		FUNCTION(glGenBuffers),
4785		FUNCTION(glGenFramebuffersOES),
4786		FUNCTION(glGenRenderbuffersOES),
4787		FUNCTION(glGenTextures),
4788		FUNCTION(glGenerateMipmapOES),
4789		FUNCTION(glGetBooleanv),
4790		FUNCTION(glGetBufferParameteriv),
4791		FUNCTION(glGetClipPlanef),
4792		FUNCTION(glGetClipPlanex),
4793		FUNCTION(glGetError),
4794		FUNCTION(glGetFixedv),
4795		FUNCTION(glGetFloatv),
4796		FUNCTION(glGetFramebufferAttachmentParameterivOES),
4797		FUNCTION(glGetIntegerv),
4798		FUNCTION(glGetLightfv),
4799		FUNCTION(glGetLightxv),
4800		FUNCTION(glGetMaterialfv),
4801		FUNCTION(glGetMaterialxv),
4802		FUNCTION(glGetPointerv),
4803		FUNCTION(glGetRenderbufferParameterivOES),
4804		FUNCTION(glGetString),
4805		FUNCTION(glGetTexEnvfv),
4806		FUNCTION(glGetTexEnviv),
4807		FUNCTION(glGetTexEnvxv),
4808		FUNCTION(glGetTexParameterfv),
4809		FUNCTION(glGetTexParameteriv),
4810		FUNCTION(glGetTexParameterxv),
4811		FUNCTION(glHint),
4812		FUNCTION(glIsBuffer),
4813		FUNCTION(glIsEnabled),
4814		FUNCTION(glIsFramebufferOES),
4815		FUNCTION(glIsRenderbufferOES),
4816		FUNCTION(glIsTexture),
4817		FUNCTION(glLightModelf),
4818		FUNCTION(glLightModelfv),
4819		FUNCTION(glLightModelx),
4820		FUNCTION(glLightModelxv),
4821		FUNCTION(glLightf),
4822		FUNCTION(glLightfv),
4823		FUNCTION(glLightx),
4824		FUNCTION(glLightxv),
4825		FUNCTION(glLineWidth),
4826		FUNCTION(glLineWidthx),
4827		FUNCTION(glLoadIdentity),
4828		FUNCTION(glLoadMatrixf),
4829		FUNCTION(glLoadMatrixx),
4830		FUNCTION(glLogicOp),
4831		FUNCTION(glMaterialf),
4832		FUNCTION(glMaterialfv),
4833		FUNCTION(glMaterialx),
4834		FUNCTION(glMaterialxv),
4835		FUNCTION(glMatrixMode),
4836		FUNCTION(glMultMatrixf),
4837		FUNCTION(glMultMatrixx),
4838		FUNCTION(glMultiTexCoord4f),
4839		FUNCTION(glMultiTexCoord4x),
4840		FUNCTION(glNormal3f),
4841		FUNCTION(glNormal3x),
4842		FUNCTION(glNormalPointer),
4843		FUNCTION(glOrthof),
4844		FUNCTION(glOrthox),
4845		FUNCTION(glPixelStorei),
4846		FUNCTION(glPointParameterf),
4847		FUNCTION(glPointParameterfv),
4848		FUNCTION(glPointParameterx),
4849		FUNCTION(glPointParameterxv),
4850		FUNCTION(glPointSize),
4851		FUNCTION(glPointSizePointerOES),
4852		FUNCTION(glPointSizex),
4853		FUNCTION(glPolygonOffset),
4854		FUNCTION(glPolygonOffsetx),
4855		FUNCTION(glPopMatrix),
4856		FUNCTION(glPushMatrix),
4857		FUNCTION(glReadPixels),
4858		FUNCTION(glRenderbufferStorageOES),
4859		FUNCTION(glRotatef),
4860		FUNCTION(glRotatex),
4861		FUNCTION(glSampleCoverage),
4862		FUNCTION(glSampleCoveragex),
4863		FUNCTION(glScalef),
4864		FUNCTION(glScalex),
4865		FUNCTION(glScissor),
4866		FUNCTION(glShadeModel),
4867		FUNCTION(glStencilFunc),
4868		FUNCTION(glStencilMask),
4869		FUNCTION(glStencilOp),
4870		FUNCTION(glTexCoordPointer),
4871		FUNCTION(glTexEnvf),
4872		FUNCTION(glTexEnvfv),
4873		FUNCTION(glTexEnvi),
4874		FUNCTION(glTexEnviv),
4875		FUNCTION(glTexEnvx),
4876		FUNCTION(glTexEnvxv),
4877		FUNCTION(glTexImage2D),
4878		FUNCTION(glTexParameterf),
4879		FUNCTION(glTexParameterfv),
4880		FUNCTION(glTexParameteri),
4881		FUNCTION(glTexParameteriv),
4882		FUNCTION(glTexParameterx),
4883		FUNCTION(glTexParameterxv),
4884		FUNCTION(glTexSubImage2D),
4885		FUNCTION(glTranslatef),
4886		FUNCTION(glTranslatex),
4887		FUNCTION(glVertexPointer),
4888		FUNCTION(glViewport),
4889
4890		#undef FUNCTION
4891	};
4892
4893	static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
4894	static const Function *const glFunctionsEnd = glFunctions + numFunctions;
4895
4896	Function needle;
4897	needle.name = procname;
4898
4899	if(procname && strncmp("gl", procname, 2) == 0)
4900	{
4901		const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
4902		if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
4903		{
4904			return (__eglMustCastToProperFunctionPointerType)result->address;
4905		}
4906	}
4907
4908	return nullptr;
4909}
4910