glsl: Use parse_program_resource_name to parse transform feedback varyings.
authorPaul Berry <stereotype441@gmail.com>
Tue, 29 Jan 2013 13:52:47 +0000 (05:52 -0800)
committerPaul Berry <stereotype441@gmail.com>
Mon, 4 Feb 2013 18:36:44 +0000 (10:36 -0800)
Previously, transform feedback varyings were parsed in an ad-hoc
fashion that wasn't compatible with structs (or array of structs).
This patch makes it use parse_program_resource_name(), which correctly
handles both.

Note that parse_program_resource_name()'s technique for handling
mal-formed input strings is to simply let them through and rely on the
fact that a future name lookup will fail.  Because of this,
tfeedback_decl::init() no longer needs to return a boolean error
code--it always succeeds, and if the input was mal-formed the error
will be detected later.

NOTE: This is a candidate for the 9.1 branch.

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/glsl/link_varyings.cpp
src/glsl/link_varyings.h

index 25681d6185bdd8c982689e5d2120304974069c93..980b8d0ac90039bbaba1d59767280591d5dbcd23 100644 (file)
@@ -35,6 +35,7 @@
 #include "linker.h"
 #include "link_varyings.h"
 #include "main/macros.h"
+#include "program.h"
 
 
 /**
@@ -154,10 +155,13 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
 
 /**
  * Initialize this object based on a string that was passed to
- * glTransformFeedbackVaryings.  If there is a parse error, the error is
- * reported using linker_error(), and false is returned.
+ * glTransformFeedbackVaryings.
+ *
+ * If the input is mal-formed, this call still succeeds, but it sets
+ * this->var_name to a mal-formed input, so tfeedback_decl::find_output_var()
+ * will fail to find any matching variable.
  */
-bool
+void
 tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
                      const void *mem_ctx, const char *input)
 {
@@ -175,7 +179,7 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
       /* Parse gl_NextBuffer. */
       if (strcmp(input, "gl_NextBuffer") == 0) {
          this->next_buffer_separator = true;
-         return true;
+         return;
       }
 
       /* Parse gl_SkipComponents. */
@@ -189,21 +193,17 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
          this->skip_components = 4;
 
       if (this->skip_components)
-         return true;
+         return;
    }
 
    /* Parse a declaration. */
-   const char *bracket = strrchr(input, '[');
-
-   if (bracket) {
-      this->var_name = ralloc_strndup(mem_ctx, input, bracket - input);
-      if (sscanf(bracket, "[%u]", &this->array_subscript) != 1) {
-         linker_error(prog, "Cannot parse transform feedback varying %s", input);
-         return false;
-      }
+   const char *base_name_end;
+   long subscript = parse_program_resource_name(input, &base_name_end);
+   this->var_name = ralloc_strndup(mem_ctx, input, base_name_end - input);
+   if (subscript >= 0) {
+      this->array_subscript = subscript;
       this->is_subscripted = true;
    } else {
-      this->var_name = ralloc_strdup(mem_ctx, input);
       this->is_subscripted = false;
    }
 
@@ -215,8 +215,6 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
        strcmp(this->var_name, "gl_ClipDistance") == 0) {
       this->is_clip_distance_mesa = true;
    }
-
-   return true;
 }
 
 
@@ -449,8 +447,7 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
                       char **varying_names, tfeedback_decl *decls)
 {
    for (unsigned i = 0; i < num_names; ++i) {
-      if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i]))
-         return false;
+      decls[i].init(ctx, prog, mem_ctx, varying_names[i]);
 
       if (!decls[i].is_varying())
          continue;
index 057e4b219252864454219fa9d0603988166a1854..806bd1c470f8ea939fa380ae8d07b8234add46c6 100644 (file)
@@ -48,7 +48,7 @@ class ir_variable;
 class tfeedback_decl
 {
 public:
-   bool init(struct gl_context *ctx, struct gl_shader_program *prog,
+   void init(struct gl_context *ctx, struct gl_shader_program *prog,
              const void *mem_ctx, const char *input);
    static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
    bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog,