OSDN Git Service

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