diff options
Diffstat (limited to 'mesalib/src')
76 files changed, 1863 insertions, 726 deletions
diff --git a/mesalib/src/gallium/Automake.inc b/mesalib/src/gallium/Automake.inc index 97735abe0..8bf2a12e8 100644 --- a/mesalib/src/gallium/Automake.inc +++ b/mesalib/src/gallium/Automake.inc @@ -41,6 +41,7 @@ GALLIUM_DRI_CFLAGS = \ GALLIUM_VIDEO_CFLAGS = \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/loader \ -I$(top_srcdir)/src/gallium/include \ -I$(top_srcdir)/src/gallium/auxiliary \ -I$(top_srcdir)/src/gallium/drivers \ @@ -58,22 +59,6 @@ GALLIUM_DRI_LINKER_FLAGS = \ -avoid-version \ $(GC_SECTIONS) -GALLIUM_VDPAU_LINKER_FLAGS = \ - -shared \ - -module \ - -no-undefined \ - -version-number $(VDPAU_MAJOR):$(VDPAU_MINOR) \ - $(GC_SECTIONS) \ - $(LD_NO_UNDEFINED) - -GALLIUM_XVMC_LINKER_FLAGS = \ - -shared \ - -module \ - -no-undefined \ - -version-number $(XVMC_MAJOR):$(XVMC_MINOR) \ - $(GC_SECTIONS) \ - $(LD_NO_UNDEFINED) - GALLIUM_OMX_LINKER_FLAGS = \ -shared \ -module \ @@ -86,12 +71,6 @@ if HAVE_LD_VERSION_SCRIPT GALLIUM_DRI_LINKER_FLAGS += \ -Wl,--version-script=$(top_srcdir)/src/gallium/targets/dri.sym -GALLIUM_VDPAU_LINKER_FLAGS += \ - -Wl,--version-script=$(top_srcdir)/src/gallium/targets/vdpau.sym - -GALLIUM_XVMC_LINKER_FLAGS += \ - -Wl,--version-script=$(top_srcdir)/src/gallium/targets/xvmc.sym - GALLIUM_OMX_LINKER_FLAGS += \ -Wl,--version-script=$(top_srcdir)/src/gallium/targets/omx.sym endif @@ -111,20 +90,6 @@ GALLIUM_DRI_LIB_DEPS = \ $(EXPAT_LIBS) \ $(GALLIUM_COMMON_LIB_DEPS) -GALLIUM_VDPAU_LIB_DEPS = \ - $(top_builddir)/src/gallium/auxiliary/libgallium.la \ - $(top_builddir)/src/gallium/state_trackers/vdpau/libvdpautracker.la \ - $(VDPAU_LIBS) \ - $(LIBDRM_LIBS) \ - $(GALLIUM_COMMON_LIB_DEPS) - -GALLIUM_XVMC_LIB_DEPS = \ - $(top_builddir)/src/gallium/auxiliary/libgallium.la \ - $(top_builddir)/src/gallium/state_trackers/xvmc/libxvmctracker.la \ - $(XVMC_LIBS) \ - $(LIBDRM_LIBS) \ - $(GALLIUM_COMMON_LIB_DEPS) - GALLIUM_OMX_LIB_DEPS = \ $(top_builddir)/src/gallium/auxiliary/libgallium.la \ $(top_builddir)/src/gallium/state_trackers/omx/libomxtracker.la \ @@ -141,13 +106,25 @@ GALLIUM_WINSYS_CFLAGS = \ if HAVE_MESA_LLVM GALLIUM_DRI_LINKER_FLAGS += $(LLVM_LDFLAGS) -GALLIUM_VDPAU_LINKER_FLAGS += $(LLVM_LDFLAGS) -GALLIUM_XVMC_LINKER_FLAGS += $(LLVM_LDFLAGS) GALLIUM_OMX_LINKER_FLAGS += $(LLVM_LDFLAGS) GALLIUM_DRI_LIB_DEPS += $(LLVM_LIBS) -GALLIUM_VDPAU_LIB_DEPS += $(LLVM_LIBS) -GALLIUM_XVMC_LIB_DEPS += $(LLVM_LIBS) GALLIUM_OMX_LIB_DEPS += $(LLVM_LIBS) endif + + +GALLIUM_PIPE_LOADER_WINSYS_LIBS = \ + $(top_builddir)/src/gallium/winsys/sw/null/libws_null.la + +if HAVE_DRISW +GALLIUM_PIPE_LOADER_WINSYS_LIBS += \ + $(top_builddir)/src/gallium/winsys/sw/dri/libswdri.la +endif + +if NEED_WINSYS_XLIB +GALLIUM_PIPE_LOADER_WINSYS_LIBS += \ + $(top_builddir)/src/gallium/winsys/sw/xlib/libws_xlib.la \ + -lX11 -lXext -lXfixes \ + $(LIBDRM_LIBS) +endif diff --git a/mesalib/src/gallium/SConscript b/mesalib/src/gallium/SConscript index 32bbdbe56..598b2f1ec 100644 --- a/mesalib/src/gallium/SConscript +++ b/mesalib/src/gallium/SConscript @@ -21,12 +21,6 @@ SConscript([ 'drivers/trace/SConscript', ]) -if not env['msvc']: - # These drivers do not build on MSVC compilers - SConscript([ - 'drivers/i915/SConscript', - ]) - # # State trackers # @@ -66,11 +60,6 @@ if env['platform'] == 'windows': 'winsys/sw/gdi/SConscript', ]) -if not env['msvc']: - SConscript([ - 'winsys/i915/sw/SConscript', - ]) - if env['platform'] == 'haiku': SConscript([ 'winsys/sw/hgl/SConscript', @@ -85,11 +74,6 @@ if env['dri']: 'winsys/svga/drm/SConscript', ]) - if env['drm_intel']: - SConscript([ - 'winsys/i915/drm/SConscript', - ]) - # # Targets # @@ -126,10 +110,6 @@ if not env['embedded']: 'targets/dri-swrast/SConscript', 'targets/dri-vmwgfx/SConscript', ]) - if env['drm_intel']: - SConscript([ - 'targets/dri-i915/SConscript', - ]) # diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c index 056f82f72..a53ed6f29 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.c +++ b/mesalib/src/gallium/auxiliary/util/u_format.c @@ -187,6 +187,17 @@ util_format_is_intensity(enum pipe_format format) return FALSE; } +boolean +util_format_is_subsampled_422(enum pipe_format format) +{ + const struct util_format_description *desc = + util_format_description(format); + + return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED && + desc->block.width == 2 && + desc->block.height == 1 && + desc->block.bits == 32; +} boolean util_format_is_supported(enum pipe_format format, unsigned bind) diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h index 1dd5d52f1..2e2bf0240 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.h +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -664,6 +664,9 @@ boolean util_format_is_intensity(enum pipe_format format); boolean +util_format_is_subsampled_422(enum pipe_format format); + +boolean util_format_is_pure_integer(enum pipe_format format); boolean diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 5945590a5..b54eae72d 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -96,6 +96,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_function_inlining.cpp \ $(GLSL_SRCDIR)/opt_if_simplification.cpp \ $(GLSL_SRCDIR)/opt_noop_swizzle.cpp \ + $(GLSL_SRCDIR)/opt_rebalance_tree.cpp \ $(GLSL_SRCDIR)/opt_redundant_jumps.cpp \ $(GLSL_SRCDIR)/opt_structure_splitting.cpp \ $(GLSL_SRCDIR)/opt_swizzle_swizzle.cpp \ diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index d1c77f1ec..7ba04a808 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -49,7 +49,6 @@ * parser (and lexer) sources. */ -#include "main/core.h" /* for struct gl_extensions */ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" @@ -2182,6 +2181,41 @@ validate_explicit_location(const struct ast_type_qualifier *qual, { bool fail = false; + /* Checks for GL_ARB_explicit_uniform_location. */ + if (qual->flags.q.uniform) { + if (!state->check_explicit_uniform_location_allowed(loc, var)) + return; + + const struct gl_context *const ctx = state->ctx; + unsigned max_loc = qual->location + var->type->uniform_locations() - 1; + + /* ARB_explicit_uniform_location specification states: + * + * "The explicitly defined locations and the generated locations + * must be in the range of 0 to MAX_UNIFORM_LOCATIONS minus one." + * + * "Valid locations for default-block uniform variable locations + * are in the range of 0 to the implementation-defined maximum + * number of uniform locations." + */ + if (qual->location < 0) { + _mesa_glsl_error(loc, state, + "explicit location < 0 for uniform %s", var->name); + return; + } + + if (max_loc >= ctx->Const.MaxUserAssignableUniformLocations) { + _mesa_glsl_error(loc, state, "location(s) consumed by uniform %s " + ">= MAX_UNIFORM_LOCATIONS (%u)", var->name, + ctx->Const.MaxUserAssignableUniformLocations); + return; + } + + var->data.explicit_location = true; + var->data.location = qual->location; + return; + } + /* Between GL_ARB_explicit_attrib_location an * GL_ARB_separate_shader_objects, the inputs and outputs of any shader * stage can be assigned explicit locations. The checking here associates @@ -2435,6 +2469,13 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, _mesa_shader_stage_to_string(state->stage)); } + /* Disallow layout qualifiers which may only appear on layout declarations. */ + if (qual->flags.q.prim_type) { + _mesa_glsl_error(loc, state, + "Primitive type may only be specified on GS input or output " + "layout declaration, not on variables."); + } + /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says: * * "However, the const qualifier cannot be used with out or inout." @@ -2649,6 +2690,36 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, const bool uses_deprecated_qualifier = qual->flags.q.attribute || qual->flags.q.varying; + + /* Validate auxiliary storage qualifiers */ + + /* From section 4.3.4 of the GLSL 1.30 spec: + * "It is an error to use centroid in in a vertex shader." + * + * From section 4.3.4 of the GLSL ES 3.00 spec: + * "It is an error to use centroid in or interpolation qualifiers in + * a vertex shader input." + */ + + /* Section 4.3.6 of the GLSL 1.30 specification states: + * "It is an error to use centroid out in a fragment shader." + * + * The GL_ARB_shading_language_420pack extension specification states: + * "It is an error to use auxiliary storage qualifiers or interpolation + * qualifiers on an output in a fragment shader." + */ + if (qual->flags.q.sample && (!is_varying_var(var, state->stage) || uses_deprecated_qualifier)) { + _mesa_glsl_error(loc, state, + "sample qualifier may only be used on `in` or `out` " + "variables between shader stages"); + } + if (qual->flags.q.centroid && !is_varying_var(var, state->stage)) { + _mesa_glsl_error(loc, state, + "centroid qualifier may only be used with `in', " + "`out' or `varying' variables between shader stages"); + } + + /* Is the 'layout' keyword used with parameters that allow relaxed checking. * Many implementations of GL_ARB_fragment_coord_conventions_enable and some * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable @@ -3606,45 +3677,6 @@ ast_declarator_list::hir(exec_list *instructions, } - /* From section 4.3.4 of the GLSL 1.30 spec: - * "It is an error to use centroid in in a vertex shader." - * - * From section 4.3.4 of the GLSL ES 3.00 spec: - * "It is an error to use centroid in or interpolation qualifiers in - * a vertex shader input." - */ - if (state->is_version(130, 300) - && this->type->qualifier.flags.q.centroid - && this->type->qualifier.flags.q.in - && state->stage == MESA_SHADER_VERTEX) { - - _mesa_glsl_error(&loc, state, - "'centroid in' cannot be used in a vertex shader"); - } - - if (state->stage == MESA_SHADER_VERTEX - && this->type->qualifier.flags.q.sample - && this->type->qualifier.flags.q.in) { - - _mesa_glsl_error(&loc, state, - "'sample in' cannot be used in a vertex shader"); - } - - /* Section 4.3.6 of the GLSL 1.30 specification states: - * "It is an error to use centroid out in a fragment shader." - * - * The GL_ARB_shading_language_420pack extension specification states: - * "It is an error to use auxiliary storage qualifiers or interpolation - * qualifiers on an output in a fragment shader." - */ - if (state->stage == MESA_SHADER_FRAGMENT && - this->type->qualifier.flags.q.out && - this->type->qualifier.has_auxiliary_storage()) { - _mesa_glsl_error(&loc, state, - "auxiliary storage qualifiers cannot be used on " - "fragment shader outputs"); - } - /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. */ if (this->type->qualifier.precision != ast_precision_none) { @@ -4632,9 +4664,51 @@ ast_case_label::hir(exec_list *instructions, ir_dereference_variable *deref_test_var = new(ctx) ir_dereference_variable(state->switch_state.test_var); - ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal, - label_const, - deref_test_var); + ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, + label_const, + deref_test_var); + + /* + * From GLSL 4.40 specification section 6.2 ("Selection"): + * + * "The type of the init-expression value in a switch statement must + * be a scalar int or uint. The type of the constant-expression value + * in a case label also must be a scalar int or uint. When any pair + * of these values is tested for "equal value" and the types do not + * match, an implicit conversion will be done to convert the int to a + * uint (see section 4.1.10 “Implicit Conversions”) before the compare + * is done." + */ + if (label_const->type != state->switch_state.test_var->type) { + YYLTYPE loc = this->test_value->get_location(); + + const glsl_type *type_a = label_const->type; + const glsl_type *type_b = state->switch_state.test_var->type; + + /* Check if int->uint implicit conversion is supported. */ + bool integer_conversion_supported = + glsl_type::int_type->can_implicitly_convert_to(glsl_type::uint_type, + state); + + if ((!type_a->is_integer() || !type_b->is_integer()) || + !integer_conversion_supported) { + _mesa_glsl_error(&loc, state, "type mismatch with switch " + "init-expression and case label (%s != %s)", + type_a->name, type_b->name); + } else { + /* Conversion of the case label. */ + if (type_a->base_type == GLSL_TYPE_INT) { + if (!apply_implicit_conversion(glsl_type::uint_type, + test_cond->operands[0], state)) + _mesa_glsl_error(&loc, state, "implicit type conversion error"); + } else { + /* Conversion of the init-expression value. */ + if (!apply_implicit_conversion(glsl_type::uint_type, + test_cond->operands[1], state)) + _mesa_glsl_error(&loc, state, "implicit type conversion error"); + } + } + } ir_assignment *set_fallthru_on_test = new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond); @@ -5041,6 +5115,13 @@ ast_process_structure_or_interface_block(exec_list *instructions, "with uniform interface blocks"); } + if ((qual->flags.q.uniform || !is_interface) && + qual->has_auxiliary_storage()) { + _mesa_glsl_error(&loc, state, + "auxiliary storage qualifiers cannot be used " + "in uniform blocks or structures."); + } + if (field_type->is_matrix() || (field_type->is_array() && field_type->fields.array->is_matrix())) { fields[i].row_major = block_row_major; @@ -5090,7 +5171,7 @@ ast_struct_specifier::hir(exec_list *instructions, */ if (state->language_version != 110 && state->struct_specifier_depth != 0) _mesa_glsl_error(&loc, state, - "embedded structure declartions are not allowed"); + "embedded structure declarations are not allowed"); state->struct_specifier_depth++; @@ -5206,6 +5287,12 @@ ast_interface_block::hir(exec_list *instructions, bool block_row_major = this->layout.flags.q.row_major; exec_list declared_variables; glsl_struct_field *fields; + + /* Treat an interface block as one level of nesting, so that embedded struct + * specifiers will be disallowed. + */ + state->struct_specifier_depth++; + unsigned int num_variables = ast_process_structure_or_interface_block(&declared_variables, state, @@ -5217,6 +5304,8 @@ ast_interface_block::hir(exec_list *instructions, redeclaring_per_vertex, var_mode); + state->struct_specifier_depth--; + if (!redeclaring_per_vertex) validate_identifier(this->block_name, loc, state); diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 0ee2c495a..77053d5b1 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -247,7 +247,7 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, q.flags.q.local_size != 0 && state->in_qualifier->flags.q.local_size == 0; - valid_in_mask.flags.q.local_size = 1; + valid_in_mask.flags.q.local_size = 7; break; default: _mesa_glsl_error(loc, state, diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 9b35850ee..b9c69d23c 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -26,7 +26,6 @@ #include "glsl_symbol_table.h" #include "main/core.h" #include "main/uniforms.h" -#include "program/prog_parameter.h" #include "program/prog_statevars.h" #include "program/prog_instruction.h" @@ -939,6 +938,11 @@ builtin_variable_generator::generate_fs_special_vars() if (state->ARB_gpu_shader5_enable) { add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn"); } + + if (state->ARB_fragment_layer_viewport_enable) { + add_input(VARYING_SLOT_LAYER, int_t, "gl_Layer"); + add_input(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex"); + } } diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index 98875837c..d8c395778 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -2086,9 +2086,15 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio add_builtin_define(parser, "GL_ARB_fragment_coord_conventions", 1); + if (extensions->ARB_fragment_layer_viewport) + add_builtin_define(parser, "GL_ARB_fragment_layer_viewport", 1); + if (extensions->ARB_explicit_attrib_location) add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); + if (extensions->ARB_explicit_uniform_location) + add_builtin_define(parser, "GL_ARB_explicit_uniform_location", 1); + if (extensions->ARB_shader_texture_lod) add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1); diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 6c3f9b692..db7b1d179 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -396,6 +396,7 @@ layout { || yyextra->AMD_conservative_depth_enable || yyextra->ARB_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable + || yyextra->ARB_explicit_uniform_location_enable || yyextra->has_separate_shader_objects() || yyextra->ARB_uniform_buffer_object_enable || yyextra->ARB_fragment_coord_conventions_enable diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index eddab0518..240995901 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -1558,11 +1558,6 @@ type_qualifier: if ($2.flags.q.invariant) _mesa_glsl_error(&@1, state, "duplicate \"invariant\" qualifier"); - if ($2.has_layout()) { - _mesa_glsl_error(&@1, state, - "\"invariant\" cannot be used with layout(...)"); - } - if (!state->ARB_shading_language_420pack_enable && $2.flags.q.precise) _mesa_glsl_error(&@1, state, "\"invariant\" must come after \"precise\""); @@ -1585,11 +1580,6 @@ type_qualifier: if ($2.has_interpolation()) _mesa_glsl_error(&@1, state, "duplicate interpolation qualifier"); - if ($2.has_layout()) { - _mesa_glsl_error(&@1, state, "interpolation qualifiers cannot be used " - "with layout(...)"); - } - if (!state->ARB_shading_language_420pack_enable && ($2.flags.q.precise || $2.flags.q.invariant)) { _mesa_glsl_error(&@1, state, "interpolation qualifiers must come " @@ -1601,28 +1591,18 @@ type_qualifier: } | layout_qualifier type_qualifier { - /* The GLSL 1.50 grammar indicates that a layout(...) declaration can be - * used standalone or immediately before a storage qualifier. It cannot - * be used with interpolation qualifiers or invariant. There does not - * appear to be any text indicating that it must come before the storage - * qualifier, but always seems to in examples. + /* In the absence of ARB_shading_language_420pack, layout qualifiers may + * appear no later than auxiliary storage qualifiers. There is no + * particularly clear spec language mandating this, but in all examples + * the layout qualifier precedes the storage qualifier. + * + * We allow combinations of layout with interpolation, invariant or + * precise qualifiers since these are useful in ARB_separate_shader_objects. + * There is no clear spec guidance on this either. */ if (!state->ARB_shading_language_420pack_enable && $2.has_layout()) _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers"); - if ($2.flags.q.invariant) - _mesa_glsl_error(&@1, state, "layout(...) cannot be used with " - "the \"invariant\" qualifier"); - - if ($2.flags.q.precise) - _mesa_glsl_error(&@1, state, "layout(...) cannot be used with " - "the \"precise\" qualifier"); - - if ($2.has_interpolation()) { - _mesa_glsl_error(&@1, state, "layout(...) cannot be used with " - "interpolation qualifiers"); - } - $$ = $1; $$.merge_qualifier(&@1, state, $2); } @@ -2180,7 +2160,7 @@ condition: ; /* - * siwtch_statement grammar is based on the syntax described in the body + * switch_statement grammar is based on the syntax described in the body * of the GLSL spec, not in it's appendix!!! */ switch_statement: diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index f3c5bd049..11a9a4320 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -515,7 +515,9 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_draw_buffers, true, false, dummy_true), EXT(ARB_draw_instanced, true, false, ARB_draw_instanced), EXT(ARB_explicit_attrib_location, true, false, ARB_explicit_attrib_location), + EXT(ARB_explicit_uniform_location, true, false, ARB_explicit_uniform_location), EXT(ARB_fragment_coord_conventions, true, false, ARB_fragment_coord_conventions), + EXT(ARB_fragment_layer_viewport, true, false, ARB_fragment_layer_viewport), EXT(ARB_gpu_shader5, true, false, ARB_gpu_shader5), EXT(ARB_sample_shading, true, false, ARB_sample_shading), EXT(ARB_separate_shader_objects, true, false, dummy_true), @@ -1568,7 +1570,8 @@ do_common_optimization(exec_list *ir, bool linked, progress = do_constant_variable_unlinked(ir) || progress; progress = do_constant_folding(ir) || progress; progress = do_cse(ir) || progress; - progress = do_algebraic(ir, native_integers) || progress; + progress = do_rebalance_tree(ir) || progress; + progress = do_algebraic(ir, native_integers, options) || progress; progress = do_lower_jumps(ir) || progress; progress = do_vec_index_to_swizzle(ir) || progress; progress = lower_vector_insert(ir, false) || progress; diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 0416a9c72..aa4a114e4 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -151,6 +151,21 @@ struct _mesa_glsl_parse_state { return true; } + bool check_explicit_uniform_location_allowed(YYLTYPE *locp, + const ir_variable *) + { + if (!this->has_explicit_attrib_location() || + !this->ARB_explicit_uniform_location_enable) { + _mesa_glsl_error(locp, this, + "uniform explicit location requires " + "GL_ARB_explicit_uniform_location and either " + "GL_ARB_explicit_attrib_location or GLSL 330."); + return false; + } + + return true; + } + bool has_explicit_attrib_location() const { return ARB_explicit_attrib_location_enable || is_version(330, 300); @@ -188,7 +203,7 @@ struct _mesa_glsl_parse_state { /** * Number of nested struct_specifier levels * - * Outside a struct_specifer, this is zero. + * Outside a struct_specifier, this is zero. */ unsigned struct_specifier_depth; @@ -363,8 +378,12 @@ struct _mesa_glsl_parse_state { bool ARB_draw_instanced_warn; bool ARB_explicit_attrib_location_enable; bool ARB_explicit_attrib_location_warn; + bool ARB_explicit_uniform_location_enable; + bool ARB_explicit_uniform_location_warn; bool ARB_fragment_coord_conventions_enable; bool ARB_fragment_coord_conventions_warn; + bool ARB_fragment_layer_viewport_enable; + bool ARB_fragment_layer_viewport_warn; bool ARB_gpu_shader5_enable; bool ARB_gpu_shader5_warn; bool ARB_sample_shading_enable; diff --git a/mesalib/src/glsl/glsl_symbol_table.h b/mesalib/src/glsl/glsl_symbol_table.h index f323fc305..25282641f 100644 --- a/mesalib/src/glsl/glsl_symbol_table.h +++ b/mesalib/src/glsl/glsl_symbol_table.h @@ -32,9 +32,9 @@ extern "C" { #include "program/symbol_table.h" } #include "ir.h" -#include "glsl_types.h" class symbol_table_entry; +struct glsl_type; /** * Facade class for _mesa_symbol_table diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index e77146cdf..f9cd258fe 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -22,9 +22,7 @@ */ #include <stdio.h> -#include <stdlib.h> -#include "main/core.h" /* for Elements */ -#include "glsl_symbol_table.h" +#include "main/core.h" /* for Elements, MAX2 */ #include "glsl_parser_extras.h" #include "glsl_types.h" extern "C" { @@ -677,6 +675,32 @@ glsl_type::component_slots() const return 0; } +unsigned +glsl_type::uniform_locations() const +{ + if (this->is_matrix()) + return 1; + + unsigned size = 0; + + switch (this->base_type) { + case GLSL_TYPE_STRUCT: + case GLSL_TYPE_INTERFACE: + for (unsigned i = 0; i < this->length; i++) + size += this->fields.structure[i].type->uniform_locations(); + return size; + case GLSL_TYPE_ARRAY: + return this->length * this->fields.array->uniform_locations(); + default: + break; + } + + /* The location count for many types match with component_slots() result, + * all expections should be handled above. + */ + return component_slots(); +} + bool glsl_type::can_implicitly_convert_to(const glsl_type *desired, _mesa_glsl_parse_state *state) const diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 35a4e6acc..f6d4a02ab 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -256,6 +256,12 @@ struct glsl_type { unsigned component_slots() const; /** + * Calculate the number of unique values from glGetUniformLocation for the + * elements of the type. + */ + unsigned uniform_locations() const; + + /** * Calculate the number of attribute slots required to hold this type * * This implements the language rules of GLSL 1.50 for counting the number diff --git a/mesalib/src/glsl/hir_field_selection.cpp b/mesalib/src/glsl/hir_field_selection.cpp index 1e92c89ae..0fa976811 100644 --- a/mesalib/src/glsl/hir_field_selection.cpp +++ b/mesalib/src/glsl/hir_field_selection.cpp @@ -22,7 +22,6 @@ */ #include "ir.h" -#include "program/symbol_table.h" #include "glsl_parser_extras.h" #include "ast.h" #include "glsl_types.h" diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 8fed768a2..10c00068e 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -23,7 +23,6 @@ #include <string.h> #include "main/core.h" /* for MAX2 */ #include "ir.h" -#include "ir_visitor.h" #include "glsl_types.h" ir_rvalue::ir_rvalue(enum ir_node_type t) diff --git a/mesalib/src/glsl/ir_basic_block.cpp b/mesalib/src/glsl/ir_basic_block.cpp index 426fda2f2..74ee4b696 100644 --- a/mesalib/src/glsl/ir_basic_block.cpp +++ b/mesalib/src/glsl/ir_basic_block.cpp @@ -28,9 +28,7 @@ */ #include "ir.h" -#include "ir_visitor.h" #include "ir_basic_block.h" -#include "glsl_types.h" /** * Calls a user function for every basic block in the instruction stream. diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index 8afe8f776..7b4a22df4 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -36,7 +36,6 @@ #include <math.h> #include "main/core.h" /* for MAX2, MIN2, CLAMP */ #include "ir.h" -#include "ir_visitor.h" #include "glsl_types.h" #include "program/hash_table.h" diff --git a/mesalib/src/glsl/ir_expression_flattening.cpp b/mesalib/src/glsl/ir_expression_flattening.cpp index c1cadb122..0b1ada519 100644 --- a/mesalib/src/glsl/ir_expression_flattening.cpp +++ b/mesalib/src/glsl/ir_expression_flattening.cpp @@ -32,10 +32,8 @@ */ #include "ir.h" -#include "ir_visitor.h" #include "ir_rvalue_visitor.h" #include "ir_expression_flattening.h" -#include "glsl_types.h" class ir_expression_flattening_visitor : public ir_rvalue_visitor { public: diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index c63921c26..b83c22592 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -71,7 +71,9 @@ bool do_common_optimization(exec_list *ir, bool linked, const struct gl_shader_compiler_options *options, bool native_integers); -bool do_algebraic(exec_list *instructions, bool native_integers); +bool do_rebalance_tree(exec_list *instructions); +bool do_algebraic(exec_list *instructions, bool native_integers, + const struct gl_shader_compiler_options *options); bool do_constant_folding(exec_list *instructions); bool do_constant_variable(exec_list *instructions); bool do_constant_variable_unlinked(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h index 3508509d4..2f7352825 100644 --- a/mesalib/src/glsl/ir_uniform.h +++ b/mesalib/src/glsl/ir_uniform.h @@ -32,12 +32,17 @@ #include "program/prog_parameter.h" /* For union gl_constant_value. */ +/** + * Used by GL_ARB_explicit_uniform_location extension code in the linker + * and glUniform* functions to identify inactive explicit uniform locations. + */ +#define INACTIVE_UNIFORM_EXPLICIT_LOCATION ((gl_uniform_storage *) -1) #ifdef __cplusplus extern "C" { #endif -enum gl_uniform_driver_format { +enum PACKED gl_uniform_driver_format { uniform_native = 0, /**< Store data in the native format. */ uniform_int_float, /**< Store integer data as floats. */ uniform_bool_float, /**< Store boolean data as floats. */ @@ -66,11 +71,8 @@ struct gl_uniform_driver_storage { /** * Base format of the stored data. - * - * This field must have a value from \c GLSL_TYPE_UINT through \c - * GLSL_TYPE_SAMPLER. */ - uint8_t format; + enum gl_uniform_driver_format format; /** * Pointer to the base of the data. diff --git a/mesalib/src/glsl/link_uniform_block_active_visitor.h b/mesalib/src/glsl/link_uniform_block_active_visitor.h index d76dbcaf1..524cd6b91 100644 --- a/mesalib/src/glsl/link_uniform_block_active_visitor.h +++ b/mesalib/src/glsl/link_uniform_block_active_visitor.h @@ -26,8 +26,6 @@ #define LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H #include "ir.h" -#include "ir_visitor.h" -#include "glsl_types.h" #include "main/hash_table.h" struct link_uniform_block_active { diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp index 2100e0517..d755cec98 100644 --- a/mesalib/src/glsl/link_uniform_initializers.cpp +++ b/mesalib/src/glsl/link_uniform_initializers.cpp @@ -25,8 +25,6 @@ #include "ir.h" #include "linker.h" #include "ir_uniform.h" -#include "glsl_symbol_table.h" -#include "program/hash_table.h" /* These functions are put in a "private" namespace instead of being marked * static so that the unit tests can access them. See diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index ba66053ed..66f6d4db3 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -37,6 +37,11 @@ */ /** + * Used by linker to indicate uniforms that have no location set. + */ +#define UNMAPPED_UNIFORM_LOC ~0u + +/** * Count the backing storage requirements for a type */ static unsigned @@ -386,6 +391,9 @@ public: void set_and_process(struct gl_shader_program *prog, ir_variable *var) { + current_var = var; + field_counter = 0; + ubo_block_index = -1; if (var->is_in_uniform_block()) { if (var->is_interface_instance() && var->type->is_array()) { @@ -542,6 +550,22 @@ private: return; } + /* Assign explicit locations. */ + if (current_var->data.explicit_location) { + /* Set sequential locations for struct fields. */ + if (record_type != NULL) { + const unsigned entries = MAX2(1, this->uniforms[id].array_elements); + this->uniforms[id].remap_location = + current_var->data.location + field_counter; + field_counter += entries; + } else { + this->uniforms[id].remap_location = current_var->data.location; + } + } else { + /* Initialize to to indicate that no location is set */ + this->uniforms[id].remap_location = UNMAPPED_UNIFORM_LOC; + } + this->uniforms[id].name = ralloc_strdup(this->uniforms, name); this->uniforms[id].type = base_type; this->uniforms[id].initialized = 0; @@ -597,6 +621,17 @@ public: gl_texture_index targets[MAX_SAMPLERS]; /** + * Current variable being processed. + */ + ir_variable *current_var; + + /** + * Field counter is used to take care that uniform structures + * with explicit locations get sequential locations. + */ + unsigned field_counter; + + /** * Mask of samplers used by the current shader stage. */ unsigned shader_samplers_used; @@ -798,10 +833,6 @@ link_assign_uniform_locations(struct gl_shader_program *prog) prog->UniformStorage = NULL; prog->NumUserUniformStorage = 0; - ralloc_free(prog->UniformRemapTable); - prog->UniformRemapTable = NULL; - prog->NumUniformRemapTable = 0; - if (prog->UniformHash != NULL) { prog->UniformHash->clear(); } else { @@ -914,8 +945,28 @@ link_assign_uniform_locations(struct gl_shader_program *prog) sizeof(prog->_LinkedShaders[i]->SamplerTargets)); } - /* Build the uniform remap table that is used to set/get uniform locations */ + /* Reserve all the explicit locations of the active uniforms. */ for (unsigned i = 0; i < num_user_uniforms; i++) { + if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) { + /* How many new entries for this uniform? */ + const unsigned entries = MAX2(1, uniforms[i].array_elements); + + /* Set remap table entries point to correct gl_uniform_storage. */ + for (unsigned j = 0; j < entries; j++) { + unsigned element_loc = uniforms[i].remap_location + j; + assert(prog->UniformRemapTable[element_loc] == + INACTIVE_UNIFORM_EXPLICIT_LOCATION); + prog->UniformRemapTable[element_loc] = &uniforms[i]; + } + } + } + + /* Reserve locations for rest of the uniforms. */ + for (unsigned i = 0; i < num_user_uniforms; i++) { + + /* Explicit ones have been set already. */ + if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) + continue; /* how many new entries for this uniform? */ const unsigned entries = MAX2(1, uniforms[i].array_elements); diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index a43d23082..0b6a71679 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -74,6 +74,7 @@ #include "link_varyings.h" #include "ir_optimization.h" #include "ir_rvalue_visitor.h" +#include "ir_uniform.h" extern "C" { #include "main/shaderobj.h" @@ -2224,6 +2225,115 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) linker_error(prog, "Too many combined image uniforms and fragment outputs"); } + +/** + * Initializes explicit location slots to INACTIVE_UNIFORM_EXPLICIT_LOCATION + * for a variable, checks for overlaps between other uniforms using explicit + * locations. + */ +static bool +reserve_explicit_locations(struct gl_shader_program *prog, + string_to_uint_map *map, ir_variable *var) +{ + unsigned slots = var->type->uniform_locations(); + unsigned max_loc = var->data.location + slots - 1; + + /* Resize remap table if locations do not fit in the current one. */ + if (max_loc + 1 > prog->NumUniformRemapTable) { + prog->UniformRemapTable = + reralloc(prog, prog->UniformRemapTable, + gl_uniform_storage *, + max_loc + 1); + + if (!prog->UniformRemapTable) { + linker_error(prog, "Out of memory during linking."); + return false; + } + + /* Initialize allocated space. */ + for (unsigned i = prog->NumUniformRemapTable; i < max_loc + 1; i++) + prog->UniformRemapTable[i] = NULL; + + prog->NumUniformRemapTable = max_loc + 1; + } + + for (unsigned i = 0; i < slots; i++) { + unsigned loc = var->data.location + i; + + /* Check if location is already used. */ + if (prog->UniformRemapTable[loc] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) { + + /* Possibly same uniform from a different stage, this is ok. */ + unsigned hash_loc; + if (map->get(hash_loc, var->name) && hash_loc == loc - i) + continue; + + /* ARB_explicit_uniform_location specification states: + * + * "No two default-block uniform variables in the program can have + * the same location, even if they are unused, otherwise a compiler + * or linker error will be generated." + */ + linker_error(prog, + "location qualifier for uniform %s overlaps" + "previously used location", + var->name); + return false; + } + + /* Initialize location as inactive before optimization + * rounds and location assignment. + */ + prog->UniformRemapTable[loc] = INACTIVE_UNIFORM_EXPLICIT_LOCATION; + } + + /* Note, base location used for arrays. */ + map->put(var->data.location, var->name); + + return true; +} + +/** + * Check and reserve all explicit uniform locations, called before + * any optimizations happen to handle also inactive uniforms and + * inactive array elements that may get trimmed away. + */ +static void +check_explicit_uniform_locations(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + if (!ctx->Extensions.ARB_explicit_uniform_location) + return; + + /* This map is used to detect if overlapping explicit locations + * occur with the same uniform (from different stage) or a different one. + */ + string_to_uint_map *uniform_map = new string_to_uint_map; + + if (!uniform_map) { + linker_error(prog, "Out of memory during linking."); + return; + } + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + + if (!sh) + continue; + + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *)node)->as_variable(); + if ((var && var->data.mode == ir_var_uniform) && + var->data.explicit_location) { + if (!reserve_explicit_locations(prog, uniform_map, var)) + return; + } + } + } + + delete uniform_map; +} + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { @@ -2372,6 +2482,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) break; } + check_explicit_uniform_locations(ctx, prog); + if (!prog->LinkStatus) + goto done; + /* Validate the inputs of each stage with the output of the preceding * stage. */ diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h index 694b686b0..576bc14e4 100644 --- a/mesalib/src/glsl/list.h +++ b/mesalib/src/glsl/list.h @@ -83,67 +83,29 @@ struct exec_node { /* empty */ } - const exec_node *get_next() const - { - return next; - } + const exec_node *get_next() const; + exec_node *get_next(); - exec_node *get_next() - { - return next; - } + const exec_node *get_prev() const; + exec_node *get_prev(); - const exec_node *get_prev() const - { - return prev; - } - - exec_node *get_prev() - { - return prev; - } - - void remove() - { - next->prev = prev; - prev->next = next; - next = NULL; - prev = NULL; - } + void remove(); /** * Link a node with itself * * This creates a sort of degenerate list that is occasionally useful. */ - void self_link() - { - next = this; - prev = this; - } + void self_link(); /** * Insert a node in the list after the current node */ - void insert_after(exec_node *after) - { - after->next = this->next; - after->prev = this; - - this->next->prev = after; - this->next = after; - } + void insert_after(exec_node *after); /** * Insert a node in the list before the current node */ - void insert_before(exec_node *before) - { - before->next = this; - before->prev = this->prev; - - this->prev->next = before; - this->prev = before; - } + void insert_before(exec_node *before); /** * Insert another list in the list before the current node @@ -153,33 +115,165 @@ struct exec_node { /** * Replace the current node with the given node. */ - void replace_with(exec_node *replacement) - { - replacement->prev = this->prev; - replacement->next = this->next; - - this->prev->next = replacement; - this->next->prev = replacement; - } + void replace_with(exec_node *replacement); /** * Is this the sentinel at the tail of the list? */ - bool is_tail_sentinel() const - { - return this->next == NULL; - } + bool is_tail_sentinel() const; /** * Is this the sentinel at the head of the list? */ - bool is_head_sentinel() const - { - return this->prev == NULL; - } + bool is_head_sentinel() const; #endif }; +static inline void +exec_node_init(struct exec_node *n) +{ + n->next = NULL; + n->prev = NULL; +} + +static inline const struct exec_node * +exec_node_get_next_const(const struct exec_node *n) +{ + return n->next; +} + +static inline struct exec_node * +exec_node_get_next(struct exec_node *n) +{ + return n->next; +} + +static inline const struct exec_node * +exec_node_get_prev_const(const struct exec_node *n) +{ + return n->prev; +} + +static inline struct exec_node * +exec_node_get_prev(struct exec_node *n) +{ + return n->prev; +} + +static inline void +exec_node_remove(struct exec_node *n) +{ + n->next->prev = n->prev; + n->prev->next = n->next; + n->next = NULL; + n->prev = NULL; +} + +static inline void +exec_node_self_link(struct exec_node *n) +{ + n->next = n; + n->prev = n; +} + +static inline void +exec_node_insert_after(struct exec_node *n, struct exec_node *after) +{ + after->next = n->next; + after->prev = n; + + n->next->prev = after; + n->next = after; +} + +static inline void +exec_node_insert_node_before(struct exec_node *n, struct exec_node *before) +{ + before->next = n; + before->prev = n->prev; + + n->prev->next = before; + n->prev = before; +} + +static inline void +exec_node_replace_with(struct exec_node *n, struct exec_node *replacement) +{ + replacement->prev = n->prev; + replacement->next = n->next; + + n->prev->next = replacement; + n->next->prev = replacement; +} + +static inline bool +exec_node_is_tail_sentinel(const struct exec_node *n) +{ + return n->next == NULL; +} + +static inline bool +exec_node_is_head_sentinel(const struct exec_node *n) +{ + return n->prev == NULL; +} + +#ifdef __cplusplus +inline const exec_node *exec_node::get_next() const +{ + return exec_node_get_next_const(this); +} + +inline exec_node *exec_node::get_next() +{ + return exec_node_get_next(this); +} + +inline const exec_node *exec_node::get_prev() const +{ + return exec_node_get_prev_const(this); +} + +inline exec_node *exec_node::get_prev() +{ + return exec_node_get_prev(this); +} + +inline void exec_node::remove() +{ + exec_node_remove(this); +} + +inline void exec_node::self_link() +{ + exec_node_self_link(this); +} + +inline void exec_node::insert_after(exec_node *after) +{ + exec_node_insert_after(this, after); +} + +inline void exec_node::insert_before(exec_node *before) +{ + exec_node_insert_node_before(this, before); +} + +inline void exec_node::replace_with(exec_node *replacement) +{ + exec_node_replace_with(this, replacement); +} + +inline bool exec_node::is_tail_sentinel() const +{ + return exec_node_is_tail_sentinel(this); +} + +inline bool exec_node::is_head_sentinel() const +{ + return exec_node_is_head_sentinel(this); +} +#endif #ifdef __cplusplus /* This macro will not work correctly if `t' uses virtual inheritance. If you @@ -221,75 +315,19 @@ struct exec_list { make_empty(); } - void make_empty() - { - head = (exec_node *) & tail; - tail = NULL; - tail_pred = (exec_node *) & head; - } - - bool is_empty() const - { - /* There are three ways to test whether a list is empty or not. - * - * - Check to see if the \c head points to the \c tail. - * - Check to see if the \c tail_pred points to the \c head. - * - Check to see if the \c head is the sentinel node by test whether its - * \c next pointer is \c NULL. - * - * The first two methods tend to generate better code on modern systems - * because they save a pointer dereference. - */ - return head == (exec_node *) &tail; - } - - const exec_node *get_head() const - { - return !is_empty() ? head : NULL; - } - - exec_node *get_head() - { - return !is_empty() ? head : NULL; - } - - const exec_node *get_tail() const - { - return !is_empty() ? tail_pred : NULL; - } - - exec_node *get_tail() - { - return !is_empty() ? tail_pred : NULL; - } + void make_empty(); - void push_head(exec_node *n) - { - n->next = head; - n->prev = (exec_node *) &head; + bool is_empty() const; - n->next->prev = n; - head = n; - } + const exec_node *get_head() const; + exec_node *get_head(); - void push_tail(exec_node *n) - { - n->next = (exec_node *) &tail; - n->prev = tail_pred; + const exec_node *get_tail() const; + exec_node *get_tail(); - n->prev->next = n; - tail_pred = n; - } - - void push_degenerate_list_at_head(exec_node *n) - { - assert(n->prev->next == n); - - n->prev->next = head; - head->prev = n->prev; - n->prev = (exec_node *) &head; - head = n; - } + void push_head(exec_node *n); + void push_tail(exec_node *n); + void push_degenerate_list_at_head(exec_node *n); /** * Remove the first node from a list and return it @@ -299,87 +337,239 @@ struct exec_list { * * \sa exec_list::get_head */ - exec_node *pop_head() - { - exec_node *const n = this->get_head(); - if (n != NULL) - n->remove(); - - return n; - } + exec_node *pop_head(); /** * Move all of the nodes from this list to the target list */ - void move_nodes_to(exec_list *target) - { - if (is_empty()) { - target->make_empty(); - } else { - target->head = head; - target->tail = NULL; - target->tail_pred = tail_pred; - - target->head->prev = (exec_node *) &target->head; - target->tail_pred->next = (exec_node *) &target->tail; - - make_empty(); - } - } + void move_nodes_to(exec_list *target); /** * Append all nodes from the source list to the target list */ - void - append_list(exec_list *source) - { - if (source->is_empty()) - return; - - /* Link the first node of the source with the last node of the target list. - */ - this->tail_pred->next = source->head; - source->head->prev = this->tail_pred; - - /* Make the tail of the source list be the tail of the target list. - */ - this->tail_pred = source->tail_pred; - this->tail_pred->next = (exec_node *) &this->tail; - - /* Make the source list empty for good measure. - */ - source->make_empty(); - } + void append_list(exec_list *source); #endif }; +static inline void +exec_list_make_empty(struct exec_list *list) +{ + list->head = (struct exec_node *) & list->tail; + list->tail = NULL; + list->tail_pred = (struct exec_node *) & list->head; +} -#ifdef __cplusplus -inline void exec_node::insert_before(exec_list *before) +static inline bool +exec_list_is_empty(const struct exec_list *list) +{ + /* There are three ways to test whether a list is empty or not. + * + * - Check to see if the \c head points to the \c tail. + * - Check to see if the \c tail_pred points to the \c head. + * - Check to see if the \c head is the sentinel node by test whether its + * \c next pointer is \c NULL. + * + * The first two methods tend to generate better code on modern systems + * because they save a pointer dereference. + */ + return list->head == (struct exec_node *) &list->tail; +} + +static inline const struct exec_node * +exec_list_get_head_const(const struct exec_list *list) +{ + return !exec_list_is_empty(list) ? list->head : NULL; +} + +static inline struct exec_node * +exec_list_get_head(struct exec_list *list) +{ + return !exec_list_is_empty(list) ? list->head : NULL; +} + +static inline const struct exec_node * +exec_list_get_tail_const(const struct exec_list *list) +{ + return !exec_list_is_empty(list) ? list->tail_pred : NULL; +} + +static inline struct exec_node * +exec_list_get_tail(struct exec_list *list) +{ + return !exec_list_is_empty(list) ? list->tail_pred : NULL; +} + +static inline void +exec_list_push_head(struct exec_list *list, struct exec_node *n) +{ + n->next = list->head; + n->prev = (struct exec_node *) &list->head; + + n->next->prev = n; + list->head = n; +} + +static inline void +exec_list_push_tail(struct exec_list *list, struct exec_node *n) +{ + n->next = (struct exec_node *) &list->tail; + n->prev = list->tail_pred; + + n->prev->next = n; + list->tail_pred = n; +} + +static inline void +exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n) +{ + assert(n->prev->next == n); + + n->prev->next = list->head; + list->head->prev = n->prev; + n->prev = (struct exec_node *) &list->head; + list->head = n; +} + +static inline struct exec_node * +exec_list_pop_head(struct exec_list *list) +{ + struct exec_node *const n = exec_list_get_head(list); + if (n != NULL) + exec_node_remove(n); + + return n; +} + +static inline void +exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target) +{ + if (exec_list_is_empty(list)) { + exec_list_make_empty(target); + } else { + target->head = list->head; + target->tail = NULL; + target->tail_pred = list->tail_pred; + + target->head->prev = (struct exec_node *) &target->head; + target->tail_pred->next = (struct exec_node *) &target->tail; + + exec_list_make_empty(list); + } +} + +static inline void +exec_list_append(struct exec_list *list, struct exec_list *source) +{ + if (exec_list_is_empty(source)) + return; + + /* Link the first node of the source with the last node of the target list. + */ + list->tail_pred->next = source->head; + source->head->prev = list->tail_pred; + + /* Make the tail of the source list be the tail of the target list. + */ + list->tail_pred = source->tail_pred; + list->tail_pred->next = (struct exec_node *) &list->tail; + + /* Make the source list empty for good measure. + */ + exec_list_make_empty(source); +} + +static inline void +exec_node_insert_list_before(struct exec_node *n, struct exec_list *before) { - if (before->is_empty()) + if (exec_list_is_empty(before)) return; - before->tail_pred->next = this; - before->head->prev = this->prev; + before->tail_pred->next = n; + before->head->prev = n->prev; - this->prev->next = before->head; - this->prev = before->tail_pred; + n->prev->next = before->head; + n->prev = before->tail_pred; - before->make_empty(); + exec_list_make_empty(before); +} + +#ifdef __cplusplus +inline void exec_list::make_empty() +{ + exec_list_make_empty(this); +} + +inline bool exec_list::is_empty() const +{ + return exec_list_is_empty(this); +} + +inline const exec_node *exec_list::get_head() const +{ + return exec_list_get_head_const(this); +} + +inline exec_node *exec_list::get_head() +{ + return exec_list_get_head(this); +} + +inline const exec_node *exec_list::get_tail() const +{ + return exec_list_get_tail_const(this); +} + +inline exec_node *exec_list::get_tail() +{ + return exec_list_get_tail(this); +} + +inline void exec_list::push_head(exec_node *n) +{ + exec_list_push_head(this, n); +} + +inline void exec_list::push_tail(exec_node *n) +{ + exec_list_push_tail(this, n); +} + +inline void exec_list::push_degenerate_list_at_head(exec_node *n) +{ + exec_list_push_degenerate_list_at_head(this, n); +} + +inline exec_node *exec_list::pop_head() +{ + return exec_list_pop_head(this); +} + +inline void exec_list::move_nodes_to(exec_list *target) +{ + exec_list_move_nodes_to(this, target); +} + +inline void exec_list::append_list(exec_list *source) +{ + exec_list_append(this, source); +} + +inline void exec_node::insert_before(exec_list *before) +{ + exec_node_insert_list_before(this, before); } #endif /** * This version is safe even if the current node is removed. */ -#define foreach_list_safe(__node, __list) \ - for (exec_node * __node = (__list)->head, * __next = __node->next \ - ; __next != NULL \ +#define foreach_list_safe(__node, __list) \ + for (struct exec_node * __node = (__list)->head, * __next = __node->next \ + ; __next != NULL \ ; __node = __next, __next = __next->next) #define foreach_list(__node, __list) \ - for (exec_node * __node = (__list)->head \ + for (struct exec_node * __node = (__list)->head \ ; (__node)->next != NULL \ ; (__node) = (__node)->next) @@ -389,19 +579,19 @@ inline void exec_node::insert_before(exec_list *before) * This is safe against either current node being removed or replaced. */ #define foreach_two_lists(__node1, __list1, __node2, __list2) \ - for (exec_node * __node1 = (__list1)->head, \ - * __node2 = (__list2)->head, \ - * __next1 = __node1->next, \ - * __next2 = __node2->next \ + for (struct exec_node * __node1 = (__list1)->head, \ + * __node2 = (__list2)->head, \ + * __next1 = __node1->next, \ + * __next2 = __node2->next \ ; __next1 != NULL && __next2 != NULL \ ; __node1 = __next1, \ __node2 = __next2, \ __next1 = __next1->next, \ __next2 = __next2->next) -#define foreach_list_const(__node, __list) \ - for (const exec_node * __node = (__list)->head \ - ; (__node)->next != NULL \ +#define foreach_list_const(__node, __list) \ + for (const struct exec_node * __node = (__list)->head \ + ; (__node)->next != NULL \ ; (__node) = (__node)->next) #define foreach_list_typed(__type, __node, __field, __list) \ diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 9d5539252..ac7514acf 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -45,7 +45,9 @@ namespace { class ir_algebraic_visitor : public ir_rvalue_visitor { public: - ir_algebraic_visitor(bool native_integers) + ir_algebraic_visitor(bool native_integers, + const struct gl_shader_compiler_options *options) + : options(options) { this->progress = false; this->mem_ctx = NULL; @@ -69,6 +71,7 @@ public: ir_rvalue *swizzle_if_required(ir_expression *expr, ir_rvalue *operand); + const struct gl_shader_compiler_options *options; void *mem_ctx; bool native_integers; @@ -116,6 +119,46 @@ update_type(ir_expression *ir) ir->type = ir->operands[1]->type; } +/* Recognize (v.x + v.y) + (v.z + v.w) as dot(v, 1.0) */ +static ir_expression * +try_replace_with_dot(ir_expression *expr0, ir_expression *expr1, void *mem_ctx) +{ + if (expr0 && expr0->operation == ir_binop_add && + expr0->type->is_float() && + expr1 && expr1->operation == ir_binop_add && + expr1->type->is_float()) { + ir_swizzle *x = expr0->operands[0]->as_swizzle(); + ir_swizzle *y = expr0->operands[1]->as_swizzle(); + ir_swizzle *z = expr1->operands[0]->as_swizzle(); + ir_swizzle *w = expr1->operands[1]->as_swizzle(); + + if (!x || x->mask.num_components != 1 || + !y || y->mask.num_components != 1 || + !z || z->mask.num_components != 1 || + !w || w->mask.num_components != 1) { + return NULL; + } + + bool swiz_seen[4] = {false, false, false, false}; + swiz_seen[x->mask.x] = true; + swiz_seen[y->mask.x] = true; + swiz_seen[z->mask.x] = true; + swiz_seen[w->mask.x] = true; + + if (!swiz_seen[0] || !swiz_seen[1] || + !swiz_seen[2] || !swiz_seen[3]) { + return NULL; + } + + if (x->val->equals(y->val) && + x->val->equals(z->val) && + x->val->equals(w->val)) { + return dot(x->val, new(mem_ctx) ir_constant(1.0f, 4)); + } + } + return NULL; +} + void ir_algebraic_visitor::reassociate_operands(ir_expression *ir1, int op1, @@ -329,6 +372,14 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (op_const[1] && !op_const[0]) reassociate_constant(ir, 1, op_const[1], op_expr[0]); + /* Recognize (v.x + v.y) + (v.z + v.w) as dot(v, 1.0) */ + if (options->OptimizeForAOS) { + ir_expression *expr = try_replace_with_dot(op_expr[0], op_expr[1], + mem_ctx); + if (expr) + return expr; + } + /* Replace (-x + y) * a + x and commutative variations with lrp(x, y, a). * * (-x + y) * a + x @@ -380,6 +431,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } } } + break; case ir_binop_sub: @@ -647,9 +699,10 @@ ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue) } bool -do_algebraic(exec_list *instructions, bool native_integers) +do_algebraic(exec_list *instructions, bool native_integers, + const struct gl_shader_compiler_options *options) { - ir_algebraic_visitor v(native_integers); + ir_algebraic_visitor v(native_integers, options); visit_list_elements(&v, instructions); diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp index 6612592aa..50c8aa763 100644 --- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -334,7 +334,7 @@ public: } void prepare_array(exec_list *ir, - struct ir_variable **new_var, + ir_variable **new_var, int max_elements, unsigned start_location, const char *var_name, const char *mode_str, unsigned usage, unsigned external_usage) diff --git a/mesalib/src/glsl/opt_rebalance_tree.cpp b/mesalib/src/glsl/opt_rebalance_tree.cpp new file mode 100644 index 000000000..773aab3f6 --- /dev/null +++ b/mesalib/src/glsl/opt_rebalance_tree.cpp @@ -0,0 +1,300 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_rebalance_tree.cpp + * + * Rebalances a reduction expression tree. + * + * For reduction operations (e.g., x + y + z + w) we generate an expression + * tree like + * + * + + * / \ + * + w + * / \ + * + z + * / \ + * x y + * + * which we can rebalance into + * + * + + * / \ + * / \ + * + + + * / \ / \ + * x y z w + * + * to get a better instruction scheduling. + * + * See "Tree Rebalancing in Optimal Editor Time and Space" by Quentin F. Stout + * and Bette L. Warren. + * + * Also see http://penguin.ewu.edu/~trolfe/DSWpaper/ for a very readable + * explanation of the of the tree_to_vine() (rightward rotation) and + * vine_to_tree() (leftward rotation) algorithms. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_rvalue_visitor.h" +#include "ir_optimization.h" + +/* The DSW algorithm generates a degenerate tree (really, a linked list) in + * tree_to_vine(). We'd rather not leave a binary expression with only one + * operand, so trivial modifications (the ternary operators below) are needed + * to ensure that we only rotate around the ir_expression nodes of the tree. + */ +static unsigned +tree_to_vine(ir_expression *root) +{ + unsigned size = 0; + ir_rvalue *vine_tail = root; + ir_rvalue *remainder = root->operands[1]; + + while (remainder != NULL) { + ir_expression *remainder_temp = remainder->as_expression(); + ir_expression *remainder_left = remainder_temp ? + remainder_temp->operands[0]->as_expression() : NULL; + + if (remainder_left == NULL) { + /* move vine_tail down one */ + vine_tail = remainder; + remainder = remainder->as_expression() ? + ((ir_expression *)remainder)->operands[1] : NULL; + size++; + } else { + /* rotate */ + ir_expression *tempptr = remainder_left; + ((ir_expression *)remainder)->operands[0] = tempptr->operands[1]; + tempptr->operands[1] = remainder; + remainder = tempptr; + ((ir_expression *)vine_tail)->operands[1] = tempptr; + } + } + + return size; +} + +static void +compression(ir_expression *root, unsigned count) +{ + ir_expression *scanner = root; + + for (unsigned i = 0; i < count; i++) { + ir_expression *child = (ir_expression *)scanner->operands[1]; + scanner->operands[1] = child->operands[1]; + scanner = (ir_expression *)scanner->operands[1]; + child->operands[1] = scanner->operands[0]; + scanner->operands[0] = child; + } +} + +static void +vine_to_tree(ir_expression *root, unsigned size) +{ + int n = size - 1; + for (int m = n / 2; m > 0; m = n / 2) { + compression(root, m); + n -= m + 1; + } +} + +namespace { + +class ir_rebalance_visitor : public ir_rvalue_enter_visitor { +public: + ir_rebalance_visitor() + { + progress = false; + } + + void handle_rvalue(ir_rvalue **rvalue); + + bool progress; +}; + +struct is_reduction_data { + ir_expression_operation operation; + const glsl_type *type; + unsigned num_expr; + bool is_reduction; + bool contains_constant; +}; + +} /* anonymous namespace */ + +static bool +is_reduction_operation(ir_expression_operation operation) +{ + switch (operation) { + case ir_binop_add: + case ir_binop_mul: + case ir_binop_bit_and: + case ir_binop_bit_xor: + case ir_binop_bit_or: + case ir_binop_logic_and: + case ir_binop_logic_xor: + case ir_binop_logic_or: + case ir_binop_min: + case ir_binop_max: + return true; + default: + return false; + } +} + +/* Note that this function does not attempt to recognize that reduction trees + * are already balanced. + * + * We return false from this function for a number of reasons other than an + * expression tree not being a mathematical reduction. Namely, + * + * - if the tree contains multiple constants that we may be able to combine. + * - if the tree contains matrices: + * - they might contain vec4's with many constant components that we can + * simplify after splitting. + * - applying the matrix chain ordering optimization is more than just + * balancing an expression tree. + * - if the tree contains operations on multiple types. + * - if the tree contains ir_dereference_{array,record}, since foo[a+b] + c + * would trick the visiting pass. + */ +static void +is_reduction(ir_instruction *ir, void *data) +{ + struct is_reduction_data *ird = (struct is_reduction_data *)data; + if (!ird->is_reduction) + return; + + /* We don't want to balance a tree that contains multiple constants, since + * we'll be able to constant fold them if they're not in separate subtrees. + */ + if (ir->as_constant()) { + if (ird->contains_constant) { + ird->is_reduction = false; + } + ird->contains_constant = true; + return; + } + + /* Array/record dereferences have subtrees that are not part of the expr + * tree we're balancing. Skip trees containing them. + */ + if (ir->ir_type == ir_type_dereference_array || + ir->ir_type == ir_type_dereference_record) { + ird->is_reduction = false; + return; + } + + ir_expression *expr = ir->as_expression(); + if (!expr) + return; + + /* Non-constant matrices might still contain constant vec4 that we can + * constant fold once split up. Handling matrices will need some more + * work. + */ + if (expr->type->is_matrix()) { + ird->is_reduction = false; + return; + } + + if (ird->type != NULL && ird->type != expr->type) { + ird->is_reduction = false; + return; + } + ird->type = expr->type; + + ird->num_expr++; + if (is_reduction_operation(expr->operation)) { + if (ird->operation != 0 && ird->operation != expr->operation) + ird->is_reduction = false; + ird->operation = expr->operation; + } else { + ird->is_reduction = false; + } +} + +static ir_rvalue * +handle_expression(ir_expression *expr) +{ + struct is_reduction_data ird; + ird.operation = (ir_expression_operation)0; + ird.type = NULL; + ird.num_expr = 0; + ird.is_reduction = true; + ird.contains_constant = false; + + visit_tree(expr, is_reduction, (void *)&ird); + + if (ird.is_reduction && ird.num_expr > 2) { + ir_constant z = ir_constant(0.0f); + ir_expression pseudo_root = ir_expression(ir_binop_add, &z, expr); + + unsigned size = tree_to_vine(&pseudo_root); + vine_to_tree(&pseudo_root, size); + + expr = (ir_expression *)pseudo_root.operands[1]; + } + return expr; +} + +void +ir_rebalance_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + ir_expression *expr = (*rvalue)->as_expression(); + if (!expr || !is_reduction_operation(expr->operation)) + return; + + ir_rvalue *new_rvalue = handle_expression(expr); + + /* If we failed to rebalance the tree (e.g., because it wasn't a reduction, + * or some other set of cases) new_rvalue will point to the same root as + * before. + * + * Similarly, if the tree rooted at *rvalue was a reduction and was already + * balanced, the algorithm will rearrange the tree but will ultimately + * return an identical tree, so this check will handle that as well and + * will not set progress = true. + */ + if (new_rvalue == *rvalue) + return; + + *rvalue = new_rvalue; + this->progress = true; +} + +bool +do_rebalance_tree(exec_list *instructions) +{ + ir_rebalance_visitor v; + + v.run(instructions); + + return v.progress; +} diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index 6c25010b7..809732c7e 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -98,6 +98,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.ARB_ES3_compatibility = true; ctx->Extensions.ARB_explicit_attrib_location = true; ctx->Extensions.ARB_fragment_coord_conventions = true; + ctx->Extensions.ARB_fragment_layer_viewport = true; ctx->Extensions.ARB_gpu_shader5 = true; ctx->Extensions.ARB_sample_shading = true; ctx->Extensions.ARB_shader_bit_encoding = true; diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp index db5cb2662..e4878bf15 100644 --- a/mesalib/src/glsl/test_optpass.cpp +++ b/mesalib/src/glsl/test_optpass.cpp @@ -65,7 +65,7 @@ do_optimization(struct exec_list *ir, const char *optimization, if (sscanf(optimization, "do_common_optimization ( %d ) ", &int_0) == 1) { return do_common_optimization(ir, int_0 != 0, false, options, true); } else if (strcmp(optimization, "do_algebraic") == 0) { - return do_algebraic(ir, true); + return do_algebraic(ir, true, options); } else if (strcmp(optimization, "do_constant_folding") == 0) { return do_constant_folding(ir); } else if (strcmp(optimization, "do_constant_variable") == 0) { diff --git a/mesalib/src/mapi/glapi/gen/ARB_compressed_texture_pixel_storage.xml b/mesalib/src/mapi/glapi/gen/ARB_compressed_texture_pixel_storage.xml new file mode 100644 index 000000000..c9d0f11be --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_compressed_texture_pixel_storage.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_compressed_texture_pixel_storage" number="110"> + + <enum name="UNPACK_COMPRESSED_BLOCK_WIDTH" value="0x9127"/> + <enum name="UNPACK_COMPRESSED_BLOCK_HEIGHT" value="0x9128"/> + <enum name="UNPACK_COMPRESSED_BLOCK_DEPTH" value="0x9129"/> + <enum name="UNPACK_COMPRESSED_BLOCK_SIZE" value="0x912A"/> + + <enum name="PACK_COMPRESSED_BLOCK_WIDTH" value="0x912B"/> + <enum name="PACK_COMPRESSED_BLOCK_HEIGHT" value="0x912C"/> + <enum name="PACK_COMPRESSED_BLOCK_DEPTH" value="0x912D"/> + <enum name="PACK_COMPRESSED_BLOCK_SIZE" value="0x912E"/> + +</category> + +</OpenGLAPI> + diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index 6f36989bc..be7d9e0ef 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -113,6 +113,7 @@ API_XML = \ ARB_blend_func_extended.xml \ ARB_clear_buffer_object.xml \ ARB_color_buffer_float.xml \ + ARB_compressed_texture_pixel_storage.xml \ ARB_compute_shader.xml \ ARB_copy_buffer.xml \ ARB_debug_output.xml \ diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 0791bfc57..0a486f070 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8276,7 +8276,9 @@ </function> </category> -<!-- ARB extensions #110...#116 --> +<xi:include href="ARB_compressed_texture_pixel_storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + +<!-- ARB extensions #111...#116 --> <xi:include href="ARB_internalformat_query.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> @@ -8310,7 +8312,19 @@ <xi:include href="ARB_ES3_compatibility.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> -<!-- ARB extensions #128...#131 --> +<!-- ARB extension #128 --> + +<category name="GL_ARB_fragment_layer_viewport" number="129"> + <!-- No new functions, types, enums. --> +</category> + +<!-- ARB extensions #130..#131 --> + +<category name="GL_ARB_explicit_uniform_location" number="128"> + <enum name="MAX_UNIFORM_LOCATIONS" count="1" value="0x826E" > + <size name="Get" mode="get"/> + </enum> +</category> <xi:include href="ARB_invalidate_subdata.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> diff --git a/mesalib/src/mesa/Android.libmesa_dricore.mk b/mesalib/src/mesa/Android.libmesa_dricore.mk index 0db5825de..217f6498a 100644 --- a/mesalib/src/mesa/Android.libmesa_dricore.mk +++ b/mesalib/src/mesa/Android.libmesa_dricore.mk @@ -47,10 +47,16 @@ ifeq ($(TARGET_ARCH),x86) endif # x86 endif # MESA_ENABLE_ASM +ifeq ($(ARCH_X86_HAVE_SSE4_1),true) +LOCAL_SRC_FILES += \ + $(SRCDIR)main/streaming-load-memcpy.c +endif + LOCAL_C_INCLUDES := \ $(call intermediates-dir-for STATIC_LIBRARIES,libmesa_program,,) \ $(MESA_TOP)/src/mapi \ - $(MESA_TOP)/src/glsl + $(MESA_TOP)/src/glsl \ + $(MESA_TOP)/src/gallium/auxiliary LOCAL_WHOLE_STATIC_LIBRARIES := \ libmesa_program diff --git a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk index 47f2e151b..e93891f07 100644 --- a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk +++ b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk @@ -56,6 +56,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := libmesa_glsl_utils LOCAL_IS_HOST_MODULE := true +LOCAL_CFLAGS := -D_POSIX_C_SOURCE=199309L LOCAL_C_INCLUDES := \ $(MESA_TOP)/src/glsl \ diff --git a/mesalib/src/mesa/Android.mesa_gen_matypes.mk b/mesalib/src/mesa/Android.mesa_gen_matypes.mk index 6e301f904..5521087c4 100644 --- a/mesalib/src/mesa/Android.mesa_gen_matypes.mk +++ b/mesalib/src/mesa/Android.mesa_gen_matypes.mk @@ -33,6 +33,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := mesa_gen_matypes LOCAL_IS_HOST_MODULE := true +LOCAL_CFLAGS := -D_POSIX_C_SOURCE=199309L LOCAL_C_INCLUDES := \ $(MESA_TOP)/src/mapi \ diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index fec0d2be5..1a2e45320 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -801,7 +801,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) int buf, real_color_buffers = 0; memset(save->ColorDrawBuffers, 0, sizeof(save->ColorDrawBuffers)); - for (buf = 0; buf < MAX_DRAW_BUFFERS; buf++) { + for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { int buf_index = ctx->DrawBuffer->_ColorDrawBufferIndexes[buf]; if (buf_index == -1) continue; @@ -1213,7 +1213,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_BindRenderbuffer(GL_RENDERBUFFER, save->RenderbufferName); if (state & MESA_META_DRAW_BUFFERS) { - _mesa_DrawBuffers(MAX_DRAW_BUFFERS, save->ColorDrawBuffers); + _mesa_DrawBuffers(ctx->Const.MaxDrawBuffers, save->ColorDrawBuffers); } ctx->Meta->SaveStackDepth--; @@ -1569,6 +1569,7 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) _mesa_AttachShader(clear->ShaderProg, vs); _mesa_DeleteShader(vs); _mesa_BindAttribLocation(clear->ShaderProg, 0, "position"); + _mesa_ObjectLabel(GL_PROGRAM, clear->ShaderProg, -1, "meta clear"); _mesa_LinkProgram(clear->ShaderProg); clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, @@ -2613,6 +2614,7 @@ _mesa_meta_setup_texture_coords(GLenum faceTarget, break; default: assert(0); + unreachable(); } coord[3] = (float) (slice / 6); diff --git a/mesalib/src/mesa/drivers/common/meta_blit.c b/mesalib/src/mesa/drivers/common/meta_blit.c index f26ef93c1..bbf0c3c45 100644 --- a/mesalib/src/mesa/drivers/common/meta_blit.c +++ b/mesalib/src/mesa/drivers/common/meta_blit.c @@ -407,7 +407,7 @@ blitframebuffer_texture(struct gl_context *ctx, } } else { GLenum tex_base_format; - int srcW = abs(srcY1 - srcY0); + int srcW = abs(srcX1 - srcX0); int srcH = abs(srcY1 - srcY0); /* Fall back to doing a CopyTexSubImage to get the destination * renderbuffer into a texture. diff --git a/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c b/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c index d12806c3d..4b1718df9 100644 --- a/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c +++ b/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c @@ -43,6 +43,7 @@ #include "main/varray.h" #include "main/viewport.h" #include "drivers/common/meta.h" +#include "program/prog_instruction.h" /** @@ -168,6 +169,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, GLenum faceTarget; GLuint dstLevel; GLuint samplerSave; + GLint swizzle[4]; + GLboolean swizzleSaved = GL_FALSE; if (fallback_required(ctx, target, texObj)) { _mesa_generate_mipmap(ctx, target, texObj); @@ -231,6 +234,13 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); + if (texObj->_Swizzle != SWIZZLE_NOOP) { + static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + memcpy(swizzle, texObj->Swizzle, sizeof(swizzle)); + swizzleSaved = GL_TRUE; + _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzleNoop); + } + /* Silence valgrind warnings about reading uninitialized stack. */ memset(verts, 0, sizeof(verts)); @@ -347,4 +357,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); if (genMipmapSave) _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave); + if (swizzleSaved) + _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle); } diff --git a/mesalib/src/mesa/drivers/dri/Android.mk b/mesalib/src/mesa/drivers/dri/Android.mk index 9adf0b386..e0cf51c58 100644 --- a/mesalib/src/mesa/drivers/dri/Android.mk +++ b/mesalib/src/mesa/drivers/dri/Android.mk @@ -43,6 +43,7 @@ MESA_DRI_C_INCLUDES := \ MESA_DRI_WHOLE_STATIC_LIBRARIES := \ libmesa_glsl \ + libmegadriver_stub \ libmesa_dri_common \ libmesa_dricore diff --git a/mesalib/src/mesa/drivers/dri/common/Android.mk b/mesalib/src/mesa/drivers/dri/common/Android.mk index 0489a32de..a172a0bc6 100644 --- a/mesalib/src/mesa/drivers/dri/common/Android.mk +++ b/mesalib/src/mesa/drivers/dri/common/Android.mk @@ -86,3 +86,20 @@ $(intermediates)/xmlpool/options.h: $$(PRIVATE_SCRIPT) $$(PRIVATE_TEMPLATE_HEADE include $(MESA_COMMON_MK) include $(BUILD_STATIC_LIBRARY) + +# +# Build libmegadriver_stub +# + +include $(CLEAR_VARS) +include $(LOCAL_PATH)/Makefile.sources + +LOCAL_MODULE := libmegadriver_stub +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_C_INCLUDES := \ + $(MESA_DRI_C_INCLUDES) + +LOCAL_SRC_FILES := $(megadriver_stub_FILES) + +include $(MESA_COMMON_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/mesalib/src/mesa/drivers/dri/common/Makefile.am b/mesalib/src/mesa/drivers/dri/common/Makefile.am index c98ccf7b8..7222a96c6 100644 --- a/mesalib/src/mesa/drivers/dri/common/Makefile.am +++ b/mesalib/src/mesa/drivers/dri/common/Makefile.am @@ -42,7 +42,7 @@ libdricommon_la_SOURCES = $(DRI_COMMON_FILES) libdri_test_stubs_la_SOURCES = $(test_stubs_FILES) libdri_test_stubs_la_CFLAGS = $(AM_CFLAGS) -DNO_MAIN -libmegadriver_stub_la_SOURCES = megadriver_stub.c +libmegadriver_stub_la_SOURCES = $(megadriver_stub_FILES) sysconf_DATA = drirc diff --git a/mesalib/src/mesa/drivers/dri/common/Makefile.sources b/mesalib/src/mesa/drivers/dri/common/Makefile.sources index 8469b4950..43b289e90 100644 --- a/mesalib/src/mesa/drivers/dri/common/Makefile.sources +++ b/mesalib/src/mesa/drivers/dri/common/Makefile.sources @@ -14,3 +14,6 @@ mesa_dri_common_INCLUDES := \ test_stubs_FILES := \ dri_test.c + +megadriver_stub_FILES := \ + megadriver_stub.c diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c index 05cbc0f1f..ebeba8883 100644 --- a/mesalib/src/mesa/main/api_arrayelt.c +++ b/mesalib/src/mesa/main/api_arrayelt.c @@ -43,18 +43,21 @@ #include "macros.h" #include "mtypes.h" #include "main/dispatch.h" +#include "varray.h" typedef void (GLAPIENTRY *array_func)( const void * ); typedef struct { - const struct gl_client_array *array; + const struct gl_vertex_attrib_array *array; + const struct gl_vertex_buffer_binding *binding; int offset; } AEarray; typedef void (GLAPIENTRY *attrib_func)( GLuint indx, const void *data ); typedef struct { - const struct gl_client_array *array; + const struct gl_vertex_attrib_array *array; + const struct gl_vertex_buffer_binding *binding; attrib_func func; GLuint index; } AEattrib; @@ -1470,18 +1473,6 @@ check_vbo(AEcontext *actx, struct gl_buffer_object *vbo) } -static inline void -update_derived_client_arrays(struct gl_context *ctx) -{ - struct gl_vertex_array_object *vao = ctx->Array.VAO; - - if (vao->NewArrays) { - _mesa_update_vao_client_arrays(ctx, vao); - vao->NewArrays = 0; - } -} - - /** * Make a list of per-vertex functions to call for each glArrayElement call. * These functions access the array data (i.e. glVertex, glColor, glNormal, @@ -1500,67 +1491,81 @@ _ae_update_state(struct gl_context *ctx) actx->nr_vbos = 0; /* conventional vertex arrays */ - if (vao->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX]; + if (vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } - if (vao->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_EDGEFLAG]; + + if (vao->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_EDGEFLAG]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = _gloffset_EdgeFlagv; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } - if (vao->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_NORMAL]; + + if (vao->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_NORMAL]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } - if (vao->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_COLOR0]; + + if (vao->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_COLOR0]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } - if (vao->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_COLOR1]; + + if (vao->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_COLOR1]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } - if (vao->_VertexAttrib[VERT_ATTRIB_FOG].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_FOG]; + + if (vao->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_FOG]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { - struct gl_client_array *attribArray = - &vao->_VertexAttrib[VERT_ATTRIB_TEX(i)]; + struct gl_vertex_attrib_array *attribArray = + &vao->VertexAttrib[VERT_ATTRIB_TEX(i)]; if (attribArray->Enabled) { /* NOTE: we use generic glVertexAttribNV functions here. * If we ever remove GL_NV_vertex_program this will have to change. */ at->array = attribArray; + at->binding = &vao->VertexBinding[attribArray->VertexBinding]; ASSERT(!at->array->Normalized); at->func = AttribFuncsNV[at->array->Normalized] [at->array->Size-1] [TYPE_IDX(at->array->Type)]; at->index = VERT_ATTRIB_TEX0 + i; - check_vbo(actx, at->array->BufferObj); + check_vbo(actx, at->binding->BufferObj); at++; } } /* generic vertex attribute arrays */ for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { /* skip zero! */ - struct gl_client_array *attribArray = - &vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]; + struct gl_vertex_attrib_array *attribArray = + &vao->VertexAttrib[VERT_ATTRIB_GENERIC(i)]; if (attribArray->Enabled) { GLint intOrNorm; at->array = attribArray; + at->binding = &vao->VertexBinding[attribArray->VertexBinding]; /* Note: we can't grab the _glapi_Dispatch->VertexAttrib1fvNV * function pointer here (for float arrays) since the pointer may * change from one execution of _ae_ArrayElement() to @@ -1578,26 +1583,28 @@ _ae_update_state(struct gl_context *ctx) [TYPE_IDX(at->array->Type)]; at->index = i; - check_vbo(actx, at->array->BufferObj); + check_vbo(actx, at->binding->BufferObj); at++; } } /* finally, vertex position */ - if (vao->_VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) { + if (vao->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) { /* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's * issued as the last (provoking) attribute). */ - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_GENERIC0]; + aa->array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC0]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; assert(aa->array->Size >= 2); /* XXX fix someday? */ aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } - else if (vao->_VertexAttrib[VERT_ATTRIB_POS].Enabled) { - aa->array = &vao->_VertexAttrib[VERT_ATTRIB_POS]; + else if (vao->VertexAttrib[VERT_ATTRIB_POS].Enabled) { + aa->array = &vao->VertexAttrib[VERT_ATTRIB_POS]; + aa->binding = &vao->VertexBinding[aa->array->VertexBinding]; aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; - check_vbo(actx, aa->array->BufferObj); + check_vbo(actx, aa->binding->BufferObj); aa++; } @@ -1625,8 +1632,6 @@ _ae_map_vbos(struct gl_context *ctx) if (actx->mapped_vbos) return; - update_derived_client_arrays(ctx); - if (actx->NewState) _ae_update_state(ctx); @@ -1679,8 +1684,6 @@ _ae_ArrayElement(GLint elt) const struct _glapi_table * const disp = GET_DISPATCH(); GLboolean do_map; - update_derived_client_arrays(ctx); - /* If PrimitiveRestart is enabled and the index is the RestartIndex * then we call PrimitiveRestartNV and return. */ @@ -1703,18 +1706,18 @@ _ae_ArrayElement(GLint elt) /* emit generic attribute elements */ for (at = actx->attribs; at->func; at++) { const GLubyte *src - = ADD_POINTERS(at->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, - at->array->Ptr) - + elt * at->array->StrideB; + = ADD_POINTERS(at->binding->BufferObj->Mappings[MAP_INTERNAL].Pointer, + _mesa_vertex_attrib_address(at->array, at->binding)) + + elt * at->binding->Stride; at->func(at->index, src); } /* emit conventional arrays elements */ for (aa = actx->arrays; aa->offset != -1 ; aa++) { const GLubyte *src - = ADD_POINTERS(aa->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, - aa->array->Ptr) - + elt * aa->array->StrideB; + = ADD_POINTERS(aa->binding->BufferObj->Mappings[MAP_INTERNAL].Pointer, + _mesa_vertex_attrib_address(aa->array, aa->binding)) + + elt * aa->binding->Stride; CALL_by_offset(disp, (array_func), aa->offset, ((const void *) src)); } diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c index 9df1f5e09..cf93418d1 100644 --- a/mesalib/src/mesa/main/clear.c +++ b/mesalib/src/mesa/main/clear.c @@ -180,11 +180,6 @@ _mesa_Clear( GLbitfield mask ) return; } - if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 || - ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax || - ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax) - return; - if (ctx->RasterDiscard) return; diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 8eb426d59..244e63ede 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -396,6 +396,8 @@ one_time_init( struct gl_context *ctx ) assert( sizeof(GLint) == 4 ); assert( sizeof(GLuint) == 4 ); + _mesa_one_time_init_extension_overrides(); + _mesa_get_cpu_features(); for (i = 0; i < 256; i++) { @@ -610,6 +612,10 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.MaxUniformBlockSize = 16384; ctx->Const.UniformBufferOffsetAlignment = 1; + /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */ + ctx->Const.MaxUserAssignableUniformLocations = + 4 * MESA_SHADER_STAGES * MAX_UNIFORMS; + for (i = 0; i < MESA_SHADER_STAGES; i++) init_program_limits(ctx, i, &ctx->Const.Program[i]); diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index c2ff7e3b7..25e3dab4f 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -37,6 +37,11 @@ #include "macros.h" #include "mtypes.h" +struct gl_extensions _mesa_extension_override_enables; +struct gl_extensions _mesa_extension_override_disables; +static char *extra_extensions = NULL; +static char *cant_disable_extensions = NULL; + enum { DISABLE = 0, GLL = 1 << API_OPENGL_COMPAT, /* GL Legacy / Compatibility */ @@ -86,6 +91,7 @@ static const struct extension extension_table[] = { { "GL_ARB_buffer_storage", o(ARB_buffer_storage), GL, 2013 }, { "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, + { "GL_ARB_compressed_texture_pixel_storage", o(dummy_true), GL, 2011 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, { "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 }, @@ -99,7 +105,9 @@ static const struct extension extension_table[] = { { "GL_ARB_draw_indirect", o(ARB_draw_indirect), GLC, 2010 }, { "GL_ARB_draw_instanced", o(ARB_draw_instanced), GL, 2008 }, { "GL_ARB_explicit_attrib_location", o(ARB_explicit_attrib_location), GL, 2009 }, + { "GL_ARB_explicit_uniform_location", o(ARB_explicit_uniform_location), GL, 2012 }, { "GL_ARB_fragment_coord_conventions", o(ARB_fragment_coord_conventions), GL, 2009 }, + { "GL_ARB_fragment_layer_viewport", o(ARB_fragment_layer_viewport), GLC, 2012 }, { "GL_ARB_fragment_program", o(ARB_fragment_program), GLL, 2002 }, { "GL_ARB_fragment_program_shadow", o(ARB_fragment_program_shadow), GLL, 2003 }, { "GL_ARB_fragment_shader", o(ARB_fragment_shader), GL, 2002 }, @@ -388,6 +396,31 @@ name_to_offset(const char* name) return 0; } +/** + * Overrides extensions in \c ctx based on the values in + * _mesa_extension_override_enables and _mesa_extension_override_disables. + */ +static void +override_extensions_in_context(struct gl_context *ctx) +{ + const struct extension *i; + const GLboolean *enables = + (GLboolean*) &_mesa_extension_override_enables; + const GLboolean *disables = + (GLboolean*) &_mesa_extension_override_disables; + GLboolean *ctx_ext = (GLboolean*)&ctx->Extensions; + + for (i = extension_table; i->name != 0; ++i) { + size_t offset = i->offset; + assert(!enables[offset] || !disables[offset]); + if (enables[offset]) { + ctx_ext[offset] = 1; + } else if (disables[offset]) { + ctx_ext[offset] = 0; + } + } +} + /** * Enable all extensions suitable for a software-only renderer. @@ -473,34 +506,19 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) /** * Either enable or disable the named extension. - * \return GL_TRUE for success, GL_FALSE if invalid extension name + * \return offset of extensions withint `ext' or 0 if extension is not known */ -static GLboolean -set_extension( struct gl_context *ctx, const char *name, GLboolean state ) +static size_t +set_extension(struct gl_extensions *ext, const char *name, GLboolean state) { size_t offset; - if (ctx->Extensions.String) { - /* The string was already queried - can't change it now! */ - _mesa_problem(ctx, "Trying to enable/disable extension after " - "glGetString(GL_EXTENSIONS): %s", name); - return GL_FALSE; - } - offset = name_to_offset(name); - if (offset == 0) { - _mesa_problem(ctx, "Trying to enable/disable unknown extension %s", - name); - return GL_FALSE; - } else if (offset == o(dummy_true) && state == GL_FALSE) { - _mesa_problem(ctx, "Trying to disable a permanently enabled extension: " - "%s", name); - return GL_FALSE; - } else { - GLboolean *base = (GLboolean *) &ctx->Extensions; - base[offset] = state; - return GL_TRUE; + if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) { + ((GLboolean *) ext)[offset] = state; } + + return offset; } /** @@ -513,32 +531,80 @@ set_extension( struct gl_context *ctx, const char *name, GLboolean state ) * - Enable recognized extension names that are not prefixed. * - Collect unrecognized extension names in a new string. * + * \c MESA_EXTENSION_OVERRIDE was previously parsed during + * _mesa_one_time_init_extension_overrides. We just use the results of that + * parsing in this function. + * * \return Space-separated list of unrecognized extension names (which must * be freed). Does not return \c NULL. */ static char * get_extension_override( struct gl_context *ctx ) { + override_extensions_in_context(ctx); + + if (cant_disable_extensions != NULL) { + _mesa_problem(ctx, + "Trying to disable permanently enabled extensions: %s", + cant_disable_extensions); + } + + if (extra_extensions == NULL) { + return calloc(1, sizeof(char)); + } else { + _mesa_problem(ctx, "Trying to enable unknown extensions: %s", + extra_extensions); + return strdup(extra_extensions); + } +} + + +/** + * \brief Free extra_extensions and cant_disable_extensions strings + * + * These strings are allocated early during the first context creation by + * _mesa_one_time_init_extension_overrides. + */ +static void +free_unknown_extensions_strings(void) +{ + free(extra_extensions); + free(cant_disable_extensions); +} + + +/** + * \brief Initialize extension override tables. + * + * This should be called one time early during first context initialization. + */ +void +_mesa_one_time_init_extension_overrides(void) +{ const char *env_const = _mesa_getenv("MESA_EXTENSION_OVERRIDE"); char *env; char *ext; - char *extra_exts; int len; + size_t offset; + + atexit(free_unknown_extensions_strings); + + memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions)); + memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions)); if (env_const == NULL) { - /* Return the empty string rather than NULL. This simplifies the logic - * of client functions. */ - return calloc(4, sizeof(char)); + return; } /* extra_exts: List of unrecognized extensions. */ - extra_exts = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char)); + extra_extensions = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char)); + cant_disable_extensions = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char)); /* Copy env_const because strtok() is destructive. */ env = strdup(env_const); for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) { int enable; - int recognized; + bool recognized; switch (ext[0]) { case '+': enable = 1; @@ -552,21 +618,43 @@ get_extension_override( struct gl_context *ctx ) enable = 1; break; } - recognized = set_extension(ctx, ext, enable); + + offset = set_extension(&_mesa_extension_override_enables, ext, enable); + if (offset != 0 && (offset != o(dummy_true) || enable != GL_FALSE)) { + ((GLboolean *) &_mesa_extension_override_disables)[offset] = !enable; + recognized = true; + } else { + recognized = false; + } + if (!recognized) { - strcat(extra_exts, ext); - strcat(extra_exts, " "); + if (enable) { + strcat(extra_extensions, ext); + strcat(extra_extensions, " "); + } else if (offset == o(dummy_true)) { + strcat(cant_disable_extensions, ext); + strcat(cant_disable_extensions, " "); + } } } free(env); - /* Remove trailing space. */ - len = strlen(extra_exts); - if (len > 0 && extra_exts[len - 1] == ' ') - extra_exts[len - 1] = '\0'; - - return extra_exts; + /* Remove trailing space, and free if unused. */ + len = strlen(extra_extensions); + if (len == 0) { + free(extra_extensions); + extra_extensions = NULL; + } else if (extra_extensions[len - 1] == ' ') { + extra_extensions[len - 1] = '\0'; + } + len = strlen(cant_disable_extensions); + if (len == 0) { + free(cant_disable_extensions); + cant_disable_extensions = NULL; + } else if (cant_disable_extensions[len - 1] == ' ') { + cant_disable_extensions[len - 1] = '\0'; + } } diff --git a/mesalib/src/mesa/main/extensions.h b/mesalib/src/mesa/main/extensions.h index a8cc2a41e..3a404d2e0 100644 --- a/mesalib/src/mesa/main/extensions.h +++ b/mesalib/src/mesa/main/extensions.h @@ -39,9 +39,12 @@ #include "glheader.h" struct gl_context; +struct gl_extensions; extern void _mesa_enable_sw_extensions(struct gl_context *ctx); +extern void _mesa_one_time_init_extension_overrides(void); + extern void _mesa_init_extensions(struct gl_context *ctx); extern GLubyte *_mesa_make_extension_string(struct gl_context *ctx); @@ -52,4 +55,7 @@ _mesa_get_extension_count(struct gl_context *ctx); extern const GLubyte * _mesa_get_enabled_extension(struct gl_context *ctx, GLuint index); +extern struct gl_extensions _mesa_extension_override_enables; +extern struct gl_extensions _mesa_extension_override_disables; + #endif diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 8c360970f..211583738 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -877,14 +877,15 @@ emit_texenv(texenv_fragment_program *p, GLuint unit) shift = new(p->mem_ctx) ir_constant((float)(1 << rgb_shift)); } else { - float const_data[4] = { - float(1 << rgb_shift), - float(1 << rgb_shift), - float(1 << rgb_shift), - float(1 << alpha_shift) - }; - shift = new(p->mem_ctx) ir_constant(glsl_type::vec4_type, - (ir_constant_data *)const_data); + ir_constant_data const_data; + + const_data.f[0] = float(1 << rgb_shift); + const_data.f[1] = float(1 << rgb_shift); + const_data.f[2] = float(1 << rgb_shift); + const_data.f[3] = float(1 << alpha_shift); + + shift = new(p->mem_ctx) ir_constant(glsl_type::vec4_type, + &const_data); } return saturate(mul(deref, shift)); diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 9b56edb74..0e2d8f687 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -278,11 +278,6 @@ static const int extra_flush_current[] = { EXTRA_END }; -static const int extra_EXT_texture_integer[] = { - EXT(EXT_texture_integer), - EXTRA_END -}; - static const int extra_EXT_texture_integer_and_new_buffers[] = { EXT(EXT_texture_integer), EXTRA_NEW_BUFFERS, @@ -395,6 +390,7 @@ EXTRA_EXT(ARB_compute_shader); EXTRA_EXT(ARB_gpu_shader5); EXTRA_EXT2(ARB_transform_feedback3, ARB_gpu_shader5); EXTRA_EXT(INTEL_performance_query); +EXTRA_EXT(ARB_explicit_uniform_location); static const int extra_ARB_color_buffer_float_or_glcore[] = { diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index c7a6e02af..d45962d95 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -480,6 +480,7 @@ descriptor=[ [ "MAX_LIST_NESTING", "CONST(MAX_LIST_NESTING), NO_EXTRA" ], [ "MAX_NAME_STACK_DEPTH", "CONST(MAX_NAME_STACK_DEPTH), NO_EXTRA" ], [ "MAX_PIXEL_MAP_TABLE", "CONST(MAX_PIXEL_MAP_TABLE), NO_EXTRA" ], + [ "MAX_UNIFORM_LOCATIONS", "CONTEXT_INT(Const.MaxUserAssignableUniformLocations), extra_ARB_explicit_uniform_location" ], [ "NAME_STACK_DEPTH", "CONTEXT_INT(Select.NameStackDepth), NO_EXTRA" ], [ "PACK_LSB_FIRST", "CONTEXT_BOOL(Pack.LsbFirst), NO_EXTRA" ], [ "PACK_SWAP_BYTES", "CONTEXT_BOOL(Pack.SwapBytes), NO_EXTRA" ], @@ -541,6 +542,16 @@ descriptor=[ [ "ARRAY_ELEMENT_LOCK_FIRST_EXT", "CONTEXT_INT(Array.LockFirst), NO_EXTRA" ], [ "ARRAY_ELEMENT_LOCK_COUNT_EXT", "CONTEXT_INT(Array.LockCount), NO_EXTRA" ], +# GL_ARB_compressed_texture_pixel_storage + [ "UNPACK_COMPRESSED_BLOCK_WIDTH", "CONTEXT_INT(Unpack.CompressedBlockWidth), NO_EXTRA" ], + [ "UNPACK_COMPRESSED_BLOCK_HEIGHT", "CONTEXT_INT(Unpack.CompressedBlockHeight), NO_EXTRA" ], + [ "UNPACK_COMPRESSED_BLOCK_DEPTH", "CONTEXT_INT(Unpack.CompressedBlockDepth), NO_EXTRA" ], + [ "UNPACK_COMPRESSED_BLOCK_SIZE", "CONTEXT_INT(Unpack.CompressedBlockSize), NO_EXTRA" ], + [ "PACK_COMPRESSED_BLOCK_WIDTH", "CONTEXT_INT(Pack.CompressedBlockWidth), NO_EXTRA" ], + [ "PACK_COMPRESSED_BLOCK_HEIGHT", "CONTEXT_INT(Pack.CompressedBlockHeight), NO_EXTRA" ], + [ "PACK_COMPRESSED_BLOCK_DEPTH", "CONTEXT_INT(Pack.CompressedBlockDepth), NO_EXTRA" ], + [ "PACK_COMPRESSED_BLOCK_SIZE", "CONTEXT_INT(Pack.CompressedBlockSize), NO_EXTRA" ], + # GL_ARB_transpose_matrix [ "TRANSPOSE_MODELVIEW_MATRIX_ARB", "CONTEXT_MATRIX_T(ModelviewMatrixStack), NO_EXTRA" ], [ "TRANSPOSE_PROJECTION_MATRIX_ARB", "CONTEXT_MATRIX_T(ProjectionMatrixStack.Top), NO_EXTRA" ], diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 9bb341cc0..aee336e12 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -458,36 +458,6 @@ _mesa_is_enum_format_integer(GLenum format) } -/** - * Test if the given type is an integer (non-normalized) format. - */ -GLboolean -_mesa_is_type_integer(GLenum type) -{ - switch (type) { - case GL_INT: - case GL_UNSIGNED_INT: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_BYTE: - case GL_UNSIGNED_BYTE: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given format or type is an integer (non-normalized) format. - */ -extern GLboolean -_mesa_is_enum_format_or_type_integer(GLenum format, GLenum type) -{ - return _mesa_is_enum_format_integer(format) || _mesa_is_type_integer(type); -} - - GLboolean _mesa_is_type_unsigned(GLenum type) { diff --git a/mesalib/src/mesa/main/glformats.h b/mesalib/src/mesa/main/glformats.h index af1089931..ccbce2dab 100644 --- a/mesalib/src/mesa/main/glformats.h +++ b/mesalib/src/mesa/main/glformats.h @@ -54,9 +54,6 @@ extern GLint _mesa_bytes_per_vertex_attrib(GLint comps, GLenum type); extern GLboolean -_mesa_is_type_integer(GLenum type); - -extern GLboolean _mesa_is_type_unsigned(GLenum type); extern GLboolean @@ -69,9 +66,6 @@ extern GLboolean _mesa_is_enum_format_signed_int(GLenum format); extern GLboolean -_mesa_is_enum_format_or_type_integer(GLenum format, GLenum type); - -extern GLboolean _mesa_is_color_format(GLenum format); extern GLboolean diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 917d071a2..4762d9616 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1502,6 +1502,10 @@ struct gl_pixelstore_attrib GLboolean SwapBytes; GLboolean LsbFirst; GLboolean Invert; /**< GL_MESA_pack_invert */ + GLint CompressedBlockWidth; /**< GL_ARB_compressed_texture_pixel_storage */ + GLint CompressedBlockHeight; + GLint CompressedBlockDepth; + GLint CompressedBlockSize; struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */ }; @@ -2172,7 +2176,7 @@ struct gl_geometry_program GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ - GLboolean UsesEndPrimitive; + bool UsesEndPrimitive; }; @@ -2675,7 +2679,7 @@ struct gl_shader_program GLboolean UsesClipDistance; GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or 0 if not present. */ - GLboolean UsesEndPrimitive; + bool UsesEndPrimitive; } Geom; /** Vertex shader state */ @@ -3319,6 +3323,11 @@ struct gl_constants GLuint UniformBufferOffsetAlignment; /** @} */ + /** + * GL_ARB_explicit_uniform_location + */ + GLuint MaxUserAssignableUniformLocations; + /** GL_ARB_geometry_shader4 */ GLuint MaxGeometryOutputVertices; GLuint MaxGeometryTotalOutputComponents; @@ -3511,11 +3520,13 @@ struct gl_extensions GLboolean ARB_draw_indirect; GLboolean ARB_draw_instanced; GLboolean ARB_fragment_coord_conventions; + GLboolean ARB_fragment_layer_viewport; GLboolean ARB_fragment_program; GLboolean ARB_fragment_program_shadow; GLboolean ARB_fragment_shader; GLboolean ARB_framebuffer_object; GLboolean ARB_explicit_attrib_location; + GLboolean ARB_explicit_uniform_location; GLboolean ARB_geometry_shader4; GLboolean ARB_gpu_shader5; GLboolean ARB_half_float_vertex; diff --git a/mesalib/src/mesa/main/performance_monitor.c b/mesalib/src/mesa/main/performance_monitor.c index 9d1a6b4d8..c26eda4c6 100644 --- a/mesalib/src/mesa/main/performance_monitor.c +++ b/mesalib/src/mesa/main/performance_monitor.c @@ -164,19 +164,6 @@ counterid_to_index(GLuint counterid) return counterid - 1; } -static inline GLuint -index_to_counterid(GLuint index) -{ - return index + 1; -} - -static inline bool -counterid_valid(const struct gl_perf_monitor_group *group_obj, - GLuint counterid) -{ - return get_counter(group_obj, counterid_to_index(counterid)) != NULL; -} - /*****************************************************************************/ void GLAPIENTRY diff --git a/mesalib/src/mesa/main/pixelstore.c b/mesalib/src/mesa/main/pixelstore.c index 0f55bc304..05f6583a4 100644 --- a/mesalib/src/mesa/main/pixelstore.c +++ b/mesalib/src/mesa/main/pixelstore.c @@ -45,176 +45,165 @@ _mesa_PixelStorei( GLenum pname, GLint param ) case GL_PACK_SWAP_BYTES: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - if (param == (GLint)ctx->Pack.SwapBytes) - return; ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE; - break; + break; case GL_PACK_LSB_FIRST: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - if (param == (GLint)ctx->Pack.LsbFirst) - return; ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE; - break; + break; case GL_PACK_ROW_LENGTH: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Pack.RowLength == param) - return; - ctx->Pack.RowLength = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Pack.RowLength = param; + break; case GL_PACK_IMAGE_HEIGHT: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Pack.ImageHeight == param) - return; - ctx->Pack.ImageHeight = param; + if (param<0) + goto invalid_value_error; + ctx->Pack.ImageHeight = param; break; case GL_PACK_SKIP_PIXELS: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Pack.SkipPixels == param) - return; - ctx->Pack.SkipPixels = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Pack.SkipPixels = param; + break; case GL_PACK_SKIP_ROWS: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Pack.SkipRows == param) - return; - ctx->Pack.SkipRows = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Pack.SkipRows = param; + break; case GL_PACK_SKIP_IMAGES: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Pack.SkipImages == param) - return; - ctx->Pack.SkipImages = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Pack.SkipImages = param; + break; case GL_PACK_ALIGNMENT: - if (param!=1 && param!=2 && param!=4 && param!=8) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Pack.Alignment == param) - return; - ctx->Pack.Alignment = param; - break; + if (param!=1 && param!=2 && param!=4 && param!=8) + goto invalid_value_error; + ctx->Pack.Alignment = param; + break; case GL_PACK_INVERT_MESA: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.MESA_pack_invert) goto invalid_enum_error; - if (!ctx->Extensions.MESA_pack_invert) { - _mesa_error( ctx, GL_INVALID_ENUM, "glPixelstore(pname)" ); - return; - } - if (ctx->Pack.Invert == param) - return; ctx->Pack.Invert = param; break; + case GL_PACK_COMPRESSED_BLOCK_WIDTH: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Pack.CompressedBlockWidth = param; + break; + case GL_PACK_COMPRESSED_BLOCK_HEIGHT: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Pack.CompressedBlockHeight = param; + break; + case GL_PACK_COMPRESSED_BLOCK_DEPTH: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Pack.CompressedBlockDepth = param; + break; + case GL_PACK_COMPRESSED_BLOCK_SIZE: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Pack.CompressedBlockSize = param; + break; case GL_UNPACK_SWAP_BYTES: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - if (param == (GLint)ctx->Unpack.SwapBytes) - return; - if ((GLint)ctx->Unpack.SwapBytes == param) - return; - ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; + ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; break; case GL_UNPACK_LSB_FIRST: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - if (param == (GLint)ctx->Unpack.LsbFirst) - return; - if ((GLint)ctx->Unpack.LsbFirst == param) - return; - ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; - break; + ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; + break; case GL_UNPACK_ROW_LENGTH: if (ctx->API == API_OPENGLES) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Unpack.RowLength == param) - return; - ctx->Unpack.RowLength = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Unpack.RowLength = param; + break; case GL_UNPACK_IMAGE_HEIGHT: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Unpack.ImageHeight == param) - return; - - ctx->Unpack.ImageHeight = param; + if (param<0) + goto invalid_value_error; + ctx->Unpack.ImageHeight = param; break; case GL_UNPACK_SKIP_PIXELS: if (ctx->API == API_OPENGLES) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Unpack.SkipPixels == param) - return; - ctx->Unpack.SkipPixels = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Unpack.SkipPixels = param; + break; case GL_UNPACK_SKIP_ROWS: if (ctx->API == API_OPENGLES) goto invalid_enum_error; - if (param<0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Unpack.SkipRows == param) - return; - ctx->Unpack.SkipRows = param; - break; + if (param<0) + goto invalid_value_error; + ctx->Unpack.SkipRows = param; + break; case GL_UNPACK_SKIP_IMAGES: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; - if (param < 0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); - return; - } - if (ctx->Unpack.SkipImages == param) - return; - ctx->Unpack.SkipImages = param; - break; + if (param < 0) + goto invalid_value_error; + ctx->Unpack.SkipImages = param; + break; case GL_UNPACK_ALIGNMENT: - if (param!=1 && param!=2 && param!=4 && param!=8) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore" ); - return; - } - if (ctx->Unpack.Alignment == param) - return; - ctx->Unpack.Alignment = param; - break; + if (param!=1 && param!=2 && param!=4 && param!=8) + goto invalid_value_error; + ctx->Unpack.Alignment = param; + break; + case GL_UNPACK_COMPRESSED_BLOCK_WIDTH: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Unpack.CompressedBlockWidth = param; + break; + case GL_UNPACK_COMPRESSED_BLOCK_HEIGHT: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Unpack.CompressedBlockHeight = param; + break; + case GL_UNPACK_COMPRESSED_BLOCK_DEPTH: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Unpack.CompressedBlockDepth = param; + break; + case GL_UNPACK_COMPRESSED_BLOCK_SIZE: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + if (param<0) + goto invalid_value_error; + ctx->Unpack.CompressedBlockSize = param; + break; default: goto invalid_enum_error; } @@ -224,6 +213,10 @@ _mesa_PixelStorei( GLenum pname, GLint param ) invalid_enum_error: _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" ); return; + +invalid_value_error: + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; } @@ -251,6 +244,10 @@ _mesa_init_pixelstore( struct gl_context *ctx ) ctx->Pack.SwapBytes = GL_FALSE; ctx->Pack.LsbFirst = GL_FALSE; ctx->Pack.Invert = GL_FALSE; + ctx->Pack.CompressedBlockWidth = 0; + ctx->Pack.CompressedBlockHeight = 0; + ctx->Pack.CompressedBlockDepth = 0; + ctx->Pack.CompressedBlockSize = 0; _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, ctx->Shared->NullBufferObj); ctx->Unpack.Alignment = 4; @@ -262,6 +259,10 @@ _mesa_init_pixelstore( struct gl_context *ctx ) ctx->Unpack.SwapBytes = GL_FALSE; ctx->Unpack.LsbFirst = GL_FALSE; ctx->Unpack.Invert = GL_FALSE; + ctx->Unpack.CompressedBlockWidth = 0; + ctx->Unpack.CompressedBlockHeight = 0; + ctx->Unpack.CompressedBlockDepth = 0; + ctx->Unpack.CompressedBlockSize = 0; _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, ctx->Shared->NullBufferObj); diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 28739daeb..2ec2444da 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1392,7 +1392,7 @@ _mesa_LinkProgram(GLhandleARB programObj) static GLcharARB * read_shader(const char *fname) { - const int max = 50*1000; + int shader_size = 0; FILE *f = fopen(fname, "r"); GLcharARB *buffer, *shader; int len; @@ -1401,8 +1401,19 @@ read_shader(const char *fname) return NULL; } - buffer = malloc(max); - len = fread(buffer, 1, max, f); + /* allocate enough room for the entire shader */ + fseek(f, 0, SEEK_END); + shader_size = ftell(f); + rewind(f); + assert(shader_size); + + /* add one for terminating zero */ + shader_size++; + + buffer = malloc(shader_size); + assert(buffer); + + len = fread(buffer, 1, shader_size, f); buffer[len] = 0; fclose(f); diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index b0f0bfa91..c6e852c87 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -248,6 +248,7 @@ _mesa_init_shader_program(struct gl_context *ctx, struct gl_shader_program *prog prog->Geom.VerticesOut = 0; prog->Geom.InputType = GL_TRIANGLES; prog->Geom.OutputType = GL_TRIANGLE_STRIP; + prog->Geom.UsesEndPrimitive = false; prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS; diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 1ac707d13..8c0d3a18e 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -43,6 +43,7 @@ #include "texcompress.h" #include "texgetimage.h" #include "teximage.h" +#include "texstore.h" @@ -686,56 +687,62 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, struct gl_texture_image *texImage, GLvoid *img) { - const GLuint row_stride = - _mesa_format_row_stride(texImage->TexFormat, texImage->Width); - GLuint i; - GLubyte *src; - GLint srcRowStride; + const GLuint dimensions = + _mesa_get_texture_dimensions(texImage->TexObject->Target); + struct compressed_pixelstore store; + GLuint i, slice; + GLubyte *dest; + + _mesa_compute_compressed_pixelstore(dimensions, texImage, + texImage->Width, texImage->Height, + texImage->Depth, + &ctx->Pack, + &store); if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack texture image into a PBO */ - GLubyte *buf = (GLubyte *) + dest = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, MAP_INTERNAL); - if (!buf) { + if (!dest) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage(map PBO failed)"); return; } - img = ADD_POINTERS(buf, img); + dest = ADD_POINTERS(dest, img); + } else { + dest = img; } - /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - 0, 0, texImage->Width, texImage->Height, - GL_MAP_READ_BIT, &src, &srcRowStride); + dest += store.SkipBytes; - if (src) { - /* no pixelstore or pixel transfer, but respect stride */ + for (slice = 0; slice < store.CopySlices; slice++) { + GLint srcRowStride; + GLubyte *src; - if (row_stride == srcRowStride) { - const GLuint size = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - texImage->Height, - texImage->Depth); - memcpy(img, src, size); - } - else { - GLuint bw, bh; - _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); - for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) { - memcpy((GLubyte *)img + i * row_stride, - (GLubyte *)src + i * srcRowStride, - row_stride); + /* map src texture buffer */ + ctx->Driver.MapTextureImage(ctx, texImage, 0, + 0, 0, texImage->Width, texImage->Height, + GL_MAP_READ_BIT, &src, &srcRowStride); + + if (src) { + + for (i = 0; i < store.CopyRowsPerSlice; i++) { + memcpy(dest, src, store.CopyBytesPerRow); + dest += store.TotalBytesPerRow; + src += srcRowStride; } - } - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); + ctx->Driver.UnmapTextureImage(ctx, texImage, 0); + + /* Advance to next slice */ + dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice); + + } else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); + } } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { @@ -963,7 +970,7 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLint maxLevels = _mesa_max_texture_levels(ctx, target); - GLuint compressedSize; + GLuint compressedSize, dimensions; if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", @@ -1004,6 +1011,14 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, texImage->Height, texImage->Depth); + /* Check for invalid pixel storage modes */ + dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); + if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions, + &ctx->Pack, + "glGetCompressedTexImageARB")) { + return GL_TRUE; + } + if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ if (clientMemSize < (GLsizei) compressedSize) { diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 845ba8014..cab29c35d 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -2242,6 +2242,36 @@ texture_error_check( struct gl_context *ctx, } +bool +_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx, + GLint dimensions, + struct gl_pixelstore_attrib *packing, + const char *caller) +{ + if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize) + return true; + + if (packing->CompressedBlockWidth && packing->SkipPixels % packing->CompressedBlockWidth) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(skip-pixels %% block-width)", caller); + return false; + } + + if (dimensions > 1 && packing->CompressedBlockHeight && packing->SkipRows % packing->CompressedBlockHeight) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(skip-rows %% block-height)", caller); + return false; + } + + if (dimensions > 2 && packing->CompressedBlockDepth && packing->SkipImages % packing->CompressedBlockDepth) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(skip-images %% block-depth)", caller); + return false; + } + + return true; +} + /** * Error checking for glCompressedTexImage[123]D(). * Note that the width, height and depth values are not fully error checked @@ -2343,6 +2373,13 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, goto error; } + /* Check for invalid pixel storage modes */ + if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions, + &ctx->Unpack, + "glCompressedTexImage")) { + return GL_FALSE; + } + /* check image size in bytes */ if (expectedSize != imageSize) { /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] @@ -3844,7 +3881,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, } if (!targetOK) { - _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target)", + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexSubImage%uD(target)", dims); return GL_TRUE; } @@ -3857,14 +3894,22 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, } if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage%uD(level=%d)", + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage%uD(level=%d)", dims, level); return GL_TRUE; } + /* Check for invalid pixel storage modes */ + if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dims, + &ctx->Unpack, + "glCompressedTexSubImage")) { + return GL_FALSE; + } + + expectedSize = compressed_tex_size(width, height, depth, format); if (expectedSize != imageSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage%uD(size=%d)", + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage%uD(size=%d)", dims, imageSize); return GL_TRUE; } diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 51d94d17e..dd1504b40 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -326,6 +326,12 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +bool +_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx, + GLint dimensions, + struct gl_pixelstore_attrib *packing, + const char *caller); + /*@}*/ #ifdef __cplusplus diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 764214669..cb81f3fde 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4195,6 +4195,61 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, } +void +_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage, + GLsizei width, GLsizei height, GLsizei depth, + const struct gl_pixelstore_attrib *packing, + struct compressed_pixelstore *store) +{ + GLuint bw, bh; + const mesa_format texFormat = texImage->TexFormat; + + _mesa_get_format_block_size(texFormat, &bw, &bh); + + store->SkipBytes = 0; + store->TotalBytesPerRow = store->CopyBytesPerRow = + _mesa_format_row_stride(texFormat, width); + store->TotalRowsPerSlice = store->CopyRowsPerSlice = + (height + bh - 1) / bh; + store->CopySlices = depth; + + if (packing->CompressedBlockWidth && + packing->CompressedBlockSize) { + + bw = packing->CompressedBlockWidth; + + if (packing->RowLength) { + store->TotalBytesPerRow = packing->CompressedBlockSize * + (packing->RowLength + bw - 1) / bw; + } + + store->SkipBytes += packing->SkipPixels * packing->CompressedBlockSize / bw; + } + + if (dims > 1 && packing->CompressedBlockHeight && + packing->CompressedBlockSize) { + + bh = packing->CompressedBlockHeight; + + store->SkipBytes += packing->SkipRows * store->TotalBytesPerRow / bh; + store->CopyRowsPerSlice = (height + bh - 1) / bh; /* rows in blocks */ + + if (packing->ImageHeight) { + store->TotalRowsPerSlice = (packing->ImageHeight + bh - 1) / bh; + } + } + + if (dims > 2 && packing->CompressedBlockDepth && + packing->CompressedBlockSize) { + + int bd = packing->CompressedBlockDepth; + + store->SkipBytes += packing->SkipImages * store->TotalBytesPerRow * + store->TotalRowsPerSlice / bd; + } +} + + /** * Fallback for Driver.CompressedTexSubImage() */ @@ -4206,20 +4261,19 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, GLenum format, GLsizei imageSize, const GLvoid *data) { - GLint bytesPerRow, dstRowStride, srcRowStride; - GLint i, rows; + struct compressed_pixelstore store; + GLint dstRowStride; + GLint i, slice; GLubyte *dstMap; const GLubyte *src; - const mesa_format texFormat = texImage->TexFormat; - GLuint bw, bh; - GLint slice; if (dims == 1) { _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call"); return; } - _mesa_get_format_block_size(texFormat, &bw, &bh); + _mesa_compute_compressed_pixelstore(dims, texImage, width, height, depth, + &ctx->Unpack, &store); /* get pointer to src pixels (may be in a pbo which we'll map here) */ data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data, @@ -4228,10 +4282,9 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, if (!data) return; - srcRowStride = _mesa_format_row_stride(texFormat, width); - src = (const GLubyte *) data; + src = (const GLubyte *) data + store.SkipBytes; - for (slice = 0; slice < depth; slice++) { + for (slice = 0; slice < store.CopySlices; slice++) { /* Map dest texture buffer */ ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, xoffset, yoffset, width, height, @@ -4239,17 +4292,18 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, &dstMap, &dstRowStride); if (dstMap) { - bytesPerRow = srcRowStride; /* bytes per row of blocks */ - rows = (height + bh - 1) / bh; /* rows in blocks */ /* copy rows of blocks */ - for (i = 0; i < rows; i++) { - memcpy(dstMap, src, bytesPerRow); + for (i = 0; i < store.CopyRowsPerSlice; i++) { + memcpy(dstMap, src, store.CopyBytesPerRow); dstMap += dstRowStride; - src += srcRowStride; + src += store.TotalBytesPerRow; } ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); + + /* advance to next slice */ + src += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD", diff --git a/mesalib/src/mesa/main/texstore.h b/mesalib/src/mesa/main/texstore.h index 490f9f5e0..c4cfffde6 100644 --- a/mesalib/src/mesa/main/texstore.h +++ b/mesalib/src/mesa/main/texstore.h @@ -132,4 +132,21 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, GLsizei imageSize, const GLvoid *data); +struct compressed_pixelstore { + int SkipBytes; + int CopyBytesPerRow; + int CopyRowsPerSlice; + int TotalBytesPerRow; + int TotalRowsPerSlice; + int CopySlices; +}; + + +extern void +_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage, + GLsizei width, GLsizei height, GLsizei depth, + const struct gl_pixelstore_attrib *packing, + struct compressed_pixelstore *store); + + #endif diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 5f1af0873..480bc6f16 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -253,6 +253,21 @@ validate_uniform_parameters(struct gl_context *ctx, return false; } + /* If the driver storage pointer in remap table is -1, we ignore silently. + * + * GL_ARB_explicit_uniform_location spec says: + * "What happens if Uniform* is called with an explicitly defined + * uniform location, but that uniform is deemed inactive by the + * linker? + * + * RESOLVED: The call is ignored for inactive uniform variables and + * no error is generated." + * + */ + if (shProg->UniformRemapTable[location] == + INACTIVE_UNIFORM_EXPLICIT_LOCATION) + return false; + _mesa_uniform_split_location_offset(shProg, location, loc, array_index); if (shProg->UniformStorage[*loc].array_elements == 0 && count > 1) { diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 1daade428..f450173af 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -112,7 +112,7 @@ _mesa_uniform_attach_driver_storage(struct gl_uniform_storage *uni, uni->driver_storage[uni->num_driver_storage].element_stride = element_stride; uni->driver_storage[uni->num_driver_storage].vector_stride = vector_stride; - uni->driver_storage[uni->num_driver_storage].format = (uint8_t) format; + uni->driver_storage[uni->num_driver_storage].format = format; uni->driver_storage[uni->num_driver_storage].data = data; uni->num_driver_storage++; diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index b7332fccf..988def1a3 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -552,6 +552,7 @@ _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) gpc->InputType = gp->InputType; gpc->Invocations = gp->Invocations; gpc->OutputType = gp->OutputType; + gpc->UsesEndPrimitive = gp->UsesEndPrimitive; } break; default: diff --git a/mesalib/src/mesa/state_tracker/st_atom_sampler.c b/mesalib/src/mesa/state_tracker/st_atom_sampler.c index 3929251f8..17b536bf5 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_sampler.c +++ b/mesalib/src/mesa/state_tracker/st_atom_sampler.c @@ -160,11 +160,8 @@ convert_sampler(struct st_context *st, sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; - sampler->min_lod = CLAMP(msamp->MinLod, - 0.0f, - (GLfloat) texobj->MaxLevel - texobj->BaseLevel); - sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel, - msamp->MaxLod); + sampler->min_lod = MAX2(msamp->MinLod, 0.0f); + sampler->max_lod = msamp->MaxLod; if (sampler->max_lod < sampler->min_lod) { /* The GL spec doesn't seem to specify what to do in this case. * Swap the values. diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c index e2d26ee24..2e10bc3e2 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_texture.c +++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c @@ -212,6 +212,12 @@ check_sampler_swizzle(const struct st_texture_object *stObj, } +static unsigned last_level(struct st_texture_object *stObj) +{ + return MIN2(stObj->base._MaxLevel, stObj->pt->last_level); +} + + static struct pipe_sampler_view * st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, struct st_texture_object *stObj, @@ -244,6 +250,8 @@ st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, templ.u.buf.last_element = f + (n - 1); } else { templ.u.tex.first_level = stObj->base.BaseLevel; + templ.u.tex.last_level = last_level(stObj); + assert(templ.u.tex.first_level <= templ.u.tex.last_level); } if (swizzle != SWIZZLE_NOOP) { @@ -279,7 +287,8 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st, if (*sv) { if (check_sampler_swizzle(stObj, *sv) || (format != (*sv)->format) || - stObj->base.BaseLevel != (*sv)->u.tex.first_level) { + stObj->base.BaseLevel != (*sv)->u.tex.first_level || + last_level(stObj) != (*sv)->u.tex.last_level) { pipe_sampler_view_reference(sv, NULL); } } @@ -434,7 +443,7 @@ update_geometry_textures(struct st_context *st) update_textures(st, PIPE_SHADER_GEOMETRY, &ctx->GeometryProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits, + ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits, st->state.sampler_views[PIPE_SHADER_GEOMETRY], &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]); } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 12ba82df3..e93804689 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -543,6 +543,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_ES2_compatibility = GL_TRUE; ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE; + ctx->Extensions.ARB_explicit_uniform_location = GL_TRUE; ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; ctx->Extensions.ARB_fragment_program = GL_TRUE; ctx->Extensions.ARB_fragment_shader = GL_TRUE; @@ -630,6 +631,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_shading_language_packing = GL_TRUE; ctx->Extensions.OES_depth_texture_cube_map = GL_TRUE; ctx->Extensions.ARB_shading_language_420pack = GL_TRUE; + ctx->Extensions.ARB_texture_query_levels = GL_TRUE; if (!st->options.disable_shader_bit_encoding) { ctx->Extensions.ARB_shader_bit_encoding = GL_TRUE; 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 739e1089e..cac1e0fe2 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -2779,7 +2779,9 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) void glsl_to_tgsi_visitor::visit(ir_texture *ir) { - st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset[MAX_GLSL_TEXTURE_OFFSET], sample_index, component; + st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy; + st_src_reg offset[MAX_GLSL_TEXTURE_OFFSET], sample_index, component; + st_src_reg levels_src; st_dst_reg result_dst, coord_dst, cube_sc_dst; glsl_to_tgsi_instruction *inst = NULL; unsigned opcode = TGSI_OPCODE_NOP; @@ -2860,6 +2862,11 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) ir->lod_info.lod->accept(this); lod_info = this->result; break; + case ir_query_levels: + opcode = TGSI_OPCODE_TXQ; + lod_info = st_src_reg(PROGRAM_IMMEDIATE, 0, GLSL_TYPE_INT); + levels_src = get_temp(ir->type); + break; case ir_txf: opcode = TGSI_OPCODE_TXF; ir->lod_info.lod->accept(this); @@ -2896,9 +2903,6 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) case ir_lod: opcode = TGSI_OPCODE_LODQ; break; - case ir_query_levels: - assert(!"Unexpected ir_query_levels opcode"); - break; } if (ir->projector) { @@ -2995,9 +2999,16 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) if (opcode == TGSI_OPCODE_TXD) inst = emit(ir, opcode, result_dst, coord, dx, dy); - else if (opcode == TGSI_OPCODE_TXQ) - inst = emit(ir, opcode, result_dst, lod_info); - else if (opcode == TGSI_OPCODE_TXF) { + else if (opcode == TGSI_OPCODE_TXQ) { + if (ir->op == ir_query_levels) { + /* the level is stored in W */ + inst = emit(ir, opcode, st_dst_reg(levels_src), lod_info); + result_dst.writemask = WRITEMASK_X; + levels_src.swizzle = SWIZZLE_WWWW; + emit(ir, TGSI_OPCODE_MOV, result_dst, levels_src); + } else + inst = emit(ir, opcode, result_dst, lod_info); + } else if (opcode == TGSI_OPCODE_TXF) { inst = emit(ir, opcode, result_dst, coord); } else if (opcode == TGSI_OPCODE_TXL2 || opcode == TGSI_OPCODE_TXB2) { inst = emit(ir, opcode, result_dst, coord, lod_info); diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index 26eb9786d..1df411c3b 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -572,6 +572,11 @@ st_translate_fragment_program(struct st_context *st, input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; + case VARYING_SLOT_LAYER: + input_semantic_name[slot] = TGSI_SEMANTIC_LAYER; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; case VARYING_SLOT_VIEWPORT: input_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; input_semantic_index[slot] = 0; diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c index 92035e801..c14882142 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.c +++ b/mesalib/src/mesa/state_tracker/st_texture.c @@ -394,6 +394,14 @@ st_texture_image_copy(struct pipe_context *pipe, src_box.width = width; src_box.height = height; src_box.depth = 1; + + if (src->target == PIPE_TEXTURE_1D_ARRAY || + src->target == PIPE_TEXTURE_2D_ARRAY || + src->target == PIPE_TEXTURE_CUBE_ARRAY) { + face = 0; + depth = src->array_size; + } + /* Loop over 3D image slices */ /* could (and probably should) use "true" 3d box here - but drivers can't quite handle it yet */ diff --git a/mesalib/src/mesa/swrast/s_aatriangle.c b/mesalib/src/mesa/swrast/s_aatriangle.c index d670d3154..219282748 100644 --- a/mesalib/src/mesa/swrast/s_aatriangle.c +++ b/mesalib/src/mesa/swrast/s_aatriangle.c @@ -112,20 +112,6 @@ solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) /* - * Return 1 / solve_plane(). - */ -static inline GLfloat -solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) -{ - const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; - if (denom == 0.0F) - return 0.0F; - else - return -plane[2] / denom; -} - - -/* * Solve plane and return clamped GLchan value. */ static inline GLchan |