aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/glsl/builtin_compiler/Makefile.am43
-rw-r--r--mesalib/src/glsl/ir_set_program_inouts.cpp38
-rw-r--r--mesalib/src/glsl/link_uniform_blocks.cpp6
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp24
-rw-r--r--mesalib/src/glsl/link_varyings.cpp227
-rw-r--r--mesalib/src/glsl/link_varyings.h59
-rw-r--r--mesalib/src/glsl/linker.cpp59
-rw-r--r--mesalib/src/glsl/linker.h33
-rw-r--r--mesalib/src/glsl/program.h4
-rwxr-xr-xmesalib/src/mesa/drivers/dri/swrast/swrast.c1
-rw-r--r--mesalib/src/mesa/main/extensions.c2
-rw-r--r--mesalib/src/mesa/main/teximage.c14
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp85
-rw-r--r--mesalib/src/mesa/main/uniforms.h4
-rw-r--r--mesalib/src/mesa/program/ir_to_mesa.cpp4
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_texture.c35
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_drawpixels.c24
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_texture.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_format.c84
-rw-r--r--mesalib/src/mesa/state_tracker/st_format.h6
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp28
-rw-r--r--mesalib/src/mesa/state_tracker/st_texture.c3
22 files changed, 473 insertions, 312 deletions
diff --git a/mesalib/src/glsl/builtin_compiler/Makefile.am b/mesalib/src/glsl/builtin_compiler/Makefile.am
index 976640822..e11a17fbe 100644
--- a/mesalib/src/glsl/builtin_compiler/Makefile.am
+++ b/mesalib/src/glsl/builtin_compiler/Makefile.am
@@ -20,23 +20,44 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
-CC = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS_FOR_BUILD@
-CPP = @CPP_FOR_BUILD@
-CPPFLAGS = @CPPFLAGS_FOR_BUILD@
-CXX = @CXX_FOR_BUILD@
-CXXFLAGS = @CXXFLAGS_FOR_BUILD@
-LD = @LD_FOR_BUILD@
-LDFLAGS = @LDFLAGS_FOR_BUILD@
-
AM_CFLAGS = \
-I $(top_srcdir)/include \
-I $(top_srcdir)/src/mapi \
-I $(top_srcdir)/src/mesa \
-I $(GLSL_SRCDIR) \
-I $(GLSL_SRCDIR)/glcpp \
- -I $(GLSL_BUILDDIR) \
- $(DEFINES_FOR_BUILD)
+ -I $(GLSL_BUILDDIR)
+
+if CROSS_COMPILING
+proxyCC = @CC_FOR_BUILD@
+proxyCFLAGS = @CFLAGS_FOR_BUILD@
+proxyCPP = @CPP_FOR_BUILD@
+proxyCPPFLAGS = @CPPFLAGS_FOR_BUILD@
+proxyCXX = @CXX_FOR_BUILD@
+proxyCXXFLAGS = @CXXFLAGS_FOR_BUILD@
+proxyLD = @LD_FOR_BUILD@
+proxyLDFLAGS = @LDFLAGS_FOR_BUILD@
+AM_CFLAGS += $(DEFINES_FOR_BUILD)
+else
+proxyCC = @CC@
+proxyCFLAGS = @CFLAGS@
+proxyCPP = @CPP@
+proxyCPPFLAGS = @CPPFLAGS@
+proxyCXX = @CXX@
+proxyCXXFLAGS = @CXXFLAGS@
+proxyLD = @LD@
+proxyLDFLAGS = @LDFLAGS@
+AM_CFLAGS += $(DEFINES)
+endif
+
+CC = $(proxyCC)
+CFLAGS = $(proxyCFLAGS)
+CPP = $(proxyCPP)
+CPPFLAGS = $(proxyCPPFLAGS)
+CXX = $(proxyCXX)
+CXXFLAGS = $(proxyCXXFLAGS)
+LD = $(proxyLD)
+LDFLAGS = $(proxyLDFLAGS)
AM_CXXFLAGS = $(AM_CFLAGS)
diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp
index 1e102bfbb..91a8b4526 100644
--- a/mesalib/src/glsl/ir_set_program_inouts.cpp
+++ b/mesalib/src/glsl/ir_set_program_inouts.cpp
@@ -38,7 +38,6 @@
*/
#include "main/core.h" /* for struct gl_program */
-#include "program/hash_table.h"
#include "ir.h"
#include "ir_visitor.h"
#include "glsl_types.h"
@@ -50,13 +49,9 @@ public:
{
this->prog = prog;
this->is_fragment_shader = is_fragment_shader;
- this->ht = hash_table_ctor(0,
- hash_table_pointer_hash,
- hash_table_pointer_compare);
}
~ir_set_program_inouts_visitor()
{
- hash_table_dtor(this->ht);
}
virtual ir_visitor_status visit_enter(ir_dereference_array *);
@@ -64,13 +59,19 @@ public:
virtual ir_visitor_status visit_enter(ir_expression *);
virtual ir_visitor_status visit_enter(ir_discard *);
virtual ir_visitor_status visit(ir_dereference_variable *);
- virtual ir_visitor_status visit(ir_variable *);
struct gl_program *prog;
- struct hash_table *ht;
bool is_fragment_shader;
};
+static inline bool
+is_shader_inout(ir_variable *var)
+{
+ return var->mode == ir_var_shader_in ||
+ var->mode == ir_var_shader_out ||
+ var->mode == ir_var_system_value;
+}
+
static void
mark(struct gl_program *prog, ir_variable *var, int offset, int len,
bool is_fragment_shader)
@@ -97,6 +98,7 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
} else if (var->mode == ir_var_system_value) {
prog->SystemValuesRead |= bitfield;
} else {
+ assert(var->mode == ir_var_shader_out);
prog->OutputsWritten |= bitfield;
}
}
@@ -106,7 +108,7 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
ir_visitor_status
ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
{
- if (hash_table_find(this->ht, ir->var) == NULL)
+ if (!is_shader_inout(ir->var))
return visit_continue;
if (ir->type->is_array()) {
@@ -127,13 +129,13 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
ir_dereference_variable *deref_var;
ir_constant *index = ir->array_index->as_constant();
deref_var = ir->array->as_dereference_variable();
- ir_variable *var = NULL;
+ ir_variable *var = deref_var ? deref_var->var : NULL;
/* Check that we're dereferencing a shader in or out */
- if (deref_var)
- var = (ir_variable *)hash_table_find(this->ht, deref_var->var);
+ if (!var || !is_shader_inout(var))
+ return visit_continue;
- if (index && var) {
+ if (index) {
int width = 1;
if (deref_var->type->is_array() &&
@@ -150,18 +152,6 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
}
ir_visitor_status
-ir_set_program_inouts_visitor::visit(ir_variable *ir)
-{
- if (ir->mode == ir_var_shader_in ||
- ir->mode == ir_var_shader_out ||
- ir->mode == ir_var_system_value) {
- hash_table_insert(this->ht, ir, ir);
- }
-
- return visit_continue;
-}
-
-ir_visitor_status
ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
{
/* We don't want to descend into the function parameters and
diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp
index 74fe1e29f..c72d1d8f1 100644
--- a/mesalib/src/glsl/link_uniform_blocks.cpp
+++ b/mesalib/src/glsl/link_uniform_blocks.cpp
@@ -29,7 +29,7 @@
#include "main/hash_table.h"
#include "program.h"
-class ubo_visitor : public uniform_field_visitor {
+class ubo_visitor : public program_resource_visitor {
public:
ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables,
unsigned num_variables)
@@ -44,7 +44,7 @@ public:
this->offset = 0;
this->buffer_size = 0;
this->is_array_instance = strchr(name, ']') != NULL;
- this->uniform_field_visitor::process(type, name);
+ this->program_resource_visitor::process(type, name);
}
unsigned index;
@@ -112,7 +112,7 @@ private:
}
};
-class count_block_size : public uniform_field_visitor {
+class count_block_size : public program_resource_visitor {
public:
count_block_size() : num_active_uniforms(0)
{
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index f869491a2..efbb60c3a 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -52,7 +52,7 @@ values_for_type(const glsl_type *type)
}
void
-uniform_field_visitor::process(const glsl_type *type, const char *name)
+program_resource_visitor::process(const glsl_type *type, const char *name)
{
assert(type->is_record()
|| (type->is_array() && type->fields.array->is_record())
@@ -65,7 +65,7 @@ uniform_field_visitor::process(const glsl_type *type, const char *name)
}
void
-uniform_field_visitor::process(ir_variable *var)
+program_resource_visitor::process(ir_variable *var)
{
const glsl_type *t = var->type;
@@ -93,8 +93,8 @@ uniform_field_visitor::process(ir_variable *var)
}
void
-uniform_field_visitor::recursion(const glsl_type *t, char **name,
- size_t name_length, bool row_major)
+program_resource_visitor::recursion(const glsl_type *t, char **name,
+ size_t name_length, bool row_major)
{
/* Records need to have each field processed individually.
*
@@ -110,7 +110,7 @@ uniform_field_visitor::recursion(const glsl_type *t, char **name,
if (t->fields.structure[i].type->is_record())
this->visit_field(&t->fields.structure[i]);
- /* Append '.field' to the current uniform name. */
+ /* Append '.field' to the current variable name. */
if (name_length == 0) {
ralloc_asprintf_rewrite_tail(name, &new_length, "%s", field);
} else {
@@ -125,7 +125,7 @@ uniform_field_visitor::recursion(const glsl_type *t, char **name,
for (unsigned i = 0; i < t->length; i++) {
size_t new_length = name_length;
- /* Append the subscript to the current uniform name */
+ /* Append the subscript to the current variable name */
ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
recursion(t->fields.array, name, new_length,
@@ -137,7 +137,7 @@ uniform_field_visitor::recursion(const glsl_type *t, char **name,
}
void
-uniform_field_visitor::visit_field(const glsl_struct_field *field)
+program_resource_visitor::visit_field(const glsl_struct_field *field)
{
(void) field;
/* empty */
@@ -153,7 +153,7 @@ uniform_field_visitor::visit_field(const glsl_struct_field *field)
* If the same uniform is added multiple times (i.e., once for each shader
* target), it will only be accounted once.
*/
-class count_uniform_size : public uniform_field_visitor {
+class count_uniform_size : public program_resource_visitor {
public:
count_uniform_size(struct string_to_uint_map *map)
: num_active_uniforms(0), num_values(0), num_shader_samplers(0),
@@ -171,10 +171,10 @@ public:
void process(ir_variable *var)
{
if (var->is_interface_instance())
- uniform_field_visitor::process(var->interface_type,
- var->interface_type->name);
+ program_resource_visitor::process(var->interface_type,
+ var->interface_type->name);
else
- uniform_field_visitor::process(var);
+ program_resource_visitor::process(var);
}
/**
@@ -258,7 +258,7 @@ private:
* the \c gl_uniform_storage and \c gl_constant_value arrays are "big
* enough."
*/
-class parcel_out_uniform_storage : public uniform_field_visitor {
+class parcel_out_uniform_storage : public program_resource_visitor {
public:
parcel_out_uniform_storage(struct string_to_uint_map *map,
struct gl_uniform_storage *uniforms,
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index 25681d618..e2cb46e8c 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -35,6 +35,8 @@
#include "linker.h"
#include "link_varyings.h"
#include "main/macros.h"
+#include "program/hash_table.h"
+#include "program.h"
/**
@@ -154,10 +156,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)
{
@@ -170,12 +175,13 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
this->is_clip_distance_mesa = false;
this->skip_components = 0;
this->next_buffer_separator = false;
+ this->matched_candidate = NULL;
if (ctx->Extensions.ARB_transform_feedback3) {
/* Parse gl_NextBuffer. */
if (strcmp(input, "gl_NextBuffer") == 0) {
this->next_buffer_separator = true;
- return true;
+ return;
}
/* Parse gl_SkipComponents. */
@@ -189,21 +195,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 +217,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;
}
@@ -240,27 +240,32 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
/**
- * Assign a location for this tfeedback_decl object based on the location
- * assignment in output_var.
+ * Assign a location for this tfeedback_decl object based on the transform
+ * feedback candidate found by find_candidate.
*
* If an error occurs, the error is reported through linker_error() and false
* is returned.
*/
bool
tfeedback_decl::assign_location(struct gl_context *ctx,
- struct gl_shader_program *prog,
- ir_variable *output_var)
+ struct gl_shader_program *prog)
{
assert(this->is_varying());
- if (output_var->type->is_array()) {
+ unsigned fine_location
+ = this->matched_candidate->toplevel_var->location * 4
+ + this->matched_candidate->toplevel_var->location_frac
+ + this->matched_candidate->offset;
+
+ if (this->matched_candidate->type->is_array()) {
/* Array variable */
const unsigned matrix_cols =
- output_var->type->fields.array->matrix_columns;
+ this->matched_candidate->type->fields.array->matrix_columns;
const unsigned vector_elements =
- output_var->type->fields.array->vector_elements;
+ this->matched_candidate->type->fields.array->vector_elements;
unsigned actual_array_size = this->is_clip_distance_mesa ?
- prog->Vert.ClipDistanceArraySize : output_var->type->array_size();
+ prog->Vert.ClipDistanceArraySize :
+ this->matched_candidate->type->array_size();
if (this->is_subscripted) {
/* Check array bounds. */
@@ -271,22 +276,11 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
actual_array_size);
return false;
}
- if (this->is_clip_distance_mesa) {
- this->location =
- output_var->location + this->array_subscript / 4;
- this->location_frac = this->array_subscript % 4;
- } else {
- unsigned fine_location
- = output_var->location * 4 + output_var->location_frac;
- unsigned array_elem_size = vector_elements * matrix_cols;
- fine_location += array_elem_size * this->array_subscript;
- this->location = fine_location / 4;
- this->location_frac = fine_location % 4;
- }
+ unsigned array_elem_size = this->is_clip_distance_mesa ?
+ 1 : vector_elements * matrix_cols;
+ fine_location += array_elem_size * this->array_subscript;
this->size = 1;
} else {
- this->location = output_var->location;
- this->location_frac = output_var->location_frac;
this->size = actual_array_size;
}
this->vector_elements = vector_elements;
@@ -294,7 +288,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
if (this->is_clip_distance_mesa)
this->type = GL_FLOAT;
else
- this->type = output_var->type->fields.array->gl_type;
+ this->type = this->matched_candidate->type->fields.array->gl_type;
} else {
/* Regular variable (scalar, vector, or matrix) */
if (this->is_subscripted) {
@@ -303,13 +297,13 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
this->orig_name, this->var_name);
return false;
}
- this->location = output_var->location;
- this->location_frac = output_var->location_frac;
this->size = 1;
- this->vector_elements = output_var->type->vector_elements;
- this->matrix_columns = output_var->type->matrix_columns;
- this->type = output_var->type->gl_type;
+ this->vector_elements = this->matched_candidate->type->vector_elements;
+ this->matrix_columns = this->matched_candidate->type->matrix_columns;
+ this->type = this->matched_candidate->type->gl_type;
}
+ this->location = fine_location / 4;
+ this->location_frac = fine_location % 4;
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
@@ -404,35 +398,26 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
}
-ir_variable *
-tfeedback_decl::find_output_var(gl_shader_program *prog,
- gl_shader *producer) const
+const tfeedback_candidate *
+tfeedback_decl::find_candidate(gl_shader_program *prog,
+ hash_table *tfeedback_candidates)
{
const char *name = this->is_clip_distance_mesa
? "gl_ClipDistanceMESA" : this->var_name;
- ir_variable *var = producer->symbols->get_variable(name);
- if (var && var->mode == ir_var_shader_out) {
- const glsl_type *type = var->type;
- while (type->base_type == GLSL_TYPE_ARRAY)
- type = type->fields.array;
- if (type->base_type == GLSL_TYPE_STRUCT) {
- linker_error(prog, "Transform feedback of varying structs not "
- "implemented yet.");
- return NULL;
- }
- return var;
+ this->matched_candidate = (const tfeedback_candidate *)
+ hash_table_find(tfeedback_candidates, name);
+ if (!this->matched_candidate) {
+ /* From GL_EXT_transform_feedback:
+ * A program will fail to link if:
+ *
+ * * any variable name specified in the <varyings> array is not
+ * declared as an output in the geometry shader (if present) or
+ * the vertex shader (if no geometry shader is present);
+ */
+ linker_error(prog, "Transform feedback varying %s undeclared.",
+ this->orig_name);
}
-
- /* From GL_EXT_transform_feedback:
- * A program will fail to link if:
- *
- * * any variable name specified in the <varyings> array is not
- * declared as an output in the geometry shader (if present) or
- * the vertex shader (if no geometry shader is present);
- */
- linker_error(prog, "Transform feedback varying %s undeclared.",
- this->orig_name);
- return NULL;
+ return this->matched_candidate;
}
@@ -449,8 +434,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;
@@ -871,6 +855,80 @@ is_varying_var(GLenum shaderType, const ir_variable *var)
/**
+ * Visitor class that generates tfeedback_candidate structs describing all
+ * possible targets of transform feedback.
+ *
+ * tfeedback_candidate structs are stored in the hash table
+ * tfeedback_candidates, which is passed to the constructor. This hash table
+ * maps varying names to instances of the tfeedback_candidate struct.
+ */
+class tfeedback_candidate_generator : public program_resource_visitor
+{
+public:
+ tfeedback_candidate_generator(void *mem_ctx,
+ hash_table *tfeedback_candidates)
+ : mem_ctx(mem_ctx),
+ tfeedback_candidates(tfeedback_candidates)
+ {
+ }
+
+ void process(ir_variable *var)
+ {
+ this->toplevel_var = var;
+ this->varying_floats = 0;
+ if (var->is_interface_instance())
+ program_resource_visitor::process(var->interface_type,
+ var->interface_type->name);
+ else
+ program_resource_visitor::process(var);
+ }
+
+private:
+ virtual void visit_field(const glsl_type *type, const char *name,
+ bool row_major)
+ {
+ assert(!type->is_record());
+ assert(!(type->is_array() && type->fields.array->is_record()));
+ assert(!type->is_interface());
+ assert(!(type->is_array() && type->fields.array->is_interface()));
+
+ (void) row_major;
+
+ tfeedback_candidate *candidate
+ = rzalloc(this->mem_ctx, tfeedback_candidate);
+ candidate->toplevel_var = this->toplevel_var;
+ candidate->type = type;
+ candidate->offset = this->varying_floats;
+ hash_table_insert(this->tfeedback_candidates, candidate,
+ ralloc_strdup(this->mem_ctx, name));
+ this->varying_floats += type->component_slots();
+ }
+
+ /**
+ * Memory context used to allocate hash table keys and values.
+ */
+ void * const mem_ctx;
+
+ /**
+ * Hash table in which tfeedback_candidate objects should be stored.
+ */
+ hash_table * const tfeedback_candidates;
+
+ /**
+ * Pointer to the toplevel variable that is being traversed.
+ */
+ ir_variable *toplevel_var;
+
+ /**
+ * Total number of varying floats that have been visited so far. This is
+ * used to determine the offset to each varying within the toplevel
+ * variable.
+ */
+ unsigned varying_floats;
+};
+
+
+/**
* Assign locations for all variables that are produced in one pipeline stage
* (the "producer") and consumed in the next stage (the "consumer").
*
@@ -902,6 +960,8 @@ assign_varying_locations(struct gl_context *ctx,
const unsigned producer_base = VERT_RESULT_VAR0;
const unsigned consumer_base = FRAG_ATTRIB_VAR0;
varying_matches matches(ctx->Const.DisableVaryingPacking);
+ hash_table *tfeedback_candidates
+ = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
/* Operate in a total of three passes.
*
@@ -920,6 +980,9 @@ assign_varying_locations(struct gl_context *ctx,
if ((output_var == NULL) || (output_var->mode != ir_var_shader_out))
continue;
+ tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
+ g.process(output_var);
+
ir_variable *input_var =
consumer ? consumer->symbols->get_variable(output_var->name) : NULL;
@@ -935,15 +998,16 @@ assign_varying_locations(struct gl_context *ctx,
if (!tfeedback_decls[i].is_varying())
continue;
- ir_variable *output_var
- = tfeedback_decls[i].find_output_var(prog, producer);
+ const tfeedback_candidate *matched_candidate
+ = tfeedback_decls[i].find_candidate(prog, tfeedback_candidates);
- if (output_var == NULL)
+ if (matched_candidate == NULL) {
+ hash_table_dtor(tfeedback_candidates);
return false;
-
- if (output_var->is_unmatched_generic_inout) {
- matches.record(output_var, NULL);
}
+
+ if (matched_candidate->toplevel_var->is_unmatched_generic_inout)
+ matches.record(matched_candidate->toplevel_var, NULL);
}
const unsigned slots_used = matches.assign_locations();
@@ -953,13 +1017,14 @@ assign_varying_locations(struct gl_context *ctx,
if (!tfeedback_decls[i].is_varying())
continue;
- ir_variable *output_var
- = tfeedback_decls[i].find_output_var(prog, producer);
-
- if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
+ if (!tfeedback_decls[i].assign_location(ctx, prog)) {
+ hash_table_dtor(tfeedback_candidates);
return false;
+ }
}
+ hash_table_dtor(tfeedback_candidates);
+
if (ctx->Const.DisableVaryingPacking) {
/* Transform feedback code assumes varyings are packed, so if the driver
* has disabled varying packing, make sure it does not support transform
diff --git a/mesalib/src/glsl/link_varyings.h b/mesalib/src/glsl/link_varyings.h
index 057e4b219..ee1010a7b 100644
--- a/mesalib/src/glsl/link_varyings.h
+++ b/mesalib/src/glsl/link_varyings.h
@@ -42,23 +42,66 @@ class ir_variable;
/**
+ * Data structure describing a varying which is available for use in transform
+ * feedback.
+ *
+ * For example, if the vertex shader contains:
+ *
+ * struct S {
+ * vec4 foo;
+ * float[3] bar;
+ * };
+ *
+ * varying S[2] v;
+ *
+ * Then there would be tfeedback_candidate objects corresponding to the
+ * following varyings:
+ *
+ * v[0].foo
+ * v[0].bar
+ * v[1].foo
+ * v[1].bar
+ */
+struct tfeedback_candidate
+{
+ /**
+ * Toplevel variable containing this varying. In the above example, this
+ * would point to the declaration of the varying v.
+ */
+ ir_variable *toplevel_var;
+
+ /**
+ * Type of this varying. In the above example, this would point to the
+ * glsl_type for "vec4" or "float[3]".
+ */
+ const glsl_type *type;
+
+ /**
+ * Offset within the toplevel variable where this varying occurs (counted
+ * in multiples of the size of a float).
+ */
+ unsigned offset;
+};
+
+
+/**
* Data structure tracking information about a transform feedback declaration
* during linking.
*/
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,
- ir_variable *output_var);
+ bool assign_location(struct gl_context *ctx,
+ struct gl_shader_program *prog);
unsigned get_num_outputs() const;
bool store(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_info *info, unsigned buffer,
const unsigned max_outputs) const;
- ir_variable *find_output_var(gl_shader_program *prog,
- gl_shader *producer) const;
+ const tfeedback_candidate *find_candidate(gl_shader_program *prog,
+ hash_table *tfeedback_candidates);
bool is_next_buffer_separator() const
{
@@ -158,6 +201,12 @@ private:
* Whether this is gl_NextBuffer from ARB_transform_feedback3.
*/
bool next_buffer_separator;
+
+ /**
+ * If find_candidate() has been called, pointer to the tfeedback_candidate
+ * data structure that was found. Otherwise NULL.
+ */
+ const tfeedback_candidate *matched_candidate;
};
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 63ce178f4..57e7a9ad3 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -200,6 +200,65 @@ linker_warning(gl_shader_program *prog, const char *fmt, ...)
}
+/**
+ * Given a string identifying a program resource, break it into a base name
+ * and an optional array index in square brackets.
+ *
+ * If an array index is present, \c out_base_name_end is set to point to the
+ * "[" that precedes the array index, and the array index itself is returned
+ * as a long.
+ *
+ * If no array index is present (or if the array index is negative or
+ * mal-formed), \c out_base_name_end, is set to point to the null terminator
+ * at the end of the input string, and -1 is returned.
+ *
+ * Only the final array index is parsed; if the string contains other array
+ * indices (or structure field accesses), they are left in the base name.
+ *
+ * No attempt is made to check that the base name is properly formed;
+ * typically the caller will look up the base name in a hash table, so
+ * ill-formed base names simply turn into hash table lookup failures.
+ */
+long
+parse_program_resource_name(const GLchar *name,
+ const GLchar **out_base_name_end)
+{
+ /* Section 7.3.1 ("Program Interfaces") of the OpenGL 4.3 spec says:
+ *
+ * "When an integer array element or block instance number is part of
+ * the name string, it will be specified in decimal form without a "+"
+ * or "-" sign or any extra leading zeroes. Additionally, the name
+ * string will not include white space anywhere in the string."
+ */
+
+ const size_t len = strlen(name);
+ *out_base_name_end = name + len;
+
+ if (len == 0 || name[len-1] != ']')
+ return -1;
+
+ /* Walk backwards over the string looking for a non-digit character. This
+ * had better be the opening bracket for an array index.
+ *
+ * Initially, i specifies the location of the ']'. Since the string may
+ * contain only the ']' charcater, walk backwards very carefully.
+ */
+ unsigned i;
+ for (i = len - 1; (i > 0) && isdigit(name[i-1]); --i)
+ /* empty */ ;
+
+ if ((i == 0) || name[i-1] != '[')
+ return -1;
+
+ long array_index = strtol(&name[i], NULL, 10);
+ if (array_index < 0)
+ return -1;
+
+ *out_base_name_end = name + (i - 1);
+ return array_index;
+}
+
+
void
link_invalidate_variable_locations(gl_shader *sh, int input_base,
int output_base)
diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h
index 14eb9c1cd..f1ce50ace 100644
--- a/mesalib/src/glsl/linker.h
+++ b/mesalib/src/glsl/linker.h
@@ -61,38 +61,39 @@ link_uniform_blocks(void *mem_ctx,
struct gl_uniform_block **blocks_ret);
/**
- * Class for processing all of the leaf fields of an uniform
+ * Class for processing all of the leaf fields of a variable that corresponds
+ * to a program resource.
*
- * Leaves are, roughly speaking, the parts of the uniform that the application
- * could query with \c glGetUniformLocation (or that could be returned by
- * \c glGetActiveUniforms).
+ * The leaf fields are all the parts of the variable that the application
+ * could query using \c glGetProgramResourceIndex (or that could be returned
+ * by \c glGetProgramResourceName).
*
* Classes my derive from this class to implement specific functionality.
* This class only provides the mechanism to iterate over the leaves. Derived
* classes must implement \c ::visit_field and may override \c ::process.
*/
-class uniform_field_visitor {
+class program_resource_visitor {
public:
/**
- * Begin processing a uniform
+ * Begin processing a variable
*
* Classes that overload this function should call \c ::process from the
- * base class to start the recursive processing of the uniform.
+ * base class to start the recursive processing of the variable.
*
- * \param var The uniform variable that is to be processed
+ * \param var The variable that is to be processed
*
- * Calls \c ::visit_field for each leaf of the uniform.
+ * Calls \c ::visit_field for each leaf of the variable.
*
* \warning
- * This entry should only be used with uniform blocks in cases where the
- * row / column ordering of matrices in the block does not matter. For
- * example, enumerating the names of members of the block, but not for
- * determining the offsets of members.
+ * When processing a uniform block, this entry should only be used in cases
+ * where the row / column ordering of matrices in the block does not
+ * matter. For example, enumerating the names of members of the block, but
+ * not for determining the offsets of members.
*/
void process(ir_variable *var);
/**
- * Begin processing a uniform of a structured type.
+ * Begin processing a variable of a structured type.
*
* This flavor of \c process should be used to handle structured types
* (i.e., structures, interfaces, or arrays there of) that need special
@@ -100,7 +101,7 @@ public:
* (instead of the instance name) is used for an interface block.
*
* \param type Type that is to be processed, associated with \c name
- * \param name Base name of the structured uniform being processed
+ * \param name Base name of the structured variable being processed
*
* \note
* \c type must be \c GLSL_TYPE_RECORD, \c GLSL_TYPE_INTERFACE, or an array
@@ -110,7 +111,7 @@ public:
protected:
/**
- * Method invoked for each leaf of the uniform
+ * Method invoked for each leaf of the variable
*
* \param type Type of the field.
* \param name Fully qualified name of the field.
diff --git a/mesalib/src/glsl/program.h b/mesalib/src/glsl/program.h
index 437ca1462..46ce9dccc 100644
--- a/mesalib/src/glsl/program.h
+++ b/mesalib/src/glsl/program.h
@@ -33,3 +33,7 @@ linker_error(gl_shader_program *prog, const char *fmt, ...)
extern void
linker_warning(gl_shader_program *prog, const char *fmt, ...)
PRINTFLIKE(2, 3);
+
+extern long
+parse_program_resource_name(const GLchar *name,
+ const GLchar **out_base_name_end);
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index 8e3851f88..e6e001cf5 100755
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -368,6 +368,7 @@ swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv,
xrb->bpp = 8;
break;
default:
+ free(xrb);
return NULL;
}
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index c9638a1af..04435e0c9 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -298,7 +298,7 @@ static const struct extension extension_table[] = {
{ "GL_ATI_texture_float", o(ARB_texture_float), GL, 2002 },
{ "GL_ATI_texture_mirror_once", o(ATI_texture_mirror_once), GL, 2006 },
{ "GL_IBM_multimode_draw_arrays", o(dummy_true), GL, 1998 },
- { "GL_IBM_rasterpos_clip", o(dummy_true), GL, 1996 },
+ { "GL_IBM_rasterpos_clip", o(dummy_true), GLL, 1996 },
{ "GL_IBM_texture_mirrored_repeat", o(dummy_true), GLL, 1998 },
{ "GL_INGR_blend_func_separate", o(EXT_blend_func_separate), GLL, 1999 },
{ "GL_MESA_pack_invert", o(MESA_pack_invert), GL, 2002 },
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index f03e84ad8..ff3c92c5e 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -3004,8 +3004,18 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
texObj = _mesa_get_current_tex_object(ctx, target);
assert(texObj);
- texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
- internalFormat, format, type);
+ if (compressed) {
+ /* For glCompressedTexImage() the driver has no choice about the
+ * texture format since we'll never transcode the user's compressed
+ * image data. The internalFormat was error checked earlier.
+ */
+ texFormat = _mesa_glenum_to_compressed_format(internalFormat);
+ }
+ else {
+ texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
+ internalFormat, format, type);
+ }
+
assert(texFormat != MESA_FORMAT_NONE);
/* check that width, height, depth are legal for the mipmap level */
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index dc550bc43..b8335fe6b 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -929,6 +929,7 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}
+
/**
* Called via glGetUniformLocation().
*
@@ -944,73 +945,35 @@ _mesa_get_uniform_location(struct gl_context *ctx,
const GLchar *name,
unsigned *out_offset)
{
- const size_t len = strlen(name);
- long offset;
- bool array_lookup;
- char *name_copy;
-
- /* If the name ends with a ']', assume that it refers to some element of an
- * array. Malformed array references will fail the hash table look up
- * below, so it doesn't matter that they are not caught here. This code
- * only wants to catch the "leaf" array references so that arrays of
- * structures containing arrays will be handled correctly.
+ /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
+ *
+ * "The first element of a uniform array is identified using the
+ * name of the uniform array appended with "[0]". Except if the last
+ * part of the string name indicates a uniform array, then the
+ * location of the first element of that array can be retrieved by
+ * either using the name of the uniform array, or the name of the
+ * uniform array appended with "[0]"."
+ *
+ * Note: since uniform names are not allowed to use whitespace, and array
+ * indices within uniform names are not allowed to use "+", "-", or leading
+ * zeros, it follows that each uniform has a unique name up to the possible
+ * ambiguity with "[0]" noted above. Therefore we don't need to worry
+ * about mal-formed inputs--they will properly fail when we try to look up
+ * the uniform name in shProg->UniformHash.
*/
- if (name[len-1] == ']') {
- unsigned i;
-
- /* Walk backwards over the string looking for a non-digit character.
- * This had better be the opening bracket for an array index.
- *
- * Initially, i specifies the location of the ']'. Since the string may
- * contain only the ']' charcater, walk backwards very carefully.
- */
- for (i = len - 1; (i > 0) && isdigit(name[i-1]); --i)
- /* empty */ ;
-
- /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
- *
- * "The first element of a uniform array is identified using the
- * name of the uniform array appended with "[0]". Except if the last
- * part of the string name indicates a uniform array, then the
- * location of the first element of that array can be retrieved by
- * either using the name of the uniform array, or the name of the
- * uniform array appended with "[0]"."
- *
- * Page 79 (page 93 of the PDF) of the OpenGL 2.1 spec says:
- *
- * "name must be a null terminated string, without white space."
- *
- * Return an error if there is no opening '[' to match the closing ']'.
- * An error will also be returned if there is intervening white space
- * (or other non-digit characters) before the opening '['.
- */
- if ((i == 0) || name[i-1] != '[')
- return GL_INVALID_INDEX;
- /* Return an error if there are no digits between the opening '[' to
- * match the closing ']'.
- */
- if (i == (len - 1))
- return GL_INVALID_INDEX;
-
- /* Make a new string that is a copy of the old string up to (but not
- * including) the '[' character.
- */
- name_copy = (char *) malloc(i);
- memcpy(name_copy, name, i - 1);
- name_copy[i-1] = '\0';
-
- offset = strtol(&name[i], NULL, 10);
- if (offset < 0) {
- free(name_copy);
- return GL_INVALID_INDEX;
- }
+ const GLchar *base_name_end;
+ long offset = parse_program_resource_name(name, &base_name_end);
+ bool array_lookup = offset >= 0;
+ char *name_copy;
- array_lookup = true;
+ if (array_lookup) {
+ name_copy = (char *) malloc(base_name_end - name + 1);
+ memcpy(name_copy, name, base_name_end - name);
+ name_copy[base_name_end - name] = '\0';
} else {
name_copy = (char *) name;
offset = 0;
- array_lookup = false;
}
unsigned location = 0;
diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h
index f17503121..a12ad9b36 100644
--- a/mesalib/src/mesa/main/uniforms.h
+++ b/mesalib/src/mesa/main/uniforms.h
@@ -167,6 +167,10 @@ _mesa_GetActiveUniformsiv(GLuint program,
void GLAPIENTRY
_mesa_GetUniformiv(GLhandleARB, GLint, GLint *);
+long
+_mesa_parse_program_resource_name(const GLchar *name,
+ const GLchar **out_base_name_end);
+
unsigned
_mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program *shProg,
const GLchar *name, unsigned *offset);
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index cd89171da..ce409eca9 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -2375,7 +2375,7 @@ print_program(struct prog_instruction *mesa_instructions,
}
}
-class add_uniform_to_shader : public uniform_field_visitor {
+class add_uniform_to_shader : public program_resource_visitor {
public:
add_uniform_to_shader(struct gl_shader_program *shader_program,
struct gl_program_parameter_list *params)
@@ -2387,7 +2387,7 @@ public:
void process(ir_variable *var)
{
this->idx = -1;
- this->uniform_field_visitor::process(var);
+ this->program_resource_visitor::process(var);
var->location = this->idx;
}
diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c
index 4b43b2a7d..28327bc14 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c
@@ -214,7 +214,7 @@ update_single_texture(struct st_context *st,
const struct gl_sampler_object *samp;
struct gl_texture_object *texObj;
struct st_texture_object *stObj;
- enum pipe_format st_view_format;
+ enum pipe_format view_format;
GLboolean retval;
samp = _mesa_get_samplerobj(ctx, texUnit);
@@ -234,32 +234,11 @@ update_single_texture(struct st_context *st,
}
/* Determine the format of the texture sampler view */
- st_view_format = stObj->pt->format;
-
- {
- gl_format texFormat;
- enum pipe_format firstImageFormat;
-
- if (texObj->Target == GL_TEXTURE_BUFFER) {
- texFormat = stObj->base._BufferObjectFormat;
- } else {
- const struct st_texture_image *firstImage =
- st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
- texFormat = firstImage->base.TexFormat;
- }
- firstImageFormat = st_mesa_format_to_pipe_format(texFormat);
- if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) &&
- (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) {
- /* Don't do sRGB->RGB conversion. Interpret the texture data as
- * linear values.
- */
- const gl_format linearFormat =
- _mesa_get_srgb_format_linear(texFormat);
- firstImageFormat = st_mesa_format_to_pipe_format(linearFormat);
- }
+ view_format = stObj->pt->format;
- if (firstImageFormat != stObj->pt->format)
- st_view_format = firstImageFormat;
+ /* If sRGB decoding is off, use the linear format */
+ if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
+ view_format = util_format_linear(view_format);
}
/* if sampler view has changed dereference it */
@@ -267,7 +246,7 @@ update_single_texture(struct st_context *st,
if (check_sampler_swizzle(stObj->sampler_view,
stObj->base._Swizzle,
stObj->base.DepthMode) ||
- (st_view_format != stObj->sampler_view->format) ||
+ (view_format != stObj->sampler_view->format) ||
stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
}
@@ -275,7 +254,7 @@ update_single_texture(struct st_context *st,
*sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
samp,
- st_view_format);
+ view_format);
return GL_TRUE;
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
index c944b81f6..26d1923b5 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -489,12 +489,14 @@ make_texture(struct st_context *st,
intFormat = internal_format(ctx, format, type);
baseInternalFormat = _mesa_base_tex_format(ctx, intFormat);
- mformat = st_ChooseTextureFormat_renderable(ctx, intFormat,
- format, type, GL_FALSE);
- assert(mformat);
-
- pipeFormat = st_mesa_format_to_pipe_format(mformat);
- assert(pipeFormat);
+ /* Choose a pixel format for the temp texture which will hold the
+ * image to draw.
+ */
+ pipeFormat = st_choose_format(pipe->screen, intFormat, format, type,
+ PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW,
+ FALSE);
+ assert(pipeFormat != PIPE_FORMAT_NONE);
+ mformat = st_pipe_format_to_mesa_format(pipeFormat);
pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
if (!pixels)
@@ -1462,8 +1464,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
if (st->pixel_xfer.pixelmap_enabled) {
- sv[1] = st->pixel_xfer.pixelmap_sampler_view;
- num_sampler_view++;
+ sv[1] = st->pixel_xfer.pixelmap_sampler_view;
+ num_sampler_view++;
}
}
else {
@@ -1499,14 +1501,16 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
if (type == GL_DEPTH) {
texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
GL_NONE, GL_NONE, st->internal_target,
- sample_count, PIPE_BIND_DEPTH_STENCIL);
+ sample_count, PIPE_BIND_DEPTH_STENCIL,
+ FALSE);
assert(texFormat != PIPE_FORMAT_NONE);
}
else {
/* default color format */
texFormat = st_choose_format(screen, GL_RGBA,
GL_NONE, GL_NONE, st->internal_target,
- sample_count, PIPE_BIND_SAMPLER_VIEW);
+ sample_count, PIPE_BIND_SAMPLER_VIEW,
+ FALSE);
assert(texFormat != PIPE_FORMAT_NONE);
}
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c
index 3cea2df07..80a440d18 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c
@@ -597,7 +597,7 @@ decompress_with_blit(struct gl_context * ctx,
/* Find the best match for the format+type combo. */
pipe_format = st_choose_format(pipe->screen, GL_RGBA8, format, type,
- pipe_target, 0, bind);
+ pipe_target, 0, bind, FALSE);
if (pipe_format == PIPE_FORMAT_NONE) {
/* unable to get an rgba format!?! */
_mesa_problem(ctx, "%s: cannot find a supported format", __func__);
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index 7ef063953..2169bed89 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -1398,18 +1398,25 @@ static const struct format_mapping format_map[] = {
/**
* Return first supported format from the given list.
+ * \param allow_dxt indicates whether it's OK to return a DXT format.
*/
static enum pipe_format
find_supported_format(struct pipe_screen *screen,
const enum pipe_format formats[],
enum pipe_texture_target target,
unsigned sample_count,
- unsigned tex_usage)
+ unsigned tex_usage,
+ boolean allow_dxt)
{
uint i;
for (i = 0; formats[i]; i++) {
if (screen->is_format_supported(screen, formats[i], target,
sample_count, tex_usage)) {
+ if (!allow_dxt && util_format_is_s3tc(formats[i])) {
+ /* we can't return a dxt format, continue searching */
+ continue;
+ }
+
return formats[i];
}
}
@@ -1514,12 +1521,16 @@ find_exact_format(GLint internalFormat, GLenum format, GLenum type)
* \param internalFormat the user value passed to glTexImage2D
* \param target one of PIPE_TEXTURE_x
* \param bindings bitmask of PIPE_BIND_x flags.
+ * \param allow_dxt indicates whether it's OK to return a DXT format. This
+ * only matters when internalFormat names a generic or
+ * specific compressed format. And that should only happen
+ * when we're getting called from gl[Copy]TexImage().
*/
enum pipe_format
st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
GLenum format, GLenum type,
enum pipe_texture_target target, unsigned sample_count,
- unsigned bindings)
+ unsigned bindings, boolean allow_dxt)
{
GET_CURRENT_CONTEXT(ctx); /* XXX this should be a function parameter */
int i, j;
@@ -1547,7 +1558,8 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
* which is supported by the driver.
*/
return find_supported_format(screen, mapping->pipeFormats,
- target, sample_count, bindings);
+ target, sample_count, bindings,
+ allow_dxt);
}
}
}
@@ -1569,27 +1581,42 @@ st_choose_renderbuffer_format(struct pipe_screen *screen,
usage = PIPE_BIND_DEPTH_STENCIL;
else
usage = PIPE_BIND_RENDER_TARGET;
- return st_choose_format(screen, internalFormat, GL_NONE, GL_NONE, PIPE_TEXTURE_2D,
- sample_count, usage);
+ return st_choose_format(screen, internalFormat, GL_NONE, GL_NONE,
+ PIPE_TEXTURE_2D, sample_count, usage, FALSE);
}
+/**
+ * Called via ctx->Driver.ChooseTextureFormat().
+ */
gl_format
-st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
- GLenum format, GLenum type, GLboolean renderable)
+st_ChooseTextureFormat(struct gl_context *ctx, GLenum target,
+ GLint internalFormat,
+ GLenum format, GLenum type)
{
+ const boolean want_renderable =
+ internalFormat == 3 || internalFormat == 4 ||
+ internalFormat == GL_RGB || internalFormat == GL_RGBA ||
+ internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 ||
+ internalFormat == GL_BGRA;
struct pipe_screen *screen = st_context(ctx)->pipe->screen;
enum pipe_format pFormat;
- uint bindings;
+ unsigned bindings;
- (void) format;
- (void) type;
+ if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY) {
+ /* We don't do compression for these texture targets because of
+ * difficulty with sub-texture updates on non-block boundaries, etc.
+ * So change the internal format request to an uncompressed format.
+ */
+ internalFormat =
+ _mesa_generic_compressed_format_to_uncompressed_format(internalFormat);
+ }
/* GL textures may wind up being render targets, but we don't know
* that in advance. Specify potential render target flags now.
*/
bindings = PIPE_BIND_SAMPLER_VIEW;
- if (renderable) {
+ if (want_renderable) {
if (_mesa_is_depth_or_stencil_format(internalFormat))
bindings |= PIPE_BIND_DEPTH_STENCIL;
else
@@ -1597,12 +1624,13 @@ st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
}
pFormat = st_choose_format(screen, internalFormat, format, type,
- PIPE_TEXTURE_2D, 0, bindings);
+ PIPE_TEXTURE_2D, 0, bindings, ctx->Mesa_DXTn);
if (pFormat == PIPE_FORMAT_NONE) {
/* try choosing format again, this time without render target bindings */
pFormat = st_choose_format(screen, internalFormat, format, type,
- PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
+ PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW,
+ ctx->Mesa_DXTn);
}
if (pFormat == PIPE_FORMAT_NONE) {
@@ -1617,34 +1645,6 @@ st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
/**
* Called via ctx->Driver.ChooseTextureFormat().
*/
-gl_format
-st_ChooseTextureFormat(struct gl_context *ctx, GLenum target,
- GLint internalFormat,
- GLenum format, GLenum type)
-{
- boolean want_renderable =
- internalFormat == 3 || internalFormat == 4 ||
- internalFormat == GL_RGB || internalFormat == GL_RGBA ||
- internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 ||
- internalFormat == GL_BGRA;
-
- if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY) {
- /* We don't do compression for these texture targets because of
- * difficulty with sub-texture updates on non-block boundaries, etc.
- * So change the internal format request to an uncompressed format.
- */
- internalFormat =
- _mesa_generic_compressed_format_to_uncompressed_format(internalFormat);
- }
-
- return st_ChooseTextureFormat_renderable(ctx, internalFormat,
- format, type, want_renderable);
-}
-
-
-/**
- * Called via ctx->Driver.ChooseTextureFormat().
- */
size_t
st_QuerySamplesForFormat(struct gl_context *ctx, GLenum internalFormat,
int samples[16])
@@ -1661,7 +1661,7 @@ st_QuerySamplesForFormat(struct gl_context *ctx, GLenum internalFormat,
/* Set sample counts in descending order. */
for (i = 16; i > 1; i--) {
format = st_choose_format(screen, internalFormat, GL_NONE, GL_NONE,
- PIPE_TEXTURE_2D, i, bind);
+ PIPE_TEXTURE_2D, i, bind, FALSE);
if (format != PIPE_FORMAT_NONE) {
samples[num_sample_counts++] = i;
diff --git a/mesalib/src/mesa/state_tracker/st_format.h b/mesalib/src/mesa/state_tracker/st_format.h
index cb6e5bc96..50588d8d4 100644
--- a/mesalib/src/mesa/state_tracker/st_format.h
+++ b/mesalib/src/mesa/state_tracker/st_format.h
@@ -51,17 +51,13 @@ extern enum pipe_format
st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
GLenum format, GLenum type,
enum pipe_texture_target target, unsigned sample_count,
- unsigned bindings);
+ unsigned bindings, boolean allow_dxt);
extern enum pipe_format
st_choose_renderbuffer_format(struct pipe_screen *screen,
GLenum internalFormat, unsigned sample_count);
-gl_format
-st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
- GLenum format, GLenum type, GLboolean renderable);
-
extern gl_format
st_ChooseTextureFormat(struct gl_context * ctx, GLenum target,
GLint internalFormat,
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index c6ac634a2..b3da2016d 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -322,6 +322,7 @@ public:
int glsl_version;
bool native_integers;
+ bool have_sqrt;
variable_storage *find_variable_storage(ir_variable *var);
@@ -1761,13 +1762,18 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
break;
case ir_unop_sqrt:
- /* sqrt(x) = x * rsq(x). */
- emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]);
- emit(ir, TGSI_OPCODE_MUL, result_dst, result_src, op[0]);
- /* For incoming channels <= 0, set the result to 0. */
- op[0].negate = ~op[0].negate;
- emit(ir, TGSI_OPCODE_CMP, result_dst,
- op[0], result_src, st_src_reg_for_float(0.0));
+ if (have_sqrt) {
+ emit_scalar(ir, TGSI_OPCODE_SQRT, result_dst, op[0]);
+ }
+ else {
+ /* sqrt(x) = x * rsq(x). */
+ emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]);
+ emit(ir, TGSI_OPCODE_MUL, result_dst, result_src, op[0]);
+ /* For incoming channels <= 0, set the result to 0. */
+ op[0].negate = ~op[0].negate;
+ emit(ir, TGSI_OPCODE_CMP, result_dst,
+ op[0], result_src, st_src_reg_for_float(0.0));
+ }
break;
case ir_unop_rsq:
emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]);
@@ -4956,18 +4962,23 @@ get_mesa_program(struct gl_context *ctx,
bool progress;
struct gl_shader_compiler_options *options =
&ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)];
+ struct pipe_screen *pscreen = ctx->st->pipe->screen;
+ unsigned ptarget;
switch (shader->Type) {
case GL_VERTEX_SHADER:
target = GL_VERTEX_PROGRAM_ARB;
+ ptarget = PIPE_SHADER_VERTEX;
target_string = "vertex";
break;
case GL_FRAGMENT_SHADER:
target = GL_FRAGMENT_PROGRAM_ARB;
+ ptarget = PIPE_SHADER_FRAGMENT;
target_string = "fragment";
break;
case GL_GEOMETRY_SHADER:
target = GL_GEOMETRY_PROGRAM_NV;
+ ptarget = PIPE_SHADER_GEOMETRY;
target_string = "geometry";
break;
default:
@@ -4989,6 +5000,9 @@ get_mesa_program(struct gl_context *ctx,
v->glsl_version = ctx->Const.GLSLVersion;
v->native_integers = ctx->Const.NativeIntegers;
+ v->have_sqrt = pscreen->get_shader_param(pscreen, ptarget,
+ PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED);
+
_mesa_generate_parameters_list_for_uniforms(shader_program, shader,
prog->Parameters);
diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c
index ee4d7622d..584eaa981 100644
--- a/mesalib/src/mesa/state_tracker/st_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_texture.c
@@ -398,7 +398,8 @@ st_create_color_map_texture(struct gl_context *ctx)
/* find an RGBA texture format */
format = st_choose_format(pipe->screen, GL_RGBA, GL_NONE, GL_NONE,
- PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
+ PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW,
+ FALSE);
/* create texture for color map/table */
pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,