Keep sampler information with Program object & cleanup 12/252112/1 accepted/tizen/unified/20210125.073655 submit/tizen/20210125.002716 submit/tizen_6.0/20210125.002404
authorLukasz Kostyra <l.kostyra@samsung.com>
Fri, 22 Jan 2021 16:12:16 +0000 (17:12 +0100)
committerLukasz Kostyra <l.kostyra@samsung.com>
Fri, 22 Jan 2021 16:21:17 +0000 (17:21 +0100)
GL/GLES specification allows (and recommends) following sequence of
events:
  glAttachShader(); glAttachShader();
  glLinkProgram();
  glDetachShader(); glDetachShader();
  glDeleteShader(); glDeleteShader();

This makes program->vertex_shader and program->fragment_shader NULL
and forgoes any information regarding sampler types, which was used
for pre/post draw calls and TEXTURE_EXTERNAL_OES support. This
information is now cached in program object and all further actions
related to them refer to these cached copies.

Additional:
* Assume sampler uniform value to be 0 (as per GLES spec)
* Adjust some logging and cleanup code
* glTexParameter* functions are now recognizing TEXTURE_EXTERNAL_OES
  target and react accordingly
* glGetActiveUniform() returns correct type of uniform to user if
  uniform type is samplerExternalOES

Change-Id: Ib5f35730dd9f2f0139780a735ea8ec4f7ba84609

GLES_common/yagl_gles_calls.c
GLES_common/yagl_gles_context.c
GLESv2/yagl_gles2_context.c
GLESv2/yagl_gles2_program.c
GLESv2/yagl_gles2_program.h
GLESv2/yagl_glsl_state.c

index 69de0c3c55f8026ac3797c5dda718e807de7fbd3..6181ff9c8a5864f27fcdb58df3075ffd105ceb26 100644 (file)
@@ -306,7 +306,16 @@ YAGL_API void glTexParameteri(GLenum target, GLenum pname, GLint param)
         tex_target_state->texture->mag_filter = param;
     }
 
-    yagl_host_glTexParameteri(target, pname, param);
+    if (target == GL_TEXTURE_EXTERNAL_OES) {
+        struct yagl_gles_texture_target_state *tex2d_target_state =
+            yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+        yagl_host_glTexParameteri(GL_TEXTURE_2D, pname, param);
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+    } else {
+        yagl_host_glTexParameteri(target, pname, param);
+    }
 
 out:
     YAGL_LOG_FUNC_EXIT(NULL);
@@ -337,7 +346,16 @@ YAGL_API void glTexParameteriv(GLenum target, GLenum pname, const GLint *params)
         tex_target_state->texture->mag_filter = params[0];
     }
 
-    yagl_host_glTexParameteriv(target, pname, params, 1);
+    if (target == GL_TEXTURE_EXTERNAL_OES) {
+        struct yagl_gles_texture_target_state *tex2d_target_state =
+            yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+        yagl_host_glTexParameteriv(GL_TEXTURE_2D, pname, params, 1);
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+    } else {
+        yagl_host_glTexParameteriv(target, pname, params, 1);
+    }
 
 out:
     YAGL_LOG_FUNC_EXIT(NULL);
index 8c23e661c23f51c4413bc423f92c947427ff85bc..b57d949250a9f4deefe1ee0faf772f9100ef61eb 100644 (file)
@@ -2341,7 +2341,16 @@ void yagl_gles_context_tex_parameterf(struct yagl_gles_context *ctx,
         tex_target_state->texture->mag_filter = param;
     }
 
-    yagl_host_glTexParameterf(target, pname, param);
+    if (target == GL_TEXTURE_EXTERNAL_OES) {
+        struct yagl_gles_texture_target_state *tex2d_target_state =
+            yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+        yagl_host_glTexParameterf(GL_TEXTURE_2D, pname, param);
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+    } else {
+        yagl_host_glTexParameterf(target, pname, param);
+    }
 }
 
 void yagl_gles_context_tex_parameterfv(struct yagl_gles_context *ctx,
@@ -2370,7 +2379,17 @@ void yagl_gles_context_tex_parameterfv(struct yagl_gles_context *ctx,
         tex_target_state->texture->mag_filter = params[0];
     }
 
-    yagl_host_glTexParameterfv(target, pname, params, 1);
+    if (target == GL_TEXTURE_EXTERNAL_OES) {
+        struct yagl_gles_texture_target_state *tex2d_target_state =
+            yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex_target_state->texture->global_name);
+        yagl_host_glTexParameterfv(GL_TEXTURE_2D, pname, params, 1);
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+    } else {
+        yagl_host_glTexParameterfv(target, pname, params, 1);
+    }
+
 }
 
 int yagl_gles_context_get_tex_parameterfv(struct yagl_gles_context *ctx,
@@ -2399,7 +2418,16 @@ int yagl_gles_context_get_tex_parameterfv(struct yagl_gles_context *ctx,
         break;
     }
 
-    yagl_host_glGetTexParameterfv(target, pname, params);
+    if (target == GL_TEXTURE_EXTERNAL_OES) {
+        struct yagl_gles_texture_target_state *tex2d_target_state =
+            yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+        yagl_host_glBindTexture(GL_TEXTURE_2D, texture_obj->global_name);
+        yagl_host_glGetTexParameterfv(GL_TEXTURE_2D, pname, params);
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+    } else {
+        yagl_host_glGetTexParameterfv(target, pname, params);
+    }
 
     return 1;
 }
@@ -2430,7 +2458,16 @@ int yagl_gles_context_get_tex_parameteriv(struct yagl_gles_context *ctx,
         break;
     }
 
-    yagl_host_glGetTexParameteriv(target, pname, params);
+    if (target == GL_TEXTURE_EXTERNAL_OES) {
+        struct yagl_gles_texture_target_state *tex2d_target_state =
+            yagl_gles_context_get_active_texture_target_state(ctx, yagl_gles_texture_target_2d);
+
+        yagl_host_glBindTexture(GL_TEXTURE_2D, texture_obj->global_name);
+        yagl_host_glGetTexParameteriv(GL_TEXTURE_2D, pname, params);
+        yagl_host_glBindTexture(GL_TEXTURE_2D, tex2d_target_state->texture->global_name);
+    } else {
+        yagl_host_glGetTexParameteriv(target, pname, params);
+    }
 
     return 1;
 }
index 64fedad3309287cc2c13c3ca344f58993426962a..295930866f37918d53d1cf5e91304bc57c5a519b 100644 (file)
@@ -474,19 +474,19 @@ struct yagl_gles_array
 }
 
 static void yagl_gles2_context_bind_externaloes(struct yagl_gles2_context *ctx,
-                                                struct yagl_gles2_shader *shader)
+                                                struct yagl_gles2_program_sampler_info *sampler_info)
 {
     struct yagl_glsl_sampler *samplers;
     int i = 0, samplers_size = 0;
     YAGL_LOG_FUNC_SET(yagl_gles2_context_bind_externaloes);
 
-    YAGL_LOG_DEBUG("Binding samplerExternalOES units into GL_TEXTURE_2D slots:");
+    YAGL_LOG_TRACE("Binding samplerExternalOES units into GL_TEXTURE_2D slots:");
     // FIXME for now assume user is always right and there is no error cases.
     // Errors to consider:
     //   * samplerExternalOES and sampler2D attempting to access same unit
     //   * samplerExternalOES points at unit having no texture bound
-    samplers = yagl_vector_data(&shader->state.samplers_ExternalOES);
-    samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+    samplers = yagl_vector_data(&sampler_info->samplers_ExternalOES);
+    samplers_size = yagl_vector_size(&sampler_info->samplers_ExternalOES);
     for (i = 0; i < samplers_size; ++i) {
         struct yagl_gles_texture_target_state *texture_2d_state, *texture_external_state;
 
@@ -500,22 +500,14 @@ static void yagl_gles2_context_bind_externaloes(struct yagl_gles2_context *ctx,
             //continue; // TODO error GL_INVALID_OPERATION?
         }
 
-        if (samplers[i].location == YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN ||
-            samplers[i].value == YAGL_GLSL_SAMPLER_VALUE_UNKNOWN) {
-            YAGL_LOG_WARN("  #%d: Unknown location/value of uniform %s - skipping", i, samplers[i].name);
-            continue;
-        }
-
         // we could have currently bound either an actual texture 2d or a "zero texture" (for binding = 0)
         // store whatever is bound from cached info, we'll restore it post-draw
         if (texture_2d_state->texture != texture_2d_state->texture_zero) {
             samplers[i].replaced_tex2d = texture_2d_state->texture->global_name;
-            YAGL_LOG_DEBUG("    -> Binding in place of existing texture");
         } else {
             samplers[i].replaced_tex2d = texture_2d_state->texture_zero->global_name;
-            YAGL_LOG_DEBUG("    -> Binding in place of zero texture");
         }
-        YAGL_LOG_DEBUG("  #%d: slot %d texture2D %d => textureExternal %d", i, samplers[i].value, samplers[i].replaced_tex2d,
+        YAGL_LOG_TRACE("  #%d: slot %d texture2D %d => textureExternal %d", i, samplers[i].value, samplers[i].replaced_tex2d,
                                                                             texture_external_state->texture->global_name);
 
         // samplers[i].value is unit requested by app from shader - replace it
@@ -524,22 +516,22 @@ static void yagl_gles2_context_bind_externaloes(struct yagl_gles2_context *ctx,
     }
 }
 
-static void yagl_gles2_context_restore_externaloes_binds(struct yagl_gles2_shader *shader)
+static void yagl_gles2_context_restore_externaloes_binds(struct yagl_gles2_program_sampler_info *sampler_info)
 {
     struct yagl_glsl_sampler *samplers;
     int i = 0, samplers_size = 0;
     YAGL_LOG_FUNC_SET(yagl_gles2_context_restore_externaloes_binds);
 
-    YAGL_LOG_DEBUG("Restoring TEXTURE_2D bindings:");
-    samplers = yagl_vector_data(&shader->state.samplers_ExternalOES);
-    samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+    YAGL_LOG_TRACE("Restoring TEXTURE_2D bindings:");
+    samplers = yagl_vector_data(&sampler_info->samplers_ExternalOES);
+    samplers_size = yagl_vector_size(&sampler_info->samplers_ExternalOES);
     for (i = 0; i < samplers_size; ++i) {
         if (samplers[i].location == YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN ||
             samplers[i].value == YAGL_GLSL_SAMPLER_VALUE_UNKNOWN) {
             continue;
         }
 
-        YAGL_LOG_DEBUG("  #%d: %d unit => %d texture", i, samplers[i].value, samplers[i].replaced_tex2d);
+        YAGL_LOG_TRACE("  #%d: %d unit => %d texture", i, samplers[i].value, samplers[i].replaced_tex2d);
         yagl_host_glActiveTexture(GL_TEXTURE0 + samplers[i].value);
         yagl_host_glBindTexture(GL_TEXTURE_2D, samplers[i].replaced_tex2d);
         samplers[i].replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
@@ -709,18 +701,18 @@ void yagl_gles2_context_pre_draw(struct yagl_gles2_context *ctx,
      * Check for currently bound shaders if any samplers are of samplerExternalOES type.
      * If they are, do some extra checks and bind some textures temporarily.
      */
-    struct yagl_gles2_shader *vertex_shader = ctx->program->vertex_shader;
-    if (vertex_shader && vertex_shader->state.have_samplerexternaloes) {
+    if (ctx->program->vertex_shader_sampler_info.fetched &&
+        ctx->program->vertex_shader_sampler_info.have_samplerexternaloes) {
         ctx->have_externaloes_rebinds_vs = 1;
-        YAGL_LOG_DEBUG("======= Vertex shader has samplerExternalOES ========");
-        yagl_gles2_context_bind_externaloes(ctx, vertex_shader);
+        YAGL_LOG_TRACE("======= Vertex shader has samplerExternalOES ========");
+        yagl_gles2_context_bind_externaloes(ctx, &ctx->program->vertex_shader_sampler_info);
     }
 
-    struct yagl_gles2_shader *fragment_shader = ctx->program->fragment_shader;
-    if (fragment_shader && fragment_shader->state.have_samplerexternaloes) {
+    if (ctx->program->fragment_shader_sampler_info.fetched &&
+        ctx->program->fragment_shader_sampler_info.have_samplerexternaloes) {
         ctx->have_externaloes_rebinds_fs = 1;
-        YAGL_LOG_DEBUG("======= Fragment shader has samplerExternalOES ========");
-        yagl_gles2_context_bind_externaloes(ctx, fragment_shader);
+        YAGL_LOG_TRACE("======= Fragment shader has samplerExternalOES ========");
+        yagl_gles2_context_bind_externaloes(ctx, &ctx->program->fragment_shader_sampler_info);
     }
 }
 
@@ -758,11 +750,11 @@ void yagl_gles2_context_post_draw(struct yagl_gles2_context *ctx,
      * Restore original TEXTURE_2D bindings
      */
     if (ctx->have_externaloes_rebinds_vs) {
-        yagl_gles2_context_restore_externaloes_binds(ctx->program->vertex_shader);
+        yagl_gles2_context_restore_externaloes_binds(&ctx->program->vertex_shader_sampler_info);
     }
 
     if (ctx->have_externaloes_rebinds_fs) {
-        yagl_gles2_context_restore_externaloes_binds(ctx->program->fragment_shader);
+        yagl_gles2_context_restore_externaloes_binds(&ctx->program->fragment_shader_sampler_info);
     }
 
     /*
index 9fe3966d5bc9865d04a97ffe47ba277b02d5edbd..1d0c3430df1c36d7744f06fedd4cb644c0fc527a 100644 (file)
@@ -41,6 +41,7 @@
 #include "yagl_log.h"
 #include "yagl_utils.h"
 #include "yagl_host_gles_calls.h"
+#include "yagl_glsl_state.h"
 #include <string.h>
 #include <stdlib.h>
 #include <pthread.h>
  */
 #define GL_INTERLEAVED_ATTRIBS 0x8C8C
 
+/*
+ * GL_OES_EGL_image_external extension
+ */
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+
 struct yagl_gles2_location_v
 {
     GLchar *name;
@@ -110,6 +116,88 @@ static void yagl_gles2_transform_feedback_info_copy(
     }
 }
 
+static void yagl_gles2_program_sampler_info_copy_from_shader(struct yagl_gles2_program_sampler_info *info,
+                                                             struct yagl_gles2_shader *shader)
+{
+    struct yagl_glsl_sampler *samplers_src;
+    int i = 0, samplers_size = 0;
+    YAGL_LOG_FUNC_SET(yagl_gles2_program_sampler_info_copy_from_shader);
+
+    if (!shader) {
+        YAGL_LOG_TRACE("No shader info available for copy");
+        return;
+    }
+
+    if (shader->state.have_error) {
+        YAGL_LOG_TRACE("Shader's GLSL state is invalid/has error");
+        return;
+    }
+
+    info->have_samplerexternaloes = shader->state.have_samplerexternaloes;
+
+    samplers_size = yagl_vector_size(&shader->state.samplers_ExternalOES);
+    samplers_src = yagl_vector_data(&shader->state.samplers_ExternalOES);
+
+    yagl_vector_init(&info->samplers_ExternalOES, sizeof(struct yagl_glsl_sampler), samplers_size);
+
+    for (i = 0; i < samplers_size; ++i) {
+        struct yagl_glsl_sampler s;
+        s.name = strdup(samplers_src[i].name);
+        s.location = samplers_src[i].location;
+        s.replaced_tex2d = samplers_src[i].replaced_tex2d;
+        s.value = samplers_src[i].value;
+
+        yagl_vector_push_back(&info->samplers_ExternalOES, &s);
+    }
+
+    samplers_size = yagl_vector_size(&shader->state.samplers_2D);
+    samplers_src = yagl_vector_data(&shader->state.samplers_2D);
+
+    yagl_vector_init(&info->samplers_2D, sizeof(struct yagl_glsl_sampler), samplers_size);
+
+    for (i = 0; i < samplers_size; ++i) {
+        struct yagl_glsl_sampler s;
+        s.name = strdup(samplers_src[i].name);
+        s.location = samplers_src[i].location;
+        s.replaced_tex2d = samplers_src[i].replaced_tex2d;
+        s.value = samplers_src[i].value;
+
+        yagl_vector_push_back(&info->samplers_2D, &s);
+    }
+
+    info->fetched = 1;
+}
+
+static void yagl_gles2_program_sampler_info_init(struct yagl_gles2_program_sampler_info *info)
+{
+    info->fetched = 0;
+    info->have_samplerexternaloes = 0;
+}
+
+static void yagl_gles2_program_sampler_info_reset(struct yagl_gles2_program_sampler_info *info)
+{
+    struct yagl_glsl_sampler *samplers;
+    int i = 0, samplers_size = 0;
+
+    info->fetched = 0;
+    info->have_samplerexternaloes = 0;
+
+    samplers_size = yagl_vector_size(&info->samplers_ExternalOES);
+    samplers = yagl_vector_data(&info->samplers_ExternalOES);
+    for (i = 0; i < samplers_size; ++i) {
+        yagl_free(samplers[i].name);
+    }
+
+    samplers_size = yagl_vector_size(&info->samplers_2D);
+    samplers = yagl_vector_data(&info->samplers_2D);
+    for (i = 0; i < samplers_size; ++i) {
+        yagl_free(samplers[i].name);
+    }
+
+    yagl_vector_cleanup(&info->samplers_ExternalOES);
+    yagl_vector_cleanup(&info->samplers_2D);
+}
+
 static void yagl_gles2_program_reset_cached(struct yagl_gles2_program *program)
 {
     int i;
@@ -177,6 +265,9 @@ static void yagl_gles2_program_reset_cached(struct yagl_gles2_program *program)
             yagl_free(location_l);
         }
     }
+
+    yagl_gles2_program_sampler_info_reset(&program->vertex_shader_sampler_info);
+    yagl_gles2_program_sampler_info_reset(&program->fragment_shader_sampler_info);
 }
 
 static void yagl_gles2_program_destroy(struct yagl_ref *ref)
@@ -262,6 +353,9 @@ struct yagl_gles2_program *yagl_gles2_program_create(int gen_locations)
 
     program->transform_feedback_info.buffer_mode = GL_INTERLEAVED_ATTRIBS;
 
+    yagl_gles2_program_sampler_info_init(&program->vertex_shader_sampler_info);
+    yagl_gles2_program_sampler_info_init(&program->fragment_shader_sampler_info);
+
     yagl_host_glCreateProgram(program->global_name);
 
     return program;
@@ -356,6 +450,15 @@ void yagl_gles2_program_link(struct yagl_gles2_program *program)
     yagl_gles2_transform_feedback_info_copy(
         &program->transform_feedback_info,
         &program->linked_transform_feedback_info);
+
+    /*
+     * There is a possibility (and even a GLES spec recommendation) to call
+     * glDetachShader/glDeleteShader after this call. Thus, program->vertex_shader
+     * and program->fragment_shader pointers become NULL and we could have no access
+     * to shader info. Copy necessary for us info to program-local space for further use.
+     */
+    yagl_gles2_program_sampler_info_copy_from_shader(&program->vertex_shader_sampler_info, program->vertex_shader);
+    yagl_gles2_program_sampler_info_copy_from_shader(&program->fragment_shader_sampler_info, program->fragment_shader);
 }
 
 int yagl_gles2_program_get_uniform_location(struct yagl_gles2_program *program,
@@ -417,13 +520,13 @@ int yagl_gles2_program_get_uniform_location(struct yagl_gles2_program *program,
      * Luckily, uniform location does not change so it has to be done
      * only once.
      */
-    if (program->vertex_shader &&
-        program->vertex_shader->state.have_samplerexternaloes) {
+    if (program->vertex_shader_sampler_info.fetched &&
+        program->vertex_shader_sampler_info.have_samplerexternaloes) {
         struct yagl_glsl_sampler *data = NULL;
         int i = 0, data_size = 0;
 
-        data = yagl_vector_data(&program->vertex_shader->state.samplers_ExternalOES);
-        data_size = yagl_vector_size(&program->vertex_shader->state.samplers_ExternalOES);
+        data = yagl_vector_data(&program->vertex_shader_sampler_info.samplers_ExternalOES);
+        data_size = yagl_vector_size(&program->vertex_shader_sampler_info.samplers_ExternalOES);
         for (i = 0; i < data_size; ++i) {
             if (strcmp(data[i].name, name) == 0) {
                 data[i].location = ret;
@@ -432,13 +535,13 @@ int yagl_gles2_program_get_uniform_location(struct yagl_gles2_program *program,
         }
     }
 
-    if (program->fragment_shader &&
-        program->fragment_shader->state.have_samplerexternaloes) {
+    if (program->fragment_shader_sampler_info.fetched &&
+        program->fragment_shader_sampler_info.have_samplerexternaloes) {
         struct yagl_glsl_sampler *data = NULL;
         int i = 0, data_size = 0;
 
-        data = yagl_vector_data(&program->fragment_shader->state.samplers_ExternalOES);
-        data_size = yagl_vector_size(&program->fragment_shader->state.samplers_ExternalOES);
+        data = yagl_vector_data(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+        data_size = yagl_vector_size(&program->fragment_shader_sampler_info.samplers_ExternalOES);
         for (i = 0; i < data_size; ++i) {
             if (strcmp(data[i].name, name) == 0) {
                 data[i].location = ret;
@@ -500,7 +603,7 @@ void yagl_gles2_program_get_active_uniform(struct yagl_gles2_program *program,
 
     if (!var->generic_fetched) {
         yagl_free(var->name);
-        var->name = yagl_malloc(program->max_active_uniform_bufsize);
+        var->name = yagl_malloc(program->max_active_uniform_bufsize + 1);
         var->name[0] = '\0';
 
         yagl_host_glGetActiveUniform(program->global_name,
@@ -513,6 +616,28 @@ void yagl_gles2_program_get_active_uniform(struct yagl_gles2_program *program,
 
         var->name_fetched = 1;
         var->generic_fetched = 1;
+
+        var->name[var->name_size] = 0;
+
+        // It is possible that our sampler2D could actually be samplerExternalOES
+        // Host doesn't know about this. In case we encounter a GL_SAMPLER_2D type
+        // of uniform, go through GLSL program state and see if we should "replace"
+        // it with GL_SAMPLER_EXTERNAL_OES.
+        if (var->type == GL_SAMPLER_2D) {
+            if (program->fragment_shader_sampler_info.fetched) {
+                struct yagl_glsl_sampler *samplers = yagl_vector_data(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+                int i = 0, samplers_size = yagl_vector_size(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+
+                for (i = 0; i < samplers_size; ++i) {
+                    if (strcmp(samplers[i].name, var->name) == 0) {
+                        // also store location because we're here anyway
+                        samplers[i].location = index;
+                        var->type = GL_SAMPLER_EXTERNAL_OES;
+                        break;
+                    }
+                }
+            }
+        }
     }
 
     yagl_gles2_set_name(var->name, var->name_size,
@@ -698,13 +823,13 @@ int yagl_gles2_program_uniform1i(struct yagl_gles2_program *program,
     /*
      * Update shader state for pre_draw/post_draw analysis
      */
-    if (program->vertex_shader &&
-        program->vertex_shader->state.have_samplerexternaloes) {
+    if (program->vertex_shader_sampler_info.fetched &&
+        program->vertex_shader_sampler_info.have_samplerexternaloes) {
         struct yagl_glsl_sampler *data = NULL;
         int i = 0, data_size = 0;
 
-        data = yagl_vector_data(&program->vertex_shader->state.samplers_ExternalOES);
-        data_size = yagl_vector_size(&program->vertex_shader->state.samplers_ExternalOES);
+        data = yagl_vector_data(&program->vertex_shader_sampler_info.samplers_ExternalOES);
+        data_size = yagl_vector_size(&program->vertex_shader_sampler_info.samplers_ExternalOES);
         for (i = 0; i < data_size; ++i) {
             if (data[i].location == location) {
                 data[i].value = x;
@@ -713,13 +838,13 @@ int yagl_gles2_program_uniform1i(struct yagl_gles2_program *program,
         }
     }
 
-    if (program->fragment_shader &&
-        program->fragment_shader->state.have_samplerexternaloes) {
+    if (program->fragment_shader_sampler_info.fetched &&
+        program->fragment_shader_sampler_info.have_samplerexternaloes) {
         struct yagl_glsl_sampler *data = NULL;
         int i = 0, data_size = 0;
 
-        data = yagl_vector_data(&program->fragment_shader->state.samplers_ExternalOES);
-        data_size = yagl_vector_size(&program->fragment_shader->state.samplers_ExternalOES);
+        data = yagl_vector_data(&program->fragment_shader_sampler_info.samplers_ExternalOES);
+        data_size = yagl_vector_size(&program->fragment_shader_sampler_info.samplers_ExternalOES);
         for (i = 0; i < data_size; ++i) {
             if (data[i].location == location) {
                 data[i].value = x;
index 9179f520970144be10c7a53a5eb5adeb581d7d8a..50880133bd0bcb35d109c9c21ad2f492c09407c2 100644 (file)
@@ -188,6 +188,15 @@ struct yagl_gles2_transform_feedback_info
     GLint max_varying_bufsize;
 };
 
+struct yagl_gles2_program_sampler_info
+{
+    int fetched;
+
+    int have_samplerexternaloes;
+    struct yagl_vector samplers_ExternalOES;
+    struct yagl_vector samplers_2D;
+};
+
 struct yagl_gles2_program
 {
     /*
@@ -213,6 +222,10 @@ struct yagl_gles2_program
 
     struct yagl_gles2_shader *fragment_shader;
 
+    struct yagl_gles2_program_sampler_info vertex_shader_sampler_info;
+
+    struct yagl_gles2_program_sampler_info fragment_shader_sampler_info;
+
     union
     {
         struct yagl_list uniform_locations_l;
index 74def144bf0c808be24423dd924c3f8f3caa7dca..2dcbb115ce535d09cc5a03f2c6558346af696ba4 100644 (file)
@@ -397,7 +397,7 @@ void yagl_glsl_state_add_sampler_ExternalOES(struct yagl_glsl_state *state,
     struct yagl_glsl_sampler sampler;
     sampler.name = strdup(str);
     sampler.location = YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN;
-    sampler.value = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
+    sampler.value = 0; // GL spec predefines uniform value as 0
     sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
     yagl_vector_push_back(&state->samplers_ExternalOES, &sampler);
 }
@@ -408,7 +408,7 @@ void yagl_glsl_state_add_sampler_2D(struct yagl_glsl_state *state,
     struct yagl_glsl_sampler sampler;
     sampler.name = strdup(str);
     sampler.location = YAGL_GLSL_SAMPLER_LOCATION_UNKNOWN;
-    sampler.value = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
+    sampler.value = 0; // GL spec predefines uniform value as 0
     sampler.replaced_tex2d = YAGL_GLSL_SAMPLER_VALUE_UNKNOWN;
     yagl_vector_push_back(&state->samplers_2D, &sampler);
 }