mojoshader.c
branchtrunk
changeset 278 5c432d216078
parent 268 6d5a1323db28
child 279 f06f4ea3d751
--- a/mojoshader.c	Sat May 03 14:16:01 2008 -0400
+++ b/mojoshader.c	Sat May 03 15:28:30 2008 -0400
@@ -228,6 +228,11 @@
     struct RegisterList *next;
 } RegisterList;
 
+typedef struct ConstantsList
+{
+    MOJOSHADER_constant constant;
+    struct ConstantsList *next;
+} ConstantsList;
 
 // result modifiers.
 #define MOD_SATURATE 0x01
@@ -348,6 +353,8 @@
     int cmps;
     RegisterList used_registers;
     RegisterList defined_registers;
+    int constant_count;
+    ConstantsList *constants;
     int uniform_count;
     RegisterList uniforms;
     int attribute_count;
@@ -3594,9 +3601,22 @@
 } // parse_args_TEX
 
 
-
 // State machine functions...
 
+static ConstantsList *alloc_constant_listitem(Context *ctx)
+{
+    ConstantsList *item = (ConstantsList *) Malloc(ctx, sizeof (ConstantsList));
+    if (item == NULL)
+        return NULL;
+
+    memset(&item->constant, '\0', sizeof (MOJOSHADER_constant));
+    item->next = ctx->constants;
+    ctx->constants = item;
+    ctx->constant_count++;
+
+    return item;
+} // alloc_constant_listitem
+
 static void state_DEF(Context *ctx)
 {
     const RegisterType regtype = ctx->dest_arg.regtype;
@@ -3604,10 +3624,19 @@
 
     ctx->instruction_count--;  // these don't increase your instruction count.
 
+    // !!! FIXME: fail if same register is defined twice.
+
     if (regtype != REG_TYPE_CONST)
         fail(ctx, "DEF token using invalid register");
     else
+    {
+        ConstantsList *item = alloc_constant_listitem(ctx);
+        item->constant.index = regnum;
+        item->constant.type = MOJOSHADER_UNIFORM_FLOAT;
+        memcpy(item->constant.value.f, ctx->dwords,
+               sizeof (item->constant.value.f));
         set_defined_register(ctx, regtype, regnum);
+    } // else
 } // state_DEF
 
 static void state_DEFI(Context *ctx)
@@ -3615,12 +3644,22 @@
     const RegisterType regtype = ctx->dest_arg.regtype;
     const int regnum = ctx->dest_arg.regnum;
 
+    // !!! FIXME: fail if same register is defined twice.
+
     ctx->instruction_count--;  // these don't increase your instruction count.
 
     if (regtype != REG_TYPE_CONSTINT)
         fail(ctx, "DEFI token using invalid register");
     else
+    {
+        ConstantsList *item = alloc_constant_listitem(ctx);
+        item->constant.index = regnum;
+        item->constant.type = MOJOSHADER_UNIFORM_INT;
+        memcpy(item->constant.value.i, ctx->dwords,
+               sizeof (item->constant.value.i));
+
         set_defined_register(ctx, regtype, regnum);
+    } // else
 } // state_DEFI
 
 static void state_DEFB(Context *ctx)
@@ -3628,12 +3667,20 @@
     const RegisterType regtype = ctx->dest_arg.regtype;
     const int regnum = ctx->dest_arg.regnum;
 
+    // !!! FIXME: fail if same register is defined twice.
+
     ctx->instruction_count--;  // these don't increase your instruction count.
 
     if (regtype != REG_TYPE_CONSTBOOL)
         fail(ctx, "DEFB token using invalid register");
     else
+    {
+        ConstantsList *item = alloc_constant_listitem(ctx);
+        item->constant.index = regnum;
+        item->constant.type = MOJOSHADER_UNIFORM_BOOL;
+        item->constant.value.b = ctx->dwords[0] ? 1 : 0;
         set_defined_register(ctx, regtype, regnum);
+    } // else
 } // state_DEFB
 
 static void state_DCL(Context *ctx)
@@ -4458,6 +4505,17 @@
 } // free_output_list
 
 
+static void free_constants_list(MOJOSHADER_free f, void *d, ConstantsList *item)
+{
+    while (item != NULL)
+    {
+        ConstantsList *next = item->next;
+        f(item, d);
+        item = next;
+    } // while
+} // free_constants_list
+
+
 static void destroy_context(Context *ctx)
 {
     if (ctx != NULL)
@@ -4472,6 +4530,7 @@
         free_output_list(f, d, ctx->mainline_intro.head.next);
         free_output_list(f, d, ctx->mainline.head.next);
         free_output_list(f, d, ctx->ignore.head.next);
+        free_constants_list(f, d, ctx->constants);
         free_reglist(f, d, ctx->used_registers.next);
         free_reglist(f, d, ctx->defined_registers.next);
         free_reglist(f, d, ctx->uniforms.next);
@@ -4593,6 +4652,33 @@
 } // build_uniforms
 
 
+static MOJOSHADER_constant *build_constants(Context *ctx)
+{
+    const size_t len = sizeof (MOJOSHADER_constant) * ctx->constant_count;
+    MOJOSHADER_constant *retval = (MOJOSHADER_constant *) Malloc(ctx, len);
+
+    if (retval != NULL)
+    {
+        ConstantsList *item = ctx->constants;
+        int i;
+
+        for (i = 0; i < ctx->constant_count; i++)
+        {
+            if (item == NULL)
+            {
+                fail(ctx, "BUG: mismatched constant list and count");
+                break;
+            } // if
+
+            memcpy(&retval[i], &item->constant, sizeof (MOJOSHADER_constant));
+            item = item->next;
+        } // for
+    } // if
+
+    return retval;
+} // build_constants
+
+
 static MOJOSHADER_sampler *build_samplers(Context *ctx)
 {
     const size_t len = sizeof (MOJOSHADER_sampler) * ctx->sampler_count;
@@ -4718,6 +4804,7 @@
 static MOJOSHADER_parseData *build_parsedata(Context *ctx)
 {
     char *output = NULL;
+    MOJOSHADER_constant *constants = NULL;
     MOJOSHADER_uniform *uniforms = NULL;
     MOJOSHADER_attribute *attributes = NULL;
     MOJOSHADER_sampler *samplers = NULL;
@@ -4734,6 +4821,9 @@
         output = build_output(ctx);
 
     if (!isfail(ctx))
+        constants = build_constants(ctx);
+
+    if (!isfail(ctx))
         uniforms = build_uniforms(ctx);
 
     if (!isfail(ctx))
@@ -4748,6 +4838,7 @@
         int i;
 
         Free(ctx, output);
+        Free(ctx, constants);
 
         if (uniforms != NULL)
         {
@@ -4784,6 +4875,8 @@
         retval->minor_ver = (int) ctx->minor_ver;
         retval->uniform_count = ctx->uniform_count;
         retval->uniforms = uniforms;
+        retval->constant_count = ctx->constant_count;
+        retval->constants = constants;
         retval->attribute_count = attribute_count;
         retval->attributes = attributes;
         retval->sampler_count = ctx->sampler_count;
@@ -4945,6 +5038,9 @@
     if (data->output != NULL)  // check for NULL in case of dumb free() impl.
         f((void *) data->output, d);
 
+    if (data->constants != NULL)
+        f((void *) data->constants, d);
+
     if (data->uniforms != NULL)
     {
         for (i = 0; i < data->uniform_count; i++)