* Mesa 3-D graphics library
* Version: 6.5
*
- * Copyright (C) 2004-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 2004-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
GLboolean (* GetLinkStatus) (struct gl2_program_intf **);
GLboolean (* GetValidateStatus) (struct gl2_program_intf **);
GLvoid (* Link) (struct gl2_program_intf **);
- GLvoid (* Validate) (struct gl2_program_intf **);\r
- GLvoid (* UpdateFixedUniforms) (struct gl2_program_intf **);\r
- GLvoid (* UpdateFixedAttribute) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,\r
- GLboolean);\r
- GLvoid (* UpdateFixedVarying) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,\r
- GLboolean);\r
- GLvoid (* GetTextureImageUsage) (struct gl2_program_intf **, GLbitfield *);\r
+ GLvoid (* Validate) (struct gl2_program_intf **);
+ GLvoid (* UpdateFixedUniforms) (struct gl2_program_intf **);
+ GLvoid (* UpdateFixedAttribute) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
+ GLboolean);
+ GLvoid (* UpdateFixedVarying) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
+ GLboolean);
+ GLvoid (* GetTextureImageUsage) (struct gl2_program_intf **, GLbitfield *);
GLboolean (* IsShaderPresent) (struct gl2_program_intf **, GLenum);
+ GLvoid (* UpdateVarying) (struct gl2_program_intf **, GLuint, GLfloat *, GLboolean);
};
struct gl2_fragment_shader_intf
{\r
GLuint n, addr, j;\r
\r
- n = pro->texture_usage.table[i].quant->array_len;\r
- if (n == 0)\r
- n = 1;\r
+ n = slang_export_data_quant_elements (pro->texture_usage.table[i].quant);\r
addr = pro->texture_usage.table[i].frag_address;\r
for (j = 0; j < n; j++)\r
{\r
image = (GLuint) *((GLfloat *) mem);\r
if (image >= 0 && image < ctx->Const.MaxTextureImageUnits)\r
{\r
- switch (pro->texture_usage.table[i].quant->u.basic_type)\r
+ switch (slang_export_data_quant_type (pro->texture_usage.table[i].quant))\r
{\r
case GL_SAMPLER_1D_ARB:\r
case GL_SAMPLER_1D_SHADOW_ARB:\r
}\r
}\r
\r
+static GLvoid\r
+_program_UpdateVarying (struct gl2_program_intf **intf, GLuint index, GLfloat *value,\r
+ GLboolean vert)\r
+{\r
+ struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
+ slang_program *pro = &impl->_obj.prog;\r
+ GLuint addr;\r
+\r
+ if (index >= pro->varyings.total)\r
+ return;\r
+ if (vert)\r
+ addr = pro->varyings.slots[index].vert_addr / 4;\r
+ else\r
+ addr = pro->varyings.slots[index].frag_addr / 4;\r
+ if (addr != ~0)\r
+ {\r
+ if (vert)\r
+ *value = pro->machines[SLANG_SHADER_VERTEX]->mem[addr]._float;\r
+ else\r
+ pro->machines[SLANG_SHADER_FRAGMENT]->mem[addr]._float = *value;\r
+ }\r
+}\r
+\r
static struct gl2_program_intf _program_vftbl = {\r
{\r
{\r
_program_UpdateFixedAttribute,\r
_program_UpdateFixedVarying,\r
_program_GetTextureImageUsage,\r
- _program_IsShaderPresent\r
+ _program_IsShaderPresent,\r
+ _program_UpdateVarying\r
};\r
\r
static void\r
\r
b = &bind->table[loc];\r
/* TODO: check sizes */\r
- if (b->quant->structure != NULL)\r
+ if (slang_export_data_quant_struct (b->quant))\r
return GL_FALSE;\r
\r
- switch (b->quant->u.basic_type)\r
+ switch (slang_export_data_quant_type (b->quant))\r
{\r
case GL_BOOL_ARB:\r
types_match = (type == GL_FLOAT) || (type == GL_INT);\r
types_match = (type == GL_INT);\r
break;\r
default:\r
- types_match = (type == b->quant->u.basic_type);\r
+ types_match = (type == slang_export_data_quant_type (b->quant));\r
break;\r
}\r
\r
const GLfloat *src = (GLfloat *) (data);\r
GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
GLuint j;\r
+ GLuint total = count * slang_export_data_quant_components (b->quant);\r
\r
- for (j = 0; j < count * b->quant->size / 4; j++)\r
+ for (j = 0; j < total; j++)\r
dst[j] = src[j] != 0.0f ? 1.0f : 0.0f;\r
}\r
}\r
const GLuint *src = (GLuint *) (data);\r
GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
GLuint j;\r
+ GLuint total = count * slang_export_data_quant_components (b->quant);\r
\r
- for (j = 0; j < count * b->quant->size / 4; j++)\r
+ for (j = 0; j < total; j++)\r
dst[j] = src[j] ? 1.0f : 0.0f;\r
}\r
}\r
const GLuint *src = (GLuint *) (data);\r
GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
GLuint j;\r
+ GLuint total = count * slang_export_data_quant_components (b->quant);\r
\r
- for (j = 0; j < count * b->quant->size / 4; j++)\r
+ for (j = 0; j < total; j++)\r
dst[j] = (GLfloat) src[j];\r
}\r
}\r
if (b->address[i] != ~0)\r
{\r
_mesa_memcpy (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4], data,\r
- count * b->quant->size);\r
+ count * slang_export_data_quant_size (b->quant));\r
}\r
}\r
return GL_TRUE;\r
name[len] = '\0';\r
if (length != NULL)\r
*length = len;\r
- *type = u->quant->u.basic_type;\r
- if (u->quant->array_len == 0)\r
- *size = 1;\r
- else\r
- *size = u->quant->array_len;\r
+ *type = slang_export_data_quant_type (u->quant);\r
+ *size = slang_export_data_quant_elements (u->quant);\r
}\r
\r
void\r
{\r
slang_uniform_binding *b = &prog->uniforms.table[i];\r
\r
- if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && b->quant->structure == NULL)\r
+ if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && !slang_export_data_quant_struct (b->quant))\r
{\r
- switch (b->quant->u.basic_type)\r
+ switch (slang_export_data_quant_type (b->quant))\r
{\r
case GL_SAMPLER_1D_ARB:\r
case GL_SAMPLER_2D_ARB:\r
{\r
slang_uniform_binding *b = &prog->uniforms.table[i];\r
\r
- if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && b->quant->structure == NULL)\r
+ if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && !slang_export_data_quant_struct (b->quant))\r
{\r
- switch (b->quant->u.basic_type)\r
+ switch (slang_export_data_quant_type (b->quant))\r
{\r
case GL_SAMPLER_1D_ARB:\r
case GL_SAMPLER_2D_ARB:\r
#define RND_NEG_FPU (FAST_X86_FPU | 0x400)\r
#endif\r
\r
+#if 0\r
+\r
+/*\r
+ * XXX\r
+ * These should produce a valid code that computes powers. Unfortunately, it does not.\r
+ */\r
static void set_fpu_round_neg_inf (codegen_ctx *G)\r
{\r
if (G->fpucntl != RND_NEG_FPU)\r
x87_fscale (&G->f); /* 2^a */\r
}\r
\r
+static void emit_pow (codegen_ctx *G)\r
+{\r
+ x87_fld (&G->f, x86_deref (G->r_esp));\r
+ x87_fld (&G->f, x86_make_disp (G->r_esp, 4));\r
+ x87_fyl2x (&G->f);\r
+ emit_x87_ex2 (G);\r
+}\r
+\r
+#endif\r
+\r
static GLfloat do_ceilf (GLfloat x)\r
{\r
return CEILF (x);\r
return FLOORF (x);\r
}\r
\r
+static GLfloat do_powf (GLfloat y, GLfloat x)\r
+{\r
+ return (GLfloat) _mesa_pow ((GLdouble) x, (GLdouble) y);\r
+}\r
+\r
static GLvoid do_print_float (GLfloat x)\r
{\r
_mesa_printf ("slang print: %f\n", x);\r
x87_fstp (&G->f, x86_deref (G->r_esp));\r
break;\r
case slang_asm_float_power:\r
- x87_fld (&G->f, x86_deref (G->r_esp));\r
- x87_fld (&G->f, x86_make_disp (G->r_esp, 4));\r
- x87_fyl2x (&G->f);\r
- emit_x87_ex2 (G);\r
+ /* TODO: use emit_pow() */\r
+ x86_call (&G->f, (GLubyte *) do_powf);\r
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));\r
x87_fstp (&G->f, x86_deref (G->r_esp));\r
break;\r
return &self->structure[n];\r
}\r
\r
+GLboolean slang_export_data_quant_array (slang_export_data_quant *self)\r
+{\r
+ return self->array_len != 0;\r
+}\r
+\r
+GLboolean slang_export_data_quant_struct (slang_export_data_quant *self)\r
+{\r
+ return self->structure != NULL;\r
+}\r
+\r
+GLenum slang_export_data_quant_type (slang_export_data_quant *self)\r
+{\r
+ assert (self->structure == NULL);\r
+ return self->u.basic_type;\r
+}\r
+\r
+GLuint slang_export_data_quant_fields (slang_export_data_quant *self)\r
+{\r
+ assert (self->structure != NULL);\r
+ return self->u.field_count;\r
+}\r
+\r
+GLuint slang_export_data_quant_elements (slang_export_data_quant *self)\r
+{\r
+ if (self->array_len == 0)\r
+ return 1;\r
+ return self->array_len;\r
+}\r
+\r
+GLuint slang_export_data_quant_components (slang_export_data_quant *self)\r
+{\r
+ return self->size / 4;\r
+}\r
+\r
+GLuint slang_export_data_quant_size (slang_export_data_quant *self)\r
+{\r
+ return self->size;\r
+}\r
+\r
/*\r
* slang_export_data_entry\r
*/\r
case EXTRACT_BASIC:\r
return GL_TRUE;\r
case EXTRACT_ARRAY:\r
- return element < q->array_len;\r
+ return element < slang_export_data_quant_elements (q);\r
case EXTRACT_STRUCT:\r
- return q->structure != NULL;\r
+ return slang_export_data_quant_struct (q);\r
case EXTRACT_STRUCT_ARRAY:\r
- return q->structure != NULL && element < q->array_len;\r
+ return slang_export_data_quant_struct (q) && element < slang_export_data_quant_elements (q);\r
}\r
return GL_FALSE;\r
}\r
\r
static GLuint calculate_offset (slang_export_data_quant *q, GLuint element)\r
{\r
- if (q->array_len != 0)\r
- return element * q->size;\r
+ if (slang_export_data_quant_array (q))\r
+ return element * slang_export_data_quant_size (q);\r
return 0;\r
}\r
\r
GLuint result, element, i;\r
const char *end;\r
slang_atom atom;\r
+ const GLuint fields = slang_export_data_quant_fields (q);\r
\r
result = extract_name (name, parsed, &element, &end);\r
if (result == EXTRACT_ERROR)\r
if (atom == SLANG_ATOM_NULL)\r
return GL_FALSE;\r
\r
- for (i = 0; i < q->u.field_count; i++)\r
+ for (i = 0; i < fields; i++)\r
if (q->structure[i].name == atom)\r
{\r
if (!validate_extracted (&q->structure[i], element, result))\r
* Basic data quantity to transfer between application and assembly.\r
* The <size> is the actual size of the data quantity including padding, if any. It is\r
* used to calculate offsets from the beginning of the data.\r
- * The <array_len> is not 0, the data quantity is an array of <array_len> size.\r
+ * If the <array_len> is not 0, the data quantity is an array of <array_len> size.\r
* If the <structure> is not NULL, the data quantity is a struct. The <basic_type> is\r
* invalid and the <field_count> holds the size of the <structure> array.\r
* The <basic_type> values match those of <type> parameter for glGetActiveUniformARB.\r
GLvoid slang_export_data_quant_dtr (slang_export_data_quant *);\r
slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_quant *);\r
\r
+/*\r
+ * Returns GL_FALSE if the quant is not an array.\r
+ */\r
+GLboolean slang_export_data_quant_array (slang_export_data_quant *);\r
+\r
+/*\r
+ * Returns GL_FALSE if the quant is not a structure.\r
+ */\r
+GLboolean slang_export_data_quant_struct (slang_export_data_quant *);\r
+\r
+/*\r
+ * Returns basic type of the quant. It must not be a structure.\r
+ */\r
+GLenum slang_export_data_quant_type (slang_export_data_quant *);\r
+\r
+/*\r
+ * Returns number of fields in the quant that is a structure.\r
+ */\r
+GLuint slang_export_data_quant_fields (slang_export_data_quant *);\r
+\r
+/*\r
+ * Return number of elements in the quant.\r
+ * For arrays, return the size of the array.\r
+ * For scalars, return 1.\r
+ */\r
+GLuint slang_export_data_quant_elements (slang_export_data_quant *);\r
+\r
+/*\r
+ * Returns total number of components withing the quant element.\r
+ */\r
+GLuint slang_export_data_quant_components (slang_export_data_quant *);\r
+\r
+/*\r
+ * Returns size of the quant element.\r
+ */\r
+GLuint slang_export_data_quant_size (slang_export_data_quant *);\r
+\r
/*\r
* Data access pattern. Specifies how data is accessed at what frequency.\r
*/\r
return GL_TRUE;\r
}\r
\r
-static GLboolean insert_binding (slang_uniform_bindings *bind, slang_export_data_quant *q,\r
+static GLboolean insert_uniform_binding (slang_uniform_bindings *bind, slang_export_data_quant *q,\r
char *name, slang_atom_pool *atoms, GLuint index, GLuint addr)\r
{\r
GLuint count, i;\r
\r
slang_string_concat (name, slang_atom_pool_id (atoms, q->name));\r
-\r
- if (q->array_len == 0)\r
- count = 1;\r
- else\r
- count = q->array_len;\r
-\r
+ count = slang_export_data_quant_elements (q);\r
for (i = 0; i < count; i++)\r
{\r
GLuint save;\r
\r
save = slang_string_length (name);\r
- if (q->array_len != 0)\r
+ if (slang_export_data_quant_array (q))\r
_mesa_sprintf (name + slang_string_length (name), "[%d]", i);\r
\r
- if (q->structure != NULL)\r
+ if (slang_export_data_quant_struct (q))\r
{\r
GLuint save, i;\r
+ const GLuint fields = slang_export_data_quant_fields (q);\r
\r
slang_string_concat (name, ".");\r
save = slang_string_length (name);\r
\r
- for (i = 0; i < q->u.field_count; i++)\r
+ for (i = 0; i < fields; i++)\r
{\r
- if (!insert_binding (bind, &q->structure[i], name, atoms, index, addr))\r
+ if (!insert_uniform_binding (bind, &q->structure[i], name, atoms, index, addr))\r
return GL_FALSE;\r
name[save] = '\0';\r
- addr += q->structure[i].size;\r
+ addr += slang_export_data_quant_size (&q->structure[i]);\r
}\r
}\r
else\r
{\r
if (!slang_uniform_bindings_add (bind, q, name, index, addr))\r
return GL_FALSE;\r
- addr += q->size;\r
+ addr += slang_export_data_quant_size (q);\r
}\r
name[save] = '\0';\r
}\r
return GL_TRUE;\r
}\r
\r
-static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, slang_export_data_table *tbl,\r
- GLuint index)\r
+static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind,\r
+ slang_export_data_table *tbl, GLuint index)\r
{\r
GLuint i;\r
\r
{\r
char name[1024] = "";\r
\r
- if (!insert_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index,\r
+ if (!insert_uniform_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index,\r
tbl->entries[i].address))\r
return GL_FALSE;\r
}\r
slang_atom_pool *atoms)\r
{\r
slang_string_concat (name, slang_atom_pool_id (atoms, q->name));\r
- if (q->array_len != 0)\r
+ if (slang_export_data_quant_array (q))\r
slang_string_concat (name, "[0]");\r
\r
- if (q->structure != NULL)\r
+ if (slang_export_data_quant_struct (q))\r
{\r
GLuint save, i;\r
+ const GLuint fields = slang_export_data_quant_fields (q);\r
\r
slang_string_concat (name, ".");\r
save = slang_string_length (name);\r
\r
- for (i = 0; i < q->u.field_count; i++)\r
+ for (i = 0; i < fields; i++)\r
{\r
if (!insert_uniform (u, &q->structure[i], name, atoms))\r
return GL_FALSE;\r
return GL_TRUE;\r
}\r
\r
+/*\r
+ * slang_varying_bindings\r
+ */\r
+\r
+static GLvoid slang_varying_bindings_ctr (slang_varying_bindings *self)\r
+{\r
+ self->count = 0;\r
+ self->total = 0;\r
+}\r
+\r
+static GLvoid slang_varying_bindings_dtr (slang_varying_bindings *self)\r
+{\r
+ GLuint i;\r
+\r
+ for (i = 0; i < self->count; i++)\r
+ slang_alloc_free (self->table[i].name);\r
+}\r
+\r
+static GLvoid update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean vert,\r
+ GLuint address, GLuint do_offset)\r
+{\r
+ GLuint i;\r
+\r
+ for (i = 0; i < count; i++)\r
+ if (vert)\r
+ slots[i].vert_addr = address + i * 4 * do_offset;\r
+ else\r
+ slots[i].frag_addr = address + i * 4 * do_offset;\r
+}\r
+\r
+static GLboolean slang_varying_bindings_add (slang_varying_bindings *self,\r
+ slang_export_data_quant *q, const char *name, GLboolean vert, GLuint address)\r
+{\r
+ const GLuint n = self->count;\r
+ const GLuint total_components =\r
+ slang_export_data_quant_components (q) * slang_export_data_quant_elements (q);\r
+ GLuint i;\r
+\r
+ for (i = 0; i < n; i++)\r
+ if (slang_string_compare (self->table[i].name, name) == 0)\r
+ {\r
+ /* TODO: data quantities must match, or else link fails */\r
+ update_varying_slots (&self->slots[self->table[i].slot], total_components, vert,\r
+ address, 1);\r
+ return GL_TRUE;\r
+ }\r
+\r
+ if (self->total + total_components > MAX_VARYING_FLOATS)\r
+ {\r
+ /* TODO: info log: error: MAX_VARYING_FLOATS exceeded */\r
+ return GL_FALSE;\r
+ }\r
+\r
+ self->table[n].quant = q;\r
+ self->table[n].slot = self->total;\r
+ self->table[n].name = slang_string_duplicate (name);\r
+ if (self->table[n].name == NULL)\r
+ return GL_FALSE;\r
+ self->count++;\r
+\r
+ update_varying_slots (&self->slots[self->table[n].slot], total_components, vert, address, 1);\r
+ update_varying_slots (&self->slots[self->table[n].slot], total_components, !vert, ~0, 0);\r
+ self->total += total_components;\r
+\r
+ return GL_TRUE;\r
+}\r
+\r
+static GLboolean entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms)\r
+{\r
+ const char *str = slang_atom_pool_id (atoms, name);\r
+ return str[0] == 'g' && str[1] == 'l' && str[2] == '_';\r
+}\r
+\r
+static GLboolean gather_varying_bindings (slang_varying_bindings *bind,\r
+ slang_export_data_table *tbl, GLboolean vert)\r
+{\r
+ GLuint i;\r
+\r
+ for (i = 0; i < tbl->count; i++)\r
+ if (tbl->entries[i].access == slang_exp_varying &&\r
+ !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms))\r
+ {\r
+ if (!slang_varying_bindings_add (bind, &tbl->entries[i].quant,\r
+ slang_atom_pool_id (tbl->atoms, tbl->entries[i].quant.name), vert,\r
+ tbl->entries[i].address))\r
+ return GL_FALSE;\r
+ }\r
+\r
+ return GL_TRUE;\r
+}\r
+\r
/*\r
* slang_texture_bindings\r
*/\r
\r
slang_uniform_bindings_ctr (&self->uniforms);\r
slang_active_uniforms_ctr (&self->active_uniforms);\r
+ slang_varying_bindings_ctr (&self->varyings);\r
slang_texture_usages_ctr (&self->texture_usage);\r
for (i = 0; i < SLANG_SHADER_MAX; i++)\r
{\r
{\r
slang_uniform_bindings_dtr (&self->uniforms);\r
slang_active_uniforms_dtr (&self->active_uniforms);\r
+ slang_varying_bindings_dtr (&self->varyings);\r
slang_texture_usages_dtr (&self->texture_usage);\r
}\r
\r
return GL_FALSE;\r
if (!gather_active_uniforms (&prog->active_uniforms, &units[i]->exp_data))\r
return GL_FALSE;\r
+ if (!gather_varying_bindings (&prog->varyings, &units[i]->exp_data,\r
+ index == SLANG_SHADER_VERTEX))\r
+ return GL_FALSE;\r
resolve_common_fixed (prog->common_fixed_entries[index], &units[i]->exp_data);\r
resolve_common_code (prog->code[index], &units[i]->exp_code);\r
prog->machines[index] = units[i]->machine;\r
prog->assemblies[index] = units[i]->assembly;\r
}\r
\r
+ /* TODO: all varyings read by fragment shader must be written by vertex shader */\r
+\r
if (!_slang_analyse_texture_usage (prog))\r
return GL_FALSE;\r
\r
GLuint count;\r
} slang_active_uniforms;\r
\r
+typedef struct\r
+{\r
+ GLuint vert_addr;\r
+ GLuint frag_addr;\r
+} slang_varying_slot;\r
+\r
+typedef struct\r
+{\r
+ slang_export_data_quant *quant;\r
+ char *name;\r
+ GLuint slot;\r
+} slang_varying_binding;\r
+\r
+typedef struct\r
+{\r
+ slang_varying_binding table[MAX_VARYING_FLOATS];\r
+ GLuint count;\r
+ slang_varying_slot slots[MAX_VARYING_FLOATS];\r
+ GLuint total;\r
+} slang_varying_bindings;\r
+\r
typedef struct\r
{\r
slang_export_data_quant *quant;\r
{\r
slang_uniform_bindings uniforms;\r
slang_active_uniforms active_uniforms;\r
+ slang_varying_bindings varyings;\r
slang_texture_usages texture_usage;\r
GLuint common_fixed_entries[SLANG_SHADER_MAX][SLANG_COMMON_FIXED_MAX];\r
GLuint vertex_fixed_entries[SLANG_VERTEX_FIXED_MAX];\r