4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * Stanislav Vorobiov <s.vorobiov@samsung.com>
8 * Jinhyung Jo <jinhyung.jo@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
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:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
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
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"
42 #include "yagl_utils.h"
43 #include "yagl_host_gles_calls.h"
49 * We don't want to include GLES3/gl3.h here
51 #define GL_INTERLEAVED_ATTRIBS 0x8C8C
53 struct yagl_gles2_location_v
57 uint32_t global_location;
60 static pthread_once_t g_gen_locations_init = PTHREAD_ONCE_INIT;
62 static pthread_mutex_t g_gen_locations_mutex;
63 static uint32_t g_gen_locations_next = 0;
65 static void yagl_gen_locations_init()
67 yagl_mutex_init(&g_gen_locations_mutex);
70 static uint32_t yagl_gen_location()
74 pthread_once(&g_gen_locations_init, yagl_gen_locations_init);
76 pthread_mutex_lock(&g_gen_locations_mutex);
78 ret = g_gen_locations_next++;
80 pthread_mutex_unlock(&g_gen_locations_mutex);
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)
91 yagl_gles2_transform_feedback_info_reset(to);
93 memcpy(to, from, sizeof(*from));
95 if (from->num_varyings > 0) {
96 to->varyings = yagl_malloc(to->num_varyings * sizeof(*to->varyings));
98 for (i = 0; i < from->num_varyings; ++i) {
99 memcpy(&to->varyings[i],
101 sizeof(from->varyings[0]));
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);
113 static void yagl_gles2_program_reset_cached(struct yagl_gles2_program *program)
116 struct yagl_gles2_location_l *location_l, *tmp_l;
118 for (i = 0; i < (int)program->num_active_attribs; ++i) {
119 yagl_free(program->active_attribs[i].name);
121 yagl_free(program->active_attribs);
122 program->active_attribs = NULL;
124 for (i = 0; i < (int)program->num_active_uniforms; ++i) {
125 yagl_free(program->active_uniforms[i].name);
127 yagl_free(program->active_uniforms);
128 program->active_uniforms = NULL;
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);
134 yagl_free(program->active_uniform_blocks);
135 program->active_uniform_blocks = NULL;
137 yagl_list_for_each_safe(struct yagl_gles2_location_l,
140 &program->frag_data_locations, list) {
141 yagl_list_remove(&location_l->list);
142 free(location_l->name);
143 yagl_free(location_l);
146 yagl_list_for_each_safe(struct yagl_gles2_location_l,
149 &program->attrib_locations, list) {
150 yagl_list_remove(&location_l->list);
151 free(location_l->name);
152 yagl_free(location_l);
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));
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);
166 yagl_host_glDeleteUniformLocationsYAGL(tmp,
167 yagl_vector_size(&program->uniform_locations_v));
169 yagl_vector_resize(&program->uniform_locations_v, 0);
171 yagl_list_for_each_safe(struct yagl_gles2_location_l,
174 &program->uniform_locations_l, list) {
175 yagl_list_remove(&location_l->list);
176 free(location_l->name);
177 yagl_free(location_l);
182 static void yagl_gles2_program_destroy(struct yagl_ref *ref)
184 struct yagl_gles2_program *program = (struct yagl_gles2_program*)ref;
186 yagl_gles2_program_reset_cached(program);
188 yagl_gles2_transform_feedback_info_reset(&program->linked_transform_feedback_info);
189 yagl_gles2_transform_feedback_info_reset(&program->transform_feedback_info);
191 if (program->gen_locations) {
192 yagl_vector_cleanup(&program->uniform_locations_v);
195 yagl_gles2_shader_release(program->fragment_shader);
196 yagl_gles2_shader_release(program->vertex_shader);
198 yagl_host_glDeleteObjects(&program->global_name, 1);
200 yagl_object_cleanup(&program->base);
205 int yagl_gles2_program_translate_location(struct yagl_gles2_program *program,
207 uint32_t *global_location)
209 struct yagl_gles2_location_v *locations;
211 if (program->gen_locations) {
212 if ((location < 0) ||
213 (location >= yagl_vector_size(&program->uniform_locations_v))) {
217 locations = yagl_vector_data(&program->uniform_locations_v);
219 *global_location = locations[location].global_location;
221 *global_location = location;
227 void yagl_gles2_transform_feedback_info_reset(
228 struct yagl_gles2_transform_feedback_info *transform_feedback_info)
232 for (i = 0; i < transform_feedback_info->num_varyings; ++i) {
233 yagl_free(transform_feedback_info->varyings[i].name);
235 yagl_free(transform_feedback_info->varyings);
237 memset(transform_feedback_info, 0, sizeof(*transform_feedback_info));
240 struct yagl_gles2_program *yagl_gles2_program_create(int gen_locations)
242 struct yagl_gles2_program *program;
244 program = yagl_malloc0(sizeof(*program));
246 yagl_object_init(&program->base, &yagl_gles2_program_destroy);
248 program->is_shader = 0;
249 program->gen_locations = gen_locations;
250 program->global_name = yagl_get_global_name();
253 yagl_vector_init(&program->uniform_locations_v,
254 sizeof(struct yagl_gles2_location_v),
257 yagl_list_init(&program->uniform_locations_l);
260 yagl_list_init(&program->attrib_locations);
261 yagl_list_init(&program->frag_data_locations);
263 program->transform_feedback_info.buffer_mode = GL_INTERLEAVED_ATTRIBS;
265 yagl_host_glCreateProgram(program->global_name);
270 int yagl_gles2_program_attach_shader(struct yagl_gles2_program *program,
271 struct yagl_gles2_shader *shader)
273 switch (shader->type) {
274 case GL_VERTEX_SHADER:
275 if (program->vertex_shader) {
278 yagl_gles2_shader_acquire(shader);
279 program->vertex_shader = shader;
281 case GL_FRAGMENT_SHADER:
282 if (program->fragment_shader) {
285 yagl_gles2_shader_acquire(shader);
286 program->fragment_shader = shader;
292 yagl_host_glAttachShader(program->global_name,
293 shader->global_name);
298 int yagl_gles2_program_detach_shader(struct yagl_gles2_program *program,
299 struct yagl_gles2_shader *shader)
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;
311 yagl_host_glDetachShader(program->global_name,
312 shader->global_name);
317 void yagl_gles2_program_link(struct yagl_gles2_program *program)
321 memset(¶ms[0], 0, sizeof(params));
323 yagl_gles2_program_reset_cached(program);
325 yagl_host_glLinkProgram(program->global_name,
327 sizeof(params)/sizeof(params[0]),
330 program->linked = params[0];
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];
341 if (program->num_active_attribs > 0) {
342 program->active_attribs = yagl_malloc0(program->num_active_attribs *
343 sizeof(program->active_attribs[0]));
346 if (program->num_active_uniforms) {
347 program->active_uniforms = yagl_malloc0(program->num_active_uniforms *
348 sizeof(program->active_uniforms[0]));
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]));
356 yagl_gles2_transform_feedback_info_copy(
357 &program->transform_feedback_info,
358 &program->linked_transform_feedback_info);
361 int yagl_gles2_program_get_uniform_location(struct yagl_gles2_program *program,
366 if (program->gen_locations) {
367 struct yagl_gles2_location_v *locations =
368 yagl_vector_data(&program->uniform_locations_v);
370 struct yagl_gles2_location_v location;
372 for (i = 0; i < yagl_vector_size(&program->uniform_locations_v); ++i) {
373 if (strcmp(locations[i].name, name) == 0) {
378 location.name = strdup(name);
379 location.global_location = yagl_gen_location();
381 yagl_vector_push_back(&program->uniform_locations_v, &location);
383 yagl_host_glGenUniformLocationYAGL(location.global_location,
384 program->global_name,
386 yagl_transport_string_count(name));
388 ret = yagl_vector_size(&program->uniform_locations_v) - 1;
390 struct yagl_gles2_location_l *location;
392 yagl_list_for_each(struct yagl_gles2_location_l,
394 &program->uniform_locations_l, list) {
395 if (strcmp(location->name, name) == 0) {
396 return location->location;
400 ret = yagl_host_glGetUniformLocation(program->global_name,
402 yagl_transport_string_count(name));
404 location = yagl_malloc(sizeof(*location));
406 yagl_list_init(&location->list);
407 location->name = strdup(name);
408 location->location = ret;
410 yagl_list_add_tail(&program->uniform_locations_l, &location->list);
416 int yagl_gles2_program_get_attrib_location(struct yagl_gles2_program *program,
419 struct yagl_gles2_location_l *location;
422 yagl_list_for_each(struct yagl_gles2_location_l,
424 &program->attrib_locations, list) {
425 if (strcmp(location->name, name) == 0) {
426 return location->location;
430 ret = yagl_host_glGetAttribLocation(program->global_name,
432 yagl_transport_string_count(name));
434 location = yagl_malloc(sizeof(*location));
436 yagl_list_init(&location->list);
437 location->name = strdup(name);
438 location->location = ret;
440 yagl_list_add_tail(&program->attrib_locations, &location->list);
445 void yagl_gles2_program_get_active_uniform(struct yagl_gles2_program *program,
453 struct yagl_gles2_uniform_variable *var;
455 YAGL_LOG_FUNC_SET(yagl_gles2_program_get_active_uniform);
457 if (index >= program->num_active_uniforms) {
462 var = &program->active_uniforms[index];
464 if (!var->generic_fetched) {
465 yagl_free(var->name);
466 var->name = yagl_malloc(program->max_active_uniform_bufsize);
469 yagl_host_glGetActiveUniform(program->global_name,
474 program->max_active_uniform_bufsize,
477 var->name_fetched = 1;
478 var->generic_fetched = 1;
481 yagl_gles2_set_name(var->name, var->name_size,
494 YAGL_LOG_DEBUG("Got uniform variable at index %u: name = %s, size = %d, type = 0x%X",
496 ((bufsize > 0) ? name : NULL),
501 void yagl_gles2_program_get_active_attrib(struct yagl_gles2_program *program,
509 struct yagl_gles2_attrib_variable *var;
511 YAGL_LOG_FUNC_SET(yagl_gles2_program_get_active_attrib);
513 if (index >= program->num_active_attribs) {
518 var = &program->active_attribs[index];
521 yagl_free(var->name);
522 var->name = yagl_malloc(program->max_active_attrib_bufsize);
525 yagl_host_glGetActiveAttrib(program->global_name,
530 program->max_active_attrib_bufsize,
536 yagl_gles2_set_name(var->name, var->name_size,
549 YAGL_LOG_DEBUG("Got attrib variable at index %u: name = %s, size = %d, type = 0x%X",
551 ((bufsize > 0) ? name : NULL),
556 int yagl_gles2_program_get_uniformfv(struct yagl_gles2_program *program,
560 uint32_t global_location;
561 GLfloat tmp[100]; // This fits all cases.
564 if (!yagl_gles2_program_translate_location(program,
570 yagl_host_glGetUniformfv(program->gen_locations,
571 program->global_name,
574 sizeof(tmp)/sizeof(tmp[0]),
578 memcpy(params, tmp, num * sizeof(tmp[0]));
584 int yagl_gles2_program_get_uniformiv(struct yagl_gles2_program *program,
588 uint32_t global_location;
589 GLint tmp[100]; // This fits all cases.
592 if (!yagl_gles2_program_translate_location(program,
598 yagl_host_glGetUniformiv(program->gen_locations,
599 program->global_name,
602 sizeof(tmp)/sizeof(tmp[0]),
606 memcpy(params, tmp, num * sizeof(tmp[0]));
612 int yagl_gles2_program_uniform1f(struct yagl_gles2_program *program,
616 uint32_t global_location;
618 if (!yagl_gles2_program_translate_location(program,
624 yagl_host_glUniform1f(program->gen_locations, global_location, x);
629 int yagl_gles2_program_uniform1fv(struct yagl_gles2_program *program,
634 uint32_t global_location;
636 if (!yagl_gles2_program_translate_location(program,
642 yagl_host_glUniform1fv(program->gen_locations, global_location, v, count);
647 int yagl_gles2_program_uniform1i(struct yagl_gles2_program *program,
651 uint32_t global_location;
653 if (!yagl_gles2_program_translate_location(program,
659 yagl_host_glUniform1i(program->gen_locations, global_location, x);
664 int yagl_gles2_program_uniform1iv(struct yagl_gles2_program *program,
669 uint32_t global_location;
671 if (!yagl_gles2_program_translate_location(program,
677 yagl_host_glUniform1iv(program->gen_locations, global_location, v, count);
682 int yagl_gles2_program_uniform2f(struct yagl_gles2_program *program,
687 uint32_t global_location;
689 if (!yagl_gles2_program_translate_location(program,
695 yagl_host_glUniform2f(program->gen_locations, global_location, x, y);
700 int yagl_gles2_program_uniform2fv(struct yagl_gles2_program *program,
705 uint32_t global_location;
707 if (!yagl_gles2_program_translate_location(program,
713 yagl_host_glUniform2fv(program->gen_locations, global_location, v, 2 * count);
718 int yagl_gles2_program_uniform2i(struct yagl_gles2_program *program,
723 uint32_t global_location;
725 if (!yagl_gles2_program_translate_location(program,
731 yagl_host_glUniform2i(program->gen_locations, global_location, x, y);
736 int yagl_gles2_program_uniform2iv(struct yagl_gles2_program *program,
741 uint32_t global_location;
743 if (!yagl_gles2_program_translate_location(program,
749 yagl_host_glUniform2iv(program->gen_locations, global_location, v, 2 * count);
754 int yagl_gles2_program_uniform3f(struct yagl_gles2_program *program,
760 uint32_t global_location;
762 if (!yagl_gles2_program_translate_location(program,
768 yagl_host_glUniform3f(program->gen_locations, global_location, x, y, z);
773 int yagl_gles2_program_uniform3fv(struct yagl_gles2_program *program,
778 uint32_t global_location;
780 if (!yagl_gles2_program_translate_location(program,
786 yagl_host_glUniform3fv(program->gen_locations, global_location, v, 3 * count);
791 int yagl_gles2_program_uniform3i(struct yagl_gles2_program *program,
797 uint32_t global_location;
799 if (!yagl_gles2_program_translate_location(program,
805 yagl_host_glUniform3i(program->gen_locations, global_location, x, y, z);
810 int yagl_gles2_program_uniform3iv(struct yagl_gles2_program *program,
815 uint32_t global_location;
817 if (!yagl_gles2_program_translate_location(program,
823 yagl_host_glUniform3iv(program->gen_locations, global_location, v, 3 * count);
828 int yagl_gles2_program_uniform4f(struct yagl_gles2_program *program,
835 uint32_t global_location;
837 if (!yagl_gles2_program_translate_location(program,
843 yagl_host_glUniform4f(program->gen_locations, global_location, x, y, z, w);
848 int yagl_gles2_program_uniform4fv(struct yagl_gles2_program *program,
853 uint32_t global_location;
855 if (!yagl_gles2_program_translate_location(program,
861 yagl_host_glUniform4fv(program->gen_locations, global_location, v, 4 * count);
866 int yagl_gles2_program_uniform4i(struct yagl_gles2_program *program,
873 uint32_t global_location;
875 if (!yagl_gles2_program_translate_location(program,
881 yagl_host_glUniform4i(program->gen_locations, global_location, x, y, z, w);
886 int yagl_gles2_program_uniform4iv(struct yagl_gles2_program *program,
891 uint32_t global_location;
893 if (!yagl_gles2_program_translate_location(program,
899 yagl_host_glUniform4iv(program->gen_locations, global_location, v, 4 * count);
904 int yagl_gles2_program_uniform_matrix2fv(struct yagl_gles2_program *program,
908 const GLfloat *value)
910 uint32_t global_location;
912 if (!yagl_gles2_program_translate_location(program,
918 yagl_host_glUniformMatrix2fv(program->gen_locations, global_location, transpose, value, 2 * 2 * count);
923 int yagl_gles2_program_uniform_matrix3fv(struct yagl_gles2_program *program,
927 const GLfloat *value)
929 uint32_t global_location;
931 if (!yagl_gles2_program_translate_location(program,
937 yagl_host_glUniformMatrix3fv(program->gen_locations, global_location, transpose, value, 3 * 3 * count);
942 int yagl_gles2_program_uniform_matrix4fv(struct yagl_gles2_program *program,
946 const GLfloat *value)
948 uint32_t global_location;
950 if (!yagl_gles2_program_translate_location(program,
956 yagl_host_glUniformMatrix4fv(program->gen_locations, global_location, transpose, value, 4 * 4 * count);
961 void yagl_gles2_program_acquire(struct yagl_gles2_program *program)
964 yagl_object_acquire(&program->base);
968 void yagl_gles2_program_release(struct yagl_gles2_program *program)
971 yagl_object_release(&program->base);