tizen 2.4 release
[sdk/emulator-yagl.git] / GLESv2 / yagl_gles2_calls.c
1 /*
2  * YaGL
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact :
7  * Stanislav Vorobiov <s.vorobiov@samsung.com>
8  * Jinhyung Jo <jinhyung.jo@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27  * THE SOFTWARE.
28  *
29  * Contributors:
30  * - S-Core Co., Ltd
31  *
32  */
33
34 #include "GLES2/gl2.h"
35 #include "GLES2/gl2ext.h"
36 #include "yagl_host_gles_calls.h"
37 #include "yagl_gles2_program.h"
38 #include "yagl_gles2_shader.h"
39 #include "yagl_gles2_validate.h"
40 #include "yagl_gles2_context.h"
41 #include "yagl_gles_validate.h"
42 #include "yagl_gles_vertex_array.h"
43 #include "yagl_gles_array.h"
44 #include "yagl_gles_buffer.h"
45 #include "yagl_gles_texture_unit.h"
46 #include "yagl_gles_texture.h"
47 #include "yagl_impl.h"
48 #include "yagl_malloc.h"
49 #include "yagl_sharegroup.h"
50 #include "yagl_transport.h"
51 #include "yagl_utils.h"
52 #include "yagl_pixel_format.h"
53 #include "yagl_glsl_state.h"
54 #include <errno.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <assert.h>
59
60 /*
61  * We can't include GL/gl.h here
62  */
63 #define GL_INT_2_10_10_10_REV 0x8D9F
64 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
65
66 #define YAGL_SET_ERR(err) \
67     yagl_gles_context_set_error(&ctx->base, err); \
68     YAGL_LOG_ERROR("error = 0x%X", err)
69
70 #define YAGL_GET_CTX_IMPL(ret_expr) \
71     struct yagl_gles2_context *ctx = \
72         (struct yagl_gles2_context*)yagl_get_client_context(); \
73     if (!ctx || ((ctx->base.base.client_api & (yagl_client_api_gles2|yagl_client_api_gles3)) == 0)) { \
74         YAGL_LOG_WARN("no current context"); \
75         YAGL_LOG_FUNC_EXIT(NULL); \
76         ret_expr; \
77     }
78
79 #define YAGL_GET_CTX_RET(ret) YAGL_GET_CTX_IMPL(return ret)
80
81 #define YAGL_GET_CTX() YAGL_GET_CTX_IMPL(return)
82
83 YAGL_API void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
84 {
85     int tmp = 0;
86
87     YAGL_LOG_FUNC_ENTER_SPLIT4(glStencilFuncSeparate, GLenum, GLenum, GLint, GLuint, face, func, ref, mask);
88
89     YAGL_GET_CTX();
90
91     if (!yagl_gles_is_stencil_func_valid(func)) {
92         YAGL_SET_ERR(GL_INVALID_ENUM);
93         goto out;
94     }
95
96     if ((face == GL_FRONT) || (face == GL_FRONT_AND_BACK)) {
97         ctx->base.stencil_front.func = func;
98         ctx->base.stencil_front.ref = ref;
99         ctx->base.stencil_front.mask = mask;
100
101         tmp = 1;
102     }
103
104     if ((face == GL_BACK) || (face == GL_FRONT_AND_BACK)) {
105         ctx->base.stencil_back.func = func;
106         ctx->base.stencil_back.ref = ref;
107         ctx->base.stencil_back.mask = mask;
108
109         tmp = 1;
110     }
111
112     if (tmp) {
113         yagl_host_glStencilFuncSeparate(face, func, ref, mask);
114     } else {
115         YAGL_SET_ERR(GL_INVALID_ENUM);
116     }
117
118 out:
119     YAGL_LOG_FUNC_EXIT(NULL);
120 }
121
122 YAGL_API void glStencilMaskSeparate(GLenum face, GLuint mask)
123 {
124     int tmp = 0;
125
126     YAGL_LOG_FUNC_ENTER_SPLIT2(glStencilMaskSeparate, GLenum, GLuint, face, mask);
127
128     YAGL_GET_CTX();
129
130     if ((face == GL_FRONT) || (face == GL_FRONT_AND_BACK)) {
131         ctx->base.stencil_front.writemask = mask;
132
133         tmp = 1;
134     }
135
136     if ((face == GL_BACK) || (face == GL_FRONT_AND_BACK)) {
137         ctx->base.stencil_back.writemask = mask;
138
139         tmp = 1;
140     }
141
142     if (tmp) {
143         yagl_host_glStencilMaskSeparate(face, mask);
144     } else {
145         YAGL_SET_ERR(GL_INVALID_ENUM);
146     }
147
148     YAGL_LOG_FUNC_EXIT(NULL);
149 }
150
151 YAGL_API void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
152 {
153     int tmp = 0;
154
155     YAGL_LOG_FUNC_ENTER_SPLIT4(glStencilOpSeparate, GLenum, GLenum, GLenum, GLenum, face, fail, zfail, zpass);
156
157     YAGL_GET_CTX();
158
159     if (!yagl_gles_is_stencil_op_valid(fail) ||
160         !yagl_gles_is_stencil_op_valid(zfail) ||
161         !yagl_gles_is_stencil_op_valid(zpass)) {
162         YAGL_SET_ERR(GL_INVALID_ENUM);
163         goto out;
164     }
165
166     if ((face == GL_FRONT) || (face == GL_FRONT_AND_BACK)) {
167         ctx->base.stencil_front.fail = fail;
168         ctx->base.stencil_front.zfail = zfail;
169         ctx->base.stencil_front.zpass = zpass;
170
171         tmp = 1;
172     }
173
174     if ((face == GL_BACK) || (face == GL_FRONT_AND_BACK)) {
175         ctx->base.stencil_back.fail = fail;
176         ctx->base.stencil_back.zfail = zfail;
177         ctx->base.stencil_back.zpass = zpass;
178
179         tmp = 1;
180     }
181
182     if (tmp) {
183         yagl_host_glStencilOpSeparate(face, fail, zfail, zpass);
184     } else {
185         YAGL_SET_ERR(GL_INVALID_ENUM);
186     }
187
188 out:
189     YAGL_LOG_FUNC_EXIT(NULL);
190 }
191
192 YAGL_API void glAttachShader(GLuint program, GLuint shader)
193 {
194     struct yagl_gles2_program *program_obj = NULL;
195     struct yagl_gles2_shader *shader_obj = NULL;
196
197     YAGL_LOG_FUNC_ENTER_SPLIT2(glAttachShader, GLuint, GLuint, program, shader);
198
199     YAGL_GET_CTX();
200
201     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
202         YAGL_NS_SHADER_PROGRAM, program);
203
204     if (!program_obj) {
205         YAGL_SET_ERR(GL_INVALID_VALUE);
206         goto out;
207     }
208
209     if (program_obj->is_shader) {
210         YAGL_SET_ERR(GL_INVALID_OPERATION);
211         goto out;
212     }
213
214     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
215         YAGL_NS_SHADER_PROGRAM, shader);
216
217     if (!shader_obj) {
218         YAGL_SET_ERR(GL_INVALID_VALUE);
219         goto out;
220     }
221
222     if (!shader_obj->is_shader) {
223         YAGL_SET_ERR(GL_INVALID_OPERATION);
224         goto out;
225     }
226
227     if (!yagl_gles2_program_attach_shader(program_obj, shader_obj)) {
228         YAGL_SET_ERR(GL_INVALID_OPERATION);
229         goto out;
230     }
231
232 out:
233     yagl_gles2_shader_release(shader_obj);
234     yagl_gles2_program_release(program_obj);
235
236     YAGL_LOG_FUNC_EXIT(NULL);
237 }
238
239 YAGL_API void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
240 {
241     struct yagl_gles2_program *program_obj = NULL;
242
243     YAGL_LOG_FUNC_ENTER_SPLIT3(glBindAttribLocation, GLuint, GLuint, const GLchar*, program, index, name);
244
245     YAGL_GET_CTX();
246
247     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
248         YAGL_NS_SHADER_PROGRAM, program);
249
250     if (!program_obj) {
251         YAGL_SET_ERR(GL_INVALID_VALUE);
252         goto out;
253     }
254
255     if (program_obj->is_shader) {
256         YAGL_SET_ERR(GL_INVALID_OPERATION);
257         goto out;
258     }
259
260     if (index >= ctx->base.num_arrays) {
261         YAGL_SET_ERR(GL_INVALID_VALUE);
262         goto out;
263     }
264
265     if (name) {
266         if (strncmp(name, "gl_", 3) == 0) {
267             YAGL_SET_ERR(GL_INVALID_OPERATION);
268             goto out;
269         }
270
271         YAGL_LOG_TRACE("binding attrib %s location to %d", name, index);
272     }
273
274     yagl_host_glBindAttribLocation(program_obj->global_name,
275                                    index,
276                                    name,
277                                    yagl_transport_string_count(name));
278
279 out:
280     yagl_gles2_program_release(program_obj);
281
282     YAGL_LOG_FUNC_EXIT(NULL);
283 }
284
285 YAGL_API void glBlendColor(GLclampf red,
286                            GLclampf green,
287                            GLclampf blue,
288                            GLclampf alpha)
289 {
290     YAGL_LOG_FUNC_ENTER_SPLIT4(glBlendColor, GLclampf, GLclampf, GLclampf, GLclampf, red, green, blue, alpha);
291
292     YAGL_GET_CTX();
293
294     ctx->blend_color[0] = yagl_clampf(red);
295     ctx->blend_color[1] = yagl_clampf(green);
296     ctx->blend_color[2] = yagl_clampf(blue);
297     ctx->blend_color[3] = yagl_clampf(alpha);
298
299     yagl_host_glBlendColor(red, green, blue, alpha);
300
301     YAGL_LOG_FUNC_EXIT(NULL);
302 }
303
304 YAGL_API void glCompileShader(GLuint shader)
305 {
306     struct yagl_gles2_shader *shader_obj = NULL;
307
308     YAGL_LOG_FUNC_ENTER_SPLIT1(glCompileShader, GLuint, shader);
309
310     YAGL_GET_CTX();
311
312     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
313         YAGL_NS_SHADER_PROGRAM, shader);
314
315     if (!shader_obj) {
316         YAGL_SET_ERR(GL_INVALID_VALUE);
317         goto out;
318     }
319
320     if (!shader_obj->is_shader) {
321         YAGL_SET_ERR(GL_INVALID_OPERATION);
322         goto out;
323     }
324
325     yagl_host_glCompileShader(shader_obj->global_name);
326
327 out:
328     yagl_gles2_shader_release(shader_obj);
329
330     YAGL_LOG_FUNC_EXIT(NULL);
331 }
332
333 YAGL_API GLuint glCreateProgram(void)
334 {
335     GLuint res = 0;
336     struct yagl_gles2_program *program = NULL;
337
338     YAGL_LOG_FUNC_ENTER_SPLIT0(glCreateProgram);
339
340     YAGL_GET_CTX_RET(0);
341
342     program = yagl_gles2_program_create(ctx->gen_locations);
343
344     if (!program) {
345         goto out;
346     }
347
348     yagl_sharegroup_add(ctx->sg, YAGL_NS_SHADER_PROGRAM, &program->base);
349     res = program->base.local_name;
350
351 out:
352     yagl_gles2_program_release(program);
353
354     YAGL_LOG_FUNC_EXIT_SPLIT(GLuint, res);
355
356     return res;
357 }
358
359 YAGL_API GLuint glCreateShader(GLenum type)
360 {
361     GLuint res = 0;
362     struct yagl_gles2_shader *shader = NULL;
363
364     YAGL_LOG_FUNC_ENTER_SPLIT1(glCreateShader, GLenum, type);
365
366     YAGL_GET_CTX_RET(0);
367
368     if (yagl_gles2_is_shader_type_valid(type)) {
369         shader = yagl_gles2_shader_create(type);
370
371         if (!shader) {
372             goto out;
373         }
374
375         yagl_sharegroup_add(ctx->sg, YAGL_NS_SHADER_PROGRAM, &shader->base);
376         res = shader->base.local_name;
377     } else {
378         YAGL_SET_ERR(GL_INVALID_ENUM);
379     }
380
381 out:
382     yagl_gles2_shader_release(shader);
383
384     YAGL_LOG_FUNC_EXIT_SPLIT(GLuint, res);
385
386     return res;
387 }
388
389 YAGL_API void glDeleteProgram(GLuint program)
390 {
391     struct yagl_gles2_program *program_obj = NULL;
392
393     YAGL_LOG_FUNC_ENTER_SPLIT1(glDeleteProgram, GLuint, program);
394
395     YAGL_GET_CTX();
396
397     if (program == 0) {
398         goto out;
399     }
400
401     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
402         YAGL_NS_SHADER_PROGRAM, program);
403
404     if (!program_obj) {
405         YAGL_SET_ERR(GL_INVALID_VALUE);
406         goto out;
407     }
408
409     if (program_obj->is_shader) {
410         goto out;
411     }
412
413     yagl_gles2_context_unuse_program(ctx, program_obj);
414
415     yagl_sharegroup_remove(ctx->sg,
416                            YAGL_NS_SHADER_PROGRAM,
417                            program);
418
419 out:
420     yagl_gles2_program_release(program_obj);
421
422     YAGL_LOG_FUNC_EXIT(NULL);
423 }
424
425 YAGL_API void glDeleteShader(GLuint shader)
426 {
427     struct yagl_gles2_shader *shader_obj = NULL;
428
429     YAGL_LOG_FUNC_ENTER_SPLIT1(glDeleteShader, GLuint, shader);
430
431     YAGL_GET_CTX();
432
433     if (shader == 0) {
434         goto out;
435     }
436
437     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
438         YAGL_NS_SHADER_PROGRAM, shader);
439
440     if (!shader_obj) {
441         YAGL_SET_ERR(GL_INVALID_VALUE);
442         goto out;
443     }
444
445     if (!shader_obj->is_shader) {
446         goto out;
447     }
448
449     yagl_sharegroup_remove(ctx->sg,
450                            YAGL_NS_SHADER_PROGRAM,
451                            shader);
452
453 out:
454     yagl_gles2_shader_release(shader_obj);
455
456     YAGL_LOG_FUNC_EXIT(NULL);
457 }
458
459 YAGL_API void glDetachShader(GLuint program, GLuint shader)
460 {
461     struct yagl_gles2_program *program_obj = NULL;
462     struct yagl_gles2_shader *shader_obj = NULL;
463
464     YAGL_LOG_FUNC_ENTER_SPLIT2(glDetachShader, GLuint, GLuint, program, shader);
465
466     YAGL_GET_CTX();
467
468     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
469         YAGL_NS_SHADER_PROGRAM, program);
470
471     if (!program_obj) {
472         YAGL_SET_ERR(GL_INVALID_VALUE);
473         goto out;
474     }
475
476     if (program_obj->is_shader) {
477         YAGL_SET_ERR(GL_INVALID_OPERATION);
478         goto out;
479     }
480
481     if (program_obj->vertex_shader &&
482         (program_obj->vertex_shader->base.local_name == shader)) {
483         shader_obj = program_obj->vertex_shader;
484         yagl_gles2_shader_acquire(shader_obj);
485     } else if (program_obj->fragment_shader &&
486                (program_obj->fragment_shader->base.local_name == shader)) {
487         shader_obj = program_obj->fragment_shader;
488         yagl_gles2_shader_acquire(shader_obj);
489     } else {
490         shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
491             YAGL_NS_SHADER_PROGRAM, shader);
492
493         if (shader_obj) {
494             YAGL_SET_ERR(GL_INVALID_OPERATION);
495         } else {
496             YAGL_SET_ERR(GL_INVALID_VALUE);
497         }
498
499         goto out;
500     }
501
502     yagl_gles2_program_detach_shader(program_obj, shader_obj);
503
504 out:
505     yagl_gles2_shader_release(shader_obj);
506     yagl_gles2_program_release(program_obj);
507
508     YAGL_LOG_FUNC_EXIT(NULL);
509 }
510
511 YAGL_API void glEnableVertexAttribArray(GLuint index)
512 {
513     YAGL_LOG_FUNC_ENTER_SPLIT1(glEnableVertexAttribArray, GLuint, index);
514
515     YAGL_GET_CTX();
516
517     if (index < ctx->base.num_arrays) {
518         yagl_gles_array_enable(&ctx->base.vao->arrays[index], 1);
519     }
520
521     yagl_host_glEnableVertexAttribArray(index);
522
523     YAGL_LOG_FUNC_EXIT(NULL);
524 }
525
526 YAGL_API void glDisableVertexAttribArray(GLuint index)
527 {
528     YAGL_LOG_FUNC_ENTER_SPLIT1(glDisableVertexAttribArray, GLuint, index);
529
530     YAGL_GET_CTX();
531
532     if (index < ctx->base.num_arrays) {
533         yagl_gles_array_enable(&ctx->base.vao->arrays[index], 0);
534     }
535
536     yagl_host_glDisableVertexAttribArray(index);
537
538     YAGL_LOG_FUNC_EXIT(NULL);
539 }
540
541 YAGL_API void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
542 {
543     struct yagl_gles2_program *program_obj = NULL;
544
545     YAGL_LOG_FUNC_ENTER_SPLIT7(glGetActiveAttrib, GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*, program, index, bufsize, length, size, type, name);
546
547     YAGL_GET_CTX();
548
549     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
550         YAGL_NS_SHADER_PROGRAM, program);
551
552     if (!program_obj) {
553         YAGL_SET_ERR(GL_INVALID_VALUE);
554         goto out;
555     }
556
557     if (program_obj->is_shader) {
558         YAGL_SET_ERR(GL_INVALID_OPERATION);
559         goto out;
560     }
561
562     if (bufsize < 0) {
563         YAGL_SET_ERR(GL_INVALID_VALUE);
564         goto out;
565     }
566
567     if (index >= program_obj->num_active_attribs) {
568         YAGL_SET_ERR(GL_INVALID_VALUE);
569         goto out;
570     }
571
572     yagl_gles2_program_get_active_attrib(program_obj, index, bufsize, length, size, type, name);
573
574 out:
575     yagl_gles2_program_release(program_obj);
576
577     YAGL_LOG_FUNC_EXIT(NULL);
578 }
579
580 YAGL_API void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
581 {
582     struct yagl_gles2_program *program_obj = NULL;
583
584     YAGL_LOG_FUNC_ENTER_SPLIT7(glGetActiveUniform, GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*, program, index, bufsize, length, size, type, name);
585
586     YAGL_GET_CTX();
587
588     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
589         YAGL_NS_SHADER_PROGRAM, program);
590
591     if (!program_obj) {
592         YAGL_SET_ERR(GL_INVALID_VALUE);
593         goto out;
594     }
595
596     if (program_obj->is_shader) {
597         YAGL_SET_ERR(GL_INVALID_OPERATION);
598         goto out;
599     }
600
601     if (bufsize < 0) {
602         YAGL_SET_ERR(GL_INVALID_VALUE);
603         goto out;
604     }
605
606     if (index >= program_obj->num_active_uniforms) {
607         YAGL_SET_ERR(GL_INVALID_VALUE);
608         goto out;
609     }
610
611     yagl_gles2_program_get_active_uniform(program_obj, index, bufsize, length, size, type, name);
612
613 out:
614     yagl_gles2_program_release(program_obj);
615
616     YAGL_LOG_FUNC_EXIT(NULL);
617 }
618
619 YAGL_API void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders)
620 {
621     struct yagl_gles2_program *program_obj = NULL;
622     GLsizei tmp = 0;
623
624     YAGL_LOG_FUNC_ENTER_SPLIT4(glGetAttachedShaders, GLuint, GLsizei, GLsizei*, GLuint*, program, maxcount, count, shaders);
625
626     YAGL_GET_CTX();
627
628     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
629         YAGL_NS_SHADER_PROGRAM, program);
630
631     if (!program_obj) {
632         YAGL_SET_ERR(GL_INVALID_VALUE);
633         goto out;
634     }
635
636     if (program_obj->is_shader) {
637         YAGL_SET_ERR(GL_INVALID_OPERATION);
638         goto out;
639     }
640
641     if (maxcount < 0) {
642         YAGL_SET_ERR(GL_INVALID_VALUE);
643         goto out;
644     }
645
646     tmp = 0;
647
648     if (program_obj->vertex_shader) {
649         if (tmp < maxcount) {
650             if (shaders) {
651                 shaders[tmp] = program_obj->vertex_shader->base.local_name;
652             }
653             ++tmp;
654         }
655     }
656
657     if (program_obj->fragment_shader) {
658         if (tmp < maxcount) {
659             if (shaders) {
660                 shaders[tmp] = program_obj->fragment_shader->base.local_name;
661             }
662             ++tmp;
663         }
664     }
665
666     if (count) {
667         *count = tmp;
668     }
669
670 out:
671     yagl_gles2_program_release(program_obj);
672
673     YAGL_LOG_FUNC_EXIT(NULL);
674 }
675
676 YAGL_API int glGetAttribLocation(GLuint program, const GLchar *name)
677 {
678     struct yagl_gles2_program *program_obj = NULL;
679     int ret = 0;
680
681     YAGL_LOG_FUNC_ENTER_SPLIT2(glGetAttribLocation, GLuint, const GLchar*, program, name);
682
683     YAGL_GET_CTX_RET(0);
684
685     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
686         YAGL_NS_SHADER_PROGRAM, program);
687
688     if (!program_obj) {
689         YAGL_SET_ERR(GL_INVALID_VALUE);
690         goto out;
691     }
692
693     if (program_obj->is_shader) {
694         YAGL_SET_ERR(GL_INVALID_OPERATION);
695         goto out;
696     }
697
698     if (!program_obj->linked) {
699         YAGL_SET_ERR(GL_INVALID_OPERATION);
700         goto out;
701     }
702
703     ret = yagl_gles2_program_get_attrib_location(program_obj, name);
704
705 out:
706     yagl_gles2_program_release(program_obj);
707
708     YAGL_LOG_FUNC_EXIT_SPLIT(int, ret);
709
710     return ret;
711 }
712
713 YAGL_API void glGetProgramiv(GLuint program, GLenum pname, GLint *params)
714 {
715     struct yagl_gles2_program *program_obj = NULL;
716
717     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetProgramiv, GLuint, GLenum, GLint*, program, pname, params);
718
719     YAGL_GET_CTX();
720
721     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
722         YAGL_NS_SHADER_PROGRAM, program);
723
724     if (!program_obj) {
725         YAGL_SET_ERR(GL_INVALID_VALUE);
726         goto out;
727     }
728
729     if (program_obj->is_shader) {
730         YAGL_SET_ERR(GL_INVALID_OPERATION);
731         goto out;
732     }
733
734     if (!ctx->get_programiv(ctx, program_obj, pname, params)) {
735         switch (pname) {
736         case GL_VALIDATE_STATUS:
737             yagl_host_glGetProgramiv(program_obj->global_name, pname, params);
738             break;
739         default:
740             YAGL_SET_ERR(GL_INVALID_ENUM);
741         }
742     }
743
744 out:
745     yagl_gles2_program_release(program_obj);
746
747     YAGL_LOG_FUNC_EXIT(NULL);
748 }
749
750 YAGL_API void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog)
751 {
752     struct yagl_gles2_program *program_obj = NULL;
753     int32_t tmp = 0;
754
755     YAGL_LOG_FUNC_ENTER_SPLIT4(glGetProgramInfoLog, GLuint, GLsizei, GLsizei*, GLchar*, program, bufsize, length, infolog);
756
757     YAGL_GET_CTX();
758
759     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
760         YAGL_NS_SHADER_PROGRAM, program);
761
762     if (!program_obj) {
763         YAGL_SET_ERR(GL_INVALID_VALUE);
764         goto out;
765     }
766
767     if (program_obj->is_shader) {
768         YAGL_SET_ERR(GL_INVALID_OPERATION);
769         goto out;
770     }
771
772     if (bufsize < 0) {
773         YAGL_SET_ERR(GL_INVALID_VALUE);
774         goto out;
775     }
776
777     if (yagl_host_glGetProgramInfoLog(program_obj->global_name, infolog, bufsize, &tmp)) {
778         if (length) {
779             *length = (tmp > 0) ? (tmp - 1) : 0;
780         }
781         YAGL_LOG_TRACE("infolog = %s", infolog);
782     }
783
784 out:
785     yagl_gles2_program_release(program_obj);
786
787     YAGL_LOG_FUNC_EXIT(NULL);
788 }
789
790 YAGL_API void glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
791 {
792     struct yagl_gles2_shader *shader_obj = NULL;
793
794     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetShaderiv, GLuint, GLenum, GLint*, shader, pname, params);
795
796     YAGL_GET_CTX();
797
798     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
799         YAGL_NS_SHADER_PROGRAM, shader);
800
801     if (!shader_obj) {
802         YAGL_SET_ERR(GL_INVALID_VALUE);
803         goto out;
804     }
805
806     if (!shader_obj->is_shader) {
807         YAGL_SET_ERR(GL_INVALID_OPERATION);
808         goto out;
809     }
810
811     switch (pname) {
812     case GL_SHADER_TYPE:
813         *params = shader_obj->type;
814         break;
815     case GL_SHADER_SOURCE_LENGTH:
816         *params = shader_obj->source ? (strlen(shader_obj->source) + 1) : 0;
817         break;
818     case GL_INFO_LOG_LENGTH:
819     case GL_DELETE_STATUS:
820     case GL_COMPILE_STATUS:
821         yagl_host_glGetShaderiv(shader_obj->global_name, pname, params);
822         break;
823     default:
824         YAGL_SET_ERR(GL_INVALID_ENUM);
825         break;
826     }
827
828 out:
829     yagl_gles2_shader_release(shader_obj);
830
831     YAGL_LOG_FUNC_EXIT(NULL);
832 }
833
834 YAGL_API void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog)
835 {
836     int32_t tmp = 0;
837     struct yagl_gles2_shader *shader_obj = NULL;
838
839     YAGL_LOG_FUNC_ENTER_SPLIT4(glGetShaderInfoLog, GLuint, GLsizei, GLsizei*, GLchar*, shader, bufsize, length, infolog);
840
841     YAGL_GET_CTX();
842
843     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
844         YAGL_NS_SHADER_PROGRAM, shader);
845
846     if (!shader_obj) {
847         YAGL_SET_ERR(GL_INVALID_VALUE);
848         goto out;
849     }
850
851     if (!shader_obj->is_shader) {
852         YAGL_SET_ERR(GL_INVALID_OPERATION);
853         goto out;
854     }
855
856     if (bufsize < 0) {
857         YAGL_SET_ERR(GL_INVALID_VALUE);
858         goto out;
859     }
860
861     if (yagl_host_glGetShaderInfoLog(shader_obj->global_name, infolog, bufsize, &tmp)) {
862         if (length) {
863             *length = (tmp > 0) ? (tmp - 1) : 0;
864         }
865         YAGL_LOG_TRACE("infolog = %s", infolog);
866     }
867
868 out:
869     yagl_gles2_shader_release(shader_obj);
870
871     YAGL_LOG_FUNC_EXIT(NULL);
872 }
873
874 YAGL_API void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision)
875 {
876     YAGL_LOG_FUNC_ENTER_SPLIT4(glGetShaderPrecisionFormat, GLenum, GLenum, GLint*, GLint*, shadertype, precisiontype, range, precision);
877
878     YAGL_GET_CTX();
879
880     switch (precisiontype) {
881     case GL_LOW_INT:
882     case GL_MEDIUM_INT:
883     case GL_HIGH_INT:
884         if (range) {
885             range[0] = range[1] = 16;
886         }
887         if (precision) {
888             *precision = 0;
889         }
890         break;
891     case GL_LOW_FLOAT:
892     case GL_MEDIUM_FLOAT:
893     case GL_HIGH_FLOAT:
894         if (range) {
895             range[0] = range[1] = 127;
896         }
897         if (precision) {
898             *precision = 24;
899         }
900         break;
901     default:
902         YAGL_SET_ERR(GL_INVALID_ENUM);
903         break;
904     }
905
906     YAGL_LOG_FUNC_EXIT(NULL);
907 }
908
909 YAGL_API void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
910 {
911     struct yagl_gles2_shader *shader_obj = NULL;
912     GLsizei tmp;
913
914     YAGL_LOG_FUNC_ENTER_SPLIT4(glGetShaderSource, GLuint, GLsizei, GLsizei*, GLchar*, shader, bufsize, length, source);
915
916     YAGL_GET_CTX();
917
918     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
919         YAGL_NS_SHADER_PROGRAM, shader);
920
921     if (!shader_obj) {
922         YAGL_SET_ERR(GL_INVALID_VALUE);
923         goto out;
924     }
925
926     if (!shader_obj->is_shader) {
927         YAGL_SET_ERR(GL_INVALID_OPERATION);
928         goto out;
929     }
930
931     if (bufsize < 0) {
932         YAGL_SET_ERR(GL_INVALID_VALUE);
933         goto out;
934     }
935
936     if (!shader_obj->source) {
937         if (length) {
938             *length = 0;
939         }
940         goto out;
941     }
942
943     tmp = strlen(shader_obj->source) + 1;
944     tmp = (bufsize <= tmp) ? bufsize : tmp;
945
946     if (source && (tmp > 0)) {
947         strncpy(source, shader_obj->source, tmp);
948         source[tmp - 1] = '\0';
949     }
950
951     if (tmp > 0) {
952         --tmp;
953     }
954
955     if (length) {
956         *length = tmp;
957     }
958
959 out:
960     yagl_gles2_shader_release(shader_obj);
961
962     YAGL_LOG_FUNC_EXIT(NULL);
963 }
964
965 YAGL_API void glGetUniformfv(GLuint program, GLint location, GLfloat *params)
966 {
967     struct yagl_gles2_program *program_obj = NULL;
968
969     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetUniformfv, GLuint, GLint, GLfloat*, program, location, params);
970
971     YAGL_GET_CTX();
972
973     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
974         YAGL_NS_SHADER_PROGRAM, program);
975
976     if (!program_obj) {
977         YAGL_SET_ERR(GL_INVALID_VALUE);
978         goto out;
979     }
980
981     if (program_obj->is_shader) {
982         YAGL_SET_ERR(GL_INVALID_OPERATION);
983         goto out;
984     }
985
986     if (!program_obj->linked) {
987         YAGL_SET_ERR(GL_INVALID_OPERATION);
988         goto out;
989     }
990
991     if (location < 0) {
992         YAGL_SET_ERR(GL_INVALID_OPERATION);
993         goto out;
994     }
995
996     if (!yagl_gles2_program_get_uniformfv(program_obj, location, params)) {
997         YAGL_SET_ERR(GL_INVALID_OPERATION);
998         goto out;
999     }
1000
1001 out:
1002     yagl_gles2_program_release(program_obj);
1003
1004     YAGL_LOG_FUNC_EXIT(NULL);
1005 }
1006
1007 YAGL_API void glGetUniformiv(GLuint program, GLint location, GLint *params)
1008 {
1009     struct yagl_gles2_program *program_obj = NULL;
1010
1011     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetUniformiv, GLuint, GLint, GLint*, program, location, params);
1012
1013     YAGL_GET_CTX();
1014
1015     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
1016         YAGL_NS_SHADER_PROGRAM, program);
1017
1018     if (!program_obj) {
1019         YAGL_SET_ERR(GL_INVALID_VALUE);
1020         goto out;
1021     }
1022
1023     if (program_obj->is_shader) {
1024         YAGL_SET_ERR(GL_INVALID_OPERATION);
1025         goto out;
1026     }
1027
1028     if (!program_obj->linked) {
1029         YAGL_SET_ERR(GL_INVALID_OPERATION);
1030         goto out;
1031     }
1032
1033     if (location < 0) {
1034         YAGL_SET_ERR(GL_INVALID_OPERATION);
1035         goto out;
1036     }
1037
1038     if (!yagl_gles2_program_get_uniformiv(program_obj, location, params)) {
1039         YAGL_SET_ERR(GL_INVALID_OPERATION);
1040         goto out;
1041     }
1042
1043 out:
1044     yagl_gles2_program_release(program_obj);
1045
1046     YAGL_LOG_FUNC_EXIT(NULL);
1047 }
1048
1049 YAGL_API int glGetUniformLocation(GLuint program, const GLchar *name)
1050 {
1051     struct yagl_gles2_program *program_obj = NULL;
1052     int ret = 0;
1053
1054     YAGL_LOG_FUNC_ENTER_SPLIT2(glGetUniformLocation, GLuint, const GLchar*, program, name);
1055
1056     YAGL_GET_CTX_RET(0);
1057
1058     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
1059         YAGL_NS_SHADER_PROGRAM, program);
1060
1061     if (!program_obj) {
1062         YAGL_SET_ERR(GL_INVALID_VALUE);
1063         goto out;
1064     }
1065
1066     if (program_obj->is_shader) {
1067         YAGL_SET_ERR(GL_INVALID_OPERATION);
1068         goto out;
1069     }
1070
1071     if (!program_obj->linked) {
1072         YAGL_SET_ERR(GL_INVALID_OPERATION);
1073         goto out;
1074     }
1075
1076     if (name) {
1077         YAGL_LOG_TRACE("getting uniform %s location", name);
1078     }
1079
1080     ret = yagl_gles2_program_get_uniform_location(program_obj, name);
1081
1082 out:
1083     yagl_gles2_program_release(program_obj);
1084
1085     YAGL_LOG_FUNC_EXIT_SPLIT(int, ret);
1086
1087     return ret;
1088 }
1089
1090 YAGL_API void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
1091 {
1092     GLint param = 0;
1093     GLfloat tmp[100]; // This fits all cases.
1094     int32_t num = 0;
1095
1096     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetVertexAttribfv, GLuint, GLenum, GLfloat*, index, pname, params);
1097
1098     YAGL_GET_CTX();
1099
1100     if ((index == 0) &&
1101         (pname == GL_CURRENT_VERTEX_ATTRIB)) {
1102         if (params) {
1103             switch (ctx->vertex_attrib0.type) {
1104             case GL_INT:
1105                 params[0] = ctx->vertex_attrib0.value.i[0];
1106                 params[1] = ctx->vertex_attrib0.value.i[1];
1107                 params[2] = ctx->vertex_attrib0.value.i[2];
1108                 params[3] = ctx->vertex_attrib0.value.i[3];
1109                 break;
1110             case GL_UNSIGNED_INT:
1111                 params[0] = ctx->vertex_attrib0.value.ui[0];
1112                 params[1] = ctx->vertex_attrib0.value.ui[1];
1113                 params[2] = ctx->vertex_attrib0.value.ui[2];
1114                 params[3] = ctx->vertex_attrib0.value.ui[3];
1115                 break;
1116             default:
1117                 assert(0);
1118             case GL_FLOAT:
1119                 params[0] = ctx->vertex_attrib0.value.f[0];
1120                 params[1] = ctx->vertex_attrib0.value.f[1];
1121                 params[2] = ctx->vertex_attrib0.value.f[2];
1122                 params[3] = ctx->vertex_attrib0.value.f[3];
1123                 break;
1124             }
1125         }
1126
1127         goto out;
1128     }
1129
1130     if (yagl_gles2_context_get_array_param(ctx,
1131                                            index,
1132                                            pname,
1133                                            &param)) {
1134         if (params) {
1135             params[0] = param;
1136         }
1137     } else {
1138         yagl_host_glGetVertexAttribfv(index, pname, tmp, sizeof(tmp)/sizeof(tmp[0]), &num);
1139         if (params) {
1140             memcpy(params, tmp, num * sizeof(tmp[0]));
1141         }
1142     }
1143
1144 out:
1145     YAGL_LOG_FUNC_EXIT(NULL);
1146 }
1147
1148 YAGL_API void glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
1149 {
1150     GLint tmp[100]; // This fits all cases.
1151     int32_t num = 0;
1152
1153     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetVertexAttribiv, GLuint, GLenum, GLint*, index, pname, params);
1154
1155     YAGL_GET_CTX();
1156
1157     if ((index == 0) &&
1158         (pname == GL_CURRENT_VERTEX_ATTRIB)) {
1159         if (params) {
1160             switch (ctx->vertex_attrib0.type) {
1161             case GL_INT:
1162                 params[0] = ctx->vertex_attrib0.value.i[0];
1163                 params[1] = ctx->vertex_attrib0.value.i[1];
1164                 params[2] = ctx->vertex_attrib0.value.i[2];
1165                 params[3] = ctx->vertex_attrib0.value.i[3];
1166                 break;
1167             case GL_UNSIGNED_INT:
1168                 params[0] = ctx->vertex_attrib0.value.ui[0];
1169                 params[1] = ctx->vertex_attrib0.value.ui[1];
1170                 params[2] = ctx->vertex_attrib0.value.ui[2];
1171                 params[3] = ctx->vertex_attrib0.value.ui[3];
1172                 break;
1173             default:
1174                 assert(0);
1175             case GL_FLOAT:
1176                 params[0] = ctx->vertex_attrib0.value.f[0];
1177                 params[1] = ctx->vertex_attrib0.value.f[1];
1178                 params[2] = ctx->vertex_attrib0.value.f[2];
1179                 params[3] = ctx->vertex_attrib0.value.f[3];
1180                 break;
1181             }
1182         }
1183
1184         goto out;
1185     }
1186
1187     if (yagl_gles2_context_get_array_param(ctx,
1188                                            index,
1189                                            pname,
1190                                            params)) {
1191     } else {
1192         yagl_host_glGetVertexAttribiv(index, pname, tmp, sizeof(tmp)/sizeof(tmp[0]), &num);
1193         if (params) {
1194             memcpy(params, tmp, num * sizeof(tmp[0]));
1195         }
1196     }
1197
1198 out:
1199     YAGL_LOG_FUNC_EXIT(NULL);
1200 }
1201
1202 YAGL_API void glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
1203 {
1204     struct yagl_gles_array *array = NULL;
1205
1206     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetVertexAttribPointerv, GLuint, GLenum, GLvoid**, index, pname, pointer);
1207
1208     YAGL_GET_CTX();
1209
1210     if (index >= ctx->base.num_arrays) {
1211         YAGL_SET_ERR(GL_INVALID_VALUE);
1212         goto out;
1213     }
1214
1215     array = &ctx->base.vao->arrays[index];
1216
1217     if (pointer) {
1218         if (array->vbo) {
1219             *pointer = (GLvoid*)array->offset;
1220         } else {
1221             *pointer = (GLvoid*)array->ptr;
1222         }
1223     }
1224
1225 out:
1226     YAGL_LOG_FUNC_EXIT(NULL);
1227 }
1228
1229 YAGL_API GLboolean glIsProgram(GLuint program)
1230 {
1231     GLboolean res = GL_FALSE;
1232     struct yagl_gles2_program *program_obj = NULL;
1233
1234     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsProgram, GLuint, program);
1235
1236     YAGL_GET_CTX_RET(GL_FALSE);
1237
1238     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
1239         YAGL_NS_SHADER_PROGRAM, program);
1240
1241     if (program_obj) {
1242         res = program_obj->is_shader ? GL_FALSE : GL_TRUE;
1243     }
1244
1245     yagl_gles2_program_release(program_obj);
1246
1247     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
1248
1249     return res;
1250 }
1251
1252 YAGL_API GLboolean glIsShader(GLuint shader)
1253 {
1254     GLboolean res = GL_FALSE;
1255     struct yagl_gles2_shader *shader_obj = NULL;
1256
1257     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsShader, GLuint, shader);
1258
1259     YAGL_GET_CTX_RET(GL_FALSE);
1260
1261     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
1262         YAGL_NS_SHADER_PROGRAM, shader);
1263
1264     if (shader_obj) {
1265         res = shader_obj->is_shader ? GL_TRUE : GL_FALSE;
1266     }
1267
1268     yagl_gles2_shader_release(shader_obj);
1269
1270     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
1271
1272     return res;
1273 }
1274
1275 YAGL_API void glLinkProgram(GLuint program)
1276 {
1277     struct yagl_gles2_program *program_obj = NULL;
1278
1279     YAGL_LOG_FUNC_ENTER_SPLIT1(glLinkProgram, GLuint, program);
1280
1281     YAGL_GET_CTX();
1282
1283     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
1284         YAGL_NS_SHADER_PROGRAM, program);
1285
1286     if (!program_obj) {
1287         YAGL_SET_ERR(GL_INVALID_VALUE);
1288         goto out;
1289     }
1290
1291     if (program_obj->is_shader) {
1292         YAGL_SET_ERR(GL_INVALID_OPERATION);
1293         goto out;
1294     }
1295
1296     if (!ctx->pre_link_program(ctx, program_obj)) {
1297         goto out;
1298     }
1299
1300     yagl_gles2_program_link(program_obj);
1301
1302 out:
1303     yagl_gles2_program_release(program_obj);
1304
1305     YAGL_LOG_FUNC_EXIT(NULL);
1306 }
1307
1308 YAGL_API void glReleaseShaderCompiler(void)
1309 {
1310     YAGL_LOG_FUNC_ENTER_SPLIT0(glReleaseShaderCompiler);
1311
1312     YAGL_GET_CTX();
1313
1314     /*
1315      * No-op.
1316      */
1317
1318     YAGL_LOG_FUNC_EXIT(NULL);
1319 }
1320
1321 YAGL_API void glShaderBinary(GLsizei n, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length)
1322 {
1323     YAGL_LOG_FUNC_ENTER_SPLIT5(glShaderBinary, GLsizei, const GLuint*, GLenum, const GLvoid*, GLsizei, n, shaders, binaryformat, binary, length);
1324
1325     YAGL_GET_CTX();
1326
1327     /*
1328      * No-op.
1329      */
1330
1331     YAGL_LOG_FUNC_EXIT(NULL);
1332 }
1333
1334 YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length)
1335 {
1336     struct yagl_gles2_shader *shader_obj = NULL;
1337     int have_strings = 0;
1338     uint32_t total_length = 0;
1339     int i;
1340
1341     YAGL_LOG_FUNC_ENTER_SPLIT4(glShaderSource, GLuint, GLsizei, const GLchar**, const GLint*, shader, count, string, length);
1342
1343     YAGL_GET_CTX();
1344
1345     if (count < 0) {
1346         YAGL_SET_ERR(GL_INVALID_VALUE);
1347         goto out;
1348     }
1349
1350     shader_obj = (struct yagl_gles2_shader*)yagl_sharegroup_acquire_object(ctx->sg,
1351         YAGL_NS_SHADER_PROGRAM, shader);
1352
1353     if (!shader_obj) {
1354         YAGL_SET_ERR(GL_INVALID_VALUE);
1355         goto out;
1356     }
1357
1358     if (!shader_obj->is_shader) {
1359         YAGL_SET_ERR(GL_INVALID_OPERATION);
1360         goto out;
1361     }
1362
1363     if (string) {
1364         for (i = 0; i < count; ++i) {
1365             if (string[i]) {
1366                 if (length && (length[i] >= 0)) {
1367                     total_length += length[i];
1368                     have_strings = 1;
1369                 } else {
1370                     total_length += strlen(string[i]);
1371                     have_strings = 1;
1372                 }
1373             }
1374         }
1375     }
1376
1377     if (have_strings) {
1378         uint8_t *tmp_buff;
1379         struct yagl_glsl_state glsl_state;
1380         int ret;
1381         int patched_len = 0;
1382         char *patched_source;
1383
1384         tmp_buff = yagl_malloc(total_length + 1);
1385         tmp_buff[0] = '\0';
1386
1387         for (i = 0; i < count; ++i) {
1388             if (string[i]) {
1389                 if (length && (length[i] >= 0)) {
1390                     strncat((char*)tmp_buff, string[i], length[i]);
1391                 } else {
1392                     strcat((char*)tmp_buff, string[i]);
1393                 }
1394             }
1395         }
1396
1397         tmp_buff[total_length] = '\0';
1398
1399         YAGL_LOG_TRACE("orig source = %s", tmp_buff);
1400
1401         yagl_glsl_state_init(&glsl_state,
1402                              shader_obj->type,
1403                              (char*)tmp_buff,
1404                              total_length,
1405                              (ctx->base.base.client_api == yagl_client_api_gles3));
1406
1407         ret = yagl_glsl_parse(&glsl_state);
1408
1409         if ((ret == 0) && !glsl_state.have_error) {
1410             patched_source = yagl_glsl_state_get_output(&glsl_state,
1411                                                         &patched_len);
1412
1413             YAGL_LOG_TRACE("patched source = %s", patched_source);
1414
1415             yagl_gles2_shader_source(shader_obj,
1416                                      (GLchar*)tmp_buff,
1417                                      patched_source,
1418                                      patched_len);
1419
1420             yagl_free(patched_source);
1421         } else {
1422             /*
1423              * Unable to parse source, pass as-is.
1424              */
1425             yagl_gles2_shader_source(shader_obj,
1426                                      (GLchar*)tmp_buff,
1427                                      (GLchar*)tmp_buff,
1428                                      total_length);
1429         }
1430
1431         yagl_glsl_state_cleanup(&glsl_state);
1432     }
1433
1434 out:
1435     yagl_gles2_shader_release(shader_obj);
1436
1437     YAGL_LOG_FUNC_EXIT(NULL);
1438 }
1439
1440 YAGL_API void glUniform1f(GLint location, GLfloat x)
1441 {
1442     YAGL_LOG_FUNC_ENTER_SPLIT2(glUniform1f, GLint, GLfloat, location, x);
1443
1444     YAGL_GET_CTX();
1445
1446     if (!ctx->program) {
1447         YAGL_SET_ERR(GL_INVALID_OPERATION);
1448         goto out;
1449     }
1450
1451     if (location == -1) {
1452         goto out;
1453     }
1454
1455     if (location < 0) {
1456         YAGL_SET_ERR(GL_INVALID_OPERATION);
1457         goto out;
1458     }
1459
1460     if (!yagl_gles2_program_uniform1f(ctx->program, location, x)) {
1461         YAGL_SET_ERR(GL_INVALID_OPERATION);
1462         goto out;
1463     }
1464
1465 out:
1466     YAGL_LOG_FUNC_EXIT(NULL);
1467 }
1468
1469 YAGL_API void glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
1470 {
1471     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform1fv, GLint, GLsizei, const GLfloat*, location, count, v);
1472
1473     YAGL_GET_CTX();
1474
1475     if (!ctx->program) {
1476         YAGL_SET_ERR(GL_INVALID_OPERATION);
1477         goto out;
1478     }
1479
1480     if (count < 0) {
1481         YAGL_SET_ERR(GL_INVALID_VALUE);
1482         goto out;
1483     }
1484
1485     if (location == -1) {
1486         goto out;
1487     }
1488
1489     if (location < 0) {
1490         YAGL_SET_ERR(GL_INVALID_OPERATION);
1491         goto out;
1492     }
1493
1494     if (!yagl_gles2_program_uniform1fv(ctx->program, location, count, v)) {
1495         YAGL_SET_ERR(GL_INVALID_OPERATION);
1496         goto out;
1497     }
1498
1499 out:
1500     YAGL_LOG_FUNC_EXIT(NULL);
1501 }
1502
1503 YAGL_API void glUniform1i(GLint location, GLint x)
1504 {
1505     YAGL_LOG_FUNC_ENTER_SPLIT2(glUniform1i, GLint, GLint, location, x);
1506
1507     YAGL_GET_CTX();
1508
1509     if (!ctx->program) {
1510         YAGL_SET_ERR(GL_INVALID_OPERATION);
1511         goto out;
1512     }
1513
1514     if (location == -1) {
1515         goto out;
1516     }
1517
1518     if (location < 0) {
1519         YAGL_SET_ERR(GL_INVALID_OPERATION);
1520         goto out;
1521     }
1522
1523     if (!yagl_gles2_program_uniform1i(ctx->program, location, x)) {
1524         YAGL_SET_ERR(GL_INVALID_OPERATION);
1525         goto out;
1526     }
1527
1528 out:
1529     YAGL_LOG_FUNC_EXIT(NULL);
1530 }
1531
1532 YAGL_API void glUniform1iv(GLint location, GLsizei count, const GLint* v)
1533 {
1534     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform1iv, GLint, GLsizei, const GLint*, location, count, v);
1535
1536     YAGL_GET_CTX();
1537
1538     if (!ctx->program) {
1539         YAGL_SET_ERR(GL_INVALID_OPERATION);
1540         goto out;
1541     }
1542
1543     if (count < 0) {
1544         YAGL_SET_ERR(GL_INVALID_VALUE);
1545         goto out;
1546     }
1547
1548     if (location == -1) {
1549         goto out;
1550     }
1551
1552     if (location < 0) {
1553         YAGL_SET_ERR(GL_INVALID_OPERATION);
1554         goto out;
1555     }
1556
1557     if (!yagl_gles2_program_uniform1iv(ctx->program, location, count, v)) {
1558         YAGL_SET_ERR(GL_INVALID_OPERATION);
1559         goto out;
1560     }
1561
1562 out:
1563     YAGL_LOG_FUNC_EXIT(NULL);
1564 }
1565
1566 YAGL_API void glUniform2f(GLint location, GLfloat x, GLfloat y)
1567 {
1568     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform2f, GLint, GLfloat, GLfloat, location, x, y);
1569
1570     YAGL_GET_CTX();
1571
1572     if (!ctx->program) {
1573         YAGL_SET_ERR(GL_INVALID_OPERATION);
1574         goto out;
1575     }
1576
1577     if (location == -1) {
1578         goto out;
1579     }
1580
1581     if (location < 0) {
1582         YAGL_SET_ERR(GL_INVALID_OPERATION);
1583         goto out;
1584     }
1585
1586     if (!yagl_gles2_program_uniform2f(ctx->program, location, x, y)) {
1587         YAGL_SET_ERR(GL_INVALID_OPERATION);
1588         goto out;
1589     }
1590
1591 out:
1592     YAGL_LOG_FUNC_EXIT(NULL);
1593 }
1594
1595 YAGL_API void glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
1596 {
1597     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform2fv, GLint, GLsizei, const GLfloat*, location, count, v);
1598
1599     YAGL_GET_CTX();
1600
1601     if (!ctx->program) {
1602         YAGL_SET_ERR(GL_INVALID_OPERATION);
1603         goto out;
1604     }
1605
1606     if (count < 0) {
1607         YAGL_SET_ERR(GL_INVALID_VALUE);
1608         goto out;
1609     }
1610
1611     if (location == -1) {
1612         goto out;
1613     }
1614
1615     if (location < 0) {
1616         YAGL_SET_ERR(GL_INVALID_OPERATION);
1617         goto out;
1618     }
1619
1620     if (!yagl_gles2_program_uniform2fv(ctx->program, location, count, v)) {
1621         YAGL_SET_ERR(GL_INVALID_OPERATION);
1622         goto out;
1623     }
1624
1625 out:
1626     YAGL_LOG_FUNC_EXIT(NULL);
1627 }
1628
1629 YAGL_API void glUniform2i(GLint location, GLint x, GLint y)
1630 {
1631     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform2i, GLint, GLint, GLint, location, x, y);
1632
1633     YAGL_GET_CTX();
1634
1635     if (!ctx->program) {
1636         YAGL_SET_ERR(GL_INVALID_OPERATION);
1637         goto out;
1638     }
1639
1640     if (location == -1) {
1641         goto out;
1642     }
1643
1644     if (location < 0) {
1645         YAGL_SET_ERR(GL_INVALID_OPERATION);
1646         goto out;
1647     }
1648
1649     if (!yagl_gles2_program_uniform2i(ctx->program, location, x, y)) {
1650         YAGL_SET_ERR(GL_INVALID_OPERATION);
1651         goto out;
1652     }
1653
1654 out:
1655     YAGL_LOG_FUNC_EXIT(NULL);
1656 }
1657
1658 YAGL_API void glUniform2iv(GLint location, GLsizei count, const GLint* v)
1659 {
1660     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform2iv, GLint, GLsizei, const GLint*, location, count, v);
1661
1662     YAGL_GET_CTX();
1663
1664     if (!ctx->program) {
1665         YAGL_SET_ERR(GL_INVALID_OPERATION);
1666         goto out;
1667     }
1668
1669     if (count < 0) {
1670         YAGL_SET_ERR(GL_INVALID_VALUE);
1671         goto out;
1672     }
1673
1674     if (location == -1) {
1675         goto out;
1676     }
1677
1678     if (location < 0) {
1679         YAGL_SET_ERR(GL_INVALID_OPERATION);
1680         goto out;
1681     }
1682
1683     if (!yagl_gles2_program_uniform2iv(ctx->program, location, count, v)) {
1684         YAGL_SET_ERR(GL_INVALID_OPERATION);
1685         goto out;
1686     }
1687
1688 out:
1689     YAGL_LOG_FUNC_EXIT(NULL);
1690 }
1691
1692 YAGL_API void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
1693 {
1694     YAGL_LOG_FUNC_ENTER_SPLIT4(glUniform3f, GLint, GLfloat, GLfloat, GLfloat, location, x, y, z);
1695
1696     YAGL_GET_CTX();
1697
1698     if (!ctx->program) {
1699         YAGL_SET_ERR(GL_INVALID_OPERATION);
1700         goto out;
1701     }
1702
1703     if (location == -1) {
1704         goto out;
1705     }
1706
1707     if (location < 0) {
1708         YAGL_SET_ERR(GL_INVALID_OPERATION);
1709         goto out;
1710     }
1711
1712     if (!yagl_gles2_program_uniform3f(ctx->program, location, x, y, z)) {
1713         YAGL_SET_ERR(GL_INVALID_OPERATION);
1714         goto out;
1715     }
1716
1717 out:
1718     YAGL_LOG_FUNC_EXIT(NULL);
1719 }
1720
1721 YAGL_API void glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
1722 {
1723     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform3fv, GLint, GLsizei, const GLfloat*, location, count, v);
1724
1725     YAGL_GET_CTX();
1726
1727     if (!ctx->program) {
1728         YAGL_SET_ERR(GL_INVALID_OPERATION);
1729         goto out;
1730     }
1731
1732     if (count < 0) {
1733         YAGL_SET_ERR(GL_INVALID_VALUE);
1734         goto out;
1735     }
1736
1737     if (location == -1) {
1738         goto out;
1739     }
1740
1741     if (location < 0) {
1742         YAGL_SET_ERR(GL_INVALID_OPERATION);
1743         goto out;
1744     }
1745
1746     if (!yagl_gles2_program_uniform3fv(ctx->program, location, count, v)) {
1747         YAGL_SET_ERR(GL_INVALID_OPERATION);
1748         goto out;
1749     }
1750
1751 out:
1752     YAGL_LOG_FUNC_EXIT(NULL);
1753 }
1754
1755 YAGL_API void glUniform3i(GLint location, GLint x, GLint y, GLint z)
1756 {
1757     YAGL_LOG_FUNC_ENTER_SPLIT4(glUniform3i, GLint, GLint, GLint, GLint, location, x, y, z);
1758
1759     YAGL_GET_CTX();
1760
1761     if (!ctx->program) {
1762         YAGL_SET_ERR(GL_INVALID_OPERATION);
1763         goto out;
1764     }
1765
1766     if (location == -1) {
1767         goto out;
1768     }
1769
1770     if (location < 0) {
1771         YAGL_SET_ERR(GL_INVALID_OPERATION);
1772         goto out;
1773     }
1774
1775     if (!yagl_gles2_program_uniform3i(ctx->program, location, x, y, z)) {
1776         YAGL_SET_ERR(GL_INVALID_OPERATION);
1777         goto out;
1778     }
1779
1780 out:
1781     YAGL_LOG_FUNC_EXIT(NULL);
1782 }
1783
1784 YAGL_API void glUniform3iv(GLint location, GLsizei count, const GLint* v)
1785 {
1786     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform3iv, GLint, GLsizei, const GLint*, location, count, v);
1787
1788     YAGL_GET_CTX();
1789
1790     if (!ctx->program) {
1791         YAGL_SET_ERR(GL_INVALID_OPERATION);
1792         goto out;
1793     }
1794
1795     if (count < 0) {
1796         YAGL_SET_ERR(GL_INVALID_VALUE);
1797         goto out;
1798     }
1799
1800     if (location == -1) {
1801         goto out;
1802     }
1803
1804     if (location < 0) {
1805         YAGL_SET_ERR(GL_INVALID_OPERATION);
1806         goto out;
1807     }
1808
1809     if (!yagl_gles2_program_uniform3iv(ctx->program, location, count, v)) {
1810         YAGL_SET_ERR(GL_INVALID_OPERATION);
1811         goto out;
1812     }
1813
1814 out:
1815     YAGL_LOG_FUNC_EXIT(NULL);
1816 }
1817
1818 YAGL_API void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1819 {
1820     YAGL_LOG_FUNC_ENTER_SPLIT5(glUniform4f, GLint, GLfloat, GLfloat, GLfloat, GLfloat, location, x, y, z, w);
1821
1822     YAGL_GET_CTX();
1823
1824     if (!ctx->program) {
1825         YAGL_SET_ERR(GL_INVALID_OPERATION);
1826         goto out;
1827     }
1828
1829     if (location == -1) {
1830         goto out;
1831     }
1832
1833     if (location < 0) {
1834         YAGL_SET_ERR(GL_INVALID_OPERATION);
1835         goto out;
1836     }
1837
1838     if (!yagl_gles2_program_uniform4f(ctx->program, location, x, y, z, w)) {
1839         YAGL_SET_ERR(GL_INVALID_OPERATION);
1840         goto out;
1841     }
1842
1843 out:
1844     YAGL_LOG_FUNC_EXIT(NULL);
1845 }
1846
1847 YAGL_API void glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
1848 {
1849     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform4fv, GLint, GLsizei, const GLfloat*, location, count, v);
1850
1851     YAGL_GET_CTX();
1852
1853     if (!ctx->program) {
1854         YAGL_SET_ERR(GL_INVALID_OPERATION);
1855         goto out;
1856     }
1857
1858     if (count < 0) {
1859         YAGL_SET_ERR(GL_INVALID_VALUE);
1860         goto out;
1861     }
1862
1863     if (location == -1) {
1864         goto out;
1865     }
1866
1867     if (location < 0) {
1868         YAGL_SET_ERR(GL_INVALID_OPERATION);
1869         goto out;
1870     }
1871
1872     if (!yagl_gles2_program_uniform4fv(ctx->program, location, count, v)) {
1873         YAGL_SET_ERR(GL_INVALID_OPERATION);
1874         goto out;
1875     }
1876
1877 out:
1878     YAGL_LOG_FUNC_EXIT(NULL);
1879 }
1880
1881 YAGL_API void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
1882 {
1883     YAGL_LOG_FUNC_ENTER_SPLIT5(glUniform4i, GLint, GLint, GLint, GLint, GLint, location, x, y, z, w);
1884
1885     YAGL_GET_CTX();
1886
1887     if (!ctx->program) {
1888         YAGL_SET_ERR(GL_INVALID_OPERATION);
1889         goto out;
1890     }
1891
1892     if (location == -1) {
1893         goto out;
1894     }
1895
1896     if (location < 0) {
1897         YAGL_SET_ERR(GL_INVALID_OPERATION);
1898         goto out;
1899     }
1900
1901     if (!yagl_gles2_program_uniform4i(ctx->program, location, x, y, z, w)) {
1902         YAGL_SET_ERR(GL_INVALID_OPERATION);
1903         goto out;
1904     }
1905
1906 out:
1907     YAGL_LOG_FUNC_EXIT(NULL);
1908 }
1909
1910 YAGL_API void glUniform4iv(GLint location, GLsizei count, const GLint* v)
1911 {
1912     YAGL_LOG_FUNC_ENTER_SPLIT3(glUniform4iv, GLint, GLsizei, const GLint*, location, count, v);
1913
1914     YAGL_GET_CTX();
1915
1916     if (!ctx->program) {
1917         YAGL_SET_ERR(GL_INVALID_OPERATION);
1918         goto out;
1919     }
1920
1921     if (count < 0) {
1922         YAGL_SET_ERR(GL_INVALID_VALUE);
1923         goto out;
1924     }
1925
1926     if (location == -1) {
1927         goto out;
1928     }
1929
1930     if (location < 0) {
1931         YAGL_SET_ERR(GL_INVALID_OPERATION);
1932         goto out;
1933     }
1934
1935     if (!yagl_gles2_program_uniform4iv(ctx->program, location, count, v)) {
1936         YAGL_SET_ERR(GL_INVALID_OPERATION);
1937         goto out;
1938     }
1939
1940 out:
1941     YAGL_LOG_FUNC_EXIT(NULL);
1942 }
1943
1944 YAGL_API void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1945 {
1946     YAGL_LOG_FUNC_ENTER_SPLIT4(glUniformMatrix2fv, GLint, GLsizei, GLboolean, const GLfloat*, location, count, transpose, value);
1947
1948     YAGL_GET_CTX();
1949
1950     if (!ctx->program) {
1951         YAGL_SET_ERR(GL_INVALID_OPERATION);
1952         goto out;
1953     }
1954
1955     if (count < 0) {
1956         YAGL_SET_ERR(GL_INVALID_VALUE);
1957         goto out;
1958     }
1959
1960     if (location == -1) {
1961         goto out;
1962     }
1963
1964     if (location < 0) {
1965         YAGL_SET_ERR(GL_INVALID_OPERATION);
1966         goto out;
1967     }
1968
1969     if (!yagl_gles2_program_uniform_matrix2fv(ctx->program, location, count, transpose, value)) {
1970         YAGL_SET_ERR(GL_INVALID_OPERATION);
1971         goto out;
1972     }
1973
1974 out:
1975     YAGL_LOG_FUNC_EXIT(NULL);
1976 }
1977
1978 YAGL_API void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
1979 {
1980     YAGL_LOG_FUNC_ENTER_SPLIT4(glUniformMatrix3fv, GLint, GLsizei, GLboolean, const GLfloat*, location, count, transpose, value);
1981
1982     YAGL_GET_CTX();
1983
1984     if (!ctx->program) {
1985         YAGL_SET_ERR(GL_INVALID_OPERATION);
1986         goto out;
1987     }
1988
1989     if (count < 0) {
1990         YAGL_SET_ERR(GL_INVALID_VALUE);
1991         goto out;
1992     }
1993
1994     if (location == -1) {
1995         goto out;
1996     }
1997
1998     if (location < 0) {
1999         YAGL_SET_ERR(GL_INVALID_OPERATION);
2000         goto out;
2001     }
2002
2003     if (!yagl_gles2_program_uniform_matrix3fv(ctx->program, location, count, transpose, value)) {
2004         YAGL_SET_ERR(GL_INVALID_OPERATION);
2005         goto out;
2006     }
2007
2008 out:
2009     YAGL_LOG_FUNC_EXIT(NULL);
2010 }
2011
2012 YAGL_API void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2013 {
2014     YAGL_LOG_FUNC_ENTER_SPLIT4(glUniformMatrix4fv, GLint, GLsizei, GLboolean, const GLfloat*, location, count, transpose, value);
2015
2016     YAGL_GET_CTX();
2017
2018     if (!ctx->program) {
2019         YAGL_SET_ERR(GL_INVALID_OPERATION);
2020         goto out;
2021     }
2022
2023     if (count < 0) {
2024         YAGL_SET_ERR(GL_INVALID_VALUE);
2025         goto out;
2026     }
2027
2028     if (location == -1) {
2029         goto out;
2030     }
2031
2032     if (location < 0) {
2033         YAGL_SET_ERR(GL_INVALID_OPERATION);
2034         goto out;
2035     }
2036
2037     if (!yagl_gles2_program_uniform_matrix4fv(ctx->program, location, count, transpose, value)) {
2038         YAGL_SET_ERR(GL_INVALID_OPERATION);
2039         goto out;
2040     }
2041
2042 out:
2043     YAGL_LOG_FUNC_EXIT(NULL);
2044 }
2045
2046 YAGL_API void glUseProgram(GLuint program)
2047 {
2048     struct yagl_gles2_program *program_obj = NULL;
2049
2050     YAGL_LOG_FUNC_ENTER_SPLIT1(glUseProgram, GLuint, program);
2051
2052     YAGL_GET_CTX();
2053
2054     if (program != 0) {
2055         program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
2056             YAGL_NS_SHADER_PROGRAM, program);
2057
2058         if (!program_obj) {
2059             YAGL_SET_ERR(GL_INVALID_VALUE);
2060             goto out;
2061         }
2062
2063         if (program_obj->is_shader) {
2064             YAGL_SET_ERR(GL_INVALID_OPERATION);
2065             goto out;
2066         }
2067
2068         if (!program_obj->linked) {
2069             YAGL_SET_ERR(GL_INVALID_OPERATION);
2070             goto out;
2071         }
2072     }
2073
2074     if (!ctx->pre_use_program(ctx, program_obj)) {
2075         goto out;
2076     }
2077
2078     yagl_gles2_context_use_program(ctx, program_obj);
2079
2080 out:
2081     yagl_gles2_program_release(program_obj);
2082
2083     YAGL_LOG_FUNC_EXIT(NULL);
2084 }
2085
2086 YAGL_API void glValidateProgram(GLuint program)
2087 {
2088     struct yagl_gles2_program *program_obj = NULL;
2089
2090     YAGL_LOG_FUNC_ENTER_SPLIT1(glValidateProgram, GLuint, program);
2091
2092     YAGL_GET_CTX();
2093
2094     program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
2095         YAGL_NS_SHADER_PROGRAM, program);
2096
2097     if (!program_obj) {
2098         YAGL_SET_ERR(GL_INVALID_VALUE);
2099         goto out;
2100     }
2101
2102     if (program_obj->is_shader) {
2103         YAGL_SET_ERR(GL_INVALID_OPERATION);
2104         goto out;
2105     }
2106
2107     yagl_host_glValidateProgram(program_obj->global_name);
2108
2109 out:
2110     yagl_gles2_program_release(program_obj);
2111
2112     YAGL_LOG_FUNC_EXIT(NULL);
2113 }
2114
2115 YAGL_API void glVertexAttrib1f(GLuint indx, GLfloat x)
2116 {
2117     YAGL_LOG_FUNC_ENTER_SPLIT2(glVertexAttrib1f, GLuint, GLfloat, indx, x);
2118
2119     YAGL_GET_CTX();
2120
2121     if (indx == 0) {
2122         ctx->vertex_attrib0.value.f[0] = x;
2123         ctx->vertex_attrib0.value.f[1] = 0.0f;
2124         ctx->vertex_attrib0.value.f[2] = 0.0f;
2125         ctx->vertex_attrib0.value.f[3] = 1.0f;
2126         ctx->vertex_attrib0.type = GL_FLOAT;
2127     } else {
2128         yagl_host_glVertexAttrib1f(indx, x);
2129     }
2130
2131     YAGL_LOG_FUNC_EXIT(NULL);
2132 }
2133
2134 YAGL_API void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
2135 {
2136     YAGL_LOG_FUNC_ENTER_SPLIT2(glVertexAttrib1fv, GLuint, const GLfloat*, indx, values);
2137
2138     YAGL_GET_CTX();
2139
2140     if (indx == 0) {
2141         ctx->vertex_attrib0.value.f[0] = values[0];
2142         ctx->vertex_attrib0.value.f[1] = 0.0f;
2143         ctx->vertex_attrib0.value.f[2] = 0.0f;
2144         ctx->vertex_attrib0.value.f[3] = 1.0f;
2145         ctx->vertex_attrib0.type = GL_FLOAT;
2146     } else {
2147         yagl_host_glVertexAttrib1fv(indx, values, 1);
2148     }
2149
2150     YAGL_LOG_FUNC_EXIT(NULL);
2151 }
2152
2153 YAGL_API void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
2154 {
2155     YAGL_LOG_FUNC_ENTER_SPLIT3(glVertexAttrib2f, GLuint, GLfloat, GLfloat, indx, x, y);
2156
2157     YAGL_GET_CTX();
2158
2159     if (indx == 0) {
2160         ctx->vertex_attrib0.value.f[0] = x;
2161         ctx->vertex_attrib0.value.f[1] = y;
2162         ctx->vertex_attrib0.value.f[2] = 0.0f;
2163         ctx->vertex_attrib0.value.f[3] = 1.0f;
2164         ctx->vertex_attrib0.type = GL_FLOAT;
2165     } else {
2166         yagl_host_glVertexAttrib2f(indx, x, y);
2167     }
2168
2169     YAGL_LOG_FUNC_EXIT(NULL);
2170 }
2171
2172 YAGL_API void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
2173 {
2174     YAGL_LOG_FUNC_ENTER_SPLIT2(glVertexAttrib2fv, GLuint, const GLfloat*, indx, values);
2175
2176     YAGL_GET_CTX();
2177
2178     if (indx == 0) {
2179         ctx->vertex_attrib0.value.f[0] = values[0];
2180         ctx->vertex_attrib0.value.f[1] = values[1];
2181         ctx->vertex_attrib0.value.f[2] = 0.0f;
2182         ctx->vertex_attrib0.value.f[3] = 1.0f;
2183         ctx->vertex_attrib0.type = GL_FLOAT;
2184     } else {
2185         yagl_host_glVertexAttrib2fv(indx, values, 2);
2186     }
2187
2188     YAGL_LOG_FUNC_EXIT(NULL);
2189 }
2190
2191 YAGL_API void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
2192 {
2193     YAGL_LOG_FUNC_ENTER_SPLIT4(glVertexAttrib3f, GLuint, GLfloat, GLfloat, GLfloat, indx, x, y, z);
2194
2195     YAGL_GET_CTX();
2196
2197     if (indx == 0) {
2198         ctx->vertex_attrib0.value.f[0] = x;
2199         ctx->vertex_attrib0.value.f[1] = y;
2200         ctx->vertex_attrib0.value.f[2] = z;
2201         ctx->vertex_attrib0.value.f[3] = 1.0f;
2202         ctx->vertex_attrib0.type = GL_FLOAT;
2203     } else {
2204         yagl_host_glVertexAttrib3f(indx, x, y, z);
2205     }
2206
2207     YAGL_LOG_FUNC_EXIT(NULL);
2208 }
2209
2210 YAGL_API void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
2211 {
2212     YAGL_LOG_FUNC_ENTER_SPLIT2(glVertexAttrib3fv, GLuint, const GLfloat*, indx, values);
2213
2214     YAGL_GET_CTX();
2215
2216     if (indx == 0) {
2217         ctx->vertex_attrib0.value.f[0] = values[0];
2218         ctx->vertex_attrib0.value.f[1] = values[1];
2219         ctx->vertex_attrib0.value.f[2] = values[2];
2220         ctx->vertex_attrib0.value.f[3] = 1.0f;
2221         ctx->vertex_attrib0.type = GL_FLOAT;
2222     } else {
2223         yagl_host_glVertexAttrib3fv(indx, values, 3);
2224     }
2225
2226     YAGL_LOG_FUNC_EXIT(NULL);
2227 }
2228
2229 YAGL_API void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2230 {
2231     YAGL_LOG_FUNC_ENTER_SPLIT5(glVertexAttrib4f, GLuint, GLfloat, GLfloat, GLfloat, GLfloat, indx, x, y, z, w);
2232
2233     YAGL_GET_CTX();
2234
2235     if (indx == 0) {
2236         ctx->vertex_attrib0.value.f[0] = x;
2237         ctx->vertex_attrib0.value.f[1] = y;
2238         ctx->vertex_attrib0.value.f[2] = z;
2239         ctx->vertex_attrib0.value.f[3] = w;
2240         ctx->vertex_attrib0.type = GL_FLOAT;
2241     } else {
2242         yagl_host_glVertexAttrib4f(indx, x, y, z, w);
2243     }
2244
2245     YAGL_LOG_FUNC_EXIT(NULL);
2246 }
2247
2248 YAGL_API void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
2249 {
2250     YAGL_LOG_FUNC_ENTER_SPLIT2(glVertexAttrib4fv, GLuint, const GLfloat*, indx, values);
2251
2252     YAGL_GET_CTX();
2253
2254     if (indx == 0) {
2255         ctx->vertex_attrib0.value.f[0] = values[0];
2256         ctx->vertex_attrib0.value.f[1] = values[1];
2257         ctx->vertex_attrib0.value.f[2] = values[2];
2258         ctx->vertex_attrib0.value.f[3] = values[3];
2259         ctx->vertex_attrib0.type = GL_FLOAT;
2260     } else {
2261         yagl_host_glVertexAttrib4fv(indx, values, 4);
2262     }
2263
2264     YAGL_LOG_FUNC_EXIT(NULL);
2265 }
2266
2267 YAGL_API void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
2268 {
2269     struct yagl_gles_array *array;
2270
2271     YAGL_LOG_FUNC_ENTER_SPLIT6(glVertexAttribPointer, GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*, indx, size, type, normalized, stride, ptr);
2272
2273     YAGL_GET_CTX();
2274
2275     if (indx >= ctx->base.num_arrays) {
2276         YAGL_SET_ERR(GL_INVALID_VALUE);
2277         goto out;
2278     }
2279
2280     if ((stride < 0) || (size < 1) || (size > 4)) {
2281         YAGL_SET_ERR(GL_INVALID_VALUE);
2282         goto out;
2283     }
2284
2285     if ((type == GL_INT_2_10_10_10_REV) ||
2286         (type == GL_UNSIGNED_INT_2_10_10_10_REV)) {
2287         if (ctx->base.base.client_api == yagl_client_api_gles2) {
2288             YAGL_SET_ERR(GL_INVALID_ENUM);
2289             goto out;
2290         } else if (size != 4) {
2291             YAGL_SET_ERR(GL_INVALID_OPERATION);
2292             goto out;
2293         }
2294     }
2295
2296     array = &ctx->base.vao->arrays[indx];
2297
2298     if (ctx->base.vbo) {
2299         if (!yagl_gles_array_update_vbo(array,
2300                                         size,
2301                                         type,
2302                                         0,
2303                                         normalized,
2304                                         stride,
2305                                         ctx->base.vbo,
2306                                         (GLint)ptr,
2307                                         0)) {
2308             YAGL_SET_ERR(GL_INVALID_ENUM);
2309         }
2310     } else {
2311         /*
2312          * GL_OES_vertex_array_object:
2313          * "Binding a zero-named vertex array buffer:
2314          * this can be detected by *Pointer(ES1) or VertexAttribPointer(ES2);
2315          * if the pointer argument is not NULL:
2316          * this means to bind a client vertex array;
2317          * an INVALID_OPERATION error will be returned."
2318          */
2319         if ((ctx->base.vao != ctx->base.va_zero) && ptr) {
2320             YAGL_SET_ERR(GL_INVALID_OPERATION);
2321             goto out;
2322         }
2323
2324         if (!yagl_gles_array_update(array,
2325                                     size,
2326                                     type,
2327                                     0,
2328                                     normalized,
2329                                     stride,
2330                                     ptr,
2331                                     0)) {
2332             YAGL_SET_ERR(GL_INVALID_ENUM);
2333         }
2334     }
2335
2336 out:
2337     YAGL_LOG_FUNC_EXIT(NULL);
2338 }
2339
2340 /*
2341  * GL_EXT_instanced_arrays.
2342  * @{
2343  */
2344
2345 YAGL_API void glDrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
2346                                     GLsizei primcount)
2347 {
2348     YAGL_LOG_FUNC_ENTER_SPLIT4(glDrawArraysInstanced, GLenum, GLint, GLsizei, GLsizei, mode, start, count, primcount);
2349
2350     YAGL_GET_CTX();
2351
2352     if (!ctx->instanced_arrays) {
2353         YAGL_SET_ERR(GL_INVALID_OPERATION);
2354         goto out;
2355     }
2356
2357     if (primcount < 0) {
2358         YAGL_SET_ERR(GL_INVALID_VALUE);
2359         goto out;
2360     }
2361
2362     yagl_gles_context_draw_arrays(&ctx->base, mode, start, count, primcount);
2363
2364 out:
2365     YAGL_LOG_FUNC_EXIT(NULL);
2366 }
2367 YAGL_API YAGL_ALIAS(glDrawArraysInstanced, glDrawArraysInstancedEXT);
2368
2369 YAGL_API void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
2370                                       const void *indices, GLsizei primcount)
2371 {
2372     YAGL_LOG_FUNC_ENTER_SPLIT5(glDrawElementsInstanced, GLenum, GLsizei, GLenum, const void*, GLsizei, mode, count, type, indices, primcount);
2373
2374     YAGL_GET_CTX();
2375
2376     if (!ctx->instanced_arrays) {
2377         YAGL_SET_ERR(GL_INVALID_OPERATION);
2378         goto out;
2379     }
2380
2381     if (primcount < 0) {
2382         YAGL_SET_ERR(GL_INVALID_VALUE);
2383         goto out;
2384     }
2385
2386     yagl_gles_context_draw_elements(&ctx->base, mode, count, type, indices, primcount);
2387
2388 out:
2389     YAGL_LOG_FUNC_EXIT(NULL);
2390 }
2391 YAGL_API YAGL_ALIAS(glDrawElementsInstanced, glDrawElementsInstancedEXT);
2392
2393 YAGL_API void glVertexAttribDivisor(GLuint index, GLuint divisor)
2394 {
2395     struct yagl_gles_array *array;
2396
2397     YAGL_LOG_FUNC_ENTER_SPLIT2(glVertexAttribDivisor, GLuint, GLuint, index, divisor);
2398
2399     YAGL_GET_CTX();
2400
2401     if (!ctx->instanced_arrays) {
2402         YAGL_SET_ERR(GL_INVALID_OPERATION);
2403         goto out;
2404     }
2405
2406     if (index >= ctx->base.num_arrays) {
2407         YAGL_SET_ERR(GL_INVALID_VALUE);
2408         goto out;
2409     }
2410
2411     array = &ctx->base.vao->arrays[index];
2412
2413     yagl_gles_array_set_divisor(array, divisor);
2414
2415 out:
2416     YAGL_LOG_FUNC_EXIT(NULL);
2417 }
2418 YAGL_API YAGL_ALIAS(glVertexAttribDivisor, glVertexAttribDivisorEXT);
2419
2420 /*
2421  * @}
2422  */
2423
2424 /*
2425  * GL_OES_texture_3D.
2426  * @{
2427  */
2428
2429 YAGL_API void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)
2430 {
2431     yagl_gles_texture_target texture_target;
2432     struct yagl_gles_texture_target_state *tex_target_state;
2433     struct yagl_pixel_format *pf;
2434     GLsizei size;
2435     int using_pbo = 0;
2436
2437     YAGL_LOG_FUNC_ENTER_SPLIT10(glTexImage3D, GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void*, target, level, internalformat, width, height, depth, border, format, type, pixels);
2438
2439     YAGL_GET_CTX();
2440
2441     if (!yagl_gles_context_validate_texture_target(&ctx->base,
2442                                                    target,
2443                                                    &texture_target)) {
2444         YAGL_SET_ERR(GL_INVALID_ENUM);
2445         goto out;
2446     }
2447
2448     if (!yagl_gles2_is_texture_target_layered(target)) {
2449         YAGL_SET_ERR(GL_INVALID_ENUM);
2450         goto out;
2451     }
2452
2453     tex_target_state =
2454         yagl_gles_context_get_active_texture_target_state(&ctx->base,
2455                                                           texture_target);
2456
2457     if ((width < 0) || (height < 0) || (depth < 0)) {
2458         YAGL_SET_ERR(GL_INVALID_VALUE);
2459         goto out;
2460     }
2461
2462     if ((width == 0) || (height == 0) || (depth == 0)) {
2463         width = height = depth = 0;
2464     }
2465
2466     pf = yagl_gles_context_validate_teximage_format(&ctx->base,
2467                                                     internalformat,
2468                                                     format,
2469                                                     type);
2470
2471     if (!pf) {
2472         YAGL_SET_ERR(GL_INVALID_OPERATION);
2473         goto out;
2474     }
2475
2476     if ((texture_target == yagl_gles_texture_target_3d) &&
2477         ((pf->src_format == GL_DEPTH_COMPONENT) ||
2478          (pf->src_format == GL_DEPTH_STENCIL_OES))) {
2479         YAGL_SET_ERR(GL_INVALID_OPERATION);
2480         goto out;
2481     }
2482
2483     if ((width != 0) && !yagl_gles_context_pre_unpack(&ctx->base, &pixels, pf->need_convert, &using_pbo)) {
2484         YAGL_SET_ERR(GL_INVALID_OPERATION);
2485         goto out;
2486     }
2487
2488     if (pixels || using_pbo) {
2489         pixels += yagl_pixel_format_get_info(pf, &ctx->base.unpack,
2490                                              width, height, depth, &size);
2491     } else {
2492         yagl_pixel_format_get_info(pf, &ctx->base.unpack,
2493                                    width, height, depth, &size);
2494     }
2495
2496     if (using_pbo) {
2497         yagl_host_glTexImage3DOffset(target,
2498                                      level,
2499                                      pf->dst_internalformat,
2500                                      width,
2501                                      height,
2502                                      depth,
2503                                      border,
2504                                      pf->dst_format,
2505                                      pf->dst_type,
2506                                      (GLsizei)pixels);
2507     } else {
2508         yagl_host_glTexImage3DData(target,
2509                                    level,
2510                                    pf->dst_internalformat,
2511                                    width,
2512                                    height,
2513                                    depth,
2514                                    border,
2515                                    pf->dst_format,
2516                                    pf->dst_type,
2517                                    yagl_pixel_format_unpack(pf,
2518                                                             &ctx->base.unpack,
2519                                                             width,
2520                                                             height,
2521                                                             depth,
2522                                                             pixels),
2523                                    size);
2524     }
2525
2526     if (width != 0) {
2527         yagl_gles_context_post_unpack(&ctx->base, pf->need_convert);
2528     }
2529
2530     yagl_gles_texture_set_internalformat(tex_target_state->texture,
2531                                          internalformat,
2532                                          type,
2533                                          yagl_gles_context_convert_textures(&ctx->base));
2534
2535 out:
2536     YAGL_LOG_FUNC_EXIT(NULL);
2537 }
2538 YAGL_API YAGL_ALIAS(glTexImage3D, glTexImage3DOES);
2539
2540 YAGL_API void glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)
2541 {
2542     yagl_gles_texture_target texture_target;
2543     struct yagl_gles_texture_target_state *tex_target_state;
2544     struct yagl_pixel_format *pf;
2545     GLsizei size;
2546     int using_pbo = 0;
2547
2548     YAGL_LOG_FUNC_ENTER_SPLIT11(glTexSubImage3D, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void*, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
2549
2550     YAGL_GET_CTX();
2551
2552     if (!yagl_gles_context_validate_texture_target(&ctx->base,
2553                                                    target,
2554                                                    &texture_target)) {
2555         YAGL_SET_ERR(GL_INVALID_ENUM);
2556         goto out;
2557     }
2558
2559     if (!yagl_gles2_is_texture_target_layered(target)) {
2560         YAGL_SET_ERR(GL_INVALID_ENUM);
2561         goto out;
2562     }
2563
2564     tex_target_state =
2565         yagl_gles_context_get_active_texture_target_state(&ctx->base,
2566                                                           texture_target);
2567
2568     if ((width < 0) || (height < 0) || (depth < 0)) {
2569         YAGL_SET_ERR(GL_INVALID_VALUE);
2570         goto out;
2571     }
2572
2573     if ((width == 0) || (height == 0) || (depth == 0)) {
2574         width = height = depth = 0;
2575     }
2576
2577     pf = yagl_gles_context_validate_teximage_format(&ctx->base,
2578         tex_target_state->texture->internalformat, format, type);
2579
2580     if (!pf) {
2581         YAGL_SET_ERR(GL_INVALID_OPERATION);
2582         goto out;
2583     }
2584
2585     if ((width != 0) && !yagl_gles_context_pre_unpack(&ctx->base, &pixels, pf->need_convert, &using_pbo)) {
2586         YAGL_SET_ERR(GL_INVALID_OPERATION);
2587         goto out;
2588     }
2589
2590     pixels += yagl_pixel_format_get_info(pf, &ctx->base.unpack,
2591                                          width, height, depth, &size);
2592
2593     if (using_pbo) {
2594         yagl_host_glTexSubImage3DOffset(target,
2595                                         level,
2596                                         xoffset,
2597                                         yoffset,
2598                                         zoffset,
2599                                         width,
2600                                         height,
2601                                         depth,
2602                                         pf->dst_format,
2603                                         pf->dst_type,
2604                                         (GLsizei)pixels);
2605     } else {
2606         yagl_host_glTexSubImage3DData(target,
2607                                       level,
2608                                       xoffset,
2609                                       yoffset,
2610                                       zoffset,
2611                                       width,
2612                                       height,
2613                                       depth,
2614                                       pf->dst_format,
2615                                       pf->dst_type,
2616                                       yagl_pixel_format_unpack(pf,
2617                                                                &ctx->base.unpack,
2618                                                                width,
2619                                                                height,
2620                                                                depth,
2621                                                                pixels),
2622                                       size);
2623     }
2624
2625     if (width != 0) {
2626         yagl_gles_context_post_unpack(&ctx->base, pf->need_convert);
2627     }
2628
2629 out:
2630     YAGL_LOG_FUNC_EXIT(NULL);
2631 }
2632 YAGL_API YAGL_ALIAS(glTexSubImage3D, glTexSubImage3DOES);
2633
2634 YAGL_API void glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
2635 {
2636     yagl_gles_texture_target texture_target;
2637
2638     YAGL_LOG_FUNC_ENTER_SPLIT9(glCopyTexSubImage3D, GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, target, level, xoffset, yoffset, zoffset, x, y, width, height);
2639
2640     YAGL_GET_CTX();
2641
2642     if (!yagl_gles_context_validate_texture_target(&ctx->base,
2643                                                    target,
2644                                                    &texture_target)) {
2645         YAGL_SET_ERR(GL_INVALID_ENUM);
2646         goto out;
2647     }
2648
2649     if (!yagl_gles2_is_texture_target_layered(target)) {
2650         YAGL_SET_ERR(GL_INVALID_ENUM);
2651         goto out;
2652     }
2653
2654     yagl_host_glCopyTexSubImage3D(target,
2655                                   level,
2656                                   xoffset,
2657                                   yoffset,
2658                                   zoffset,
2659                                   x,
2660                                   y,
2661                                   width,
2662                                   height);
2663
2664 out:
2665     YAGL_LOG_FUNC_EXIT(NULL);
2666 }
2667 YAGL_API YAGL_ALIAS(glCopyTexSubImage3D, glCopyTexSubImage3DOES);
2668
2669 YAGL_API void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
2670 {
2671     yagl_gles_texture_target texture_target;
2672     struct yagl_gles_texture_target_state *tex_target_state;
2673     int using_pbo = 0;
2674
2675     YAGL_LOG_FUNC_ENTER_SPLIT9(glCompressedTexImage3D, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*, target, level, internalformat, width, height, depth, border, imageSize, data);
2676
2677     YAGL_GET_CTX();
2678
2679     if (!yagl_gles_context_validate_texture_target(&ctx->base,
2680                                                    target,
2681                                                    &texture_target)) {
2682         YAGL_SET_ERR(GL_INVALID_ENUM);
2683         goto out;
2684     }
2685
2686     if (!yagl_gles2_is_texture_target_layered(target)) {
2687         YAGL_SET_ERR(GL_INVALID_ENUM);
2688         goto out;
2689     }
2690
2691     tex_target_state =
2692         yagl_gles_context_get_active_texture_target_state(&ctx->base,
2693                                                           texture_target);
2694
2695     if ((width < 0) || (height < 0) || (depth < 0)) {
2696         YAGL_SET_ERR(GL_INVALID_VALUE);
2697         goto out;
2698     }
2699
2700     if ((width == 0) || (height == 0) || (depth == 0)) {
2701         width = height = depth = 0;
2702     }
2703
2704     if ((width != 0) && !yagl_gles_context_pre_unpack(&ctx->base, &data, 1, &using_pbo)) {
2705         YAGL_SET_ERR(GL_INVALID_OPERATION);
2706         goto out;
2707     }
2708
2709     assert(!using_pbo);
2710
2711     yagl_gles2_context_compressed_tex_image_3d(ctx,
2712                                                target,
2713                                                tex_target_state->texture,
2714                                                level,
2715                                                internalformat,
2716                                                width,
2717                                                height,
2718                                                depth,
2719                                                border,
2720                                                imageSize,
2721                                                data);
2722
2723     if (width != 0) {
2724         yagl_gles_context_post_unpack(&ctx->base, 1);
2725     }
2726
2727 out:
2728     YAGL_LOG_FUNC_EXIT(NULL);
2729 }
2730 YAGL_API YAGL_ALIAS(glCompressedTexImage3D, glCompressedTexImage3DOES);
2731
2732 YAGL_API void glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
2733 {
2734     yagl_gles_texture_target texture_target;
2735     int using_pbo = 0;
2736
2737     YAGL_LOG_FUNC_ENTER_SPLIT11(glCompressedTexSubImage3D, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
2738
2739     YAGL_GET_CTX();
2740
2741     if (!yagl_gles_context_validate_texture_target(&ctx->base,
2742                                                    target,
2743                                                    &texture_target)) {
2744         YAGL_SET_ERR(GL_INVALID_ENUM);
2745         goto out;
2746     }
2747
2748     if (!yagl_gles2_is_texture_target_layered(target)) {
2749         YAGL_SET_ERR(GL_INVALID_ENUM);
2750         goto out;
2751     }
2752
2753     if ((width < 0) || (height < 0) || (depth < 0)) {
2754         YAGL_SET_ERR(GL_INVALID_VALUE);
2755         goto out;
2756     }
2757
2758     if ((width == 0) || (height == 0) || (depth == 0)) {
2759         width = height = depth = 0;
2760     }
2761
2762     if ((width != 0) && !yagl_gles_context_pre_unpack(&ctx->base, &data, 1, &using_pbo)) {
2763         YAGL_SET_ERR(GL_INVALID_OPERATION);
2764         goto out;
2765     }
2766
2767     assert(!using_pbo);
2768
2769     yagl_gles2_context_compressed_tex_sub_image_3d(ctx,
2770                                                    target,
2771                                                    level,
2772                                                    xoffset,
2773                                                    yoffset,
2774                                                    zoffset,
2775                                                    width,
2776                                                    height,
2777                                                    depth,
2778                                                    format,
2779                                                    imageSize,
2780                                                    data);
2781
2782     if (width != 0) {
2783         yagl_gles_context_post_unpack(&ctx->base, 1);
2784     }
2785
2786 out:
2787     YAGL_LOG_FUNC_EXIT(NULL);
2788 }
2789 YAGL_API YAGL_ALIAS(glCompressedTexSubImage3D, glCompressedTexSubImage3DOES);
2790
2791 YAGL_API void glFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
2792 {
2793     fprintf(stderr, "glFramebufferTexture3D not supported in YaGL\n");
2794 }
2795 YAGL_API YAGL_ALIAS(glFramebufferTexture3D, glFramebufferTexture3DOES);
2796
2797 /*
2798  * @}
2799  */
2800
2801 /*
2802  * GL_EXT_texture_storage.
2803  * @{
2804  */
2805
2806 YAGL_API void glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
2807 {
2808     yagl_gles_texture_target texture_target;
2809     struct yagl_gles_texture_target_state *tex_target_state;
2810     GLenum base_internalformat, format, type;
2811     GLsizei i;
2812
2813     YAGL_LOG_FUNC_ENTER_SPLIT6(glTexStorage3D, GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, target, levels, internalformat, width, height, depth);
2814
2815     YAGL_GET_CTX();
2816
2817     if ((levels <= 0) || (width <= 0) || (height <= 0)) {
2818         YAGL_SET_ERR(GL_INVALID_VALUE);
2819         goto out;
2820     }
2821
2822     if (!yagl_gles_context_validate_texstorage_format(&ctx->base,
2823                                                       &internalformat,
2824                                                       &base_internalformat,
2825                                                       &format,
2826                                                       &type)) {
2827         YAGL_SET_ERR(GL_INVALID_ENUM);
2828         goto out;
2829     }
2830
2831     if (!yagl_gles_context_validate_texture_target(&ctx->base, target, &texture_target)) {
2832         YAGL_SET_ERR(GL_INVALID_ENUM);
2833         goto out;
2834     }
2835
2836     tex_target_state = yagl_gles_context_get_active_texture_target_state(&ctx->base,
2837                                                                          texture_target);
2838
2839     if ((tex_target_state->texture == tex_target_state->texture_zero) ||
2840         tex_target_state->texture->immutable) {
2841         YAGL_SET_ERR(GL_INVALID_OPERATION);
2842         goto out;
2843     }
2844
2845     if ((texture_target == yagl_gles_texture_target_3d) &&
2846         ((format == GL_DEPTH_COMPONENT) ||
2847          (format == GL_DEPTH_STENCIL_OES))) {
2848         YAGL_SET_ERR(GL_INVALID_OPERATION);
2849         goto out;
2850     }
2851
2852     switch (texture_target) {
2853     case yagl_gles_texture_target_3d:
2854         for (i = 0; i < levels; ++i) {
2855             yagl_host_glTexImage3DData(target, i, internalformat,
2856                                        width, height, depth, 0, format, type,
2857                                        NULL, 0);
2858
2859             width >>= 1;
2860             if (width == 0) {
2861                 width = 1;
2862             }
2863
2864             height >>= 1;
2865             if (height == 0) {
2866                 height = 1;
2867             }
2868
2869             depth >>= 1;
2870             if (depth == 0) {
2871                 depth = 1;
2872             }
2873         }
2874         break;
2875     case yagl_gles_texture_target_2d_array:
2876         for (i = 0; i < levels; ++i) {
2877             yagl_host_glTexImage3DData(target, i, internalformat,
2878                                        width, height, depth, 0, format, type,
2879                                        NULL, 0);
2880
2881             width >>= 1;
2882             if (width == 0) {
2883                 width = 1;
2884             }
2885
2886             height >>= 1;
2887             if (height == 0) {
2888                 height = 1;
2889             }
2890         }
2891         break;
2892     default:
2893         YAGL_SET_ERR(GL_INVALID_ENUM);
2894         goto out;
2895     }
2896
2897     yagl_gles_texture_set_immutable(tex_target_state->texture,
2898                                     base_internalformat,
2899                                     type,
2900                                     yagl_gles_context_convert_textures(&ctx->base));
2901
2902 out:
2903     YAGL_LOG_FUNC_EXIT(NULL);
2904 }
2905 YAGL_API YAGL_ALIAS(glTexStorage3D, glTexStorage3DEXT);
2906
2907 /*
2908  * @}
2909  */