diff options
Diffstat (limited to 'mesalib')
24 files changed, 521 insertions, 315 deletions
diff --git a/mesalib/configure.ac b/mesalib/configure.ac index cfd52bfcf..abfe3d7bd 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -611,7 +611,7 @@ AC_ARG_ENABLE([opencl], [enable OpenCL library NOTE: Enabling this option will also enable --with-llvm-shared-libs @<:@default=no@:>@])], - [enable_opencl="$enableval" with_llvm_shared_libs="$enableval"], + [], [enable_opencl=no]) AC_ARG_ENABLE([xlib_glx], [AS_HELP_STRING([--enable-xlib-glx], @@ -701,6 +701,16 @@ if test "x$enable_dri$enable_xlib_glx" = xyesyes; then AC_MSG_ERROR([DRI and Xlib-GLX cannot be built together]) fi +if test "x$enable_opengl$enable_xlib_glx" = xnoyes; then + AC_MSG_ERROR([Xlib-GLX cannot be built without OpenGL]) +fi + +# Disable GLX if OpenGL is not enabled +if test "x$enable_glx$enable_opengl" = xyesno; then + AC_MSG_WARN([OpenGL not enabled, disabling GLX]) + enable_glx=no +fi + # Disable GLX if DRI and Xlib-GLX are not enabled if test "x$enable_glx" = xyes -a \ "x$enable_dri" = xno -a \ @@ -1619,8 +1629,13 @@ AC_ARG_ENABLE([gallium-llvm], AC_ARG_WITH([llvm-shared-libs], [AS_HELP_STRING([--with-llvm-shared-libs], [link with LLVM shared libraries @<:@default=disabled@:>@])], - [with_llvm_shared_libs=yes], + [], [with_llvm_shared_libs=no]) +AS_IF([test x$enable_opencl = xyes], + [ + AC_MSG_WARN([OpenCL required, forcing LLVM shared libraries]) + with_llvm_shared_libs=yes + ]) AC_ARG_WITH([llvm-prefix], [AS_HELP_STRING([--with-llvm-prefix], diff --git a/mesalib/include/GL/internal/dri_interface.h b/mesalib/include/GL/internal/dri_interface.h index c236cb732..42147e90e 100644 --- a/mesalib/include/GL/internal/dri_interface.h +++ b/mesalib/include/GL/internal/dri_interface.h @@ -938,7 +938,7 @@ struct __DRIdri2ExtensionRec { * extensions. */ #define __DRI_IMAGE "DRI_IMAGE" -#define __DRI_IMAGE_VERSION 5 +#define __DRI_IMAGE_VERSION 6 /** * These formats correspond to the similarly named MESA_FORMAT_* @@ -1022,6 +1022,23 @@ struct __DRIdri2ExtensionRec { #define __DRI_IMAGE_ATTRIB_HEIGHT 0x2005 #define __DRI_IMAGE_ATTRIB_COMPONENTS 0x2006 /* available in versions 5+ */ +/** + * \name Reasons that __DRIimageExtensionRec::createImageFromTexture might fail + */ +/*@{*/ +/** Success! */ +#define __DRI_IMAGE_ERROR_SUCCESS 0 + +/** Memory allocation failure */ +#define __DRI_IMAGE_ERROR_BAD_ALLOC 1 + +/** Client requested an invalid attribute for a texture object */ +#define __DRI_IMAGE_ERROR_BAD_MATCH 2 + +/** Client requested an invalid texture object */ +#define __DRI_IMAGE_ERROR_BAD_PARAMETER 3 +/*@}*/ + typedef struct __DRIimageRec __DRIimage; typedef struct __DRIimageExtensionRec __DRIimageExtension; struct __DRIimageExtensionRec { @@ -1087,6 +1104,19 @@ struct __DRIimageExtensionRec { */ __DRIimage *(*fromPlanar)(__DRIimage *image, int plane, void *loaderPrivate); + + /** + * Create image from texture. + * + * \since 6 + */ + __DRIimage *(*createImageFromTexture)(__DRIcontext *context, + int target, + unsigned texture, + int depth, + int level, + unsigned *error, + void *loaderPrivate); }; 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 f1284adb2..d457e4d0c 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 96382718a..b380de307 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -363,6 +363,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, |