tizen 2.4 release
[sdk/emulator-yagl.git] / GLES_common / yagl_gles_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 "GL/gl.h"
35 #include "GL/glext.h"
36 #include "yagl_gles_calls.h"
37 #include "yagl_host_gles_calls.h"
38 #include "yagl_impl.h"
39 #include "yagl_malloc.h"
40 #include "yagl_render.h"
41 #include "yagl_utils.h"
42 #include "yagl_sharegroup.h"
43 #include "yagl_state.h"
44 #include "yagl_pixel_format.h"
45 #include "yagl_gles_context.h"
46 #include "yagl_gles_vertex_array.h"
47 #include "yagl_gles_buffer.h"
48 #include "yagl_gles_texture.h"
49 #include "yagl_gles_texture_unit.h"
50 #include "yagl_gles_framebuffer.h"
51 #include "yagl_gles_renderbuffer.h"
52 #include "yagl_gles_image.h"
53 #include "yagl_gles_array.h"
54 #include "yagl_gles_validate.h"
55 #include "yagl_gles_utils.h"
56 #include <errno.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <assert.h>
61
62 #define YAGL_SET_ERR(err) \
63     yagl_gles_context_set_error(ctx, err); \
64     YAGL_LOG_ERROR("error = 0x%X", err)
65
66 #define YAGL_GET_CTX_IMPL(ret_expr) \
67     struct yagl_gles_context *ctx = \
68         (struct yagl_gles_context*)yagl_get_client_context(); \
69     if (!ctx) { \
70         YAGL_LOG_WARN("no current context"); \
71         YAGL_LOG_FUNC_EXIT(NULL); \
72         ret_expr; \
73     }
74
75 #define YAGL_GET_CTX_RET(ret) YAGL_GET_CTX_IMPL(return ret)
76
77 #define YAGL_GET_CTX() YAGL_GET_CTX_IMPL(return)
78
79 YAGL_API void glClearStencil(GLint s)
80 {
81     YAGL_LOG_FUNC_ENTER_SPLIT1(glClearStencil, GLint, s);
82
83     YAGL_GET_CTX();
84
85     ctx->clear_stencil = s;
86
87     yagl_host_glClearStencil(s);
88
89     YAGL_LOG_FUNC_EXIT(NULL);
90 }
91
92 YAGL_API void glHint(GLenum target, GLenum mode)
93 {
94     YAGL_LOG_FUNC_ENTER_SPLIT2(glHint, GLenum, GLenum, target, mode);
95
96     YAGL_GET_CTX();
97
98     if (yagl_gles_is_hint_mode_valid(mode)) {
99         yagl_gles_context_hint(ctx, target, mode);
100     } else {
101         YAGL_SET_ERR(GL_INVALID_ENUM);
102     }
103
104     YAGL_LOG_FUNC_EXIT(NULL);
105 }
106
107 YAGL_API void glLineWidth(GLfloat width)
108 {
109     YAGL_LOG_FUNC_ENTER_SPLIT1(glLineWidth, GLfloat, width);
110
111     YAGL_GET_CTX();
112
113     yagl_gles_context_line_width(ctx, width);
114
115     YAGL_LOG_FUNC_EXIT(NULL);
116 }
117
118 YAGL_API void glPolygonOffset(GLfloat factor, GLfloat units)
119 {
120     YAGL_LOG_FUNC_ENTER_SPLIT2(glPolygonOffset, GLfloat, GLfloat, factor, units);
121
122     YAGL_GET_CTX();
123
124     yagl_gles_context_polygon_offset(ctx, factor, units);
125
126     YAGL_LOG_FUNC_EXIT(NULL);
127 }
128
129 void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
130 {
131     GLenum actual_internalformat = internalformat;
132     struct yagl_gles_renderbuffer *renderbuffer_obj = NULL;
133
134     YAGL_LOG_FUNC_ENTER_SPLIT4(glRenderbufferStorage, GLenum, GLenum, GLsizei, GLsizei, target, internalformat, width, height);
135
136     YAGL_GET_CTX();
137
138     if (!yagl_gles_context_validate_renderbuffer_format(ctx, &actual_internalformat)) {
139         YAGL_SET_ERR(GL_INVALID_ENUM);
140         goto out;
141     }
142
143     if (!yagl_gles_context_acquire_binded_renderbuffer(ctx, target, &renderbuffer_obj)) {
144         YAGL_SET_ERR(GL_INVALID_ENUM);
145         goto out;
146     }
147
148     if (!renderbuffer_obj) {
149         goto out;
150     }
151
152     yagl_gles_renderbuffer_set_internalformat(renderbuffer_obj, internalformat);
153
154     yagl_host_glRenderbufferStorage(target, actual_internalformat, width, height);
155
156 out:
157     yagl_gles_renderbuffer_release(renderbuffer_obj);
158
159     YAGL_LOG_FUNC_EXIT(NULL);
160 }
161
162 YAGL_API void glSampleCoverage(GLclampf value, GLboolean invert)
163 {
164     YAGL_LOG_FUNC_ENTER_SPLIT2(glSampleCoverage, GLclampf, GLboolean, value, invert);
165
166     YAGL_GET_CTX();
167
168     yagl_gles_context_sample_coverage(ctx, value, invert);
169
170     YAGL_LOG_FUNC_EXIT(NULL);
171 }
172
173 YAGL_API void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
174 {
175     YAGL_LOG_FUNC_ENTER_SPLIT4(glScissor, GLint, GLint, GLsizei, GLsizei, x, y, width, height);
176
177     YAGL_GET_CTX();
178
179     if ((width < 0) || (height < 0)) {
180         YAGL_SET_ERR(GL_INVALID_VALUE);
181         goto out;
182     }
183
184     yagl_render_invalidate(0);
185
186     ctx->have_scissor_box = 1;
187     ctx->scissor_box[0] = x;
188     ctx->scissor_box[1] = y;
189     ctx->scissor_box[2] = width;
190     ctx->scissor_box[3] = height;
191
192     yagl_host_glScissor(x, y, width, height);
193
194 out:
195     YAGL_LOG_FUNC_EXIT(NULL);
196 }
197
198 YAGL_API void glStencilFunc(GLenum func, GLint ref, GLuint mask)
199 {
200     YAGL_LOG_FUNC_ENTER_SPLIT3(glStencilFunc, GLenum, GLint, GLuint, func, ref, mask);
201
202     YAGL_GET_CTX();
203
204     if (yagl_gles_is_stencil_func_valid(func)) {
205         ctx->stencil_front.func = func;
206         ctx->stencil_front.ref = ref;
207         ctx->stencil_front.mask = mask;
208
209         ctx->stencil_back.func = func;
210         ctx->stencil_back.ref = ref;
211         ctx->stencil_back.mask = mask;
212
213         yagl_host_glStencilFunc(func, ref, mask);
214     } else {
215         YAGL_SET_ERR(GL_INVALID_ENUM);
216     }
217
218     YAGL_LOG_FUNC_EXIT(NULL);
219 }
220
221 YAGL_API void glStencilMask(GLuint mask)
222 {
223     YAGL_LOG_FUNC_ENTER_SPLIT1(glStencilMask, GLuint, mask);
224
225     YAGL_GET_CTX();
226
227     ctx->stencil_front.writemask = mask;
228     ctx->stencil_back.writemask = mask;
229
230     yagl_host_glStencilMask(mask);
231
232     YAGL_LOG_FUNC_EXIT(NULL);
233 }
234
235 YAGL_API void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
236 {
237     YAGL_LOG_FUNC_ENTER_SPLIT3(glStencilOp, GLenum, GLenum, GLenum, fail, zfail, zpass);
238
239     YAGL_GET_CTX();
240
241     if (yagl_gles_is_stencil_op_valid(fail) &&
242         yagl_gles_is_stencil_op_valid(zfail) &&
243         yagl_gles_is_stencil_op_valid(zpass)) {
244         ctx->stencil_front.fail = fail;
245         ctx->stencil_front.zfail = zfail;
246         ctx->stencil_front.zpass = zpass;
247
248         ctx->stencil_back.fail = fail;
249         ctx->stencil_back.zfail = zfail;
250         ctx->stencil_back.zpass = zpass;
251
252         yagl_host_glStencilOp(fail, zfail, zpass);
253     } else {
254         YAGL_SET_ERR(GL_INVALID_ENUM);
255     }
256
257     YAGL_LOG_FUNC_EXIT(NULL);
258 }
259
260 YAGL_API void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
261 {
262     YAGL_LOG_FUNC_ENTER_SPLIT3(glTexParameterf, GLenum, GLenum, GLfloat, target, pname, param);
263
264     YAGL_GET_CTX();
265
266     yagl_gles_context_tex_parameterf(ctx, target, pname, param);
267
268     YAGL_LOG_FUNC_EXIT(NULL);
269 }
270
271 YAGL_API void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
272 {
273     YAGL_LOG_FUNC_ENTER_SPLIT3(glTexParameterfv, GLenum, GLenum, const GLfloat*, target, pname, params);
274
275     YAGL_GET_CTX();
276
277     yagl_gles_context_tex_parameterfv(ctx, target, pname, params);
278
279     YAGL_LOG_FUNC_EXIT(NULL);
280 }
281
282 YAGL_API void glTexParameteri(GLenum target, GLenum pname, GLint param)
283 {
284     yagl_gles_texture_target texture_target;
285     struct yagl_gles_texture_target_state *tex_target_state;
286
287     YAGL_LOG_FUNC_ENTER_SPLIT3(glTexParameteri, GLenum, GLenum, GLint, target, pname, param);
288
289     YAGL_GET_CTX();
290
291     if (!yagl_gles_context_validate_texture_target(ctx,
292                                                    target,
293                                                    &texture_target)) {
294         YAGL_SET_ERR(GL_INVALID_ENUM);
295         goto out;
296     }
297
298     tex_target_state =
299         yagl_gles_context_get_active_texture_target_state(ctx, texture_target);
300
301     if (pname == GL_TEXTURE_MIN_FILTER) {
302         tex_target_state->texture->min_filter = param;
303     } else if (pname == GL_TEXTURE_MAG_FILTER) {
304         tex_target_state->texture->mag_filter = param;
305     }
306
307     yagl_host_glTexParameteri(target, pname, param);
308
309 out:
310     YAGL_LOG_FUNC_EXIT(NULL);
311 }
312
313 YAGL_API void glTexParameteriv(GLenum target, GLenum pname, const GLint *params)
314 {
315     yagl_gles_texture_target texture_target;
316     struct yagl_gles_texture_target_state *tex_target_state;
317
318     YAGL_LOG_FUNC_ENTER_SPLIT3(glTexParameteriv, GLenum, GLenum, const GLint*, target, pname, params);
319
320     YAGL_GET_CTX();
321
322     if (!yagl_gles_context_validate_texture_target(ctx,
323                                                    target,
324                                                    &texture_target)) {
325         YAGL_SET_ERR(GL_INVALID_ENUM);
326         goto out;
327     }
328
329     tex_target_state =
330         yagl_gles_context_get_active_texture_target_state(ctx, texture_target);
331
332     if (pname == GL_TEXTURE_MIN_FILTER) {
333         tex_target_state->texture->min_filter = params[0];
334     } else if (pname == GL_TEXTURE_MAG_FILTER) {
335         tex_target_state->texture->mag_filter = params[0];
336     }
337
338     yagl_host_glTexParameteriv(target, pname, params, 1);
339
340 out:
341     YAGL_LOG_FUNC_EXIT(NULL);
342 }
343
344 YAGL_API void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
345 {
346     YAGL_LOG_FUNC_ENTER_SPLIT4(glViewport, GLint, GLint, GLsizei, GLsizei, x, y, width, height);
347
348     YAGL_GET_CTX();
349
350     if ((width < 0) || (height < 0)) {
351         YAGL_SET_ERR(GL_INVALID_VALUE);
352         goto out;
353     }
354
355     yagl_render_invalidate(0);
356
357     ctx->have_viewport = 1;
358     ctx->viewport[0] = x;
359     ctx->viewport[1] = y;
360     ctx->viewport[2] = width;
361     ctx->viewport[3] = height;
362
363     yagl_host_glViewport(x, y, width, height);
364
365 out:
366     YAGL_LOG_FUNC_EXIT(NULL);
367 }
368
369 YAGL_API const GLubyte *glGetString(GLenum name)
370 {
371     struct yagl_gles_context *ctx;
372     const char *str = NULL;
373
374     YAGL_LOG_FUNC_ENTER(glGetString, "name = 0x%X", name);
375
376     ctx = (struct yagl_gles_context*)yagl_get_client_context();
377
378     switch (name) {
379     case GL_VENDOR:
380         str = "Samsung";
381         break;
382     case GL_EXTENSIONS:
383         if (ctx) {
384             str = ctx->extension_string;
385         } else {
386             str = "";
387         }
388         break;
389     default:
390         if (ctx) {
391             str = ctx->get_string(ctx, name);
392         } else {
393             str = "";
394         }
395     }
396
397     YAGL_LOG_FUNC_EXIT("%s", str);
398
399     return (const GLubyte*)str;
400 }
401
402 YAGL_API void glActiveTexture(GLenum texture)
403 {
404     YAGL_LOG_FUNC_ENTER_SPLIT1(glActiveTexture, GLenum, texture);
405
406     YAGL_GET_CTX();
407
408     yagl_gles_context_set_active_texture(ctx, texture);
409
410     YAGL_LOG_FUNC_EXIT(NULL);
411 }
412
413 YAGL_API void glBindBuffer(GLenum target, GLuint buffer)
414 {
415     struct yagl_gles_buffer *buffer_obj = NULL;
416
417     YAGL_LOG_FUNC_ENTER_SPLIT2(glBindBuffer, GLenum, GLuint, target, buffer);
418
419     YAGL_GET_CTX();
420
421     if (buffer != 0) {
422         buffer_obj = (struct yagl_gles_buffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
423             YAGL_NS_BUFFER, buffer);
424
425         if (!buffer_obj) {
426             buffer_obj = yagl_gles_buffer_create();
427
428             if (!buffer_obj) {
429                 goto out;
430             }
431
432             buffer_obj = (struct yagl_gles_buffer*)yagl_sharegroup_add_named(ctx->base.sg,
433                YAGL_NS_BUFFER, buffer, &buffer_obj->base);
434         }
435     }
436
437     yagl_gles_context_bind_buffer(ctx, target, buffer_obj);
438
439 out:
440     yagl_gles_buffer_release(buffer_obj);
441
442     YAGL_LOG_FUNC_EXIT(NULL);
443 }
444
445 void glBindFramebuffer(GLenum target, GLuint framebuffer)
446 {
447     struct yagl_gles_framebuffer *framebuffer_obj = NULL;
448
449     YAGL_LOG_FUNC_ENTER_SPLIT2(glBindFramebuffer, GLenum, GLuint, target, framebuffer);
450
451     YAGL_GET_CTX();
452
453     if (framebuffer != 0) {
454         framebuffer_obj = (struct yagl_gles_framebuffer*)yagl_namespace_acquire(&ctx->framebuffers,
455             framebuffer);
456
457         if (!framebuffer_obj) {
458             framebuffer_obj = yagl_gles_framebuffer_create();
459
460             if (!framebuffer_obj) {
461                 goto out;
462             }
463
464             framebuffer_obj = (struct yagl_gles_framebuffer*)yagl_namespace_add_named(&ctx->framebuffers,
465                framebuffer, &framebuffer_obj->base);
466         }
467     }
468
469     yagl_gles_context_bind_framebuffer(ctx, target, framebuffer_obj);
470
471 out:
472     yagl_gles_framebuffer_release(framebuffer_obj);
473
474     YAGL_LOG_FUNC_EXIT(NULL);
475 }
476
477 void glBindRenderbuffer(GLenum target, GLuint renderbuffer)
478 {
479     struct yagl_gles_renderbuffer *renderbuffer_obj = NULL;
480
481     YAGL_LOG_FUNC_ENTER_SPLIT2(glBindRenderbuffer, GLenum, GLuint, target, renderbuffer);
482
483     YAGL_GET_CTX();
484
485     if (renderbuffer != 0) {
486         renderbuffer_obj = (struct yagl_gles_renderbuffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
487             YAGL_NS_RENDERBUFFER, renderbuffer);
488
489         if (!renderbuffer_obj) {
490             renderbuffer_obj = yagl_gles_renderbuffer_create();
491
492             if (!renderbuffer_obj) {
493                 goto out;
494             }
495
496             renderbuffer_obj = (struct yagl_gles_renderbuffer*)yagl_sharegroup_add_named(ctx->base.sg,
497                YAGL_NS_RENDERBUFFER, renderbuffer, &renderbuffer_obj->base);
498         }
499     }
500
501     yagl_gles_context_bind_renderbuffer(ctx, target, renderbuffer_obj);
502
503 out:
504     yagl_gles_renderbuffer_release(renderbuffer_obj);
505
506     YAGL_LOG_FUNC_EXIT(NULL);
507 }
508
509 YAGL_API void glBindTexture(GLenum target, GLuint texture)
510 {
511     struct yagl_gles_texture *texture_obj = NULL;
512     yagl_gles_texture_target texture_target;
513
514     YAGL_LOG_FUNC_ENTER_SPLIT2(glBindTexture, GLenum, GLuint, target, texture);
515
516     YAGL_GET_CTX();
517
518     if (!yagl_gles_context_validate_texture_target(ctx, target, &texture_target)) {
519         YAGL_SET_ERR(GL_INVALID_ENUM);
520         goto out;
521     }
522
523     if (texture != 0) {
524         texture_obj = (struct yagl_gles_texture*)yagl_sharegroup_acquire_object(ctx->base.sg,
525             YAGL_NS_TEXTURE, texture);
526
527         if (!texture_obj) {
528             texture_obj = yagl_gles_texture_create();
529
530             if (!texture_obj) {
531                 goto out;
532             }
533
534             texture_obj = (struct yagl_gles_texture*)yagl_sharegroup_add_named(ctx->base.sg,
535                YAGL_NS_TEXTURE, texture, &texture_obj->base);
536         }
537     }
538
539     yagl_gles_context_bind_texture(ctx, target, texture_obj);
540
541 out:
542     yagl_gles_texture_release(texture_obj);
543
544     YAGL_LOG_FUNC_EXIT(NULL);
545 }
546
547 void glBlendEquation(GLenum mode)
548 {
549     YAGL_LOG_FUNC_ENTER_SPLIT1(glBlendEquation, GLenum, mode);
550
551     YAGL_GET_CTX();
552
553     if (yagl_gles_is_blend_equation_valid(mode)) {
554         ctx->blend_equation_rgb = mode;
555         ctx->blend_equation_alpha = mode;
556
557         yagl_host_glBlendEquation(mode);
558     } else {
559         YAGL_SET_ERR(GL_INVALID_ENUM);
560     }
561
562     YAGL_LOG_FUNC_EXIT(NULL);
563 }
564
565 void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
566 {
567     YAGL_LOG_FUNC_ENTER_SPLIT2(glBlendEquationSeparate, GLenum, GLenum, modeRGB, modeAlpha);
568
569     YAGL_GET_CTX();
570
571     if (yagl_gles_is_blend_equation_valid(modeRGB) &&
572         yagl_gles_is_blend_equation_valid(modeAlpha)) {
573         ctx->blend_equation_rgb = modeRGB;
574         ctx->blend_equation_alpha = modeAlpha;
575
576         yagl_host_glBlendEquationSeparate(modeRGB, modeAlpha);
577     } else {
578         YAGL_SET_ERR(GL_INVALID_ENUM);
579     }
580
581     YAGL_LOG_FUNC_EXIT(NULL);
582 }
583
584 YAGL_API void glBlendFunc(GLenum sfactor, GLenum dfactor)
585 {
586     YAGL_LOG_FUNC_ENTER_SPLIT2(glBlendFunc, GLenum, GLenum, sfactor, dfactor);
587
588     YAGL_GET_CTX();
589
590     if (yagl_gles_is_blend_func_valid(sfactor) &&
591         yagl_gles_is_blend_func_valid(dfactor)) {
592         ctx->blend_src_rgb = sfactor;
593         ctx->blend_src_alpha = sfactor;
594
595         ctx->blend_dst_rgb = dfactor;
596         ctx->blend_dst_alpha = dfactor;
597
598         yagl_host_glBlendFunc(sfactor, dfactor);
599     } else {
600         YAGL_SET_ERR(GL_INVALID_ENUM);
601     }
602
603     YAGL_LOG_FUNC_EXIT(NULL);
604 }
605
606 void glBlendFuncSeparate(GLenum srcRGB,
607                          GLenum dstRGB,
608                          GLenum srcAlpha,
609                          GLenum dstAlpha)
610 {
611     YAGL_LOG_FUNC_ENTER_SPLIT4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, srcRGB, dstRGB, srcAlpha, dstAlpha);
612
613     YAGL_GET_CTX();
614
615     if (yagl_gles_is_blend_func_valid(srcRGB) &&
616         yagl_gles_is_blend_func_valid(dstRGB) &&
617         yagl_gles_is_blend_func_valid(srcAlpha) &&
618         yagl_gles_is_blend_func_valid(dstAlpha)) {
619         ctx->blend_src_rgb = srcRGB;
620         ctx->blend_src_alpha = srcAlpha;
621
622         ctx->blend_dst_rgb = dstRGB;
623         ctx->blend_dst_alpha = dstAlpha;
624
625         yagl_host_glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
626     } else {
627         YAGL_SET_ERR(GL_INVALID_ENUM);
628     }
629
630     YAGL_LOG_FUNC_EXIT(NULL);
631 }
632
633 YAGL_API void glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
634 {
635     struct yagl_gles_buffer *buffer_obj = NULL;
636
637     YAGL_LOG_FUNC_ENTER_SPLIT4(glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum, target, size, data, usage);
638
639     YAGL_GET_CTX();
640
641     if (size < 0) {
642         YAGL_SET_ERR(GL_INVALID_VALUE);
643         goto out;
644     }
645
646     if (!yagl_gles_is_buffer_usage_valid(usage)) {
647         YAGL_SET_ERR(GL_INVALID_ENUM);
648         goto out;
649     }
650
651     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
652         YAGL_SET_ERR(GL_INVALID_ENUM);
653         goto out;
654     }
655
656     if (!buffer_obj) {
657         YAGL_SET_ERR(GL_INVALID_OPERATION);
658         goto out;
659     }
660
661     yagl_gles_buffer_set_data(buffer_obj, size, data, usage);
662
663 out:
664     yagl_gles_buffer_release(buffer_obj);
665
666     YAGL_LOG_FUNC_EXIT(NULL);
667 }
668
669 YAGL_API void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
670 {
671     struct yagl_gles_buffer *buffer_obj = NULL;
672
673     YAGL_LOG_FUNC_ENTER_SPLIT4(glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*, target, offset, size, data);
674
675     YAGL_GET_CTX();
676
677     if ((offset < 0) || (size < 0)) {
678         YAGL_SET_ERR(GL_INVALID_VALUE);
679         goto out;
680     }
681
682     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
683         YAGL_SET_ERR(GL_INVALID_ENUM);
684         goto out;
685     }
686
687     if (!buffer_obj) {
688         YAGL_SET_ERR(GL_INVALID_OPERATION);
689         goto out;
690     }
691
692     if (size == 0) {
693         goto out;
694     }
695
696     if (!yagl_gles_buffer_update_data(buffer_obj, offset, size, data)) {
697         YAGL_SET_ERR(GL_INVALID_VALUE);
698         goto out;
699     }
700
701 out:
702     yagl_gles_buffer_release(buffer_obj);
703
704     YAGL_LOG_FUNC_EXIT(NULL);
705 }
706
707 GLenum glCheckFramebufferStatus(GLenum target)
708 {
709     GLenum res = 0;
710     struct yagl_gles_framebuffer *framebuffer_obj = NULL;
711
712     YAGL_LOG_FUNC_ENTER_SPLIT1(glCheckFramebufferStatus, GLenum, target);
713
714     YAGL_GET_CTX_RET(0);
715
716     if (!yagl_gles_context_acquire_binded_framebuffer(ctx, target, &framebuffer_obj)) {
717         YAGL_SET_ERR(GL_INVALID_ENUM);
718         goto out;
719     }
720
721     res = yagl_gles_context_check_framebuffer_status(ctx, framebuffer_obj);
722
723 out:
724     yagl_gles_framebuffer_release(framebuffer_obj);
725
726     YAGL_LOG_FUNC_EXIT_SPLIT(GLenum, res);
727
728     return res;
729 }
730
731 YAGL_API void glClear(GLbitfield mask)
732 {
733     YAGL_LOG_FUNC_ENTER_SPLIT1(glClear, GLbitfield, mask);
734
735     YAGL_GET_CTX();
736
737     yagl_render_invalidate((mask & GL_COLOR_BUFFER_BIT));
738
739     yagl_host_glClear(mask);
740
741     YAGL_LOG_FUNC_EXIT(NULL);
742 }
743
744 YAGL_API void glClearColor(GLclampf red,
745                            GLclampf green,
746                            GLclampf blue,
747                            GLclampf alpha)
748 {
749     YAGL_LOG_FUNC_ENTER_SPLIT4(glClearColor, GLclampf, GLclampf, GLclampf, GLclampf, red, green, blue, alpha);
750
751     YAGL_GET_CTX();
752
753     yagl_gles_context_clear_color(ctx,
754                                   red,
755                                   green,
756                                   blue,
757                                   alpha);
758
759     YAGL_LOG_FUNC_EXIT(NULL);
760 }
761
762 YAGL_API void glClearDepthf(GLclampf depth)
763 {
764     YAGL_LOG_FUNC_ENTER_SPLIT1(glClearDepthf, GLclampf, depth);
765
766     YAGL_GET_CTX();
767
768     yagl_gles_context_clear_depthf(ctx, depth);
769
770     YAGL_LOG_FUNC_EXIT(NULL);
771 }
772
773 YAGL_API void glColorMask(GLboolean red,
774                           GLboolean green,
775                           GLboolean blue,
776                           GLboolean alpha)
777 {
778     YAGL_LOG_FUNC_ENTER_SPLIT4(glColorMask, GLboolean, GLboolean, GLboolean, GLboolean, red, green, blue, alpha);
779
780     YAGL_GET_CTX();
781
782     ctx->color_writemask[0] = red;
783     ctx->color_writemask[1] = green;
784     ctx->color_writemask[2] = blue;
785     ctx->color_writemask[3] = alpha;
786
787     yagl_host_glColorMask(red, green, blue, alpha);
788
789     YAGL_LOG_FUNC_EXIT(NULL);
790 }
791
792 YAGL_API void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
793 {
794     GLenum squashed_target;
795     yagl_gles_texture_target texture_target;
796     struct yagl_gles_texture_target_state *tex_target_state;
797     int using_pbo = 0;
798
799     YAGL_LOG_FUNC_ENTER_SPLIT8(glCompressedTexImage2D, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*, target, level, internalformat, width, height, border, imageSize, data);
800
801     YAGL_GET_CTX();
802
803     if ((width < 0) || (height < 0)) {
804         YAGL_SET_ERR(GL_INVALID_VALUE);
805         goto out;
806     }
807
808     if (!yagl_gles_validate_texture_target_squash(target, &squashed_target)) {
809         YAGL_SET_ERR(GL_INVALID_ENUM);
810         goto out;
811     }
812
813     if (!yagl_gles_context_validate_texture_target(ctx,
814                                                    squashed_target,
815                                                    &texture_target)) {
816         YAGL_SET_ERR(GL_INVALID_ENUM);
817         goto out;
818     }
819
820     tex_target_state =
821         yagl_gles_context_get_active_texture_target_state(ctx, texture_target);
822
823     if ((width == 0) || (height == 0)) {
824         width = height = 0;
825     }
826
827     if ((width != 0) && !yagl_gles_context_pre_unpack(ctx, &data, 1, &using_pbo)) {
828         YAGL_SET_ERR(GL_INVALID_OPERATION);
829         goto out;
830     }
831
832     assert(!using_pbo);
833
834     if (target == GL_TEXTURE_2D) {
835         if (tex_target_state->texture != tex_target_state->texture_zero) {
836             /*
837              * This operation should orphan EGLImage according
838              * to OES_EGL_image specs.
839              *
840              * This operation should release TexImage according
841              * to eglBindTexImage spec.
842              */
843             yagl_gles_texture_unset_image(tex_target_state->texture);
844         }
845     }
846
847     ctx->compressed_tex_image_2d(ctx,
848                                  target,
849                                  tex_target_state->texture,
850                                  level,
851                                  internalformat,
852                                  width,
853                                  height,
854                                  border,
855                                  imageSize,
856                                  data);
857
858     if (width != 0) {
859         yagl_gles_context_post_unpack(ctx, 1);
860     }
861
862 out:
863     YAGL_LOG_FUNC_EXIT(NULL);
864 }
865
866 YAGL_API void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
867 {
868     int using_pbo = 0;
869
870     YAGL_LOG_FUNC_ENTER_SPLIT9(glCompressedTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*, target, level, xoffset, yoffset, width, height, format, imageSize, data);
871
872     YAGL_GET_CTX();
873
874     if ((width < 0) || (height < 0)) {
875         YAGL_SET_ERR(GL_INVALID_VALUE);
876         goto out;
877     }
878
879     if ((width == 0) || (height == 0)) {
880         width = height = 0;
881     }
882
883     if ((width != 0) && !yagl_gles_context_pre_unpack(ctx, &data, 1, &using_pbo)) {
884         YAGL_SET_ERR(GL_INVALID_OPERATION);
885         goto out;
886     }
887
888     assert(!using_pbo);
889
890     ctx->compressed_tex_sub_image_2d(ctx,
891                                      target,
892                                      level,
893                                      xoffset,
894                                      yoffset,
895                                      width,
896                                      height,
897                                      format,
898                                      imageSize,
899                                      data);
900
901     if (width != 0) {
902         yagl_gles_context_post_unpack(ctx, 1);
903     }
904
905 out:
906     YAGL_LOG_FUNC_EXIT(NULL);
907 }
908
909 YAGL_API void glCopyTexImage2D(GLenum target,
910                                GLint level,
911                                GLenum internalformat,
912                                GLint x,
913                                GLint y,
914                                GLsizei width,
915                                GLsizei height,
916                                GLint border)
917 {
918     GLenum actual_internalformat = internalformat;
919     GLenum squashed_target;
920     yagl_gles_texture_target texture_target;
921     struct yagl_gles_texture_target_state *tex_target_state;
922     int is_float;
923
924     YAGL_LOG_FUNC_ENTER_SPLIT8(glCopyTexImage2D, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, target, level, internalformat, x, y, width, height, border);
925
926     YAGL_GET_CTX();
927
928     if (border != 0) {
929         YAGL_SET_ERR(GL_INVALID_VALUE);
930         goto out;
931     }
932
933     if (!yagl_gles_validate_texture_target_squash(target, &squashed_target)) {
934         YAGL_SET_ERR(GL_INVALID_ENUM);
935         goto out;
936     }
937
938     if (!yagl_gles_context_validate_texture_target(ctx,
939                                                    squashed_target,
940                                                    &texture_target)) {
941         YAGL_SET_ERR(GL_INVALID_ENUM);
942         goto out;
943     }
944
945     tex_target_state =
946         yagl_gles_context_get_active_texture_target_state(ctx, texture_target);
947
948     if (!yagl_gles_context_validate_copyteximage_format(ctx,
949                                                         &actual_internalformat,
950                                                         &is_float)) {
951         YAGL_SET_ERR(GL_INVALID_OPERATION);
952         goto out;
953     }
954
955     yagl_host_glCopyTexImage2D(target,
956                                level,
957                                actual_internalformat,
958                                x,
959                                y,
960                                width,
961                                height,
962                                border);
963
964     yagl_gles_texture_set_internalformat(tex_target_state->texture,
965                                          internalformat,
966                                          (is_float ? GL_FLOAT : 0),
967                                          yagl_gles_context_convert_textures(ctx));
968
969 out:
970     YAGL_LOG_FUNC_EXIT(NULL);
971 }
972
973 YAGL_API void glCopyTexSubImage2D(GLenum target,
974                                   GLint level,
975                                   GLint xoffset,
976                                   GLint yoffset,
977                                   GLint x,
978                                   GLint y,
979                                   GLsizei width,
980                                   GLsizei height)
981 {
982     YAGL_LOG_FUNC_ENTER_SPLIT8(glCopyTexSubImage2D, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, target, level, xoffset, yoffset, x, y, width, height);
983
984     YAGL_GET_CTX();
985
986     if ((ctx->base.client_api == yagl_client_api_gles1) &&
987         (target != GL_TEXTURE_2D)) {
988         YAGL_SET_ERR(GL_INVALID_ENUM);
989         goto out;
990     }
991
992     yagl_host_glCopyTexSubImage2D(target,
993                                   level,
994                                   xoffset,
995                                   yoffset,
996                                   x,
997                                   y,
998                                   width,
999                                   height);
1000
1001 out:
1002     YAGL_LOG_FUNC_EXIT(NULL);
1003 }
1004
1005 YAGL_API void glCullFace(GLenum mode)
1006 {
1007     YAGL_LOG_FUNC_ENTER_SPLIT1(glCullFace, GLenum, mode);
1008
1009     YAGL_GET_CTX();
1010
1011     if (yagl_gles_is_cull_face_mode_valid(mode)) {
1012         ctx->cull_face_mode = mode;
1013
1014         yagl_host_glCullFace(mode);
1015     } else {
1016         YAGL_SET_ERR(GL_INVALID_ENUM);
1017     }
1018
1019     YAGL_LOG_FUNC_EXIT(NULL);
1020 }
1021
1022 YAGL_API void glDeleteBuffers(GLsizei n, const GLuint *buffers)
1023 {
1024     GLsizei i;
1025
1026     YAGL_LOG_FUNC_ENTER_SPLIT2(glDeleteBuffers, GLsizei, const GLuint*, n, buffers);
1027
1028     YAGL_GET_CTX();
1029
1030     if (n < 0) {
1031         YAGL_SET_ERR(GL_INVALID_VALUE);
1032         goto out;
1033     }
1034
1035     if (buffers) {
1036         for (i = 0; i < n; ++i) {
1037             yagl_gles_context_unbind_buffer(ctx, buffers[i]);
1038
1039             yagl_sharegroup_remove(ctx->base.sg,
1040                                    YAGL_NS_BUFFER,
1041                                    buffers[i]);
1042         }
1043     }
1044
1045 out:
1046     YAGL_LOG_FUNC_EXIT(NULL);
1047 }
1048
1049 void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
1050 {
1051     GLsizei i;
1052
1053     YAGL_LOG_FUNC_ENTER_SPLIT2(glDeleteFramebuffers, GLsizei, const GLuint*, n, framebuffers);
1054
1055     YAGL_GET_CTX();
1056
1057     if (n < 0) {
1058         YAGL_SET_ERR(GL_INVALID_VALUE);
1059         goto out;
1060     }
1061
1062     if (framebuffers) {
1063         for (i = 0; i < n; ++i) {
1064             yagl_gles_context_unbind_framebuffer(ctx, framebuffers[i]);
1065
1066             yagl_namespace_remove(&ctx->framebuffers,
1067                                   framebuffers[i]);
1068         }
1069     }
1070
1071 out:
1072     YAGL_LOG_FUNC_EXIT(NULL);
1073 }
1074
1075 void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
1076 {
1077     GLsizei i;
1078
1079     YAGL_LOG_FUNC_ENTER_SPLIT2(glDeleteRenderbuffers, GLsizei, const GLuint*, n, renderbuffers);
1080
1081     YAGL_GET_CTX();
1082
1083     if (n < 0) {
1084         YAGL_SET_ERR(GL_INVALID_VALUE);
1085         goto out;
1086     }
1087
1088     if (renderbuffers) {
1089         for (i = 0; i < n; ++i) {
1090             yagl_gles_context_unbind_renderbuffer(ctx, renderbuffers[i]);
1091
1092             yagl_sharegroup_remove(ctx->base.sg,
1093                                    YAGL_NS_RENDERBUFFER,
1094                                    renderbuffers[i]);
1095         }
1096     }
1097
1098 out:
1099     YAGL_LOG_FUNC_EXIT(NULL);
1100 }
1101
1102 YAGL_API void glDeleteTextures(GLsizei n, const GLuint *textures)
1103 {
1104     GLsizei i;
1105
1106     YAGL_LOG_FUNC_ENTER_SPLIT2(glDeleteTextures, GLsizei, const GLuint*, n, textures);
1107
1108     YAGL_GET_CTX();
1109
1110     if (n < 0) {
1111         YAGL_SET_ERR(GL_INVALID_VALUE);
1112         goto out;
1113     }
1114
1115     if (textures) {
1116         for (i = 0; i < n; ++i) {
1117             yagl_gles_context_unbind_texture(ctx, textures[i]);
1118
1119             yagl_sharegroup_remove(ctx->base.sg,
1120                                    YAGL_NS_TEXTURE,
1121                                    textures[i]);
1122
1123         }
1124     }
1125
1126 out:
1127     YAGL_LOG_FUNC_EXIT(NULL);
1128 }
1129
1130 YAGL_API void glDepthFunc(GLenum func)
1131 {
1132     YAGL_LOG_FUNC_ENTER_SPLIT1(glDepthFunc, GLenum, func);
1133
1134     YAGL_GET_CTX();
1135
1136     if (yagl_gles_is_depth_func_valid(func)) {
1137         ctx->depth_func = func;
1138
1139         yagl_host_glDepthFunc(func);
1140     } else {
1141         YAGL_SET_ERR(GL_INVALID_ENUM);
1142     }
1143
1144     YAGL_LOG_FUNC_EXIT(NULL);
1145 }
1146
1147 YAGL_API void glDepthMask(GLboolean flag)
1148 {
1149     YAGL_LOG_FUNC_ENTER_SPLIT1(glDepthMask, GLboolean, flag);
1150
1151     YAGL_GET_CTX();
1152
1153     ctx->depth_writemask = flag;
1154
1155     yagl_host_glDepthMask(flag);
1156
1157     YAGL_LOG_FUNC_EXIT(NULL);
1158 }
1159
1160 YAGL_API void glDepthRangef(GLclampf zNear, GLclampf zFar)
1161 {
1162     YAGL_LOG_FUNC_ENTER_SPLIT2(glDepthRangef, GLclampf, GLclampf, zNear, zFar);
1163
1164     YAGL_GET_CTX();
1165
1166     yagl_gles_context_depth_rangef(ctx, zNear, zFar);
1167
1168     YAGL_LOG_FUNC_EXIT(NULL);
1169 }
1170
1171 YAGL_API void glDisable(GLenum cap)
1172 {
1173     YAGL_LOG_FUNC_ENTER_SPLIT1(glDisable, GLenum, cap);
1174
1175     YAGL_GET_CTX();
1176
1177     yagl_gles_context_enable(ctx, cap, GL_FALSE);
1178
1179     YAGL_LOG_FUNC_EXIT(NULL);
1180 }
1181
1182 YAGL_API void glDrawArrays(GLenum mode, GLint first, GLsizei count)
1183 {
1184     YAGL_LOG_FUNC_ENTER_SPLIT3(glDrawArrays, GLenum, GLint, GLsizei, mode, first, count);
1185
1186     YAGL_GET_CTX();
1187
1188     yagl_gles_context_draw_arrays(ctx, mode, first, count, -1);
1189
1190     YAGL_LOG_FUNC_EXIT(NULL);
1191 }
1192
1193 YAGL_API void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
1194 {
1195     YAGL_LOG_FUNC_ENTER_SPLIT4(glDrawElements, GLenum, GLsizei, GLenum, const GLvoid*, mode, count, type, indices);
1196
1197     YAGL_GET_CTX();
1198
1199     yagl_gles_context_draw_elements(ctx, mode, count, type, indices, -1);
1200
1201     YAGL_LOG_FUNC_EXIT(NULL);
1202 }
1203
1204 YAGL_API void glEnable(GLenum cap)
1205 {
1206     YAGL_LOG_FUNC_ENTER_SPLIT1(glEnable, GLenum, cap);
1207
1208     YAGL_GET_CTX();
1209
1210     yagl_gles_context_enable(ctx, cap, GL_TRUE);
1211
1212     YAGL_LOG_FUNC_EXIT(NULL);
1213 }
1214
1215 YAGL_API void glFinish()
1216 {
1217     YAGL_LOG_FUNC_ENTER_SPLIT0(glFinish);
1218
1219     yagl_render_finish();
1220
1221     YAGL_LOG_FUNC_EXIT(NULL);
1222 }
1223
1224 YAGL_IMPLEMENT_API_NORET0(glFlush)
1225
1226 void glFramebufferRenderbuffer(GLenum target,
1227                                GLenum attachment,
1228                                GLenum renderbuffertarget,
1229                                GLuint renderbuffer)
1230 {
1231     struct yagl_gles_framebuffer *framebuffer_obj = NULL;
1232     struct yagl_gles_renderbuffer *renderbuffer_obj = NULL;
1233     yagl_gles_framebuffer_attachment framebuffer_attachment;
1234
1235     YAGL_LOG_FUNC_ENTER_SPLIT4(glFramebufferRenderbuffer, GLenum, GLenum, GLenum, GLuint, target, attachment, renderbuffertarget, renderbuffer);
1236
1237     YAGL_GET_CTX();
1238
1239     if (!yagl_gles_context_acquire_binded_framebuffer(ctx, target, &framebuffer_obj)) {
1240         YAGL_SET_ERR(GL_INVALID_ENUM);
1241         goto out;
1242     }
1243
1244     if (!framebuffer_obj) {
1245         YAGL_SET_ERR(GL_INVALID_OPERATION);
1246         goto out;
1247     }
1248
1249     if (renderbuffer) {
1250         renderbuffer_obj = (struct yagl_gles_renderbuffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
1251             YAGL_NS_RENDERBUFFER, renderbuffer);
1252
1253         if (!renderbuffer_obj) {
1254             YAGL_SET_ERR(GL_INVALID_OPERATION);
1255             goto out;
1256         }
1257     }
1258
1259     if (renderbuffer_obj && (renderbuffertarget != GL_RENDERBUFFER)) {
1260         YAGL_SET_ERR(GL_INVALID_ENUM);
1261         goto out;
1262     }
1263
1264     if ((ctx->base.client_api == yagl_client_api_gles3) &&
1265         (attachment == GL_DEPTH_STENCIL_ATTACHMENT)) {
1266         yagl_gles_framebuffer_renderbuffer(framebuffer_obj,
1267                                            target, GL_DEPTH_ATTACHMENT,
1268                                            yagl_gles_framebuffer_attachment_depth,
1269                                            renderbuffertarget,
1270                                            renderbuffer_obj);
1271         yagl_gles_framebuffer_renderbuffer(framebuffer_obj,
1272                                            target, GL_STENCIL_ATTACHMENT,
1273                                            yagl_gles_framebuffer_attachment_stencil,
1274                                            renderbuffertarget,
1275                                            renderbuffer_obj);
1276     } else {
1277         if (!yagl_gles_validate_framebuffer_attachment(attachment,
1278                                                        ctx->max_color_attachments,
1279                                                        &framebuffer_attachment)) {
1280             YAGL_SET_ERR(GL_INVALID_ENUM);
1281             goto out;
1282         }
1283
1284         yagl_gles_framebuffer_renderbuffer(framebuffer_obj,
1285                                            target, attachment,
1286                                            framebuffer_attachment,
1287                                            renderbuffertarget,
1288                                            renderbuffer_obj);
1289     }
1290
1291 out:
1292     yagl_gles_renderbuffer_release(renderbuffer_obj);
1293     yagl_gles_framebuffer_release(framebuffer_obj);
1294
1295     YAGL_LOG_FUNC_EXIT(NULL);
1296 }
1297
1298 void glFramebufferTexture2D(GLenum target,
1299                             GLenum attachment,
1300                             GLenum textarget,
1301                             GLuint texture,
1302                             GLint level)
1303 {
1304     struct yagl_gles_framebuffer *framebuffer_obj = NULL;
1305     struct yagl_gles_texture *texture_obj = NULL;
1306     yagl_gles_framebuffer_attachment framebuffer_attachment;
1307     GLenum squashed_textarget;
1308
1309     YAGL_LOG_FUNC_ENTER_SPLIT5(glFramebufferTexture2D, GLenum, GLenum, GLenum, GLuint, GLint, target, attachment, textarget, texture, level);
1310
1311     YAGL_GET_CTX();
1312
1313     if (!yagl_gles_context_acquire_binded_framebuffer(ctx, target, &framebuffer_obj)) {
1314         YAGL_SET_ERR(GL_INVALID_ENUM);
1315         goto out;
1316     }
1317
1318     if (!framebuffer_obj) {
1319         YAGL_SET_ERR(GL_INVALID_OPERATION);
1320         goto out;
1321     }
1322
1323     if (texture) {
1324         texture_obj = (struct yagl_gles_texture*)yagl_sharegroup_acquire_object(ctx->base.sg,
1325             YAGL_NS_TEXTURE, texture);
1326
1327         if (!texture_obj) {
1328             YAGL_SET_ERR(GL_INVALID_OPERATION);
1329             goto out;
1330         }
1331     }
1332
1333     if (texture_obj && (level != 0)) {
1334         YAGL_SET_ERR(GL_INVALID_ENUM);
1335         goto out;
1336     }
1337
1338     if (!yagl_gles_validate_texture_target_squash(textarget,
1339                                                   &squashed_textarget)) {
1340         YAGL_SET_ERR(GL_INVALID_ENUM);
1341         goto out;
1342     }
1343
1344     if (texture_obj && (texture_obj->target != squashed_textarget)) {
1345         YAGL_SET_ERR(GL_INVALID_ENUM);
1346         goto out;
1347     }
1348
1349     if ((ctx->base.client_api == yagl_client_api_gles3) &&
1350         (attachment == GL_DEPTH_STENCIL_ATTACHMENT)) {
1351         yagl_gles_framebuffer_texture2d(framebuffer_obj,
1352                                         target, GL_DEPTH_ATTACHMENT,
1353                                         yagl_gles_framebuffer_attachment_depth,
1354                                         textarget,
1355                                         level,
1356                                         texture_obj);
1357         yagl_gles_framebuffer_texture2d(framebuffer_obj,
1358                                         target, GL_STENCIL_ATTACHMENT,
1359                                         yagl_gles_framebuffer_attachment_stencil,
1360                                         textarget,
1361                                         level,
1362                                         texture_obj);
1363     } else {
1364         if (!yagl_gles_validate_framebuffer_attachment(attachment,
1365                                                        ctx->max_color_attachments,
1366                                                        &framebuffer_attachment)) {
1367             YAGL_SET_ERR(GL_INVALID_ENUM);
1368             goto out;
1369         }
1370
1371         yagl_gles_framebuffer_texture2d(framebuffer_obj,
1372                                         target, attachment,
1373                                         framebuffer_attachment,
1374                                         textarget,
1375                                         level,
1376                                         texture_obj);
1377     }
1378
1379 out:
1380     yagl_gles_texture_release(texture_obj);
1381     yagl_gles_framebuffer_release(framebuffer_obj);
1382
1383     YAGL_LOG_FUNC_EXIT(NULL);
1384 }
1385
1386 YAGL_API void glFrontFace(GLenum mode)
1387 {
1388     YAGL_LOG_FUNC_ENTER_SPLIT1(glFrontFace, GLenum, mode);
1389
1390     YAGL_GET_CTX();
1391
1392     if (yagl_gles_is_front_face_mode_valid(mode)) {
1393         ctx->front_face_mode = mode;
1394
1395         yagl_host_glFrontFace(mode);
1396     } else {
1397         YAGL_SET_ERR(GL_INVALID_ENUM);
1398     }
1399
1400     YAGL_LOG_FUNC_EXIT(NULL);
1401 }
1402
1403 YAGL_API void glGenBuffers(GLsizei n, GLuint *buffer_names)
1404 {
1405     struct yagl_gles_buffer **buffers = NULL;
1406     GLsizei i;
1407
1408     YAGL_LOG_FUNC_ENTER_SPLIT2(glGenBuffers, GLsizei, GLuint*, n, buffer_names);
1409
1410     YAGL_GET_CTX();
1411
1412     if (n < 0) {
1413         YAGL_SET_ERR(GL_INVALID_VALUE);
1414         goto out;
1415     }
1416
1417     buffers = yagl_malloc0(n * sizeof(*buffers));
1418
1419     for (i = 0; i < n; ++i) {
1420         buffers[i] = yagl_gles_buffer_create();
1421
1422         if (!buffers[i]) {
1423             goto out;
1424         }
1425     }
1426
1427     for (i = 0; i < n; ++i) {
1428         yagl_sharegroup_add(ctx->base.sg,
1429                             YAGL_NS_BUFFER,
1430                             &buffers[i]->base);
1431
1432         if (buffer_names) {
1433             buffer_names[i] = buffers[i]->base.local_name;
1434         }
1435     }
1436
1437 out:
1438     for (i = 0; i < n; ++i) {
1439         yagl_gles_buffer_release(buffers[i]);
1440     }
1441     yagl_free(buffers);
1442
1443     YAGL_LOG_FUNC_EXIT(NULL);
1444 }
1445
1446 void glGenerateMipmap(GLenum target)
1447 {
1448     YAGL_LOG_FUNC_ENTER_SPLIT1(glGenerateMipmap, GLenum, target);
1449
1450     YAGL_GET_CTX();
1451
1452     yagl_host_glGenerateMipmap(target);
1453
1454     YAGL_LOG_FUNC_EXIT(NULL);
1455 }
1456
1457 void glGenFramebuffers(GLsizei n, GLuint *framebuffer_names)
1458 {
1459     struct yagl_gles_framebuffer **framebuffers = NULL;
1460     GLsizei i;
1461
1462     YAGL_LOG_FUNC_ENTER_SPLIT2(glGenFramebuffers, GLsizei, GLuint*, n, framebuffer_names);
1463
1464     YAGL_GET_CTX();
1465
1466     if (n < 0) {
1467         YAGL_SET_ERR(GL_INVALID_VALUE);
1468         goto out;
1469     }
1470
1471     framebuffers = yagl_malloc0(n * sizeof(*framebuffers));
1472
1473     for (i = 0; i < n; ++i) {
1474         framebuffers[i] = yagl_gles_framebuffer_create();
1475
1476         if (!framebuffers[i]) {
1477             goto out;
1478         }
1479     }
1480
1481     for (i = 0; i < n; ++i) {
1482         yagl_namespace_add(&ctx->framebuffers,
1483                            &framebuffers[i]->base);
1484
1485         if (framebuffer_names) {
1486             framebuffer_names[i] = framebuffers[i]->base.local_name;
1487         }
1488     }
1489
1490 out:
1491     for (i = 0; i < n; ++i) {
1492         yagl_gles_framebuffer_release(framebuffers[i]);
1493     }
1494     yagl_free(framebuffers);
1495
1496     YAGL_LOG_FUNC_EXIT(NULL);
1497 }
1498
1499 void glGenRenderbuffers(GLsizei n, GLuint *renderbuffer_names)
1500 {
1501     struct yagl_gles_renderbuffer **renderbuffers = NULL;
1502     GLsizei i;
1503
1504     YAGL_LOG_FUNC_ENTER_SPLIT2(glGenRenderbuffers, GLsizei, GLuint*, n, renderbuffer_names);
1505
1506     YAGL_GET_CTX();
1507
1508     if (n < 0) {
1509         YAGL_SET_ERR(GL_INVALID_VALUE);
1510         goto out;
1511     }
1512
1513     renderbuffers = yagl_malloc0(n * sizeof(*renderbuffers));
1514
1515     for (i = 0; i < n; ++i) {
1516         renderbuffers[i] = yagl_gles_renderbuffer_create();
1517
1518         if (!renderbuffers[i]) {
1519             goto out;
1520         }
1521     }
1522
1523     for (i = 0; i < n; ++i) {
1524         yagl_sharegroup_add(ctx->base.sg,
1525                             YAGL_NS_RENDERBUFFER,
1526                             &renderbuffers[i]->base);
1527
1528         if (renderbuffer_names) {
1529             renderbuffer_names[i] = renderbuffers[i]->base.local_name;
1530         }
1531     }
1532
1533 out:
1534     for (i = 0; i < n; ++i) {
1535         yagl_gles_renderbuffer_release(renderbuffers[i]);
1536     }
1537     yagl_free(renderbuffers);
1538
1539     YAGL_LOG_FUNC_EXIT(NULL);
1540 }
1541
1542 YAGL_API void glGenTextures(GLsizei n, GLuint *texture_names)
1543 {
1544     struct yagl_gles_texture **textures = NULL;
1545     GLsizei i;
1546
1547     YAGL_LOG_FUNC_ENTER_SPLIT2(glGenTextures, GLsizei, GLuint*, n, texture_names);
1548
1549     YAGL_GET_CTX();
1550
1551     if (n < 0) {
1552         YAGL_SET_ERR(GL_INVALID_VALUE);
1553         goto out;
1554     }
1555
1556     textures = yagl_malloc0(n * sizeof(*textures));
1557
1558     for (i = 0; i < n; ++i) {
1559         textures[i] = yagl_gles_texture_create();
1560
1561         if (!textures[i]) {
1562             goto out;
1563         }
1564     }
1565
1566     for (i = 0; i < n; ++i) {
1567         yagl_sharegroup_add(ctx->base.sg,
1568                             YAGL_NS_TEXTURE,
1569                             &textures[i]->base);
1570
1571         if (texture_names) {
1572             texture_names[i] = textures[i]->base.local_name;
1573         }
1574     }
1575
1576 out:
1577     for (i = 0; i < n; ++i) {
1578         yagl_gles_texture_release(textures[i]);
1579     }
1580     yagl_free(textures);
1581
1582     YAGL_LOG_FUNC_EXIT(NULL);
1583 }
1584
1585 YAGL_API void glGetBooleanv(GLenum pname, GLboolean *params)
1586 {
1587     GLint ints[100]; // This fits all cases.
1588     uint32_t i, num = 0;
1589     int needs_map;
1590
1591     YAGL_LOG_FUNC_ENTER_SPLIT2(glGetBooleanv, GLenum, GLboolean*, pname, params);
1592
1593     YAGL_GET_CTX();
1594
1595     if (yagl_gles_context_get_integerv(ctx, pname, ints, &num)) {
1596         for (i = 0; i < num; ++i) {
1597             params[i] = ints[i] ? GL_TRUE : GL_FALSE;
1598         }
1599     } else {
1600         GLfloat floats[100]; // This fits all cases.
1601         if (yagl_gles_context_get_floatv(ctx, pname, floats, &num, &needs_map)) {
1602             for (i = 0; i < num; ++i) {
1603                 params[i] = (floats[i] == 0.0f) ? GL_FALSE : GL_TRUE;
1604             }
1605         } else {
1606             YAGL_SET_ERR(GL_INVALID_ENUM);
1607         }
1608     }
1609
1610     YAGL_LOG_FUNC_EXIT(NULL);
1611 }
1612
1613 YAGL_API void glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
1614 {
1615     struct yagl_gles_buffer *buffer_obj = NULL;
1616
1617     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetBufferParameteriv, GLenum, GLenum, GLint*, target, pname, params);
1618
1619     YAGL_GET_CTX();
1620
1621     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
1622         YAGL_SET_ERR(GL_INVALID_ENUM);
1623         goto out;
1624     }
1625
1626     if (!buffer_obj) {
1627         YAGL_SET_ERR(GL_INVALID_OPERATION);
1628         goto out;
1629     }
1630
1631     if (!yagl_gles_buffer_get_parameter(buffer_obj,
1632                                         pname,
1633                                         params)) {
1634         YAGL_SET_ERR(GL_INVALID_ENUM);
1635         goto out;
1636     }
1637
1638 out:
1639     yagl_gles_buffer_release(buffer_obj);
1640
1641     YAGL_LOG_FUNC_EXIT(NULL);
1642 }
1643
1644 YAGL_API GLenum glGetError(void)
1645 {
1646     GLenum ret;
1647
1648     YAGL_LOG_FUNC_ENTER_SPLIT0(glGetError);
1649
1650     YAGL_GET_CTX_RET(GL_NO_ERROR);
1651
1652     ret = yagl_gles_context_get_error(ctx);
1653
1654     YAGL_LOG_FUNC_EXIT_SPLIT(GLenum, ret);
1655
1656     return ret;
1657 }
1658
1659 YAGL_API void glGetFloatv(GLenum pname, GLfloat *params)
1660 {
1661     uint32_t i, num = 0;
1662     int needs_map;
1663
1664     YAGL_LOG_FUNC_ENTER_SPLIT2(glGetFloatv, GLenum, GLfloat*, pname, params);
1665
1666     YAGL_GET_CTX();
1667
1668     if (!yagl_gles_context_get_floatv(ctx, pname, params, &num, &needs_map)) {
1669         GLint ints[100]; // This fits all cases.
1670         if (yagl_gles_context_get_integerv(ctx, pname, ints, &num)) {
1671             for (i = 0; i < num; ++i) {
1672                 params[i] = ints[i];
1673             }
1674         } else {
1675             YAGL_SET_ERR(GL_INVALID_ENUM);
1676         }
1677     }
1678
1679     YAGL_LOG_FUNC_EXIT(NULL);
1680 }
1681
1682 void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params)
1683 {
1684     struct yagl_gles_framebuffer *framebuffer_obj = NULL;
1685     yagl_gles_framebuffer_attachment framebuffer_attachment;
1686
1687     YAGL_LOG_FUNC_ENTER_SPLIT4(glGetFramebufferAttachmentParameteriv, GLenum, GLenum, GLenum, GLint*, target, attachment, pname, params);
1688
1689     YAGL_GET_CTX();
1690
1691     if (!yagl_gles_context_acquire_binded_framebuffer(ctx, target, &framebuffer_obj)) {
1692         YAGL_SET_ERR(GL_INVALID_ENUM);
1693         goto out;
1694     }
1695
1696     if (!framebuffer_obj) {
1697         /*
1698          * Default framebuffer, special handling.
1699          */
1700
1701         switch (attachment) {
1702         case GL_BACK:
1703         case GL_DEPTH:
1704         case GL_STENCIL:
1705             break;
1706         default:
1707             YAGL_SET_ERR(GL_INVALID_OPERATION);
1708             goto out;
1709         }
1710
1711         switch (pname) {
1712         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
1713             *params = GL_FRAMEBUFFER_DEFAULT;
1714             break;
1715         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
1716             *params = 0;
1717             break;
1718         case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
1719         case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
1720         case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
1721         case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
1722         case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
1723         case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
1724         case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
1725             /*
1726              * TODO: implement.
1727              */
1728             *params = 0;
1729             break;
1730         case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
1731             *params = GL_LINEAR;
1732             break;
1733         default:
1734             YAGL_SET_ERR(GL_INVALID_ENUM);
1735             break;
1736         }
1737
1738         goto out;
1739     }
1740
1741     if ((ctx->base.client_api == yagl_client_api_gles3) &&
1742         (attachment == GL_DEPTH_STENCIL_ATTACHMENT)) {
1743         if (memcmp(&framebuffer_obj->attachment_states[yagl_gles_framebuffer_attachment_depth],
1744                    &framebuffer_obj->attachment_states[yagl_gles_framebuffer_attachment_stencil],
1745                    sizeof(struct yagl_gles_framebuffer_attachment_state)) != 0) {
1746             YAGL_SET_ERR(GL_INVALID_OPERATION);
1747             goto out;
1748         }
1749         framebuffer_attachment = yagl_gles_framebuffer_attachment_depth;
1750     } else if (!yagl_gles_validate_framebuffer_attachment(attachment,
1751                                                           ctx->max_color_attachments,
1752                                                           &framebuffer_attachment)) {
1753         YAGL_SET_ERR(GL_INVALID_ENUM);
1754         goto out;
1755     }
1756
1757     switch (pname) {
1758     case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
1759         *params = framebuffer_obj->attachment_states[framebuffer_attachment].type;
1760         break;
1761     case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
1762         *params = framebuffer_obj->attachment_states[framebuffer_attachment].local_name;
1763         break;
1764     case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
1765         if (framebuffer_obj->attachment_states[framebuffer_attachment].type == GL_TEXTURE) {
1766             *params = 0;
1767         } else {
1768             YAGL_SET_ERR(GL_INVALID_ENUM);
1769         }
1770         break;
1771     case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
1772         if (framebuffer_obj->attachment_states[framebuffer_attachment].type == GL_TEXTURE) {
1773             *params =
1774                 (framebuffer_obj->attachment_states[framebuffer_attachment].textarget == GL_TEXTURE_2D)
1775                 ? 0 : framebuffer_obj->attachment_states[framebuffer_attachment].textarget;
1776         } else {
1777             YAGL_SET_ERR(GL_INVALID_ENUM);
1778         }
1779         break;
1780     case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
1781         if (framebuffer_obj->attachment_states[framebuffer_attachment].type == GL_TEXTURE) {
1782             *params = framebuffer_obj->attachment_states[framebuffer_attachment].layer;
1783         } else {
1784             YAGL_SET_ERR(GL_INVALID_ENUM);
1785         }
1786         break;
1787     default:
1788         if (framebuffer_obj->attachment_states[framebuffer_attachment].type != GL_NONE) {
1789             GLenum internalformat = 0;
1790             const struct yagl_gles_format_info *format_info;
1791
1792             yagl_gles_framebuffer_attachment_internalformat(
1793                 &framebuffer_obj->attachment_states[framebuffer_attachment],
1794                 &internalformat);
1795
1796             format_info = yagl_gles_internalformat_info(internalformat);
1797
1798             switch (pname) {
1799             case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
1800                 *params = format_info->red_size;
1801                 break;
1802             case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
1803                 *params = format_info->green_size;
1804                 break;
1805             case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
1806                 *params = format_info->blue_size;
1807                 break;
1808             case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
1809                 *params = format_info->alpha_size;
1810                 break;
1811             case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
1812                 *params = format_info->depth_size;
1813                 break;
1814             case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
1815                 *params = format_info->stencil_size;
1816                 break;
1817             case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
1818                 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
1819                     YAGL_SET_ERR(GL_INVALID_OPERATION);
1820                 } else {
1821                     /*
1822                      * TODO: implement.
1823                      */
1824                     *params = 0;
1825                 }
1826                 break;
1827             case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
1828                 *params = ((format_info->flags & yagl_gles_format_srgb) != 0) ?
1829                           GL_SRGB : GL_LINEAR;
1830                 break;
1831             default:
1832                 YAGL_SET_ERR(GL_INVALID_ENUM);
1833                 break;
1834             }
1835         } else {
1836             YAGL_SET_ERR(GL_INVALID_ENUM);
1837         }
1838         break;
1839     }
1840
1841 out:
1842     yagl_gles_framebuffer_release(framebuffer_obj);
1843
1844     YAGL_LOG_FUNC_EXIT(NULL);
1845 }
1846
1847 YAGL_API void glGetIntegerv(GLenum pname, GLint *params)
1848 {
1849     uint32_t i, num = 0;
1850     int needs_map = 0;
1851
1852     YAGL_LOG_FUNC_ENTER_SPLIT2(glGetIntegerv, GLenum, GLint*, pname, params);
1853
1854     YAGL_GET_CTX();
1855
1856     if (!yagl_gles_context_get_integerv(ctx, pname, params, &num)) {
1857         GLfloat floats[100]; // This fits all cases.
1858         if (yagl_gles_context_get_floatv(ctx, pname, floats, &num, &needs_map)) {
1859             for (i = 0; i < num; ++i) {
1860                 if (needs_map) {
1861                     params[i] = 2147483647.0 * floats[i];
1862                 } else {
1863                     params[i] = floats[i];
1864                 }
1865             }
1866         } else {
1867             YAGL_SET_ERR(GL_INVALID_ENUM);
1868         }
1869     }
1870
1871     YAGL_LOG_FUNC_EXIT(NULL);
1872 }
1873
1874 void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
1875 {
1876     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetRenderbufferParameteriv, GLenum, GLenum, GLint*, target, pname, params);
1877
1878     YAGL_GET_CTX();
1879
1880     /*
1881      * TODO: Passthrough for now.
1882      */
1883
1884     yagl_host_glGetRenderbufferParameteriv(target, pname, params);
1885
1886     YAGL_LOG_FUNC_EXIT(NULL);
1887 }
1888
1889 YAGL_API void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
1890 {
1891     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetTexParameterfv, GLenum, GLenum, GLfloat*, target, pname, params);
1892
1893     YAGL_GET_CTX();
1894
1895     if (!yagl_gles_context_get_tex_parameterfv(ctx, target, pname, params)) {
1896         YAGL_SET_ERR(GL_INVALID_ENUM);
1897     }
1898
1899     YAGL_LOG_FUNC_EXIT(NULL);
1900 }
1901
1902 YAGL_API void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
1903 {
1904     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetTexParameteriv, GLenum, GLenum, GLint*, target, pname, params);
1905
1906     YAGL_GET_CTX();
1907
1908     if (!yagl_gles_context_get_tex_parameteriv(ctx, target, pname, params)) {
1909         YAGL_SET_ERR(GL_INVALID_ENUM);
1910     }
1911
1912     YAGL_LOG_FUNC_EXIT(NULL);
1913 }
1914
1915 YAGL_API GLboolean glIsBuffer(GLuint buffer)
1916 {
1917     GLboolean res = GL_FALSE;
1918     struct yagl_gles_buffer *buffer_obj = NULL;
1919
1920     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsBuffer, GLuint, buffer);
1921
1922     YAGL_GET_CTX_RET(GL_FALSE);
1923
1924     buffer_obj = (struct yagl_gles_buffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
1925         YAGL_NS_BUFFER, buffer);
1926
1927     if (buffer_obj && yagl_gles_buffer_was_bound(buffer_obj)) {
1928         res = GL_TRUE;
1929     }
1930
1931     yagl_gles_buffer_release(buffer_obj);
1932
1933     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
1934
1935     return res;
1936 }
1937
1938 YAGL_API GLboolean glIsEnabled(GLenum cap)
1939 {
1940     GLboolean res;
1941
1942     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsEnabled, GLenum, cap);
1943
1944     YAGL_GET_CTX_RET(GL_FALSE);
1945
1946     res = yagl_gles_context_is_enabled(ctx, cap);
1947
1948     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
1949
1950     return res;
1951 }
1952
1953 GLboolean glIsFramebuffer(GLuint framebuffer)
1954 {
1955     GLboolean res = GL_FALSE;
1956     struct yagl_gles_framebuffer *framebuffer_obj = NULL;
1957
1958     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsFramebuffer, GLuint, framebuffer);
1959
1960     YAGL_GET_CTX_RET(GL_FALSE);
1961
1962     framebuffer_obj = (struct yagl_gles_framebuffer*)yagl_namespace_acquire(&ctx->framebuffers,
1963         framebuffer);
1964
1965     if (framebuffer_obj && yagl_gles_framebuffer_was_bound(framebuffer_obj)) {
1966         res = GL_TRUE;
1967     }
1968
1969     yagl_gles_framebuffer_release(framebuffer_obj);
1970
1971     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
1972
1973     return res;
1974 }
1975
1976 GLboolean glIsRenderbuffer(GLuint renderbuffer)
1977 {
1978     GLboolean res = GL_FALSE;
1979     struct yagl_gles_renderbuffer *renderbuffer_obj = NULL;
1980
1981     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsRenderbuffer, GLuint, renderbuffer);
1982
1983     YAGL_GET_CTX_RET(GL_FALSE);
1984
1985     renderbuffer_obj = (struct yagl_gles_renderbuffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
1986         YAGL_NS_RENDERBUFFER, renderbuffer);
1987
1988     if (renderbuffer_obj && yagl_gles_renderbuffer_was_bound(renderbuffer_obj)) {
1989         res = GL_TRUE;
1990     }
1991
1992     yagl_gles_renderbuffer_release(renderbuffer_obj);
1993
1994     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
1995
1996     return res;
1997 }
1998
1999 YAGL_API GLboolean glIsTexture(GLuint texture)
2000 {
2001     GLboolean res = GL_FALSE;
2002     struct yagl_gles_texture *texture_obj = NULL;
2003
2004     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsTexture, GLuint, texture);
2005
2006     YAGL_GET_CTX_RET(GL_FALSE);
2007
2008     texture_obj = (struct yagl_gles_texture*)yagl_sharegroup_acquire_object(ctx->base.sg,
2009         YAGL_NS_TEXTURE, texture);
2010
2011     if (texture_obj && (texture_obj->target != 0)) {
2012         res = GL_TRUE;
2013     }
2014
2015     yagl_gles_texture_release(texture_obj);
2016
2017     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
2018
2019     return res;
2020 }
2021
2022 YAGL_API void glPixelStorei(GLenum pname, GLint param)
2023 {
2024     YAGL_LOG_FUNC_ENTER_SPLIT2(glPixelStorei, GLenum, GLint, pname, param);
2025
2026     YAGL_GET_CTX();
2027
2028     /*
2029      * We don't pass GL_XXX_SKIP_YYY to host, this
2030      * is intentionally so that we can pass less data later in glTexImage*
2031      * and glReadPixels, i.e. we process skips ourselves and feed biased
2032      * data to host.
2033      */
2034
2035     switch (pname) {
2036     case GL_PACK_ALIGNMENT:
2037         if (yagl_gles_is_alignment_valid(param)) {
2038             ctx->pack.alignment = param;
2039         } else {
2040             YAGL_SET_ERR(GL_INVALID_VALUE);
2041             goto out;
2042         }
2043         break;
2044     case GL_PACK_ROW_LENGTH:
2045         if (param >= 0) {
2046             ctx->pack.row_length = param;
2047         } else {
2048             YAGL_SET_ERR(GL_INVALID_VALUE);
2049             goto out;
2050         }
2051         break;
2052     case GL_PACK_IMAGE_HEIGHT:
2053         if (param >= 0) {
2054             ctx->pack.image_height = param;
2055         } else {
2056             YAGL_SET_ERR(GL_INVALID_VALUE);
2057             goto out;
2058         }
2059         break;
2060     case GL_PACK_SKIP_PIXELS:
2061         if (param >= 0) {
2062             ctx->pack.skip_pixels = param;
2063         } else {
2064             YAGL_SET_ERR(GL_INVALID_VALUE);
2065         }
2066         goto out;
2067         break;
2068     case GL_PACK_SKIP_ROWS:
2069         if (param >= 0) {
2070             ctx->pack.skip_rows = param;
2071         } else {
2072             YAGL_SET_ERR(GL_INVALID_VALUE);
2073         }
2074         goto out;
2075         break;
2076     case GL_PACK_SKIP_IMAGES:
2077         if (param >= 0) {
2078             ctx->pack.skip_images = param;
2079         } else {
2080             YAGL_SET_ERR(GL_INVALID_VALUE);
2081         }
2082         goto out;
2083         break;
2084     case GL_UNPACK_ALIGNMENT:
2085         if (yagl_gles_is_alignment_valid(param)) {
2086             ctx->unpack.alignment = param;
2087         } else {
2088             YAGL_SET_ERR(GL_INVALID_VALUE);
2089             goto out;
2090         }
2091         break;
2092     case GL_UNPACK_ROW_LENGTH:
2093         if (param >= 0) {
2094             ctx->unpack.row_length = param;
2095         } else {
2096             YAGL_SET_ERR(GL_INVALID_VALUE);
2097             goto out;
2098         }
2099         break;
2100     case GL_UNPACK_IMAGE_HEIGHT:
2101         if (param >= 0) {
2102             ctx->unpack.image_height = param;
2103         } else {
2104             YAGL_SET_ERR(GL_INVALID_VALUE);
2105             goto out;
2106         }
2107         break;
2108     case GL_UNPACK_SKIP_PIXELS:
2109         if (param >= 0) {
2110             ctx->unpack.skip_pixels = param;
2111         } else {
2112             YAGL_SET_ERR(GL_INVALID_VALUE);
2113         }
2114         goto out;
2115         break;
2116     case GL_UNPACK_SKIP_ROWS:
2117         if (param >= 0) {
2118             ctx->unpack.skip_rows = param;
2119         } else {
2120             YAGL_SET_ERR(GL_INVALID_VALUE);
2121         }
2122         goto out;
2123         break;
2124     case GL_UNPACK_SKIP_IMAGES:
2125         if (param >= 0) {
2126             ctx->unpack.skip_images = param;
2127         } else {
2128             YAGL_SET_ERR(GL_INVALID_VALUE);
2129         }
2130         goto out;
2131         break;
2132     default:
2133         YAGL_SET_ERR(GL_INVALID_ENUM);
2134         goto out;
2135     }
2136
2137     yagl_host_glPixelStorei(pname, param);
2138
2139 out:
2140     YAGL_LOG_FUNC_EXIT(NULL);
2141 }
2142
2143 YAGL_API void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
2144 {
2145     struct yagl_pixel_format *pf;
2146     GLsizei size;
2147     int using_pbo = 0;
2148
2149     YAGL_LOG_FUNC_ENTER_SPLIT7(glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*, x, y, width, height, format, type, pixels);
2150
2151     YAGL_GET_CTX();
2152
2153     if ((width < 0) || (height < 0)) {
2154         YAGL_SET_ERR(GL_INVALID_VALUE);
2155         goto out;
2156     }
2157
2158     if ((width == 0) || (height == 0)) {
2159         width = height = 0;
2160     }
2161
2162     pf = yagl_gles_context_validate_getteximage_format(ctx, format, type);
2163
2164     if (!pf) {
2165         YAGL_SET_ERR(GL_INVALID_OPERATION);
2166         goto out;
2167     }
2168
2169     yagl_render_invalidate(0);
2170
2171     if ((width != 0) && !yagl_gles_context_pre_pack(ctx, &pixels, pf->need_convert, &using_pbo)) {
2172         YAGL_SET_ERR(GL_INVALID_OPERATION);
2173         goto out;
2174     }
2175
2176     pixels += yagl_pixel_format_get_info(pf, &ctx->pack,
2177                                          width, height, 1, &size);
2178
2179     if (using_pbo) {
2180         yagl_host_glReadPixelsOffset(x, y,
2181                                      width, height,
2182                                      pf->dst_format,
2183                                      pf->dst_type,
2184                                      (GLsizei)pixels);
2185     } else {
2186         GLvoid *pixels_from;
2187
2188         pixels_from = yagl_pixel_format_pack_alloc(pf, &ctx->pack,
2189                                                    width,
2190                                                    height,
2191                                                    pixels);
2192
2193         yagl_host_glReadPixelsData(x, y,
2194                                    width, height,
2195                                    pf->dst_format,
2196                                    pf->dst_type,
2197                                    pixels_from,
2198                                    size,
2199                                    NULL);
2200
2201         yagl_pixel_format_pack(pf, &ctx->pack,
2202                                width,
2203                                height,
2204                                pixels_from,
2205                                pixels);
2206     }
2207
2208     if (width != 0) {
2209         yagl_gles_context_post_pack(ctx, pixels, size, pf->need_convert);
2210     }
2211
2212 out:
2213     YAGL_LOG_FUNC_EXIT(NULL);
2214 }
2215
2216 YAGL_API void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
2217 {
2218     GLenum squashed_target;
2219     yagl_gles_texture_target texture_target;
2220     struct yagl_gles_texture_target_state *tex_target_state;
2221     struct yagl_pixel_format *pf;
2222     GLsizei size;
2223     int using_pbo = 0;
2224
2225     YAGL_LOG_FUNC_ENTER_SPLIT9(glTexImage2D, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*, target, level, internalformat, width, height, border, format, type, pixels);
2226
2227     YAGL_GET_CTX();
2228
2229     if ((width < 0) || (height < 0)) {
2230         YAGL_SET_ERR(GL_INVALID_VALUE);
2231         goto out;
2232     }
2233
2234     if (!yagl_gles_validate_texture_target_squash(target, &squashed_target)) {
2235         YAGL_SET_ERR(GL_INVALID_ENUM);
2236         goto out;
2237     }
2238
2239     if (!yagl_gles_context_validate_texture_target(ctx,
2240                                                    squashed_target,
2241                                                    &texture_target)) {
2242         YAGL_SET_ERR(GL_INVALID_ENUM);
2243         goto out;
2244     }
2245
2246     if (squashed_target == GL_TEXTURE_CUBE_MAP && width != height) {
2247         YAGL_SET_ERR(GL_INVALID_VALUE);
2248         goto out;
2249     }
2250
2251     tex_target_state =
2252         yagl_gles_context_get_active_texture_target_state(ctx, texture_target);
2253
2254     if ((width == 0) || (height == 0)) {
2255         width = height = 0;
2256     }
2257
2258     pf = yagl_gles_context_validate_teximage_format(ctx, internalformat, format, type);
2259
2260     if (!pf) {
2261         YAGL_SET_ERR(GL_INVALID_OPERATION);
2262         goto out;
2263     }
2264
2265     if ((width != 0) && !yagl_gles_context_pre_unpack(ctx, &pixels, pf->need_convert, &using_pbo)) {
2266         YAGL_SET_ERR(GL_INVALID_OPERATION);
2267         goto out;
2268     }
2269
2270     if (target == GL_TEXTURE_2D) {
2271         if (tex_target_state->texture != tex_target_state->texture_zero) {
2272             /*
2273              * This operation should orphan EGLImage according
2274              * to OES_EGL_image specs.
2275              *
2276              * This operation should release TexImage according
2277              * to eglBindTexImage spec.
2278              */
2279             yagl_gles_texture_unset_image(tex_target_state->texture);
2280         }
2281     }
2282
2283     if (pixels || using_pbo) {
2284         pixels += yagl_pixel_format_get_info(pf, &ctx->unpack,
2285                                              width, height, 1, &size);
2286     } else {
2287         yagl_pixel_format_get_info(pf, &ctx->unpack,
2288                                    width, height, 1, &size);
2289     }
2290
2291     if (using_pbo) {
2292         yagl_host_glTexImage2DOffset(target,
2293                                      level,
2294                                      pf->dst_internalformat,
2295                                      width,
2296                                      height,
2297                                      border,
2298                                      pf->dst_format,
2299                                      pf->dst_type,
2300                                      (GLsizei)pixels);
2301     } else {
2302         yagl_host_glTexImage2DData(target,
2303                                    level,
2304                                    pf->dst_internalformat,
2305                                    width,
2306                                    height,
2307                                    border,
2308                                    pf->dst_format,
2309                                    pf->dst_type,
2310                                    yagl_pixel_format_unpack(pf, &ctx->unpack,
2311                                                             width,
2312                                                             height,
2313                                                             1,
2314                                                             pixels),
2315                                    size);
2316     }
2317
2318     if (width != 0) {
2319         yagl_gles_context_post_unpack(ctx, pf->need_convert);
2320     }
2321
2322     yagl_gles_texture_set_internalformat(tex_target_state->texture,
2323                                          internalformat,
2324                                          type,
2325                                          yagl_gles_context_convert_textures(ctx));
2326
2327 out:
2328     YAGL_LOG_FUNC_EXIT(NULL);
2329 }
2330
2331 YAGL_API void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
2332 {
2333     GLenum squashed_target;
2334     yagl_gles_texture_target texture_target;
2335     struct yagl_gles_texture_target_state *tex_target_state;
2336     struct yagl_pixel_format *pf;
2337     GLsizei size;
2338     int using_pbo = 0;
2339
2340     YAGL_LOG_FUNC_ENTER_SPLIT9(glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*, target, level, xoffset, yoffset, width, height, format, type, pixels);
2341
2342     YAGL_GET_CTX();
2343
2344     if ((width < 0) || (height < 0)) {
2345         YAGL_SET_ERR(GL_INVALID_VALUE);
2346         goto out;
2347     }
2348
2349     if (!yagl_gles_validate_texture_target_squash(target, &squashed_target)) {
2350         YAGL_SET_ERR(GL_INVALID_ENUM);
2351         goto out;
2352     }
2353
2354     if (!yagl_gles_context_validate_texture_target(ctx,
2355                                                    squashed_target,
2356                                                    &texture_target)) {
2357         YAGL_SET_ERR(GL_INVALID_ENUM);
2358         goto out;
2359     }
2360
2361     tex_target_state =
2362         yagl_gles_context_get_active_texture_target_state(ctx, texture_target);
2363
2364     if ((width == 0) || (height == 0)) {
2365         width = height = 0;
2366     }
2367
2368     pf = yagl_gles_context_validate_teximage_format(ctx,
2369         tex_target_state->texture->internalformat, format, type);
2370
2371     if (!pf) {
2372         YAGL_SET_ERR(GL_INVALID_OPERATION);
2373         goto out;
2374     }
2375
2376     if ((width != 0) && !yagl_gles_context_pre_unpack(ctx, &pixels, pf->need_convert, &using_pbo)) {
2377         YAGL_SET_ERR(GL_INVALID_OPERATION);
2378         goto out;
2379     }
2380
2381     pixels += yagl_pixel_format_get_info(pf, &ctx->unpack,
2382                                          width, height, 1, &size);
2383
2384     if (using_pbo) {
2385         yagl_host_glTexSubImage2DOffset(target,
2386                                         level,
2387                                         xoffset,
2388                                         yoffset,
2389                                         width,
2390                                         height,
2391                                         pf->dst_format,
2392                                         pf->dst_type,
2393                                         (GLsizei)pixels);
2394     } else {
2395         yagl_host_glTexSubImage2DData(target,
2396                                       level,
2397                                       xoffset,
2398                                       yoffset,
2399                                       width,
2400                                       height,
2401                                       pf->dst_format,
2402                                       pf->dst_type,
2403                                       yagl_pixel_format_unpack(pf, &ctx->unpack,
2404                                                                width,
2405                                                                height,
2406                                                                1,
2407                                                                pixels),
2408                                       size);
2409     }
2410
2411     if (width != 0) {
2412         yagl_gles_context_post_unpack(ctx, pf->need_convert);
2413     }
2414
2415 out:
2416     YAGL_LOG_FUNC_EXIT(NULL);
2417 }
2418
2419 YAGL_API void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
2420 {
2421     struct yagl_gles_image *image_obj = NULL;
2422     struct yagl_gles_texture_target_state *tex_target_state;
2423
2424     YAGL_LOG_FUNC_ENTER_SPLIT2(glEGLImageTargetTexture2DOES, GLenum, GLeglImageOES, target, image);
2425
2426     YAGL_GET_CTX();
2427
2428     if (target != GL_TEXTURE_2D) {
2429         YAGL_SET_ERR(GL_INVALID_ENUM);
2430         goto out;
2431     }
2432
2433     image_obj = (struct yagl_gles_image*)yagl_acquire_client_image((yagl_host_handle)image);
2434
2435     if (!image_obj) {
2436         YAGL_SET_ERR(GL_INVALID_OPERATION);
2437         goto out;
2438     }
2439
2440     tex_target_state =
2441         yagl_gles_context_get_active_texture_target_state(ctx,
2442                                                           yagl_gles_texture_target_2d);
2443
2444     if (tex_target_state->texture == tex_target_state->texture_zero) {
2445         YAGL_SET_ERR(GL_INVALID_OPERATION);
2446         goto out;
2447     }
2448
2449     yagl_gles_texture_set_image(tex_target_state->texture, image_obj);
2450
2451 out:
2452     yagl_gles_image_release(image_obj);
2453
2454     YAGL_LOG_FUNC_EXIT(NULL);
2455 }
2456
2457 YAGL_API void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
2458 {
2459     fprintf(stderr, "glEGLImageTargetRenderbufferStorageOES not supported in YaGL\n");
2460 }
2461
2462 /*
2463  *  GL_ANGLE_framebuffer_blit.
2464  * @{
2465  */
2466
2467 YAGL_API void glBlitFramebuffer(GLint srcX0, GLint srcY0,
2468                                 GLint srcX1, GLint srcY1,
2469                                 GLint dstX0, GLint dstY0,
2470                                 GLint dstX1, GLint dstY1,
2471                                 GLbitfield mask, GLenum filter)
2472 {
2473     GLenum read_status, draw_status;
2474
2475     YAGL_LOG_FUNC_ENTER_SPLIT10(glBlitFramebuffer, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
2476
2477     YAGL_GET_CTX();
2478
2479     if (mask & ~(GL_COLOR_BUFFER_BIT |
2480                  GL_DEPTH_BUFFER_BIT |
2481                  GL_STENCIL_BUFFER_BIT)) {
2482         YAGL_SET_ERR(GL_INVALID_VALUE);
2483         goto out;
2484     }
2485
2486     switch (filter) {
2487     case GL_NEAREST:
2488     case GL_LINEAR:
2489         break;
2490     default:
2491         YAGL_SET_ERR(GL_INVALID_VALUE);
2492         goto out;
2493     }
2494
2495     if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) &&
2496         (filter != GL_NEAREST)) {
2497         YAGL_SET_ERR(GL_INVALID_OPERATION);
2498         goto out;
2499     }
2500
2501     read_status = yagl_gles_context_check_framebuffer_status(ctx,
2502                                                              ctx->fbo_read);
2503
2504     if (read_status != GL_FRAMEBUFFER_COMPLETE) {
2505         YAGL_SET_ERR(GL_INVALID_FRAMEBUFFER_OPERATION);
2506         goto out;
2507     }
2508
2509     draw_status = yagl_gles_context_check_framebuffer_status(ctx,
2510                                                              ctx->fbo_draw);
2511
2512     if (draw_status != GL_FRAMEBUFFER_COMPLETE) {
2513         YAGL_SET_ERR(GL_INVALID_FRAMEBUFFER_OPERATION);
2514         goto out;
2515     }
2516
2517     if (!ctx->min_mag_blits &&
2518         ((abs(dstX0 - dstX1) != abs(srcX0 - srcX1)) ||
2519          (abs(dstY0 - dstY1) != abs(srcY0 - srcY1)))) {
2520         /*
2521          * Minifying/magnifying blits cause crashes with some host OpenGL
2522          * drivers, so disable them for now.
2523          */
2524         YAGL_SET_ERR(GL_INVALID_OPERATION);
2525         goto out;
2526     }
2527
2528     yagl_render_invalidate(0);
2529
2530     yagl_host_glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
2531
2532 out:
2533     YAGL_LOG_FUNC_EXIT(NULL);
2534 }
2535 YAGL_API YAGL_ALIAS(glBlitFramebuffer, glBlitFramebufferANGLE);
2536
2537 /*
2538  * @}
2539  */
2540
2541 /*
2542  * GL_OES_vertex_array_object.
2543  * @{
2544  */
2545
2546 YAGL_API void glBindVertexArray(GLuint array)
2547 {
2548     struct yagl_gles_vertex_array *va_obj = NULL;
2549
2550     YAGL_LOG_FUNC_ENTER_SPLIT1(glBindVertexArray, GLuint, array);
2551
2552     YAGL_GET_CTX();
2553
2554     if (!ctx->vertex_arrays_supported) {
2555         YAGL_SET_ERR(GL_INVALID_OPERATION);
2556         goto out;
2557     }
2558
2559     if (array != 0) {
2560         va_obj = (struct yagl_gles_vertex_array*)yagl_namespace_acquire(&ctx->vertex_arrays,
2561             array);
2562
2563         if (!va_obj) {
2564             YAGL_SET_ERR(GL_INVALID_OPERATION);
2565             goto out;
2566         }
2567     }
2568
2569     yagl_gles_context_bind_vertex_array(ctx, va_obj);
2570
2571 out:
2572     yagl_gles_vertex_array_release(va_obj);
2573
2574     YAGL_LOG_FUNC_EXIT(NULL);
2575 }
2576 YAGL_API YAGL_ALIAS(glBindVertexArray, glBindVertexArrayOES);
2577
2578 YAGL_API void glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
2579 {
2580     GLsizei i;
2581
2582     YAGL_LOG_FUNC_ENTER_SPLIT2(glDeleteVertexArrays, GLsizei, const GLuint*, n, arrays);
2583
2584     YAGL_GET_CTX();
2585
2586     if (!ctx->vertex_arrays_supported) {
2587         YAGL_SET_ERR(GL_INVALID_OPERATION);
2588         goto out;
2589     }
2590
2591     if (n < 0) {
2592         YAGL_SET_ERR(GL_INVALID_VALUE);
2593         goto out;
2594     }
2595
2596     if (arrays) {
2597         for (i = 0; i < n; ++i) {
2598             yagl_gles_context_unbind_vertex_array(ctx, arrays[i]);
2599             yagl_namespace_remove(&ctx->vertex_arrays, arrays[i]);
2600         }
2601     }
2602
2603 out:
2604     YAGL_LOG_FUNC_EXIT(NULL);
2605 }
2606 YAGL_API YAGL_ALIAS(glDeleteVertexArrays, glDeleteVertexArraysOES);
2607
2608 YAGL_API void glGenVertexArrays(GLsizei n, GLuint *array_names)
2609 {
2610     struct yagl_gles_vertex_array **arrays = NULL;
2611     GLsizei i;
2612
2613     YAGL_LOG_FUNC_ENTER_SPLIT2(glGenVertexArrays, GLsizei, GLuint*, n, array_names);
2614
2615     YAGL_GET_CTX();
2616
2617     if (!ctx->vertex_arrays_supported) {
2618         YAGL_SET_ERR(GL_INVALID_OPERATION);
2619         goto out;
2620     }
2621
2622     if (n < 0) {
2623         YAGL_SET_ERR(GL_INVALID_VALUE);
2624         goto out;
2625     }
2626
2627     arrays = yagl_malloc0(n * sizeof(*arrays));
2628
2629     for (i = 0; i < n; ++i) {
2630         arrays[i] = yagl_gles_vertex_array_create(0,
2631                                                   ctx->create_arrays(ctx),
2632                                                   ctx->num_arrays);
2633
2634         if (!arrays[i]) {
2635             goto out;
2636         }
2637     }
2638
2639     for (i = 0; i < n; ++i) {
2640         yagl_namespace_add(&ctx->vertex_arrays,
2641                            &arrays[i]->base);
2642
2643         if (array_names) {
2644             array_names[i] = arrays[i]->base.local_name;
2645         }
2646     }
2647
2648 out:
2649     for (i = 0; i < n; ++i) {
2650         yagl_gles_vertex_array_release(arrays[i]);
2651     }
2652     yagl_free(arrays);
2653
2654     YAGL_LOG_FUNC_EXIT(NULL);
2655 }
2656 YAGL_API YAGL_ALIAS(glGenVertexArrays, glGenVertexArraysOES);
2657
2658 YAGL_API GLboolean glIsVertexArray(GLuint array)
2659 {
2660     GLboolean res = GL_FALSE;
2661     struct yagl_gles_vertex_array *va_obj = NULL;
2662
2663     YAGL_LOG_FUNC_ENTER_SPLIT1(glIsVertexArray, GLuint, array);
2664
2665     YAGL_GET_CTX_RET(GL_FALSE);
2666
2667     if (!ctx->vertex_arrays_supported) {
2668         YAGL_SET_ERR(GL_INVALID_OPERATION);
2669         goto out;
2670     }
2671
2672     va_obj = (struct yagl_gles_vertex_array*)yagl_namespace_acquire(&ctx->vertex_arrays,
2673         array);
2674
2675     if (va_obj && yagl_gles_vertex_array_was_bound(va_obj)) {
2676         res = GL_TRUE;
2677     }
2678
2679     yagl_gles_vertex_array_release(va_obj);
2680
2681 out:
2682     YAGL_LOG_FUNC_EXIT_SPLIT(GLboolean, res);
2683
2684     return res;
2685 }
2686 YAGL_API YAGL_ALIAS(glIsVertexArray, glIsVertexArrayOES);
2687
2688 /*
2689  * @}
2690  */
2691
2692 /*
2693  * GL_EXT_draw_buffers.
2694  * @{
2695  */
2696
2697 YAGL_API void glDrawBuffers(GLsizei n, const GLenum *bufs)
2698 {
2699     GLsizei i;
2700
2701     YAGL_LOG_FUNC_ENTER_SPLIT2(glDrawBuffers, GLsizei, const GLenum*, n, bufs);
2702
2703     YAGL_GET_CTX();
2704
2705     if ((n < 0) || (n > ctx->max_draw_buffers)) {
2706         YAGL_SET_ERR(GL_INVALID_VALUE);
2707         goto out;
2708     }
2709
2710     if (ctx->fbo_draw) {
2711         for (i = 0; i < n; ++i) {
2712             if (bufs[i] == GL_NONE) {
2713                 continue;
2714             }
2715
2716             if ((bufs[i] == GL_BACK) ||
2717                 (bufs[i] >= (GL_COLOR_ATTACHMENT0 + ctx->max_color_attachments))) {
2718                 YAGL_SET_ERR(GL_INVALID_OPERATION);
2719                 goto out;
2720             }
2721
2722             if (bufs[i] < GL_COLOR_ATTACHMENT0) {
2723                 YAGL_SET_ERR(GL_INVALID_ENUM);
2724                 goto out;
2725             }
2726
2727             if ((bufs[i] - GL_COLOR_ATTACHMENT0) != i) {
2728                 YAGL_SET_ERR(GL_INVALID_OPERATION);
2729                 goto out;
2730             }
2731         }
2732
2733         memcpy(&ctx->fbo_draw->draw_buffers[0], bufs, n * sizeof(bufs[0]));
2734
2735         for (i = n; i < ctx->max_draw_buffers; ++i) {
2736             ctx->fbo_draw->draw_buffers[i] = GL_NONE;
2737         }
2738     } else {
2739         if ((n != 1) || ((bufs[0] != GL_NONE) && (bufs[0] != GL_BACK))) {
2740             YAGL_SET_ERR(GL_INVALID_OPERATION);
2741             goto out;
2742         }
2743
2744         ctx->fb0_draw_buffer = bufs[0];
2745     }
2746
2747     yagl_host_glDrawBuffers(bufs, n);
2748
2749 out:
2750     YAGL_LOG_FUNC_EXIT(NULL);
2751 }
2752 YAGL_API YAGL_ALIAS(glDrawBuffers, glDrawBuffersEXT);
2753
2754 /*
2755  * @}
2756  */
2757
2758 /*
2759  * GL_NV_read_buffer.
2760  * @{
2761  */
2762
2763 YAGL_API void glReadBuffer(GLenum mode)
2764 {
2765     YAGL_LOG_FUNC_ENTER_SPLIT1(glReadBuffer, GLenum, mode);
2766
2767     YAGL_GET_CTX();
2768
2769     if (ctx->fbo_read) {
2770         if (mode != GL_NONE) {
2771             if ((mode < GL_COLOR_ATTACHMENT0) ||
2772                 (mode >= (GL_COLOR_ATTACHMENT0 + ctx->max_color_attachments))) {
2773                 YAGL_SET_ERR(GL_INVALID_OPERATION);
2774                 goto out;
2775             }
2776         }
2777
2778         ctx->fbo_read->read_buffer = mode;
2779     } else {
2780         if ((mode != GL_NONE) && (mode != GL_BACK)) {
2781             YAGL_SET_ERR(GL_INVALID_OPERATION);
2782             goto out;
2783         }
2784
2785         ctx->fb0_read_buffer = mode;
2786     }
2787
2788     yagl_host_glReadBuffer(mode);
2789
2790 out:
2791     YAGL_LOG_FUNC_EXIT(NULL);
2792 }
2793 YAGL_API YAGL_ALIAS(glReadBuffer, glReadBufferNV);
2794
2795 /*
2796  * @}
2797  */
2798
2799 /*
2800  * GL_OES_mapbuffer.
2801  * @{
2802  */
2803
2804 YAGL_API void *glMapBuffer(GLenum target, GLenum access)
2805 {
2806     void *ptr = NULL;
2807     struct yagl_gles_buffer *buffer_obj = NULL;
2808
2809     YAGL_LOG_FUNC_ENTER_SPLIT2(glMapBuffer, GLenum, GLenum, target, access);
2810
2811     YAGL_GET_CTX_RET(NULL);
2812
2813     if (access != GL_WRITE_ONLY) {
2814         YAGL_SET_ERR(GL_INVALID_ENUM);
2815         goto out;
2816     }
2817
2818     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
2819         YAGL_SET_ERR(GL_INVALID_ENUM);
2820         goto out;
2821     }
2822
2823     if (!buffer_obj) {
2824         YAGL_SET_ERR(GL_INVALID_OPERATION);
2825         goto out;
2826     }
2827
2828     if (yagl_gles_buffer_mapped(buffer_obj)) {
2829         YAGL_SET_ERR(GL_INVALID_OPERATION);
2830         goto out;
2831     }
2832
2833     if (!yagl_gles_buffer_map(buffer_obj, 0, buffer_obj->size, GL_MAP_WRITE_BIT)) {
2834         YAGL_SET_ERR(GL_OUT_OF_MEMORY);
2835         goto out;
2836     }
2837
2838     ptr = buffer_obj->map_pointer;
2839
2840 out:
2841     yagl_gles_buffer_release(buffer_obj);
2842
2843     YAGL_LOG_FUNC_EXIT("%p", ptr);
2844
2845     return ptr;
2846 }
2847 YAGL_API YAGL_ALIAS(glMapBuffer, glMapBufferOES);
2848
2849 YAGL_API GLboolean glUnmapBuffer(GLenum target)
2850 {
2851     GLboolean ret = GL_FALSE;
2852     struct yagl_gles_buffer *buffer_obj = NULL;
2853
2854     YAGL_LOG_FUNC_ENTER_SPLIT1(glUnmapBuffer, GLenum, target);
2855
2856     YAGL_GET_CTX_RET(GL_FALSE);
2857
2858     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
2859         YAGL_SET_ERR(GL_INVALID_ENUM);
2860         goto out;
2861     }
2862
2863     if (!buffer_obj) {
2864         YAGL_SET_ERR(GL_INVALID_OPERATION);
2865         goto out;
2866     }
2867
2868     if (!yagl_gles_buffer_mapped(buffer_obj)) {
2869         YAGL_SET_ERR(GL_INVALID_OPERATION);
2870         goto out;
2871     }
2872
2873     yagl_gles_buffer_unmap(buffer_obj);
2874
2875     ret = GL_TRUE;
2876
2877 out:
2878     yagl_gles_buffer_release(buffer_obj);
2879
2880     YAGL_LOG_FUNC_EXIT("%u", ret);
2881
2882     return ret;
2883 }
2884 YAGL_API YAGL_ALIAS(glUnmapBuffer, glUnmapBufferOES);
2885
2886 YAGL_API void glGetBufferPointerv(GLenum target,
2887                                   GLenum pname,
2888                                   GLvoid **params)
2889 {
2890     struct yagl_gles_buffer *buffer_obj = NULL;
2891
2892     YAGL_LOG_FUNC_ENTER_SPLIT3(glGetBufferPointerv, GLenum, GLenum, GLvoid**, target, pname, params);
2893
2894     YAGL_GET_CTX();
2895
2896     if (pname != GL_BUFFER_MAP_POINTER) {
2897         YAGL_SET_ERR(GL_INVALID_ENUM);
2898         goto out;
2899     }
2900
2901     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
2902         YAGL_SET_ERR(GL_INVALID_ENUM);
2903         goto out;
2904     }
2905
2906     if (!buffer_obj) {
2907         YAGL_SET_ERR(GL_INVALID_OPERATION);
2908         goto out;
2909     }
2910
2911     *params = buffer_obj->map_pointer;
2912
2913 out:
2914     yagl_gles_buffer_release(buffer_obj);
2915
2916     YAGL_LOG_FUNC_EXIT(NULL);
2917 }
2918 YAGL_API YAGL_ALIAS(glGetBufferPointerv, glGetBufferPointervOES);
2919
2920 /*
2921  * @}
2922  */
2923
2924 /*
2925  * GL_EXT_map_buffer_range.
2926  * @{
2927  */
2928
2929 YAGL_API void *glMapBufferRange(GLenum target, GLintptr offset,
2930                                 GLsizeiptr length, GLbitfield access)
2931 {
2932     void *ptr = NULL;
2933     struct yagl_gles_buffer *buffer_obj = NULL;
2934
2935     YAGL_LOG_FUNC_ENTER_SPLIT4(glMapBufferRange, GLenum, GLintptr, GLsizeiptr, GLbitfield, target, offset, length, access);
2936
2937     YAGL_GET_CTX_RET(NULL);
2938
2939     if ((offset < 0) || (length < 0)) {
2940         YAGL_SET_ERR(GL_INVALID_VALUE);
2941         goto out;
2942     }
2943
2944     if (length == 0) {
2945         YAGL_SET_ERR(GL_INVALID_OPERATION);
2946         goto out;
2947     }
2948
2949     if (access & ~(GL_MAP_READ_BIT |
2950                    GL_MAP_WRITE_BIT |
2951                    GL_MAP_INVALIDATE_RANGE_BIT |
2952                    GL_MAP_INVALIDATE_BUFFER_BIT |
2953                    GL_MAP_FLUSH_EXPLICIT_BIT |
2954                    GL_MAP_UNSYNCHRONIZED_BIT)) {
2955         YAGL_SET_ERR(GL_INVALID_VALUE);
2956         goto out;
2957     }
2958
2959     if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
2960         YAGL_SET_ERR(GL_INVALID_OPERATION);
2961         goto out;
2962     }
2963
2964     if ((access & GL_MAP_READ_BIT) &&
2965         (access & (GL_MAP_INVALIDATE_RANGE_BIT |
2966                    GL_MAP_INVALIDATE_BUFFER_BIT |
2967                    GL_MAP_UNSYNCHRONIZED_BIT))) {
2968         YAGL_SET_ERR(GL_INVALID_OPERATION);
2969         goto out;
2970     }
2971
2972     if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
2973         ((access & GL_MAP_WRITE_BIT) == 0)) {
2974         YAGL_SET_ERR(GL_INVALID_OPERATION);
2975         goto out;
2976     }
2977
2978     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
2979         YAGL_SET_ERR(GL_INVALID_ENUM);
2980         goto out;
2981     }
2982
2983     if (!buffer_obj) {
2984         YAGL_SET_ERR(GL_INVALID_OPERATION);
2985         goto out;
2986     }
2987
2988     if (yagl_gles_buffer_mapped(buffer_obj)) {
2989         YAGL_SET_ERR(GL_INVALID_OPERATION);
2990         goto out;
2991     }
2992
2993     if (!yagl_gles_buffer_map(buffer_obj, offset, length, access)) {
2994         YAGL_SET_ERR(GL_INVALID_VALUE);
2995         goto out;
2996     }
2997
2998     ptr = buffer_obj->map_pointer;
2999
3000 out:
3001     yagl_gles_buffer_release(buffer_obj);
3002
3003     YAGL_LOG_FUNC_EXIT("%p", ptr);
3004
3005     return ptr;
3006 }
3007 YAGL_API YAGL_ALIAS(glMapBufferRange, glMapBufferRangeEXT);
3008
3009 YAGL_API void glFlushMappedBufferRange(GLenum target, GLintptr offset,
3010                                        GLsizeiptr length)
3011 {
3012     struct yagl_gles_buffer *buffer_obj = NULL;
3013
3014     YAGL_LOG_FUNC_ENTER_SPLIT3(glFlushMappedBufferRange, GLenum, GLintptr, GLsizeiptr, target, offset, length);
3015
3016     YAGL_GET_CTX();
3017
3018     if ((offset < 0) || (length < 0)) {
3019         YAGL_SET_ERR(GL_INVALID_VALUE);
3020         goto out;
3021     }
3022
3023     if (!yagl_gles_context_acquire_binded_buffer(ctx, target, &buffer_obj)) {
3024         YAGL_SET_ERR(GL_INVALID_ENUM);
3025         goto out;
3026     }
3027
3028     if (!buffer_obj) {
3029         YAGL_SET_ERR(GL_INVALID_OPERATION);
3030         goto out;
3031     }
3032
3033     if (!yagl_gles_buffer_mapped(buffer_obj)) {
3034         YAGL_SET_ERR(GL_INVALID_OPERATION);
3035         goto out;
3036     }
3037
3038     if ((buffer_obj->map_access & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
3039         YAGL_SET_ERR(GL_INVALID_OPERATION);
3040         goto out;
3041     }
3042
3043     if (!yagl_gles_buffer_flush_mapped_range(buffer_obj, offset, length)) {
3044         YAGL_SET_ERR(GL_INVALID_VALUE);
3045         goto out;
3046     }
3047
3048 out:
3049     yagl_gles_buffer_release(buffer_obj);
3050
3051     YAGL_LOG_FUNC_EXIT(NULL);
3052 }
3053 YAGL_API YAGL_ALIAS(glFlushMappedBufferRange, glFlushMappedBufferRangeEXT);
3054
3055 /*
3056  * @}
3057  */
3058
3059 /*
3060  * GL_EXT_texture_storage.
3061  * @{
3062  */
3063
3064 YAGL_API void glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
3065 {
3066     yagl_gles_texture_target texture_target;
3067     struct yagl_gles_texture_target_state *tex_target_state;
3068     GLenum base_internalformat, format, type;
3069     GLsizei i, j;
3070     GLenum cubemap_targets[] =
3071     {
3072         GL_TEXTURE_CUBE_MAP_POSITIVE_X,
3073         GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
3074         GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
3075         GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
3076         GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
3077         GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
3078     };
3079
3080     YAGL_LOG_FUNC_ENTER_SPLIT5(glTexStorage2D, GLenum, GLsizei, GLenum, GLsizei, GLsizei, target, levels, internalformat, width, height);
3081
3082     YAGL_GET_CTX();
3083
3084     if ((levels <= 0) || (width <= 0) || (height <= 0)) {
3085         YAGL_SET_ERR(GL_INVALID_VALUE);
3086         goto out;
3087     }
3088
3089     if (!yagl_gles_context_validate_texstorage_format(ctx,
3090                                                       &internalformat,
3091                                                       &base_internalformat,
3092                                                       &format,
3093                                                       &type)) {
3094         YAGL_SET_ERR(GL_INVALID_ENUM);
3095         goto out;
3096     }
3097
3098     if (!yagl_gles_context_validate_texture_target(ctx, target, &texture_target)) {
3099         YAGL_SET_ERR(GL_INVALID_ENUM);
3100         goto out;
3101     }
3102
3103     tex_target_state = yagl_gles_context_get_active_texture_target_state(ctx,
3104                                                                          texture_target);
3105
3106     if ((tex_target_state->texture == tex_target_state->texture_zero) ||
3107         tex_target_state->texture->immutable) {
3108         YAGL_SET_ERR(GL_INVALID_OPERATION);
3109         goto out;
3110     }
3111
3112     switch (texture_target) {
3113     case yagl_gles_texture_target_2d:
3114         for (i = 0; i < levels; ++i) {
3115             yagl_host_glTexImage2DData(target, i, internalformat,
3116                                        width, height, 0, format, type,
3117                                        NULL, 0);
3118
3119             width >>= 1;
3120             if (width == 0) {
3121                 width = 1;
3122             }
3123
3124             height >>= 1;
3125             if (height == 0) {
3126                 height = 1;
3127             }
3128         }
3129         break;
3130     case yagl_gles_texture_target_cubemap:
3131         for (i = 0; i < levels; ++i) {
3132             for (j = 0;
3133                  j < sizeof(cubemap_targets)/sizeof(cubemap_targets[0]);
3134                  ++j) {
3135                 yagl_host_glTexImage2DData(cubemap_targets[j], i, internalformat,
3136                                            width, height, 0, format, type,
3137                                            NULL, 0);
3138             }
3139
3140             width >>= 1;
3141             if (width == 0) {
3142                 width = 1;
3143             }
3144
3145             height >>= 1;
3146             if (height == 0) {
3147                 height = 1;
3148             }
3149         }
3150         break;
3151     default:
3152         YAGL_SET_ERR(GL_INVALID_ENUM);
3153         goto out;
3154     }
3155
3156     yagl_gles_texture_set_immutable(tex_target_state->texture,
3157                                     base_internalformat,
3158                                     type,
3159                                     yagl_gles_context_convert_textures(ctx));
3160
3161 out:
3162     YAGL_LOG_FUNC_EXIT(NULL);
3163 }
3164 YAGL_API YAGL_ALIAS(glTexStorage2D, glTexStorage2DEXT);
3165
3166 /*
3167  * @}
3168  */