tizen 2.4 release
[sdk/emulator-yagl.git] / GLESv2 / yagl_gles2_program.c
1 /*
2  * YaGL
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact :
7  * Stanislav Vorobiov <s.vorobiov@samsung.com>
8  * Jinhyung Jo <jinhyung.jo@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27  * THE SOFTWARE.
28  *
29  * Contributors:
30  * - S-Core Co., Ltd
31  *
32  */
33
34 #include "GLES2/gl2.h"
35 #include "yagl_gles2_program.h"
36 #include "yagl_gles2_shader.h"
37 #include "yagl_gles2_utils.h"
38 #include "yagl_malloc.h"
39 #include "yagl_state.h"
40 #include "yagl_transport.h"
41 #include "yagl_log.h"
42 #include "yagl_utils.h"
43 #include "yagl_host_gles_calls.h"
44 #include <string.h>
45 #include <stdlib.h>
46 #include <pthread.h>
47
48 /*
49  * We don't want to include GLES3/gl3.h here
50  */
51 #define GL_INTERLEAVED_ATTRIBS 0x8C8C
52
53 struct yagl_gles2_location_v
54 {
55     GLchar *name;
56
57     uint32_t global_location;
58 };
59
60 static pthread_once_t g_gen_locations_init = PTHREAD_ONCE_INIT;
61
62 static pthread_mutex_t g_gen_locations_mutex;
63 static uint32_t g_gen_locations_next = 0;
64
65 static void yagl_gen_locations_init()
66 {
67     yagl_mutex_init(&g_gen_locations_mutex);
68 }
69
70 static uint32_t yagl_gen_location()
71 {
72     uint32_t ret;
73
74     pthread_once(&g_gen_locations_init, yagl_gen_locations_init);
75
76     pthread_mutex_lock(&g_gen_locations_mutex);
77
78     ret = g_gen_locations_next++;
79
80     pthread_mutex_unlock(&g_gen_locations_mutex);
81
82     return ret;
83 }
84
85 static void yagl_gles2_transform_feedback_info_copy(
86     struct yagl_gles2_transform_feedback_info *from,
87     struct yagl_gles2_transform_feedback_info *to)
88 {
89     GLuint i;
90
91     yagl_gles2_transform_feedback_info_reset(to);
92
93     memcpy(to, from, sizeof(*from));
94
95     if (from->num_varyings > 0) {
96         to->varyings = yagl_malloc(to->num_varyings * sizeof(*to->varyings));
97
98         for (i = 0; i < from->num_varyings; ++i) {
99             memcpy(&to->varyings[i],
100                    &from->varyings[i],
101                    sizeof(from->varyings[0]));
102
103             if (from->varyings[i].name) {
104                 to->varyings[i].name = yagl_malloc(from->varyings[i].name_size);
105                 memcpy(to->varyings[i].name,
106                        from->varyings[i].name,
107                        from->varyings[i].name_size);
108             }
109         }
110     }
111 }
112
113 static void yagl_gles2_program_reset_cached(struct yagl_gles2_program *program)
114 {
115     int i;
116     struct yagl_gles2_location_l *location_l, *tmp_l;
117
118     for (i = 0; i < (int)program->num_active_attribs; ++i) {
119         yagl_free(program->active_attribs[i].name);
120     }
121     yagl_free(program->active_attribs);
122     program->active_attribs = NULL;
123
124     for (i = 0; i < (int)program->num_active_uniforms; ++i) {
125         yagl_free(program->active_uniforms[i].name);
126     }
127     yagl_free(program->active_uniforms);
128     program->active_uniforms = NULL;
129
130     for (i = 0; i < (int)program->num_active_uniform_blocks; ++i) {
131         yagl_free(program->active_uniform_blocks[i].name);
132         yagl_free(program->active_uniform_blocks[i].active_uniform_indices);
133     }
134     yagl_free(program->active_uniform_blocks);
135     program->active_uniform_blocks = NULL;
136
137     yagl_list_for_each_safe(struct yagl_gles2_location_l,
138                             location_l,
139                             tmp_l,
140                             &program->frag_data_locations, list) {
141         yagl_list_remove(&location_l->list);
142         free(location_l->name);
143         yagl_free(location_l);
144     }
145
146     yagl_list_for_each_safe(struct yagl_gles2_location_l,
147                             location_l,
148                             tmp_l,
149                             &program->attrib_locations, list) {
150         yagl_list_remove(&location_l->list);
151         free(location_l->name);
152         yagl_free(location_l);
153     }
154
155     if (program->gen_locations) {
156         struct yagl_gles2_location_v *locations =
157             yagl_vector_data(&program->uniform_locations_v);
158         uint32_t *tmp = (uint32_t*)yagl_get_tmp_buffer(
159             yagl_vector_size(&program->uniform_locations_v) * sizeof(uint32_t));
160
161         for (i = 0; i < yagl_vector_size(&program->uniform_locations_v); ++i) {
162             tmp[i] = locations[i].global_location;
163             free(locations[i].name);
164         }
165
166         yagl_host_glDeleteUniformLocationsYAGL(tmp,
167                                                yagl_vector_size(&program->uniform_locations_v));
168
169         yagl_vector_resize(&program->uniform_locations_v, 0);
170     } else {
171         yagl_list_for_each_safe(struct yagl_gles2_location_l,
172                                 location_l,
173                                 tmp_l,
174                                 &program->uniform_locations_l, list) {
175             yagl_list_remove(&location_l->list);
176             free(location_l->name);
177             yagl_free(location_l);
178         }
179     }
180 }
181
182 static void yagl_gles2_program_destroy(struct yagl_ref *ref)
183 {
184     struct yagl_gles2_program *program = (struct yagl_gles2_program*)ref;
185
186     yagl_gles2_program_reset_cached(program);
187
188     yagl_gles2_transform_feedback_info_reset(&program->linked_transform_feedback_info);
189     yagl_gles2_transform_feedback_info_reset(&program->transform_feedback_info);
190
191     if (program->gen_locations) {
192         yagl_vector_cleanup(&program->uniform_locations_v);
193     }
194
195     yagl_gles2_shader_release(program->fragment_shader);
196     yagl_gles2_shader_release(program->vertex_shader);
197
198     yagl_host_glDeleteObjects(&program->global_name, 1);
199
200     yagl_object_cleanup(&program->base);
201
202     yagl_free(program);
203 }
204
205 int yagl_gles2_program_translate_location(struct yagl_gles2_program *program,
206                                           GLint location,
207                                           uint32_t *global_location)
208 {
209     struct yagl_gles2_location_v *locations;
210
211     if (program->gen_locations) {
212         if ((location < 0) ||
213             (location >= yagl_vector_size(&program->uniform_locations_v))) {
214             return 0;
215         }
216
217         locations = yagl_vector_data(&program->uniform_locations_v);
218
219         *global_location = locations[location].global_location;
220     } else {
221         *global_location = location;
222     }
223
224     return 1;
225 }
226
227 void yagl_gles2_transform_feedback_info_reset(
228     struct yagl_gles2_transform_feedback_info *transform_feedback_info)
229 {
230     GLuint i;
231
232     for (i = 0; i < transform_feedback_info->num_varyings; ++i) {
233         yagl_free(transform_feedback_info->varyings[i].name);
234     }
235     yagl_free(transform_feedback_info->varyings);
236
237     memset(transform_feedback_info, 0, sizeof(*transform_feedback_info));
238 }
239
240 struct yagl_gles2_program *yagl_gles2_program_create(int gen_locations)
241 {
242     struct yagl_gles2_program *program;
243
244     program = yagl_malloc0(sizeof(*program));
245
246     yagl_object_init(&program->base, &yagl_gles2_program_destroy);
247
248     program->is_shader = 0;
249     program->gen_locations = gen_locations;
250     program->global_name = yagl_get_global_name();
251
252     if (gen_locations) {
253         yagl_vector_init(&program->uniform_locations_v,
254                          sizeof(struct yagl_gles2_location_v),
255                          0);
256     } else {
257         yagl_list_init(&program->uniform_locations_l);
258     }
259
260     yagl_list_init(&program->attrib_locations);
261     yagl_list_init(&program->frag_data_locations);
262
263     program->transform_feedback_info.buffer_mode = GL_INTERLEAVED_ATTRIBS;
264
265     yagl_host_glCreateProgram(program->global_name);
266
267     return program;
268 }
269
270 int yagl_gles2_program_attach_shader(struct yagl_gles2_program *program,
271                                      struct yagl_gles2_shader *shader)
272 {
273     switch (shader->type) {
274     case GL_VERTEX_SHADER:
275         if (program->vertex_shader) {
276             return 0;
277         }
278         yagl_gles2_shader_acquire(shader);
279         program->vertex_shader = shader;
280         break;
281     case GL_FRAGMENT_SHADER:
282         if (program->fragment_shader) {
283             return 0;
284         }
285         yagl_gles2_shader_acquire(shader);
286         program->fragment_shader = shader;
287         break;
288     default:
289         return 0;
290     }
291
292     yagl_host_glAttachShader(program->global_name,
293                              shader->global_name);
294
295     return 1;
296 }
297
298 int yagl_gles2_program_detach_shader(struct yagl_gles2_program *program,
299                                      struct yagl_gles2_shader *shader)
300 {
301     if (program->vertex_shader == shader) {
302         yagl_gles2_shader_release(program->vertex_shader);
303         program->vertex_shader = NULL;
304     } else if (program->fragment_shader == shader) {
305         yagl_gles2_shader_release(program->fragment_shader);
306         program->fragment_shader = NULL;
307     } else {
308         return 0;
309     }
310
311     yagl_host_glDetachShader(program->global_name,
312                              shader->global_name);
313
314     return 1;
315 }
316
317 void yagl_gles2_program_link(struct yagl_gles2_program *program)
318 {
319     GLint params[8];
320
321     memset(&params[0], 0, sizeof(params));
322
323     yagl_gles2_program_reset_cached(program);
324
325     yagl_host_glLinkProgram(program->global_name,
326                             params,
327                             sizeof(params)/sizeof(params[0]),
328                             NULL);
329
330     program->linked = params[0];
331
332     program->link_status = params[0];
333     program->info_log_length = params[1];
334     program->num_active_attribs = params[2];
335     program->max_active_attrib_bufsize = params[3];
336     program->num_active_uniforms = params[4];
337     program->max_active_uniform_bufsize = params[5];
338     program->num_active_uniform_blocks = params[6];
339     program->max_active_uniform_block_bufsize = params[7];
340
341     if (program->num_active_attribs > 0) {
342         program->active_attribs = yagl_malloc0(program->num_active_attribs *
343                                                sizeof(program->active_attribs[0]));
344     }
345
346     if (program->num_active_uniforms) {
347         program->active_uniforms = yagl_malloc0(program->num_active_uniforms *
348                                                 sizeof(program->active_uniforms[0]));
349     }
350
351     if (program->num_active_uniform_blocks) {
352         program->active_uniform_blocks = yagl_malloc0(program->num_active_uniform_blocks *
353                                                       sizeof(program->active_uniform_blocks[0]));
354     }
355
356     yagl_gles2_transform_feedback_info_copy(
357         &program->transform_feedback_info,
358         &program->linked_transform_feedback_info);
359 }
360
361 int yagl_gles2_program_get_uniform_location(struct yagl_gles2_program *program,
362                                             const GLchar *name)
363 {
364     int ret = 0;
365
366     if (program->gen_locations) {
367         struct yagl_gles2_location_v *locations =
368             yagl_vector_data(&program->uniform_locations_v);
369         int i;
370         struct yagl_gles2_location_v location;
371
372         for (i = 0; i < yagl_vector_size(&program->uniform_locations_v); ++i) {
373             if (strcmp(locations[i].name, name) == 0) {
374                 return i;
375             }
376         }
377
378         location.name = strdup(name);
379         location.global_location = yagl_gen_location();
380
381         yagl_vector_push_back(&program->uniform_locations_v, &location);
382
383         yagl_host_glGenUniformLocationYAGL(location.global_location,
384                                            program->global_name,
385                                            name,
386                                            yagl_transport_string_count(name));
387
388         ret = yagl_vector_size(&program->uniform_locations_v) - 1;
389     } else {
390         struct yagl_gles2_location_l *location;
391
392         yagl_list_for_each(struct yagl_gles2_location_l,
393                            location,
394                            &program->uniform_locations_l, list) {
395             if (strcmp(location->name, name) == 0) {
396                 return location->location;
397             }
398         }
399
400         ret = yagl_host_glGetUniformLocation(program->global_name,
401                                              name,
402                                              yagl_transport_string_count(name));
403
404         location = yagl_malloc(sizeof(*location));
405
406         yagl_list_init(&location->list);
407         location->name = strdup(name);
408         location->location = ret;
409
410         yagl_list_add_tail(&program->uniform_locations_l, &location->list);
411     }
412
413     return ret;
414 }
415
416 int yagl_gles2_program_get_attrib_location(struct yagl_gles2_program *program,
417                                            const GLchar *name)
418 {
419     struct yagl_gles2_location_l *location;
420     int ret;
421
422     yagl_list_for_each(struct yagl_gles2_location_l,
423                        location,
424                        &program->attrib_locations, list) {
425         if (strcmp(location->name, name) == 0) {
426             return location->location;
427         }
428     }
429
430     ret = yagl_host_glGetAttribLocation(program->global_name,
431                                         name,
432                                         yagl_transport_string_count(name));
433
434     location = yagl_malloc(sizeof(*location));
435
436     yagl_list_init(&location->list);
437     location->name = strdup(name);
438     location->location = ret;
439
440     yagl_list_add_tail(&program->attrib_locations, &location->list);
441
442     return ret;
443 }
444
445 void yagl_gles2_program_get_active_uniform(struct yagl_gles2_program *program,
446                                            GLuint index,
447                                            GLsizei bufsize,
448                                            GLsizei *length,
449                                            GLint *size,
450                                            GLenum *type,
451                                            GLchar *name)
452 {
453     struct yagl_gles2_uniform_variable *var;
454
455     YAGL_LOG_FUNC_SET(yagl_gles2_program_get_active_uniform);
456
457     if (index >= program->num_active_uniforms) {
458         assert(0);
459         return;
460     }
461
462     var = &program->active_uniforms[index];
463
464     if (!var->generic_fetched) {
465         yagl_free(var->name);
466         var->name = yagl_malloc(program->max_active_uniform_bufsize);
467         var->name[0] = '\0';
468
469         yagl_host_glGetActiveUniform(program->global_name,
470                                      index,
471                                      &var->size,
472                                      &var->type,
473                                      var->name,
474                                      program->max_active_uniform_bufsize,
475                                      &var->name_size);
476
477         var->name_fetched = 1;
478         var->generic_fetched = 1;
479     }
480
481     yagl_gles2_set_name(var->name, var->name_size,
482                         bufsize,
483                         length,
484                         name);
485
486     if (size) {
487         *size = var->size;
488     }
489
490     if (type) {
491         *type = var->type;
492     }
493
494     YAGL_LOG_DEBUG("Got uniform variable at index %u: name = %s, size = %d, type = 0x%X",
495                    index,
496                    ((bufsize > 0) ? name : NULL),
497                    var->size,
498                    var->type);
499 }
500
501 void yagl_gles2_program_get_active_attrib(struct yagl_gles2_program *program,
502                                           GLuint index,
503                                           GLsizei bufsize,
504                                           GLsizei *length,
505                                           GLint *size,
506                                           GLenum *type,
507                                           GLchar *name)
508 {
509     struct yagl_gles2_attrib_variable *var;
510
511     YAGL_LOG_FUNC_SET(yagl_gles2_program_get_active_attrib);
512
513     if (index >= program->num_active_attribs) {
514         assert(0);
515         return;
516     }
517
518     var = &program->active_attribs[index];
519
520     if (!var->fetched) {
521         yagl_free(var->name);
522         var->name = yagl_malloc(program->max_active_attrib_bufsize);
523         var->name[0] = '\0';
524
525         yagl_host_glGetActiveAttrib(program->global_name,
526                                     index,
527                                     &var->size,
528                                     &var->type,
529                                     var->name,
530                                     program->max_active_attrib_bufsize,
531                                     &var->name_size);
532
533         var->fetched = 1;
534     }
535
536     yagl_gles2_set_name(var->name, var->name_size,
537                         bufsize,
538                         length,
539                         name);
540
541     if (size) {
542         *size = var->size;
543     }
544
545     if (type) {
546         *type = var->type;
547     }
548
549     YAGL_LOG_DEBUG("Got attrib variable at index %u: name = %s, size = %d, type = 0x%X",
550                    index,
551                    ((bufsize > 0) ? name : NULL),
552                    var->size,
553                    var->type);
554 }
555
556 int yagl_gles2_program_get_uniformfv(struct yagl_gles2_program *program,
557                                      GLint location,
558                                      GLfloat *params)
559 {
560     uint32_t global_location;
561     GLfloat tmp[100]; // This fits all cases.
562     int32_t num = 0;
563
564     if (!yagl_gles2_program_translate_location(program,
565                                                location,
566                                                &global_location)) {
567         return 0;
568     }
569
570     yagl_host_glGetUniformfv(program->gen_locations,
571                              program->global_name,
572                              global_location,
573                              tmp,
574                              sizeof(tmp)/sizeof(tmp[0]),
575                              &num);
576
577     if (params) {
578         memcpy(params, tmp, num * sizeof(tmp[0]));
579     }
580
581     return 1;
582 }
583
584 int yagl_gles2_program_get_uniformiv(struct yagl_gles2_program *program,
585                                      GLint location,
586                                      GLint *params)
587 {
588     uint32_t global_location;
589     GLint tmp[100]; // This fits all cases.
590     int32_t num = 0;
591
592     if (!yagl_gles2_program_translate_location(program,
593                                                location,
594                                                &global_location)) {
595         return 0;
596     }
597
598     yagl_host_glGetUniformiv(program->gen_locations,
599                              program->global_name,
600                              global_location,
601                              tmp,
602                              sizeof(tmp)/sizeof(tmp[0]),
603                              &num);
604
605     if (params) {
606         memcpy(params, tmp, num * sizeof(tmp[0]));
607     }
608
609     return 1;
610 }
611
612 int yagl_gles2_program_uniform1f(struct yagl_gles2_program *program,
613                                  GLint location,
614                                  GLfloat x)
615 {
616     uint32_t global_location;
617
618     if (!yagl_gles2_program_translate_location(program,
619                                                location,
620                                                &global_location)) {
621         return 0;
622     }
623
624     yagl_host_glUniform1f(program->gen_locations, global_location, x);
625
626     return 1;
627 }
628
629 int yagl_gles2_program_uniform1fv(struct yagl_gles2_program *program,
630                                   GLint location,
631                                   GLsizei count,
632                                   const GLfloat *v)
633 {
634     uint32_t global_location;
635
636     if (!yagl_gles2_program_translate_location(program,
637                                                location,
638                                                &global_location)) {
639         return 0;
640     }
641
642     yagl_host_glUniform1fv(program->gen_locations, global_location, v, count);
643
644     return 1;
645 }
646
647 int yagl_gles2_program_uniform1i(struct yagl_gles2_program *program,
648                                  GLint location,
649                                  GLint x)
650 {
651     uint32_t global_location;
652
653     if (!yagl_gles2_program_translate_location(program,
654                                                location,
655                                                &global_location)) {
656         return 0;
657     }
658
659     yagl_host_glUniform1i(program->gen_locations, global_location, x);
660
661     return 1;
662 }
663
664 int yagl_gles2_program_uniform1iv(struct yagl_gles2_program *program,
665                                   GLint location,
666                                   GLsizei count,
667                                   const GLint *v)
668 {
669     uint32_t global_location;
670
671     if (!yagl_gles2_program_translate_location(program,
672                                                location,
673                                                &global_location)) {
674         return 0;
675     }
676
677     yagl_host_glUniform1iv(program->gen_locations, global_location, v, count);
678
679     return 1;
680 }
681
682 int yagl_gles2_program_uniform2f(struct yagl_gles2_program *program,
683                                  GLint location,
684                                  GLfloat x,
685                                  GLfloat y)
686 {
687     uint32_t global_location;
688
689     if (!yagl_gles2_program_translate_location(program,
690                                                location,
691                                                &global_location)) {
692         return 0;
693     }
694
695     yagl_host_glUniform2f(program->gen_locations, global_location, x, y);
696
697     return 1;
698 }
699
700 int yagl_gles2_program_uniform2fv(struct yagl_gles2_program *program,
701                                   GLint location,
702                                   GLsizei count,
703                                   const GLfloat *v)
704 {
705     uint32_t global_location;
706
707     if (!yagl_gles2_program_translate_location(program,
708                                                location,
709                                                &global_location)) {
710         return 0;
711     }
712
713     yagl_host_glUniform2fv(program->gen_locations, global_location, v, 2 * count);
714
715     return 1;
716 }
717
718 int yagl_gles2_program_uniform2i(struct yagl_gles2_program *program,
719                                  GLint location,
720                                  GLint x,
721                                  GLint y)
722 {
723     uint32_t global_location;
724
725     if (!yagl_gles2_program_translate_location(program,
726                                                location,
727                                                &global_location)) {
728         return 0;
729     }
730
731     yagl_host_glUniform2i(program->gen_locations, global_location, x, y);
732
733     return 1;
734 }
735
736 int yagl_gles2_program_uniform2iv(struct yagl_gles2_program *program,
737                                   GLint location,
738                                   GLsizei count,
739                                   const GLint *v)
740 {
741     uint32_t global_location;
742
743     if (!yagl_gles2_program_translate_location(program,
744                                                location,
745                                                &global_location)) {
746         return 0;
747     }
748
749     yagl_host_glUniform2iv(program->gen_locations, global_location, v, 2 * count);
750
751     return 1;
752 }
753
754 int yagl_gles2_program_uniform3f(struct yagl_gles2_program *program,
755                                  GLint location,
756                                  GLfloat x,
757                                  GLfloat y,
758                                  GLfloat z)
759 {
760     uint32_t global_location;
761
762     if (!yagl_gles2_program_translate_location(program,
763                                                location,
764                                                &global_location)) {
765         return 0;
766     }
767
768     yagl_host_glUniform3f(program->gen_locations, global_location, x, y, z);
769
770     return 1;
771 }
772
773 int yagl_gles2_program_uniform3fv(struct yagl_gles2_program *program,
774                                   GLint location,
775                                   GLsizei count,
776                                   const GLfloat *v)
777 {
778     uint32_t global_location;
779
780     if (!yagl_gles2_program_translate_location(program,
781                                                location,
782                                                &global_location)) {
783         return 0;
784     }
785
786     yagl_host_glUniform3fv(program->gen_locations, global_location, v, 3 * count);
787
788     return 1;
789 }
790
791 int yagl_gles2_program_uniform3i(struct yagl_gles2_program *program,
792                                  GLint location,
793                                  GLint x,
794                                  GLint y,
795                                  GLint z)
796 {
797     uint32_t global_location;
798
799     if (!yagl_gles2_program_translate_location(program,
800                                                location,
801                                                &global_location)) {
802         return 0;
803     }
804
805     yagl_host_glUniform3i(program->gen_locations, global_location, x, y, z);
806
807     return 1;
808 }
809
810 int yagl_gles2_program_uniform3iv(struct yagl_gles2_program *program,
811                                   GLint location,
812                                   GLsizei count,
813                                   const GLint *v)
814 {
815     uint32_t global_location;
816
817     if (!yagl_gles2_program_translate_location(program,
818                                                location,
819                                                &global_location)) {
820         return 0;
821     }
822
823     yagl_host_glUniform3iv(program->gen_locations, global_location, v, 3 * count);
824
825     return 1;
826 }
827
828 int yagl_gles2_program_uniform4f(struct yagl_gles2_program *program,
829                                  GLint location,
830                                  GLfloat x,
831                                  GLfloat y,
832                                  GLfloat z,
833                                  GLfloat w)
834 {
835     uint32_t global_location;
836
837     if (!yagl_gles2_program_translate_location(program,
838                                                location,
839                                                &global_location)) {
840         return 0;
841     }
842
843     yagl_host_glUniform4f(program->gen_locations, global_location, x, y, z, w);
844
845     return 1;
846 }
847
848 int yagl_gles2_program_uniform4fv(struct yagl_gles2_program *program,
849                                   GLint location,
850                                   GLsizei count,
851                                   const GLfloat *v)
852 {
853     uint32_t global_location;
854
855     if (!yagl_gles2_program_translate_location(program,
856                                                location,
857                                                &global_location)) {
858         return 0;
859     }
860
861     yagl_host_glUniform4fv(program->gen_locations, global_location, v, 4 * count);
862
863     return 1;
864 }
865
866 int yagl_gles2_program_uniform4i(struct yagl_gles2_program *program,
867                                  GLint location,
868                                  GLint x,
869                                  GLint y,
870                                  GLint z,
871                                  GLint w)
872 {
873     uint32_t global_location;
874
875     if (!yagl_gles2_program_translate_location(program,
876                                                location,
877                                                &global_location)) {
878         return 0;
879     }
880
881     yagl_host_glUniform4i(program->gen_locations, global_location, x, y, z, w);
882
883     return 1;
884 }
885
886 int yagl_gles2_program_uniform4iv(struct yagl_gles2_program *program,
887                                   GLint location,
888                                   GLsizei count,
889                                   const GLint *v)
890 {
891     uint32_t global_location;
892
893     if (!yagl_gles2_program_translate_location(program,
894                                                location,
895                                                &global_location)) {
896         return 0;
897     }
898
899     yagl_host_glUniform4iv(program->gen_locations, global_location, v, 4 * count);
900
901     return 1;
902 }
903
904 int yagl_gles2_program_uniform_matrix2fv(struct yagl_gles2_program *program,
905                                          GLint location,
906                                          GLsizei count,
907                                          GLboolean transpose,
908                                          const GLfloat *value)
909 {
910     uint32_t global_location;
911
912     if (!yagl_gles2_program_translate_location(program,
913                                                location,
914                                                &global_location)) {
915         return 0;
916     }
917
918     yagl_host_glUniformMatrix2fv(program->gen_locations, global_location, transpose, value, 2 * 2 * count);
919
920     return 1;
921 }
922
923 int yagl_gles2_program_uniform_matrix3fv(struct yagl_gles2_program *program,
924                                          GLint location,
925                                          GLsizei count,
926                                          GLboolean transpose,
927                                          const GLfloat *value)
928 {
929     uint32_t global_location;
930
931     if (!yagl_gles2_program_translate_location(program,
932                                                location,
933                                                &global_location)) {
934         return 0;
935     }
936
937     yagl_host_glUniformMatrix3fv(program->gen_locations, global_location, transpose, value, 3 * 3 * count);
938
939     return 1;
940 }
941
942 int yagl_gles2_program_uniform_matrix4fv(struct yagl_gles2_program *program,
943                                          GLint location,
944                                          GLsizei count,
945                                          GLboolean transpose,
946                                          const GLfloat *value)
947 {
948     uint32_t global_location;
949
950     if (!yagl_gles2_program_translate_location(program,
951                                                location,
952                                                &global_location)) {
953         return 0;
954     }
955
956     yagl_host_glUniformMatrix4fv(program->gen_locations, global_location, transpose, value, 4 * 4 * count);
957
958     return 1;
959 }
960
961 void yagl_gles2_program_acquire(struct yagl_gles2_program *program)
962 {
963     if (program) {
964         yagl_object_acquire(&program->base);
965     }
966 }
967
968 void yagl_gles2_program_release(struct yagl_gles2_program *program)
969 {
970     if (program) {
971         yagl_object_release(&program->base);
972     }
973 }