aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/gallium/Automake.inc57
-rw-r--r--mesalib/src/gallium/SConscript20
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.c11
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.h3
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp177
-rw-r--r--mesalib/src/glsl/ast_type.cpp2
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp6
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y6
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll1
-rw-r--r--mesalib/src/glsl/glsl_parser.yy38
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp5
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h21
-rw-r--r--mesalib/src/glsl/glsl_symbol_table.h2
-rw-r--r--mesalib/src/glsl/glsl_types.cpp30
-rw-r--r--mesalib/src/glsl/glsl_types.h6
-rw-r--r--mesalib/src/glsl/hir_field_selection.cpp1
-rw-r--r--mesalib/src/glsl/ir.cpp1
-rw-r--r--mesalib/src/glsl/ir_basic_block.cpp2
-rwxr-xr-xmesalib/src/glsl/ir_constant_expression.cpp1
-rw-r--r--mesalib/src/glsl/ir_expression_flattening.cpp2
-rw-r--r--mesalib/src/glsl/ir_optimization.h4
-rw-r--r--mesalib/src/glsl/ir_uniform.h12
-rw-r--r--mesalib/src/glsl/link_uniform_block_active_visitor.h2
-rw-r--r--mesalib/src/glsl/link_uniform_initializers.cpp2
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp61
-rw-r--r--mesalib/src/glsl/linker.cpp114
-rw-r--r--mesalib/src/glsl/list.h568
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp59
-rw-r--r--mesalib/src/glsl/opt_dead_builtin_varyings.cpp2
-rw-r--r--mesalib/src/glsl/opt_rebalance_tree.cpp300
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.cpp1
-rw-r--r--mesalib/src/glsl/test_optpass.cpp2
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_compressed_texture_pixel_storage.xml21
-rw-r--r--mesalib/src/mapi/glapi/gen/Makefile.am1
-rwxr-xr-xmesalib/src/mapi/glapi/gen/gl_API.xml18
-rw-r--r--mesalib/src/mesa/Android.libmesa_dricore.mk8
-rw-r--r--mesalib/src/mesa/Android.libmesa_glsl_utils.mk1
-rw-r--r--mesalib/src/mesa/Android.mesa_gen_matypes.mk1
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c6
-rw-r--r--mesalib/src/mesa/drivers/common/meta_blit.c2
-rw-r--r--mesalib/src/mesa/drivers/common/meta_generate_mipmap.c12
-rw-r--r--mesalib/src/mesa/drivers/dri/Android.mk1
-rw-r--r--mesalib/src/mesa/drivers/dri/common/Android.mk17
-rw-r--r--mesalib/src/mesa/drivers/dri/common/Makefile.am2
-rw-r--r--mesalib/src/mesa/drivers/dri/common/Makefile.sources3
-rw-r--r--mesalib/src/mesa/main/api_arrayelt.c111
-rw-r--r--mesalib/src/mesa/main/clear.c5
-rw-r--r--mesalib/src/mesa/main/context.c6
-rw-r--r--mesalib/src/mesa/main/extensions.c162
-rw-r--r--mesalib/src/mesa/main/extensions.h6
-rw-r--r--mesalib/src/mesa/main/ff_fragment_shader.cpp17
-rw-r--r--mesalib/src/mesa/main/get.c6
-rw-r--r--mesalib/src/mesa/main/get_hash_params.py11
-rw-r--r--mesalib/src/mesa/main/glformats.c30
-rw-r--r--mesalib/src/mesa/main/glformats.h6
-rw-r--r--mesalib/src/mesa/main/mtypes.h15
-rw-r--r--mesalib/src/mesa/main/performance_monitor.c13
-rw-r--r--mesalib/src/mesa/main/pixelstore.c239
-rw-r--r--mesalib/src/mesa/main/shaderapi.c17
-rw-r--r--mesalib/src/mesa/main/shaderobj.c1
-rw-r--r--mesalib/src/mesa/main/texgetimage.c83
-rw-r--r--mesalib/src/mesa/main/teximage.c51
-rw-r--r--mesalib/src/mesa/main/teximage.h6
-rw-r--r--mesalib/src/mesa/main/texstore.c82
-rw-r--r--mesalib/src/mesa/main/texstore.h17
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp15
-rw-r--r--mesalib/src/mesa/main/uniforms.c2
-rw-r--r--mesalib/src/mesa/program/program.c1
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_sampler.c7
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_texture.c13
-rw-r--r--mesalib/src/mesa/state_tracker/st_extensions.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp25
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_texture.c8
-rw-r--r--mesalib/src/mesa/swrast/s_aatriangle.c14
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 b69802ddb..2b2de3047 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -1559,11 +1559,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\"");
@@ -1586,11 +1581,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 "
@@ -1602,28 +1592,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);
}
@@ -2181,7 +2161,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 49402fa21..2a5aea477 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -155,6 +155,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);
@@ -192,7 +207,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;
@@ -367,8 +382,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 83d7935d8..db8863a20 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 2f4a0bec8..67dbac1eb 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 f5cb12343..73380d243 100755
--- 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 377fed64a..5dcb7b571 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 b2e249657..fa6ec12cc 100644
--- a/mesalib/src/glsl/list.h
+++ b/mesalib/src/glsl/list.h
@@ -87,67 +87,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
@@ -157,33 +119,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
@@ -229,75 +323,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
@@ -307,87 +345,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)
@@ -397,19 +587,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 58aed8e6f..a43410322 100755
--- 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