aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/gallium/auxiliary/Makefile.sources1
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.c41
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.h11
-rw-r--r--mesalib/src/glsl/ast_array_index.cpp4
-rw-r--r--mesalib/src/glsl/ast_function.cpp14
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp222
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp229
-rw-r--r--mesalib/src/glsl/builtin_type_macros.h2
-rw-r--r--mesalib/src/glsl/builtin_types.cpp6
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp15
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y3
-rw-r--r--mesalib/src/glsl/glsl_parser.yy42
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp7
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h32
-rw-r--r--mesalib/src/glsl/glsl_types.cpp20
-rw-r--r--mesalib/src/glsl/glsl_types.h38
-rw-r--r--mesalib/src/glsl/hir_field_selection.cpp2
-rw-r--r--mesalib/src/glsl/ir.cpp49
-rw-r--r--mesalib/src/glsl/ir.h17
-rw-r--r--mesalib/src/glsl/ir_clone.cpp3
-rw-r--r--mesalib/src/glsl/ir_uniform.h7
-rw-r--r--mesalib/src/glsl/link_functions.cpp16
-rw-r--r--mesalib/src/glsl/link_uniform_initializers.cpp1
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp1
-rw-r--r--mesalib/src/glsl/linker.cpp27
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp166
-rw-r--r--mesalib/src/glsl/opt_array_splitting.cpp2
-rw-r--r--mesalib/src/glsl/opt_dead_builtin_varyings.cpp167
-rw-r--r--mesalib/src/glsl/opt_function_inlining.cpp66
-rw-r--r--mesalib/src/glsl/ralloc.h14
-rw-r--r--mesalib/src/mapi/glapi/SConscript7
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml47
-rw-r--r--mesalib/src/mapi/glapi/gen/Makefile.am2
-rw-r--r--mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml69
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_API.xml4
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_genexec.py1
-rw-r--r--mesalib/src/mesa/Makefile.sources4
-rw-r--r--mesalib/src/mesa/SConscript2
-rw-r--r--mesalib/src/mesa/drivers/dri/common/Makefile.am1
-rw-r--r--mesalib/src/mesa/main/bufferobj.c58
-rw-r--r--mesalib/src/mesa/main/compiler.h24
-rw-r--r--mesalib/src/mesa/main/config.h5
-rw-r--r--mesalib/src/mesa/main/context.c9
-rw-r--r--mesalib/src/mesa/main/dd.h14
-rw-r--r--mesalib/src/mesa/main/extensions.c2
-rw-r--r--mesalib/src/mesa/main/get.c40
-rw-r--r--mesalib/src/mesa/main/get_hash_params.py12
-rw-r--r--mesalib/src/mesa/main/imports.h1
-rw-r--r--mesalib/src/mesa/main/mtypes.h69
-rw-r--r--mesalib/src/mesa/main/queryobj.c25
-rw-r--r--mesalib/src/mesa/main/shaderapi.c14
-rw-r--r--mesalib/src/mesa/main/texparam.c12
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp14
-rw-r--r--mesalib/src/mesa/main/uniforms.c68
-rw-r--r--mesalib/src/mesa/main/uniforms.h3
-rw-r--r--mesalib/src/mesa/main/vdpau.c424
-rw-r--r--mesalib/src/mesa/main/vdpau.h72
-rw-r--r--mesalib/src/mesa/program/ir_to_mesa.cpp2
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.c3
-rw-r--r--mesalib/src/mesa/state_tracker/st_draw.c7
-rw-r--r--mesalib/src/mesa/state_tracker/st_extensions.c8
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp1
-rw-r--r--mesalib/src/mesa/state_tracker/st_vdpau.c181
-rw-r--r--mesalib/src/mesa/state_tracker/st_vdpau.h42
64 files changed, 2075 insertions, 397 deletions
diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources
index acbcef7e2..c89cbddd0 100644
--- a/mesalib/src/gallium/auxiliary/Makefile.sources
+++ b/mesalib/src/gallium/auxiliary/Makefile.sources
@@ -43,6 +43,7 @@ C_SOURCES := \
hud/hud_cpu.c \
hud/hud_fps.c \
hud/hud_driver_query.c \
+ indices/u_primconvert.c \
os/os_misc.c \
os/os_process.c \
os/os_time.c \
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c
index a8aa5719d..9ef3bb53f 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.c
+++ b/mesalib/src/gallium/auxiliary/util/u_format.c
@@ -208,6 +208,47 @@ util_format_is_supported(enum pipe_format format, unsigned bind)
}
+/**
+ * Calculates the MRD for the depth format. MRD is used in depth bias
+ * for UNORM and unbound depth buffers. When the depth buffer is floating
+ * point, the depth bias calculation does not use the MRD. However, the
+ * default MRD will be 1.0 / ((1 << 24) - 1).
+ */
+double
+util_get_depth_format_mrd(enum pipe_format format)
+{
+ struct util_format_description *format_desc;
+ /*
+ * Depth buffer formats without a depth component OR scenarios
+ * without a bound depth buffer default to D24.
+ */
+ double mrd = 1.0 / ((1 << 24) - 1);
+ unsigned depth_channel;
+
+ format_desc = (struct util_format_description *)
+ util_format_description(format);
+
+ assert(format_desc);
+
+ /*
+ * Some depth formats do not store the depth component in the first
+ * channel, detect the format and adjust the depth channel. Get the
+ * swizzled depth component channel.
+ */
+ depth_channel = format_desc->swizzle[0];
+
+ if (format_desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
+ format_desc->channel[depth_channel].normalized) {
+ int depth_bits;
+
+ depth_bits = format_desc->channel[depth_channel].size;
+ mrd = 1.0 / ((1ULL << depth_bits) - 1);
+ }
+
+ return mrd;
+}
+
+
void
util_format_read_4f(enum pipe_format format,
float *dst, unsigned dst_stride,
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h
index 84f16d503..dc777c35c 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.h
+++ b/mesalib/src/gallium/auxiliary/util/u_format.h
@@ -544,6 +544,17 @@ util_format_is_depth_and_stencil(enum pipe_format format)
util_format_has_stencil(desc);
}
+
+/**
+ * Calculates the MRD for the depth format. MRD is used in depth bias
+ * for UNORM and unbound depth buffers. When the depth buffer is floating
+ * point, the depth bias calculation does not use the MRD. However, the
+ * default MRD will be 1.0 / ((1 << 24) - 1).
+ */
+double
+util_get_depth_format_mrd(enum pipe_format format);
+
+
/**
* Return whether this is an RGBA, Z, S, or combined ZS format.
* Useful for initializing pipe_blit_info::mask.
diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp
index b457ec899..f7b5e8350 100644
--- a/mesalib/src/glsl/ast_array_index.cpp
+++ b/mesalib/src/glsl/ast_array_index.cpp
@@ -143,7 +143,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
bound = array->type->vector_elements;
}
} else {
- /* glsl_type::array_size() returns 0 for non-array types. This means
+ /* glsl_type::array_size() returns -1 for non-array types. This means
* that we don't need to verify that the type is an array before
* doing the bounds checking.
*/
@@ -165,7 +165,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
if (array->type->is_array())
update_max_array_access(array, idx, &loc, state);
} else if (const_index == NULL && array->type->is_array()) {
- if (array->type->array_size() == 0) {
+ if (array->type->is_unsized_array()) {
_mesa_glsl_error(&loc, state, "unsized array index must be constant");
} else if (array->type->fields.array->is_interface()
&& array->variable_referenced()->mode == ir_var_uniform) {
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 02aad4f8f..2707522ef 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -732,21 +732,21 @@ process_array_constructor(exec_list *instructions,
exec_list actual_parameters;
const unsigned parameter_count =
process_parameters(instructions, &actual_parameters, parameters, state);
+ bool is_unsized_array = constructor_type->is_unsized_array();
- if ((parameter_count == 0)
- || ((constructor_type->length != 0)
- && (constructor_type->length != parameter_count))) {
- const unsigned min_param = (constructor_type->length == 0)
- ? 1 : constructor_type->length;
+ if ((parameter_count == 0) ||
+ (!is_unsized_array && (constructor_type->length != parameter_count))) {
+ const unsigned min_param = is_unsized_array
+ ? 1 : constructor_type->length;
_mesa_glsl_error(loc, state, "array constructor must have %s %u "
"parameter%s",
- (constructor_type->length == 0) ? "at least" : "exactly",
+ is_unsized_array ? "at least" : "exactly",
min_param, (min_param <= 1) ? "" : "s");
return ir_rvalue::error_value(ctx);
}
- if (constructor_type->length == 0) {
+ if (is_unsized_array) {
constructor_type =
glsl_type::get_array_instance(constructor_type->element_type(),
parameter_count);
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 3551a5956..f75e68ce1 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -675,8 +675,8 @@ shift_result_type(const struct glsl_type *type_a,
*/
ir_rvalue *
validate_assignment(struct _mesa_glsl_parse_state *state,
- const glsl_type *lhs_type, ir_rvalue *rhs,
- bool is_initializer)
+ YYLTYPE loc, const glsl_type *lhs_type,
+ ir_rvalue *rhs, bool is_initializer)
{
/* If there is already some error in the RHS, just return it. Anything
* else will lead to an avalanche of error message back to the user.
@@ -689,16 +689,15 @@ validate_assignment(struct _mesa_glsl_parse_state *state,
if (rhs->type == lhs_type)
return rhs;
- /* If the array element types are the same and the size of the LHS is zero,
+ /* If the array element types are the same and the LHS is unsized,
* the assignment is okay for initializers embedded in variable
* declarations.
*
* Note: Whole-array assignments are not permitted in GLSL 1.10, but this
* is handled by ir_dereference::is_lvalue.
*/
- if (is_initializer && lhs_type->is_array() && rhs->type->is_array()
- && (lhs_type->element_type() == rhs->type->element_type())
- && (lhs_type->array_size() == 0)) {
+ if (is_initializer && lhs_type->is_unsized_array() && rhs->type->is_array()
+ && (lhs_type->element_type() == rhs->type->element_type())) {
return rhs;
}
@@ -708,6 +707,12 @@ validate_assignment(struct _mesa_glsl_parse_state *state,
return rhs;
}
+ _mesa_glsl_error(&loc, state,
+ "%s of type %s cannot be assigned to "
+ "variable of type %s",
+ is_initializer ? "initializer" : "value",
+ rhs->type->name, lhs_type->name);
+
return NULL;
}
@@ -738,10 +743,10 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
if (unlikely(expr->operation == ir_binop_vector_extract)) {
ir_rvalue *new_rhs =
- validate_assignment(state, lhs->type, rhs, is_initializer);
+ validate_assignment(state, lhs_loc, lhs->type,
+ rhs, is_initializer);
if (new_rhs == NULL) {
- _mesa_glsl_error(& lhs_loc, state, "type mismatch");
return lhs;
} else {
rhs = new(ctx) ir_expression(ir_triop_vector_insert,
@@ -790,10 +795,8 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
}
ir_rvalue *new_rhs =
- validate_assignment(state, lhs->type, rhs, is_initializer);
- if (new_rhs == NULL) {
- _mesa_glsl_error(& lhs_loc, state, "type mismatch");
- } else {
+ validate_assignment(state, lhs_loc, lhs->type, rhs, is_initializer);
+ if (new_rhs != NULL) {
rhs = new_rhs;
/* If the LHS array was not declared with a size, it takes it size from
@@ -801,7 +804,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
* dereference of a variable. Any other case would require that the LHS
* is either not an l-value or not a whole array.
*/
- if (lhs->type->array_size() == 0) {
+ if (lhs->type->is_unsized_array()) {
ir_dereference *const d = lhs->as_dereference();
assert(d != NULL);
@@ -940,6 +943,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
case GLSL_TYPE_VOID:
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_INTERFACE:
+ case GLSL_TYPE_ATOMIC_UINT:
/* I assume a comparison of a struct containing a sampler just
* ignores the sampler present in the type.
*/
@@ -1234,6 +1238,10 @@ ast_expression::hir(exec_list *instructions,
!state->check_version(120, 300, &loc,
"array comparisons forbidden")) {
error_emitted = true;
+ } else if ((op[0]->type->contains_opaque() ||
+ op[1]->type->contains_opaque())) {
+ _mesa_glsl_error(&loc, state, "opaque type comparisons forbidden");
+ error_emitted = true;
}
if (error_emitted) {
@@ -2039,6 +2047,96 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual,
static void
+validate_explicit_location(const struct ast_type_qualifier *qual,
+ ir_variable *var,
+ struct _mesa_glsl_parse_state *state,
+ YYLTYPE *loc)
+{
+ bool fail = false;
+
+ /* In the vertex shader only shader inputs can be given explicit
+ * locations.
+ *
+ * In the fragment shader only shader outputs can be given explicit
+ * locations.
+ */
+ switch (state->target) {
+ case vertex_shader:
+ if (var->mode == ir_var_shader_in) {
+ if (!state->check_explicit_attrib_location_allowed(loc, var))
+ return;
+
+ break;
+ }
+
+ fail = true;
+ break;
+
+ case geometry_shader:
+ _mesa_glsl_error(loc, state,
+ "geometry shader variables cannot be given "
+ "explicit locations");
+ return;
+
+ case fragment_shader:
+ if (var->mode == ir_var_shader_out) {
+ if (!state->check_explicit_attrib_location_allowed(loc, var))
+ return;
+
+ break;
+ }
+
+ fail = true;
+ break;
+ };
+
+ if (fail) {
+ _mesa_glsl_error(loc, state,
+ "%s cannot be given an explicit location in %s shader",
+ mode_string(var),
+ _mesa_glsl_shader_target_name(state->target));
+ } else {
+ var->explicit_location = true;
+
+ /* This bit of silliness is needed because invalid explicit locations
+ * are supposed to be flagged during linking. Small negative values
+ * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias
+ * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS).
+ * The linker needs to be able to differentiate these cases. This
+ * ensures that negative values stay negative.
+ */
+ if (qual->location >= 0) {
+ var->location = (state->target == vertex_shader)
+ ? (qual->location + VERT_ATTRIB_GENERIC0)
+ : (qual->location + FRAG_RESULT_DATA0);
+ } else {
+ var->location = qual->location;
+ }
+
+ if (qual->flags.q.explicit_index) {
+ /* From the GLSL 4.30 specification, section 4.4.2 (Output
+ * Layout Qualifiers):
+ *
+ * "It is also a compile-time error if a fragment shader
+ * sets a layout index to less than 0 or greater than 1."
+ *
+ * Older specifications don't mandate a behavior; we take
+ * this as a clarification and always generate the error.
+ */
+ if (qual->index < 0 || qual->index > 1) {
+ _mesa_glsl_error(loc, state,
+ "explicit index may only be 0 or 1");
+ } else {
+ var->explicit_index = true;
+ var->index = qual->index;
+ }
+ }
+ }
+
+ return;
+}
+
+static void
apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
ir_variable *var,
struct _mesa_glsl_parse_state *state,
@@ -2190,81 +2288,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
}
if (qual->flags.q.explicit_location) {
- const bool global_scope = (state->current_function == NULL);
- bool fail = false;
- const char *string = "";
-
- /* In the vertex shader only shader inputs can be given explicit
- * locations.
- *
- * In the fragment shader only shader outputs can be given explicit
- * locations.
- */
- switch (state->target) {
- case vertex_shader:
- if (!global_scope || (var->mode != ir_var_shader_in)) {
- fail = true;
- string = "input";
- }
- break;
-
- case geometry_shader:
- _mesa_glsl_error(loc, state,
- "geometry shader variables cannot be given "
- "explicit locations");
- break;
-
- case fragment_shader:
- if (!global_scope || (var->mode != ir_var_shader_out)) {
- fail = true;
- string = "output";
- }
- break;
- };
-
- if (fail) {
- _mesa_glsl_error(loc, state,
- "only %s shader %s variables can be given an "
- "explicit location",
- _mesa_glsl_shader_target_name(state->target),
- string);
- } else {
- var->explicit_location = true;
-
- /* This bit of silliness is needed because invalid explicit locations
- * are supposed to be flagged during linking. Small negative values
- * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias
- * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS).
- * The linker needs to be able to differentiate these cases. This
- * ensures that negative values stay negative.
- */
- if (qual->location >= 0) {
- var->location = (state->target == vertex_shader)
- ? (qual->location + VERT_ATTRIB_GENERIC0)
- : (qual->location + FRAG_RESULT_DATA0);
- } else {
- var->location = qual->location;
- }
-
- if (qual->flags.q.explicit_index) {
- /* From the GLSL 4.30 specification, section 4.4.2 (Output
- * Layout Qualifiers):
- *
- * "It is also a compile-time error if a fragment shader
- * sets a layout index to less than 0 or greater than 1."
- *
- * Older specifications don't mandate a behavior; we take
- * this as a clarification and always generate the error.
- */
- if (qual->index < 0 || qual->index > 1) {
- _mesa_glsl_error(loc, state,
- "explicit index may only be 0 or 1");
- } else {
- var->explicit_index = true;
- var->index = qual->index;
- }
- }
- }
+ validate_explicit_location(qual, var, state, loc);
} else if (qual->flags.q.explicit_index) {
_mesa_glsl_error(loc, state,
"explicit index requires explicit location");
@@ -2403,8 +2427,7 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
* later re-declare the same name as an array of the same
* type and specify a size."
*/
- if ((earlier->type->array_size() == 0)
- && var->type->is_array()
+ if (earlier->type->is_unsized_array() && var->type->is_array()
&& (var->type->element_type() == earlier->type->element_type())) {
/* FINISHME: This doesn't match the qualifiers on the two
* FINISHME: declarations. It's not 100% clear whether this is
@@ -2547,7 +2570,8 @@ process_initializer(ir_variable *var, ast_declaration *decl,
*/
if (type->qualifier.flags.q.constant
|| type->qualifier.flags.q.uniform) {
- ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs, true);
+ ir_rvalue *new_rhs = validate_assignment(state, initializer_loc,
+ var->type, rhs, true);
if (new_rhs != NULL) {
rhs = new_rhs;
@@ -2576,10 +2600,6 @@ process_initializer(ir_variable *var, ast_declaration *decl,
var->constant_value = constant_value;
}
} else {
- _mesa_glsl_error(&initializer_loc, state,
- "initializer of type %s cannot be assigned to "
- "variable of type %s",
- rhs->type->name, var->type->name);
if (var->type->is_numeric()) {
/* Reduce cascading errors. */
var->constant_value = ir_constant::zero(state, var->type);
@@ -2659,7 +2679,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state,
return;
}
- if (var->type->length == 0) {
+ if (var->type->is_unsized_array()) {
/* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says:
*
* All geometry shader input unsized array declarations will be
@@ -3308,7 +3328,7 @@ ast_declarator_list::hir(exec_list *instructions,
const glsl_type *const t = (earlier == NULL)
? var->type : earlier->type;
- if (t->is_array() && t->length == 0)
+ if (t->is_unsized_array())
/* Section 10.17 of the GLSL ES 1.00 specification states that
* unsized array declarations have been removed from the language.
* Arrays that are sized using an initializer are still explicitly
@@ -3441,7 +3461,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
type = process_array_type(&loc, type, this->array_size, state);
}
- if (!type->is_error() && type->array_size() == 0) {
+ if (!type->is_error() && type->is_unsized_array()) {
_mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
"a declared size");
type = glsl_type::error_type;
@@ -3613,7 +3633,7 @@ ast_function::hir(exec_list *instructions,
* "Arrays are allowed as arguments and as the return type. In both
* cases, the array must be explicitly sized."
*/
- if (return_type->is_array() && return_type->length == 0) {
+ if (return_type->is_unsized_array()) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state,
"function `%s' return type array must be explicitly "
@@ -5099,10 +5119,8 @@ ast_gs_input_layout::hir(exec_list *instructions,
/* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an
* array; skip it.
*/
- if (!var->type->is_array())
- continue;
- if (var->type->length == 0) {
+ if (var->type->is_unsized_array()) {
if (var->max_array_access >= num_vertices) {
_mesa_glsl_error(&loc, state,
"this geometry shader input layout implies %u"
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index d40888d38..3fa0cb5ad 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -277,6 +277,17 @@ texture_gather(const _mesa_glsl_parse_state *state)
state->ARB_gpu_shader5_enable;
}
+/* Only ARB_texture_gather but not GLSL 4.0 or ARB_gpu_shader5.
+ * used for relaxation of const offset requirements.
+ */
+static bool
+texture_gather_only(const _mesa_glsl_parse_state *state)
+{
+ return !state->is_version(400, 0) &&
+ !state->ARB_gpu_shader5_enable &&
+ state->ARB_texture_gather_enable;
+}
+
/* Desktop GL or OES_standard_derivatives + fragment shader only */
static bool
fs_oes_derivatives(const _mesa_glsl_parse_state *state)
@@ -315,6 +326,13 @@ tex3d_lod(const _mesa_glsl_parse_state *state)
{
return tex3d(state) && lod_exists_in_stage(state);
}
+
+static bool
+shader_atomic_counters(const _mesa_glsl_parse_state *state)
+{
+ return state->ARB_shader_atomic_counters_enable;
+}
+
/** @} */
/******************************************************************************/
@@ -354,6 +372,7 @@ private:
ir_variable *gl_Vertex;
void create_shader();
+ void create_intrinsics();
void create_builtins();
/**
@@ -375,6 +394,14 @@ private:
ir_expression *asin_expr(ir_variable *x);
+ /**
+ * Call function \param f with parameters specified as the linked
+ * list \param params of \c ir_variable objects. \param ret should
+ * point to the ir_variable that will hold the function return
+ * value, or be \c NULL if the function has void return type.
+ */
+ ir_call *call(ir_function *f, ir_variable *ret, exec_list params);
+
/** Create a new function and add the given signatures. */
void add_function(const char *name, ...);
@@ -495,6 +522,8 @@ private:
#define TEX_PROJECT 1
#define TEX_OFFSET 2
#define TEX_COMPONENT 4
+#define TEX_OFFSET_NONCONST 8
+#define TEX_OFFSET_ARRAY 16
ir_function_signature *_texture(ir_texture_opcode opcode,
builtin_available_predicate avail,
@@ -534,6 +563,11 @@ private:
B1(uaddCarry)
B1(usubBorrow)
B1(mulExtended)
+
+ ir_function_signature *_atomic_intrinsic(builtin_available_predicate avail);
+ ir_function_signature *_atomic_op(const char *intrinsic,
+ builtin_available_predicate avail);
+
#undef B0
#undef B1
#undef B2
@@ -596,6 +630,7 @@ builtin_builder::initialize()
mem_ctx = ralloc_context(NULL);
create_shader();
+ create_intrinsics();
create_builtins();
}
@@ -633,6 +668,24 @@ builtin_builder::create_shader()
/** @} */
/**
+ * Create ir_function and ir_function_signature objects for each
+ * intrinsic.
+ */
+void
+builtin_builder::create_intrinsics()
+{
+ add_function("__intrinsic_atomic_read",
+ _atomic_intrinsic(shader_atomic_counters),
+ NULL);
+ add_function("__intrinsic_atomic_increment",
+ _atomic_intrinsic(shader_atomic_counters),
+ NULL);
+ add_function("__intrinsic_atomic_predecrement",
+ _atomic_intrinsic(shader_atomic_counters),
+ NULL);
+}
+
+/**
* Create ir_function and ir_function_signature objects for each built-in.
*
* Contains a list of every available built-in.
@@ -1909,16 +1962,80 @@ builtin_builder::create_builtins()
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec4_type),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type),
NULL);
add_function("textureGatherOffset",
- _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+
+ _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+ NULL);
+
+ add_function("textureGatherOffsets",
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY),
- _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT),
+
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY),
+ _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY),
NULL);
F(dFdx)
@@ -1974,6 +2091,20 @@ builtin_builder::create_builtins()
_mulExtended(glsl_type::uvec3_type),
_mulExtended(glsl_type::uvec4_type),
NULL);
+
+ add_function("atomicCounter",
+ _atomic_op("__intrinsic_atomic_read",
+ shader_atomic_counters),
+ NULL);
+ add_function("atomicCounterIncrement",
+ _atomic_op("__intrinsic_atomic_increment",
+ shader_atomic_counters),
+ NULL);
+ add_function("atomicCounterDecrement",
+ _atomic_op("__intrinsic_atomic_predecrement",
+ shader_atomic_counters),
+ NULL);
+
#undef F
#undef FI
#undef FIU
@@ -1994,8 +2125,6 @@ builtin_builder::add_function(const char *name, ...)
if (sig == NULL)
break;
- sig->is_defined = true;
-
if (false) {
exec_list stuff;
stuff.push_tail(sig);
@@ -2093,7 +2222,13 @@ builtin_builder::new_sig(const glsl_type *return_type,
#define MAKE_SIG(return_type, avail, ...) \
ir_function_signature *sig = \
new_sig(return_type, avail, __VA_ARGS__); \
- ir_factory body(&sig->body, mem_ctx);
+ ir_factory body(&sig->body, mem_ctx); \
+ sig->is_defined = true;
+
+#define MAKE_INTRINSIC(return_type, avail, ...) \
+ ir_function_signature *sig = \
+ new_sig(return_type, avail, __VA_ARGS__); \
+ sig->is_intrinsic = true;
ir_function_signature *
builtin_builder::unop(builtin_available_predicate avail,
@@ -2185,6 +2320,26 @@ builtin_builder::asin_expr(ir_variable *x)
mul(abs(x), imm(-0.03102955f))))))))));
}
+ir_call *
+builtin_builder::call(ir_function *f, ir_variable *ret, exec_list params)
+{
+ exec_list actual_params;
+
+ foreach_iter(exec_list_iterator, it, params) {
+ ir_variable *var = ((ir_instruction *)it.get())->as_variable();
+ actual_params.push_tail(var_ref(var));
+ }
+
+ ir_function_signature *sig =
+ f->exact_matching_signature(NULL, &actual_params);
+ if (!sig)
+ return NULL;
+
+ ir_dereference_variable *deref =
+ (sig->return_type->is_void() ? NULL : var_ref(ret));
+
+ return new(mem_ctx) ir_call(sig, deref, &actual_params);
+}
ir_function_signature *
builtin_builder::_asin(const glsl_type *type)
@@ -3347,11 +3502,21 @@ builtin_builder::_texture(ir_texture_opcode opcode,
if (flags & TEX_PROJECT)
tex->projector = swizzle(P, coord_type->vector_elements - 1, 1);
- /* The shadow comparitor is normally in the Z component, but a few types
- * have sufficiently large coordinates that it's in W.
- */
- if (sampler_type->sampler_shadow)
- tex->shadow_comparitor = swizzle(P, MAX2(coord_size, SWIZZLE_Z), 1);
+ if (sampler_type->sampler_shadow) {
+ if (opcode == ir_tg4) {
+ /* gather has refz as a separate parameter, immediately after the
+ * coordinate
+ */
+ ir_variable *refz = in_var(glsl_type::float_type, "refz");
+ sig->parameters.push_tail(refz);
+ tex->shadow_comparitor = var_ref(refz);
+ } else {
+ /* The shadow comparitor is normally in the Z component, but a few types
+ * have sufficiently large coordinates that it's in W.
+ */
+ tex->shadow_comparitor = swizzle(P, MAX2(coord_size, SWIZZLE_Z), 1);
+ }
+ }
if (opcode == ir_txl) {
ir_variable *lod = in_var(glsl_type::float_type, "lod");
@@ -3367,14 +3532,23 @@ builtin_builder::_texture(ir_texture_opcode opcode,
tex->lod_info.grad.dPdy = var_ref(dPdy);
}
- if (flags & TEX_OFFSET) {
+ if (flags & (TEX_OFFSET | TEX_OFFSET_NONCONST)) {
int offset_size = coord_size - (sampler_type->sampler_array ? 1 : 0);
ir_variable *offset =
- new(mem_ctx) ir_variable(glsl_type::ivec(offset_size), "offset", ir_var_const_in);
+ new(mem_ctx) ir_variable(glsl_type::ivec(offset_size), "offset",
+ (flags & TEX_OFFSET) ? ir_var_const_in : ir_var_function_in);
sig->parameters.push_tail(offset);
tex->offset = var_ref(offset);
}
+ if (flags & TEX_OFFSET_ARRAY) {
+ ir_variable *offsets =
+ new(mem_ctx) ir_variable(glsl_type::get_array_instance(glsl_type::ivec2_type, 4),
+ "offsets", ir_var_const_in);
+ sig->parameters.push_tail(offsets);
+ tex->offset = var_ref(offsets);
+ }
+
if (opcode == ir_tg4) {
if (flags & TEX_COMPONENT) {
ir_variable *component =
@@ -3793,6 +3967,29 @@ builtin_builder::_mulExtended(const glsl_type *type)
return sig;
}
+
+ir_function_signature *
+builtin_builder::_atomic_intrinsic(builtin_available_predicate avail)
+{
+ ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter");
+ MAKE_INTRINSIC(glsl_type::uint_type, avail, 1, counter);
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_atomic_op(const char *intrinsic,
+ builtin_available_predicate avail)
+{
+ ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter");
+ MAKE_SIG(glsl_type::uint_type, avail, 1, counter);
+
+ ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval");
+ body.emit(call(shader->symbols->get_function(intrinsic), retval,
+ sig->parameters));
+ body.emit(ret(retval));
+ return sig;
+}
+
/** @} */
/******************************************************************************/
diff --git a/mesalib/src/glsl/builtin_type_macros.h b/mesalib/src/glsl/builtin_type_macros.h
index fec38da12..263fd83ff 100644
--- a/mesalib/src/glsl/builtin_type_macros.h
+++ b/mesalib/src/glsl/builtin_type_macros.h
@@ -110,6 +110,8 @@ DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_SAMPLER
DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT)
+DECL_TYPE(atomic_uint, GL_UNSIGNED_INT_ATOMIC_COUNTER, GLSL_TYPE_ATOMIC_UINT, 1, 1)
+
STRUCT_TYPE(gl_DepthRangeParameters)
STRUCT_TYPE(gl_PointParameters)
STRUCT_TYPE(gl_MaterialParameters)
diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp
index 1a5e5a190..92e386057 100644
--- a/mesalib/src/glsl/builtin_types.cpp
+++ b/mesalib/src/glsl/builtin_types.cpp
@@ -203,6 +203,8 @@ const static struct builtin_type_versions {
T(sampler2DRectShadow, 140, 999)
T(struct_gl_DepthRangeParameters, 110, 100)
+
+ T(atomic_uint, 420, 999)
};
const glsl_type *const deprecated_types[] = {
@@ -284,5 +286,9 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
if (state->OES_texture_3D_enable) {
add_type(symbols, glsl_type::sampler3D_type);
}
+
+ if (state->ARB_shader_atomic_counters_enable) {
+ add_type(symbols, glsl_type::atomic_uint_type);
+ }
}
/** @} */
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 018daf67f..7a3505ace 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -638,6 +638,21 @@ builtin_variable_generator::generate_constants()
*/
add_const("gl_MaxTextureCoords", state->Const.MaxTextureCoords);
}
+
+ if (state->ARB_shader_atomic_counters_enable) {
+ add_const("gl_MaxVertexAtomicCounters",
+ state->Const.MaxVertexAtomicCounters);
+ add_const("gl_MaxGeometryAtomicCounters",
+ state->Const.MaxGeometryAtomicCounters);
+ add_const("gl_MaxFragmentAtomicCounters",
+ state->Const.MaxFragmentAtomicCounters);
+ add_const("gl_MaxCombinedAtomicCounters",
+ state->Const.MaxCombinedAtomicCounters);
+ add_const("gl_MaxAtomicCounterBindings",
+ state->Const.MaxAtomicBufferBindings);
+ add_const("gl_MaxTessControlAtomicCounters", 0);
+ add_const("gl_MaxTessEvaluationAtomicCounters", 0);
+ }
}
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index 02100ab0c..86f3cd5aa 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -1254,6 +1254,9 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
if (extensions->ARB_texture_gather)
add_builtin_define(parser, "GL_ARB_texture_gather", 1);
+
+ if (extensions->ARB_shader_atomic_counters)
+ add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
}
}
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 0a0708e95..14420f8a3 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -66,14 +66,8 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
*/
if (state->es_shader)
return strcmp(s1, s2);
- else {
-#if defined(_MSC_VER)
- /* MSVC doesn't have a strcasecmp() function; instead it has _stricmp. */
- return _stricmp(s1, s2);
-#else
+ else
return strcasecmp(s1, s2);
-#endif
- }
}
%}
@@ -1308,29 +1302,25 @@ layout_qualifier_id:
{
memset(& $$, 0, sizeof($$));
- if (state->has_explicit_attrib_location()) {
- if (match_layout_qualifier("location", $1, state) == 0) {
- $$.flags.q.explicit_location = 1;
+ if (match_layout_qualifier("location", $1, state) == 0) {
+ $$.flags.q.explicit_location = 1;
- if ($3 >= 0) {
- $$.location = $3;
- } else {
- _mesa_glsl_error(& @3, state,
- "invalid location %d specified", $3);
- YYERROR;
- }
+ if ($3 >= 0) {
+ $$.location = $3;
+ } else {
+ _mesa_glsl_error(& @3, state, "invalid location %d specified", $3);
+ YYERROR;
}
+ }
- if (match_layout_qualifier("index", $1, state) == 0) {
- $$.flags.q.explicit_index = 1;
+ if (match_layout_qualifier("index", $1, state) == 0) {
+ $$.flags.q.explicit_index = 1;
- if ($3 >= 0) {
- $$.index = $3;
- } else {
- _mesa_glsl_error(& @3, state,
- "invalid index %d specified", $3);
- YYERROR;
- }
+ if ($3 >= 0) {
+ $$.index = $3;
+ } else {
+ _mesa_glsl_error(& @3, state, "invalid index %d specified", $3);
+ YYERROR;
}
}
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index be17109e1..77e8816c4 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -118,6 +118,12 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxGeometryTotalOutputComponents = ctx->Const.MaxGeometryTotalOutputComponents;
this->Const.MaxGeometryUniformComponents = ctx->Const.GeometryProgram.MaxUniformComponents;
+ this->Const.MaxVertexAtomicCounters = ctx->Const.VertexProgram.MaxAtomicCounters;
+ this->Const.MaxGeometryAtomicCounters = ctx->Const.GeometryProgram.MaxAtomicCounters;
+ this->Const.MaxFragmentAtomicCounters = ctx->Const.FragmentProgram.MaxAtomicCounters;
+ this->Const.MaxCombinedAtomicCounters = ctx->Const.MaxCombinedAtomicCounters;
+ this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings;
+
this->current_function = NULL;
this->toplevel_ir = NULL;
this->found_return = false;
@@ -533,6 +539,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer),
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
EXT(ARB_texture_gather, true, false, ARB_texture_gather),
+ EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
};
#undef EXT
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index a67438412..f22dac355 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -69,6 +69,10 @@ typedef struct YYLTYPE {
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
+extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
+ const char *fmt, ...);
+
+
struct _mesa_glsl_parse_state {
_mesa_glsl_parse_state(struct gl_context *_ctx, GLenum target,
void *mem_ctx);
@@ -121,6 +125,22 @@ struct _mesa_glsl_parse_state {
return check_version(130, 300, locp, "bit-wise operations are forbidden");
}
+ bool check_explicit_attrib_location_allowed(YYLTYPE *locp,
+ const ir_variable *var)
+ {
+ if (!this->has_explicit_attrib_location()) {
+ const char *const requirement = this->es_shader
+ ? "GLSL ES 300"
+ : "GL_ARB_explicit_attrib_location extension or GLSL 330";
+
+ _mesa_glsl_error(locp, this, "%s explicit location requires %s",
+ mode_string(var), requirement);
+ return false;
+ }
+
+ return true;
+ }
+
bool has_explicit_attrib_location() const
{
return ARB_explicit_attrib_location_enable || is_version(330, 300);
@@ -229,6 +249,13 @@ struct _mesa_glsl_parse_state {
unsigned MaxGeometryOutputVertices;
unsigned MaxGeometryTotalOutputComponents;
unsigned MaxGeometryUniformComponents;
+
+ /* ARB_shader_atomic_counters */
+ unsigned MaxVertexAtomicCounters;
+ unsigned MaxGeometryAtomicCounters;
+ unsigned MaxFragmentAtomicCounters;
+ unsigned MaxCombinedAtomicCounters;
+ unsigned MaxAtomicBufferBindings;
} Const;
/**
@@ -325,6 +352,8 @@ struct _mesa_glsl_parse_state {
bool ARB_shading_language_420pack_warn;
bool EXT_shader_integer_mix_enable;
bool EXT_shader_integer_mix_warn;
+ bool ARB_shader_atomic_counters_enable;
+ bool ARB_shader_atomic_counters_warn;
/*@}*/
/** Extensions supported by the OpenGL implementation. */
@@ -363,9 +392,6 @@ do { \
(Current).source = 0; \
} while (0)
-extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
- const char *fmt, ...);
-
/**
* Emit a warning to the shader log
*
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index bc8d87f5f..f74013096 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -168,6 +168,24 @@ glsl_type::contains_integer() const
}
}
+bool
+glsl_type::contains_opaque() const {
+ switch (base_type) {
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_ATOMIC_UINT:
+ return true;
+ case GLSL_TYPE_ARRAY:
+ return element_type()->contains_opaque();
+ case GLSL_TYPE_STRUCT:
+ for (unsigned int i = 0; i < length; i++) {
+ if (fields.structure[i].type->contains_opaque())
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
gl_texture_index
glsl_type::sampler_index() const
@@ -601,6 +619,7 @@ glsl_type::component_slots() const
return this->length * this->fields.array->component_slots();
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
break;
@@ -889,6 +908,7 @@ glsl_type::count_attribute_slots() const
return this->length * this->fields.array->count_attribute_slots();
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
break;
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index 4b5b6efb3..fdb1f3a6e 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -53,6 +53,7 @@ enum glsl_base_type {
GLSL_TYPE_FLOAT,
GLSL_TYPE_BOOL,
GLSL_TYPE_SAMPLER,
+ GLSL_TYPE_ATOMIC_UINT,
GLSL_TYPE_STRUCT,
GLSL_TYPE_INTERFACE,
GLSL_TYPE_ARRAY,
@@ -441,6 +442,32 @@ struct glsl_type {
}
/**
+ * Return the amount of atomic counter storage required for a type.
+ */
+ unsigned atomic_size() const
+ {
+ if (base_type == GLSL_TYPE_ATOMIC_UINT)
+ return ATOMIC_COUNTER_SIZE;
+ else if (is_array())
+ return length * element_type()->atomic_size();
+ else
+ return 0;
+ }
+
+ /**
+ * Return whether a type contains any atomic counters.
+ */
+ bool contains_atomic() const
+ {
+ return atomic_size();
+ }
+
+ /**
+ * Return whether a type contains any opaque types.
+ */
+ bool contains_opaque() const;
+
+ /**
* Query the full type of a matrix row
*
* \return
@@ -468,7 +495,6 @@ struct glsl_type {
: error_type;
}
-
/**
* Get the type of a structure field
*
@@ -478,13 +504,11 @@ struct glsl_type {
*/
const glsl_type *field_type(const char *name) const;
-
/**
* Get the location of a filed within a record type
*/
int field_index(const char *name) const;
-
/**
* Query the number of elements in an array type
*
@@ -499,6 +523,14 @@ struct glsl_type {
}
/**
+ * Query whether the array size for all dimensions has been declared.
+ */
+ bool is_unsized_array() const
+ {
+ return is_array() && length == 0;
+ }
+
+ /**
* Return the number of coordinate components needed for this sampler type.
*
* This is based purely on the sampler's dimensionality. For example, this
diff --git a/mesalib/src/glsl/hir_field_selection.cpp b/mesalib/src/glsl/hir_field_selection.cpp
index 08be74365..1e92c89ae 100644
--- a/mesalib/src/glsl/hir_field_selection.cpp
+++ b/mesalib/src/glsl/hir_field_selection.cpp
@@ -72,7 +72,7 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr,
_mesa_glsl_error(&loc, state, "length method takes no arguments");
if (op->type->is_array()) {
- if (op->type->array_size() == 0)
+ if (op->type->is_unsized_array())
_mesa_glsl_error(&loc, state, "length called on unsized array");
result = new(ctx) ir_constant(op->type->array_size());
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index c682e3ed5..1b4973612 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -1586,7 +1586,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
ir_variable_mode mode)
: max_array_access(0), max_ifc_array_access(NULL),
read_only(false), centroid(false), invariant(false),
- mode(mode), interpolation(INTERP_QUALIFIER_NONE)
+ mode(mode), interpolation(INTERP_QUALIFIER_NONE), atomic()
{
this->ir_type = ir_type_variable;
this->type = type;
@@ -1647,8 +1647,8 @@ ir_variable::determine_interpolation_mode(bool flat_shade)
ir_function_signature::ir_function_signature(const glsl_type *return_type,
builtin_available_predicate b)
- : return_type(return_type), is_defined(false), builtin_avail(b),
- _function(NULL)
+ : return_type(return_type), is_defined(false), is_intrinsic(false),
+ builtin_avail(b), _function(NULL)
{
this->ir_type = ir_type_function_signature;
this->origin = NULL;
@@ -1891,3 +1891,46 @@ vertices_per_prim(GLenum prim)
return 3;
}
}
+
+/**
+ * Generate a string describing the mode of a variable
+ */
+const char *
+mode_string(const ir_variable *var)
+{
+ switch (var->mode) {
+ case ir_var_auto:
+ return (var->read_only) ? "global constant" : "global variable";
+
+ case ir_var_uniform:
+ return "uniform";
+
+ case ir_var_shader_in:
+ return "shader input";
+
+ case ir_var_shader_out:
+ return "shader output";
+
+ case ir_var_function_in:
+ case ir_var_const_in:
+ return "function input";
+
+ case ir_var_function_out:
+ return "function output";
+
+ case ir_var_function_inout:
+ return "function inout";
+
+ case ir_var_system_value:
+ return "shader input";
+
+ case ir_var_temporary:
+ return "compiler temporary";
+
+ case ir_var_mode_count:
+ break;
+ }
+
+ assert(!"Should not get here.");
+ return "invalid variable";
+}
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 8d5bec9c1..5b30fe59b 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -639,6 +639,14 @@ public:
int binding;
/**
+ * Location an atomic counter is stored at.
+ */
+ struct {
+ unsigned buffer_index;
+ unsigned offset;
+ } atomic;
+
+ /**
* Built-in state that backs this uniform
*
* Once set at variable creation, \c state_slots must remain invariant.
@@ -779,6 +787,12 @@ public:
/** Whether or not this function signature is a built-in. */
bool is_builtin() const;
+ /**
+ * Whether or not this function is an intrinsic to be implemented
+ * by the driver.
+ */
+ bool is_intrinsic;
+
/** Whether or not a built-in is available for this shader. */
bool is_builtin_available(const _mesa_glsl_parse_state *state) const;
@@ -2292,6 +2306,9 @@ extern char *
prototype_string(const glsl_type *return_type, const char *name,
exec_list *parameters);
+const char *
+mode_string(const ir_variable *var);
+
extern "C" {
#endif /* __cplusplus */
diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp
index 105f9063a..b0f173a62 100644
--- a/mesalib/src/glsl/ir_clone.cpp
+++ b/mesalib/src/glsl/ir_clone.cpp
@@ -57,6 +57,8 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
var->location = this->location;
var->index = this->index;
var->binding = this->binding;
+ var->atomic.buffer_index = this->atomic.buffer_index;
+ var->atomic.offset = this->atomic.offset;
var->warn_extension = this->warn_extension;
var->origin_upper_left = this->origin_upper_left;
var->pixel_center_integer = this->pixel_center_integer;
@@ -395,6 +397,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
}
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h
index 8198c4819..13faab7c0 100644
--- a/mesalib/src/glsl/ir_uniform.h
+++ b/mesalib/src/glsl/ir_uniform.h
@@ -166,6 +166,13 @@ struct gl_uniform_storage {
bool row_major;
/** @} */
+
+ /**
+ * Index within gl_shader_program::AtomicBuffers[] of the atomic
+ * counter buffer this uniform is stored in, or -1 if this is not
+ * an atomic counter.
+ */
+ int atomic_buffer_index;
};
#ifdef __cplusplus
diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp
index fd8009998..68aa62032 100644
--- a/mesalib/src/glsl/link_functions.cpp
+++ b/mesalib/src/glsl/link_functions.cpp
@@ -155,14 +155,17 @@ public:
linked_sig->replace_parameters(&formal_parameters);
- foreach_list_const(node, &sig->body) {
- const ir_instruction *const original = (ir_instruction *) node;
+ if (sig->is_defined) {
+ foreach_list_const(node, &sig->body) {
+ const ir_instruction *const original = (ir_instruction *) node;
- ir_instruction *copy = original->clone(linked, ht);
- linked_sig->body.push_tail(copy);
+ ir_instruction *copy = original->clone(linked, ht);
+ linked_sig->body.push_tail(copy);
+ }
+
+ linked_sig->is_defined = true;
}
- linked_sig->is_defined = true;
hash_table_dtor(ht);
/* Patch references inside the function to things outside the function
@@ -307,7 +310,8 @@ find_matching_signature(const char *name, const exec_list *actual_parameters,
ir_function_signature *sig =
f->matching_signature(NULL, actual_parameters);
- if ((sig == NULL) || !sig->is_defined)
+ if ((sig == NULL) ||
+ (!sig->is_defined && !sig->is_intrinsic))
continue;
/* If this function expects to bind to a built-in function and the
diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp
index 3f6671047..786aaf0b4 100644
--- a/mesalib/src/glsl/link_uniform_initializers.cpp
+++ b/mesalib/src/glsl/link_uniform_initializers.cpp
@@ -69,6 +69,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
break;
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_STRUCT:
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index ea71b3063..0a15739c2 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -513,6 +513,7 @@ private:
this->uniforms[id].num_driver_storage = 0;
this->uniforms[id].driver_storage = NULL;
this->uniforms[id].storage = this->values;
+ this->uniforms[id].atomic_buffer_index = -1;
if (this->ubo_block_index != -1) {
this->uniforms[id].block_index = this->ubo_block_index;
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index d8f655c39..49bb142a8 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -558,29 +558,6 @@ validate_geometry_shader_executable(struct gl_shader_program *prog,
/**
- * Generate a string describing the mode of a variable
- */
-static const char *
-mode_string(const ir_variable *var)
-{
- switch (var->mode) {
- case ir_var_auto:
- return (var->read_only) ? "global constant" : "global variable";
-
- case ir_var_uniform: return "uniform";
- case ir_var_shader_in: return "shader input";
- case ir_var_shader_out: return "shader output";
-
- case ir_var_const_in:
- case ir_var_temporary:
- default:
- assert(!"Should not get here.");
- return "invalid variable";
- }
-}
-
-
-/**
* Perform validation of global variables used across multiple shaders
*/
void
@@ -1108,7 +1085,7 @@ private:
*/
static void fixup_type(const glsl_type **type, unsigned max_array_access)
{
- if ((*type)->is_array() && (*type)->length == 0) {
+ if ((*type)->is_unsized_array()) {
*type = glsl_type::get_array_instance((*type)->fields.array,
max_array_access + 1);
assert(*type != NULL);
@@ -1123,7 +1100,7 @@ private:
{
for (unsigned i = 0; i < type->length; i++) {
const glsl_type *elem_type = type->fields.structure[i].type;
- if (elem_type->is_array() && elem_type->length == 0)
+ if (elem_type->is_unsized_array())
return true;
}
return false;
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp
index 37b2f02c6..a07e153ae 100644
--- a/mesalib/src/glsl/opt_algebraic.cpp
+++ b/mesalib/src/glsl/opt_algebraic.cpp
@@ -32,8 +32,11 @@
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h"
+#include "ir_builder.h"
#include "glsl_types.h"
+using namespace ir_builder;
+
namespace {
/**
@@ -194,7 +197,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
{
ir_constant *op_const[4] = {NULL, NULL, NULL, NULL};
ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL};
- ir_expression *temp;
unsigned int i;
assert(ir->get_num_operands() <= 4);
@@ -217,12 +219,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
switch (op_expr[0]->operation) {
case ir_unop_abs:
case ir_unop_neg:
- this->progress = true;
- temp = new(mem_ctx) ir_expression(ir_unop_abs,
- ir->type,
- op_expr[0]->operands[0],
- NULL);
- return swizzle_if_required(ir, temp);
+ return abs(op_expr[0]->operands[0]);
default:
break;
}
@@ -233,8 +230,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
break;
if (op_expr[0]->operation == ir_unop_neg) {
- this->progress = true;
- return swizzle_if_required(ir, op_expr[0]->operands[0]);
+ return op_expr[0]->operands[0];
}
break;
@@ -261,7 +257,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
}
if (new_op != ir_unop_logic_not) {
- this->progress = true;
return new(mem_ctx) ir_expression(new_op,
ir->type,
op_expr[0]->operands[0],
@@ -272,14 +267,10 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
}
case ir_binop_add:
- if (is_vec_zero(op_const[0])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[1]);
- }
- if (is_vec_zero(op_const[1])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[0]);
- }
+ if (is_vec_zero(op_const[0]))
+ return ir->operands[1];
+ if (is_vec_zero(op_const[1]))
+ return ir->operands[0];
/* Reassociate addition of constants so that we can do constant
* folding.
@@ -291,50 +282,25 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
break;
case ir_binop_sub:
- if (is_vec_zero(op_const[0])) {
- this->progress = true;
- temp = new(mem_ctx) ir_expression(ir_unop_neg,
- ir->operands[1]->type,
- ir->operands[1],
- NULL);
- return swizzle_if_required(ir, temp);
- }
- if (is_vec_zero(op_const[1])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[0]);
- }
+ if (is_vec_zero(op_const[0]))
+ return neg(ir->operands[1]);
+ if (is_vec_zero(op_const[1]))
+ return ir->operands[0];
break;
case ir_binop_mul:
- if (is_vec_one(op_const[0])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[1]);
- }
- if (is_vec_one(op_const[1])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[0]);
- }
+ if (is_vec_one(op_const[0]))
+ return ir->operands[1];
+ if (is_vec_one(op_const[1]))
+ return ir->operands[0];
- if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
- this->progress = true;
+ if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1]))
return ir_constant::zero(ir, ir->type);
- }
- if (is_vec_negative_one(op_const[0])) {
- this->progress = true;
- temp = new(mem_ctx) ir_expression(ir_unop_neg,
- ir->operands[1]->type,
- ir->operands[1],
- NULL);
- return swizzle_if_required(ir, temp);
- }
- if (is_vec_negative_one(op_const[1])) {
- this->progress = true;
- temp = new(mem_ctx) ir_expression(ir_unop_neg,
- ir->operands[0]->type,
- ir->operands[0],
- NULL);
- return swizzle_if_required(ir, temp);
- }
+
+ if (is_vec_negative_one(op_const[0]))
+ return neg(ir->operands[1]);
+ if (is_vec_negative_one(op_const[1]))
+ return neg(ir->operands[0]);
/* Reassociate multiplication of constants so that we can do
@@ -349,26 +315,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
case ir_binop_div:
if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
- this->progress = true;
- temp = new(mem_ctx) ir_expression(ir_unop_rcp,
+ return new(mem_ctx) ir_expression(ir_unop_rcp,
ir->operands[1]->type,
ir->operands[1],
NULL);
- return swizzle_if_required(ir, temp);
- }
- if (is_vec_one(op_const[1])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[0]);
}
+ if (is_vec_one(op_const[1]))
+ return ir->operands[0];
break;
case ir_binop_dot:
- if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
- this->progress = true;
+ if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1]))
return ir_constant::zero(mem_ctx, ir->type);
- }
+
if (is_vec_basis(op_const[0])) {
- this->progress = true;
unsigned component = 0;
for (unsigned c = 0; c < op_const[0]->type->vector_elements; c++) {
if (op_const[0]->value.f[c] == 1.0)
@@ -377,7 +337,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
return new(mem_ctx) ir_swizzle(ir->operands[1], component, 0, 0, 0, 1);
}
if (is_vec_basis(op_const[1])) {
- this->progress = true;
unsigned component = 0;
for (unsigned c = 0; c < op_const[1]->type->vector_elements; c++) {
if (op_const[1]->value.f[c] == 1.0)
@@ -387,46 +346,52 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
}
break;
+ case ir_binop_rshift:
+ case ir_binop_lshift:
+ /* 0 >> x == 0 */
+ if (is_vec_zero(op_const[0]))
+ return ir->operands[0];
+ /* x >> 0 == x */
+ if (is_vec_zero(op_const[1]))
+ return ir->operands[0];
+ break;
+
case ir_binop_logic_and:
/* FINISHME: Also simplify (a && a) to (a). */
if (is_vec_one(op_const[0])) {
- this->progress = true;
return ir->operands[1];
} else if (is_vec_one(op_const[1])) {
- this->progress = true;
return ir->operands[0];
} else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
- this->progress = true;
return ir_constant::zero(mem_ctx, ir->type);
+ } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not &&
+ op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) {
+ /* De Morgan's Law:
+ * (not A) and (not B) === not (A or B)
+ */
+ return logic_not(logic_or(op_expr[0]->operands[0],
+ op_expr[1]->operands[0]));
}
break;
case ir_binop_logic_xor:
/* FINISHME: Also simplify (a ^^ a) to (false). */
if (is_vec_zero(op_const[0])) {
- this->progress = true;
return ir->operands[1];
} else if (is_vec_zero(op_const[1])) {
- this->progress = true;
return ir->operands[0];
} else if (is_vec_one(op_const[0])) {
- this->progress = true;
- return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
- ir->operands[1], NULL);
+ return logic_not(ir->operands[1]);
} else if (is_vec_one(op_const[1])) {
- this->progress = true;
- return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
- ir->operands[0], NULL);
+ return logic_not(ir->operands[0]);
}
break;
case ir_binop_logic_or:
/* FINISHME: Also simplify (a || a) to (a). */
if (is_vec_zero(op_const[0])) {
- this->progress = true;
return ir->operands[1];
} else if (is_vec_zero(op_const[1])) {
- this->progress = true;
return ir->operands[0];
} else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
ir_constant_data data;
@@ -434,16 +399,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
for (unsigned i = 0; i < 16; i++)
data.b[i] = true;
- this->progress = true;
return new(mem_ctx) ir_constant(ir->type, &data);
+ } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not &&
+ op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) {
+ /* De Morgan's Law:
+ * (not A) or (not B) === not (A and B)
+ */
+ return logic_not(logic_and(op_expr[0]->operands[0],
+ op_expr[1]->operands[0]));
}
break;
case ir_unop_rcp:
- if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
- this->progress = true;
+ if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp)
return op_expr[0]->operands[0];
- }
/* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
* backends, except that some backends will have done sqrt ->
@@ -452,12 +421,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
/* As far as we know, all backends are OK with rsq. */
if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
- this->progress = true;
- temp = new(mem_ctx) ir_expression(ir_unop_rsq,
- op_expr[0]->operands[0]->type,
- op_expr[0]->operands[0],
- NULL);
- return swizzle_if_required(ir, temp);
+ return rsq(op_expr[0]->operands[0]);
}
break;
@@ -465,11 +429,9 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
case ir_triop_lrp:
/* Operands are (x, y, a). */
if (is_vec_zero(op_const[2])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[0]);
+ return ir->operands[0];
} else if (is_vec_one(op_const[2])) {
- this->progress = true;
- return swizzle_if_required(ir, ir->operands[1]);
+ return ir->operands[1];
}
break;
@@ -490,7 +452,17 @@ ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
if (!expr || expr->operation == ir_quadop_vector)
return;
- *rvalue = handle_expression(expr);
+ ir_rvalue *new_rvalue = handle_expression(expr);
+ if (new_rvalue == *rvalue)
+ return;
+
+ /* If the expr used to be some vec OP scalar returning a vector, and the
+ * optimization gave us back a scalar, we still need to turn it into a
+ * vector.
+ */
+ *rvalue = swizzle_if_required(expr, new_rvalue);
+
+ this->progress = true;
}
bool
diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp
index 34ac836ae..c7c5f6712 100644
--- a/mesalib/src/glsl/opt_array_splitting.cpp
+++ b/mesalib/src/glsl/opt_array_splitting.cpp
@@ -132,7 +132,7 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var)
/* If the array hasn't been sized yet, we can't split it. After
* linking, this should be resolved.
*/
- if (var->type->is_array() && var->type->length == 0)
+ if (var->type->is_unsized_array())
return NULL;
foreach_iter(exec_list_iterator, iter, this->variable_list) {
diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
index 7e8cd4372..b336bc0a8 100644
--- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
+++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
@@ -42,9 +42,11 @@
* If any texture coordinate slots can be eliminated, the gl_TexCoord array is
* broken down into separate vec4 variables with locations equal to
* VARYING_SLOT_TEX0 + i.
+ *
+ * The same is done for the gl_FragData fragment shader output.
*/
-#include "main/imports.h" /* for snprintf */
+#include "main/core.h" /* for snprintf and ARRAY_SIZE */
#include "ir.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h"
@@ -60,10 +62,14 @@ namespace {
class varying_info_visitor : public ir_hierarchical_visitor {
public:
/* "mode" can be either ir_var_shader_in or ir_var_shader_out */
- varying_info_visitor(ir_variable_mode mode)
+ varying_info_visitor(ir_variable_mode mode, bool find_frag_outputs = false)
: lower_texcoord_array(true),
texcoord_array(NULL),
texcoord_usage(0),
+ find_frag_outputs(find_frag_outputs),
+ lower_fragdata_array(true),
+ fragdata_array(NULL),
+ fragdata_usage(0),
color_usage(0),
tfeedback_color_usage(0),
fog(NULL),
@@ -79,8 +85,27 @@ public:
{
ir_variable *var = ir->variable_referenced();
- if (var && var->mode == this->mode &&
- var->location == VARYING_SLOT_TEX0) {
+ if (!var || var->mode != this->mode)
+ return visit_continue;
+
+ if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) {
+ this->fragdata_array = var;
+
+ ir_constant *index = ir->array_index->as_constant();
+ if (index == NULL) {
+ /* This is variable indexing. */
+ this->fragdata_usage |= (1 << var->type->array_size()) - 1;
+ this->lower_fragdata_array = false;
+ }
+ else {
+ this->fragdata_usage |= 1 << index->get_uint_component(0);
+ }
+
+ /* Don't visit the leaves of ir_dereference_array. */
+ return visit_continue_with_parent;
+ }
+
+ if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) {
this->texcoord_array = var;
ir_constant *index = ir->array_index->as_constant();
@@ -105,8 +130,17 @@ public:
{
ir_variable *var = ir->variable_referenced();
- if (var->mode == this->mode && var->type->is_array() &&
- var->location == VARYING_SLOT_TEX0) {
+ if (var->mode != this->mode || !var->type->is_array())
+ return visit_continue;
+
+ if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) {
+ /* This is a whole array dereference. */
+ this->fragdata_usage |= (1 << var->type->array_size()) - 1;
+ this->lower_fragdata_array = false;
+ return visit_continue;
+ }
+
+ if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) {
/* This is a whole array dereference like "gl_TexCoord = x;",
* there's probably no point in lowering that.
*/
@@ -121,6 +155,10 @@ public:
if (var->mode != this->mode)
return visit_continue;
+ /* Nothing to do here for fragment outputs. */
+ if (this->find_frag_outputs)
+ return visit_continue;
+
/* Handle colors and fog. */
switch (var->location) {
case VARYING_SLOT_COL0:
@@ -185,12 +223,20 @@ public:
if (!this->texcoord_array) {
this->lower_texcoord_array = false;
}
+ if (!this->fragdata_array) {
+ this->lower_fragdata_array = false;
+ }
}
bool lower_texcoord_array;
ir_variable *texcoord_array;
unsigned texcoord_usage; /* bitmask */
+ bool find_frag_outputs; /* false if it's looking for varyings */
+ bool lower_fragdata_array;
+ ir_variable *fragdata_array;
+ unsigned fragdata_usage; /* bitmask */
+
ir_variable *color[2];
ir_variable *backcolor[2];
unsigned color_usage; /* bitmask */
@@ -222,6 +268,7 @@ public:
{
void *const ctx = ir;
+ memset(this->new_fragdata, 0, sizeof(this->new_fragdata));
memset(this->new_texcoord, 0, sizeof(this->new_texcoord));
memset(this->new_color, 0, sizeof(this->new_color));
memset(this->new_backcolor, 0, sizeof(this->new_backcolor));
@@ -236,31 +283,16 @@ public:
* occurences of gl_TexCoord will be replaced with.
*/
if (info->lower_texcoord_array) {
- for (int i = MAX_TEXTURE_COORD_UNITS-1; i >= 0; i--) {
- if (info->texcoord_usage & (1 << i)) {
- char name[32];
-
- if (!(external_texcoord_usage & (1 << i))) {
- /* This varying is unused in the next stage. Declare
- * a temporary instead of an output. */
- snprintf(name, 32, "gl_%s_TexCoord%i_dummy", mode_str, i);
- this->new_texcoord[i] =
- new (ctx) ir_variable(glsl_type::vec4_type, name,
- ir_var_temporary);
- }
- else {
- snprintf(name, 32, "gl_%s_TexCoord%i", mode_str, i);
- this->new_texcoord[i] =
- new(ctx) ir_variable(glsl_type::vec4_type, name,
- info->mode);
- this->new_texcoord[i]->location = VARYING_SLOT_TEX0 + i;
- this->new_texcoord[i]->explicit_location = true;
- this->new_texcoord[i]->explicit_index = 0;
- }
-
- ir->head->insert_before(new_texcoord[i]);
- }
- }
+ prepare_array(ir, this->new_texcoord, ARRAY_SIZE(this->new_texcoord),
+ VARYING_SLOT_TEX0, "TexCoord", mode_str,
+ info->texcoord_usage, external_texcoord_usage);
+ }
+
+ /* Handle gl_FragData in the same way like gl_TexCoord. */
+ if (info->lower_fragdata_array) {
+ prepare_array(ir, this->new_fragdata, ARRAY_SIZE(this->new_fragdata),
+ FRAG_RESULT_DATA0, "FragData", mode_str,
+ info->fragdata_usage, (1 << MAX_DRAW_BUFFERS) - 1);
}
/* Create dummy variables which will replace set-but-unused color and
@@ -301,6 +333,41 @@ public:
visit_list_elements(this, ir);
}
+ void prepare_array(exec_list *ir,
+ struct ir_variable **new_var,
+ int max_elements, unsigned start_location,
+ const char *var_name, const char *mode_str,
+ unsigned usage, unsigned external_usage)
+ {
+ void *const ctx = ir;
+
+ for (int i = max_elements-1; i >= 0; i--) {
+ if (usage & (1 << i)) {
+ char name[32];
+
+ if (!(external_usage & (1 << i))) {
+ /* This varying is unused in the next stage. Declare
+ * a temporary instead of an output. */
+ snprintf(name, 32, "gl_%s_%s%i_dummy", mode_str, var_name, i);
+ new_var[i] =
+ new (ctx) ir_variable(glsl_type::vec4_type, name,
+ ir_var_temporary);
+ }
+ else {
+ snprintf(name, 32, "gl_%s_%s%i", mode_str, var_name, i);
+ new_var[i] =
+ new(ctx) ir_variable(glsl_type::vec4_type, name,
+ this->info->mode);
+ new_var[i]->location = start_location + i;
+ new_var[i]->explicit_location = true;
+ new_var[i]->explicit_index = 0;
+ }
+
+ ir->head->insert_before(new_var[i]);
+ }
+ }
+ }
+
virtual ir_visitor_status visit(ir_variable *var)
{
/* Remove the gl_TexCoord array. */
@@ -309,6 +376,12 @@ public:
var->remove();
}
+ /* Remove the gl_FragData array. */
+ if (this->info->lower_fragdata_array &&
+ var == this->info->fragdata_array) {
+ var->remove();
+ }
+
/* Replace set-but-unused color and fog outputs with dummy variables. */
for (int i = 0; i < 2; i++) {
if (var == this->info->color[i] && this->new_color[i]) {
@@ -350,6 +423,19 @@ public:
}
}
+ /* Same for gl_FragData. */
+ if (this->info->lower_fragdata_array) {
+ /* gl_FragData[i] occurence */
+ ir_dereference_array *const da = (*rvalue)->as_dereference_array();
+
+ if (da && da->variable_referenced() == this->info->fragdata_array) {
+ unsigned i = da->array_index->as_constant()->get_uint_component(0);
+
+ *rvalue = new(ctx) ir_dereference_variable(this->new_fragdata[i]);
+ return;
+ }
+ }
+
/* Replace set-but-unused color and fog outputs with dummy variables. */
ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable();
if (!dv)
@@ -392,6 +478,7 @@ public:
private:
const varying_info_visitor *info;
+ ir_variable *new_fragdata[MAX_DRAW_BUFFERS];
ir_variable *new_texcoord[MAX_TEXTURE_COORD_UNITS];
ir_variable *new_color[2];
ir_variable *new_backcolor[2];
@@ -408,6 +495,15 @@ lower_texcoord_array(exec_list *ir, const varying_info_visitor *info)
1 | 2, true);
}
+static void
+lower_fragdata_array(exec_list *ir)
+{
+ varying_info_visitor info(ir_var_shader_out, true);
+ info.get(ir, 0, NULL);
+
+ replace_varyings_visitor(ir, &info, 0, 0, 0);
+}
+
void
do_dead_builtin_varyings(struct gl_context *ctx,
@@ -415,8 +511,13 @@ do_dead_builtin_varyings(struct gl_context *ctx,
unsigned num_tfeedback_decls,
tfeedback_decl *tfeedback_decls)
{
- /* This optimization has no effect with the core context and GLES2, because
- * the built-in varyings we're eliminating here are not available there.
+ /* Lower the gl_FragData array to separate variables. */
+ if (consumer && consumer->Type == GL_FRAGMENT_SHADER) {
+ lower_fragdata_array(consumer->ir);
+ }
+
+ /* Lowering of built-in varyings has no effect with the core context and
+ * GLES2, because they are not available there.
*
* EXT_separate_shader_objects doesn't allow this optimization,
* because a program object can be bound partially (e.g. only one
diff --git a/mesalib/src/glsl/opt_function_inlining.cpp b/mesalib/src/glsl/opt_function_inlining.cpp
index 0733d5180..f8033a095 100644
--- a/mesalib/src/glsl/opt_function_inlining.cpp
+++ b/mesalib/src/glsl/opt_function_inlining.cpp
@@ -35,9 +35,9 @@
#include "program/hash_table.h"
static void
-do_sampler_replacement(exec_list *instructions,
- ir_variable *sampler,
- ir_dereference *deref);
+do_variable_replacement(exec_list *instructions,
+ ir_variable *orig,
+ ir_dereference *repl);
namespace {
@@ -123,11 +123,11 @@ ir_call::generate_inline(ir_instruction *next_ir)
ir_rvalue *param = (ir_rvalue *) param_iter.get();
/* Generate a new variable for the parameter. */
- if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
- /* For samplers, we want the inlined sampler references
- * referencing the passed in sampler variable, since that
- * will have the location information, which an assignment of
- * a sampler wouldn't. Fix it up below.
+ if (sig_param->type->contains_opaque()) {
+ /* For opaque types, we want the inlined variable references
+ * referencing the passed in variable, since that will have
+ * the location information, which an assignment of an opaque
+ * variable wouldn't. Fix it up below.
*/
parameters[i] = NULL;
} else {
@@ -169,8 +169,8 @@ ir_call::generate_inline(ir_instruction *next_ir)
visit_tree(new_ir, replace_return_with_assignment, this->return_deref);
}
- /* If any samplers were passed in, replace any deref of the sampler
- * with a deref of the sampler argument.
+ /* If any opaque types were passed in, replace any deref of the
+ * opaque variable with a deref of the argument.
*/
param_iter = this->actual_parameters.iterator();
sig_param_iter = this->callee->parameters.iterator();
@@ -178,11 +178,11 @@ ir_call::generate_inline(ir_instruction *next_ir)
ir_instruction *const param = (ir_instruction *) param_iter.get();
ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
- if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
+ if (sig_param->type->contains_opaque()) {
ir_dereference *deref = param->as_dereference();
assert(deref);
- do_sampler_replacement(&new_instructions, sig_param, deref);
+ do_variable_replacement(&new_instructions, sig_param, deref);
}
param_iter.next();
sig_param_iter.next();
@@ -268,23 +268,23 @@ ir_function_inlining_visitor::visit_enter(ir_call *ir)
/**
- * Replaces references to the "sampler" variable with a clone of "deref."
+ * Replaces references to the "orig" variable with a clone of "repl."
*
- * From the spec, samplers can appear in the tree as function
+ * From the spec, opaque types can appear in the tree as function
* (non-out) parameters and as the result of array indexing and
* structure field selection. In our builtin implementation, they
* also appear in the sampler field of an ir_tex instruction.
*/
-class ir_sampler_replacement_visitor : public ir_hierarchical_visitor {
+class ir_variable_replacement_visitor : public ir_hierarchical_visitor {
public:
- ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref)
+ ir_variable_replacement_visitor(ir_variable *orig, ir_dereference *repl)
{
- this->sampler = sampler;
- this->deref = deref;
+ this->orig = orig;
+ this->repl = repl;
}
- virtual ~ir_sampler_replacement_visitor()
+ virtual ~ir_variable_replacement_visitor()
{
}
@@ -296,21 +296,21 @@ public:
void replace_deref(ir_dereference **deref);
void replace_rvalue(ir_rvalue **rvalue);
- ir_variable *sampler;
- ir_dereference *deref;
+ ir_variable *orig;
+ ir_dereference *repl;
};
void
-ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref)
+ir_variable_replacement_visitor::replace_deref(ir_dereference **deref)
{
ir_dereference_variable *deref_var = (*deref)->as_dereference_variable();
- if (deref_var && deref_var->var == this->sampler) {
- *deref = this->deref->clone(ralloc_parent(*deref), NULL);
+ if (deref_var && deref_var->var == this->orig) {
+ *deref = this->repl->clone(ralloc_parent(*deref), NULL);
}
}
void
-ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
+ir_variable_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
{
if (!*rvalue)
return;
@@ -325,7 +325,7 @@ ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
}
ir_visitor_status
-ir_sampler_replacement_visitor::visit_leave(ir_texture *ir)
+ir_variable_replacement_visitor::visit_leave(ir_texture *ir)
{
replace_deref(&ir->sampler);
@@ -333,21 +333,21 @@ ir_sampler_replacement_visitor::visit_leave(ir_texture *ir)
}
ir_visitor_status
-ir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir)
+ir_variable_replacement_visitor::visit_leave(ir_dereference_array *ir)
{
replace_rvalue(&ir->array);
return visit_continue;
}
ir_visitor_status
-ir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir)
+ir_variable_replacement_visitor::visit_leave(ir_dereference_record *ir)
{
replace_rvalue(&ir->record);
return visit_continue;
}
ir_visitor_status
-ir_sampler_replacement_visitor::visit_leave(ir_call *ir)
+ir_variable_replacement_visitor::visit_leave(ir_call *ir)
{
foreach_iter(exec_list_iterator, iter, *ir) {
ir_rvalue *param = (ir_rvalue *)iter.get();
@@ -362,11 +362,11 @@ ir_sampler_replacement_visitor::visit_leave(ir_call *ir)
}
static void
-do_sampler_replacement(exec_list *instructions,
- ir_variable *sampler,
- ir_dereference *deref)
+do_variable_replacement(exec_list *instructions,
+ ir_variable *orig,
+ ir_dereference *repl)
{
- ir_sampler_replacement_visitor v(sampler, deref);
+ ir_variable_replacement_visitor v(orig, repl);
visit_list_elements(&v, instructions);
}
diff --git a/mesalib/src/glsl/ralloc.h b/mesalib/src/glsl/ralloc.h
index 31682d515..4581a7a4e 100644
--- a/mesalib/src/glsl/ralloc.h
+++ b/mesalib/src/glsl/ralloc.h
@@ -415,15 +415,29 @@ bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args);
* which is more idiomatic in C++ than calling ralloc.
*/
#define DECLARE_RALLOC_CXX_OPERATORS(TYPE) \
+private: \
+ static void _ralloc_destructor(void *p) \
+ { \
+ reinterpret_cast<TYPE *>(p)->~TYPE(); \
+ } \
+public: \
static void* operator new(size_t size, void *mem_ctx) \
{ \
void *p = ralloc_size(mem_ctx, size); \
assert(p != NULL); \
+ if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \
+ ralloc_set_destructor(p, _ralloc_destructor); \
return p; \
} \
\
static void operator delete(void *p) \
{ \
+ /* The object's destructor is guaranteed to have already been \
+ * called by the delete operator at this point -- Make sure it's \
+ * not called again. \
+ */ \
+ if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \
+ ralloc_set_destructor(p, NULL); \
ralloc_free(p); \
}
diff --git a/mesalib/src/mapi/glapi/SConscript b/mesalib/src/mapi/glapi/SConscript
index c4ac080aa..152818d22 100644
--- a/mesalib/src/mapi/glapi/SConscript
+++ b/mesalib/src/mapi/glapi/SConscript
@@ -52,6 +52,7 @@ for s in mapi_sources:
if (env['gcc'] or env['clang']) and \
env['platform'] not in ('cygwin', 'darwin', 'windows'):
GLAPI = '#src/mapi/glapi/'
+ sources = [GLAPI + 'gen/gl_and_es_API.xml'] + env.Glob(GLAPI + 'gen/*.xml')
if env['machine'] == 'x86':
env.Append(CPPDEFINES = [
@@ -63,7 +64,7 @@ if (env['gcc'] or env['clang']) and \
env.CodeGenerate(
target = 'glapi_x86.S',
script = GLAPI + 'gen/gl_x86_asm.py',
- source = GLAPI + 'gen/gl_and_es_API.xml',
+ source = sources,
command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET'
)
elif env['machine'] == 'x86_64':
@@ -76,7 +77,7 @@ if (env['gcc'] or env['clang']) and \
env.CodeGenerate(
target = 'glapi_x86-64.S',
script = GLAPI + 'gen/gl_x86-64_asm.py',
- source = GLAPI + 'gen/gl_and_es_API.xml',
+ source = sources,
command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET'
)
elif env['machine'] == 'sparc':
@@ -89,7 +90,7 @@ if (env['gcc'] or env['clang']) and \
env.CodeGenerate(
target = 'glapi_sparc.S',
script = GLAPI + 'gen/gl_SPARC_asm.py',
- source = GLAPI + 'gen/gl_and_es_API.xml',
+ source = sources,
command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET'
)
else:
diff --git a/mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml b/mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml
new file mode 100644
index 000000000..f3b74e9c2
--- /dev/null
+++ b/mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_shader_atomic_counters" number="114">
+
+<enum name="ATOMIC_COUNTER_BUFFER" value="0x92C0"/>
+<enum name="ATOMIC_COUNTER_BUFFER_BINDING" value="0x92C1"/>
+<enum name="ATOMIC_COUNTER_BUFFER_START" value="0x92C2"/>
+<enum name="ATOMIC_COUNTER_BUFFER_SIZE" value="0x92C3"/>
+<enum name="ATOMIC_COUNTER_BUFFER_DATA_SIZE" value="0x92C4"/>
+<enum name="ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS" value="0x92C5"/>
+<enum name="ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES" value="0x92C6"/>
+<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER" value="0x92C7"/>
+<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER" value="0x92C8"/>
+<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER" value="0x92C9"/>
+<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER" value="0x92CA"/>
+<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER" value="0x92CB"/>
+<enum name="MAX_VERTEX_ATOMIC_COUNTER_BUFFERS" value="0x92CC"/>
+<enum name="MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS" value="0x92CD"/>
+<enum name="MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS" value="0x92CE"/>
+<enum name="MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS" value="0x92CF"/>
+<enum name="MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS" value="0x92D0"/>
+<enum name="MAX_COMBINED_ATOMIC_COUNTER_BUFFERS" value="0x92D1"/>
+<enum name="MAX_VERTEX_ATOMIC_COUNTERS" value="0x92D2"/>
+<enum name="MAX_TESS_CONTROL_ATOMIC_COUNTERS" value="0x92D3"/>
+<enum name="MAX_TESS_EVALUATION_ATOMIC_COUNTERS" value="0x92D4"/>
+<enum name="MAX_GEOMETRY_ATOMIC_COUNTERS" value="0x92D5"/>
+<enum name="MAX_FRAGMENT_ATOMIC_COUNTERS" value="0x92D6"/>
+<enum name="MAX_COMBINED_ATOMIC_COUNTERS" value="0x92D7"/>
+<enum name="MAX_ATOMIC_COUNTER_BUFFER_SIZE" value="0x92D8"/>
+<enum name="ACTIVE_ATOMIC_COUNTER_BUFFERS" value="0x92D9"/>
+<enum name="UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX" value="0x92DA"/>
+<enum name="UNSIGNED_INT_ATOMIC_COUNTER" value="0x92DB"/>
+<enum name="MAX_ATOMIC_COUNTER_BUFFER_BINDINGS" value="0x92DC"/>
+
+<function name="GetActiveAtomicCounterBufferiv" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="bufferIndex" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="params" type="GLint *" />
+</function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am
index d71d5d2a8..390245216 100644
--- a/mesalib/src/mapi/glapi/gen/Makefile.am
+++ b/mesalib/src/mapi/glapi/gen/Makefile.am
@@ -110,6 +110,7 @@ API_XML = \
ARB_robustness.xml \
ARB_sampler_objects.xml \
ARB_seamless_cube_map.xml \
+ ARB_shader_atomic_counters.xml \
ARB_sync.xml \
ARB_texture_buffer_object.xml \
ARB_texture_buffer_range.xml \
@@ -141,6 +142,7 @@ API_XML = \
NV_conditional_render.xml \
NV_primitive_restart.xml \
NV_texture_barrier.xml \
+ NV_vdpau_interop.xml \
OES_EGL_image.xml \
GL3x.xml
diff --git a/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml b/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml
new file mode 100644
index 000000000..cf5f0eddd
--- /dev/null
+++ b/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_NV_vdpau_interop" number="396">
+
+ <function name="VDPAUInitNV" offset="assign">
+ <param name="vdpDevice" type="const GLvoid *"/>
+ <param name="getProcAddress" type="const GLvoid *"/>
+ </function>
+
+ <function name="VDPAUFiniNV" offset="assign"/>
+
+ <function name="VDPAURegisterVideoSurfaceNV" offset="assign">
+ <return type="GLintptr"/>
+ <param name="vdpSurface" type="const GLvoid *"/>
+ <param name="target" type="GLenum"/>
+ <param name="numTextureNames" type="GLsizei"/>
+ <param name="textureNames" type="const GLuint *"/>
+ </function>
+
+ <function name="VDPAURegisterOutputSurfaceNV" offset="assign">
+ <return type="GLintptr"/>
+ <param name="vdpSurface" type="const GLvoid *"/>
+ <param name="target" type="GLenum"/>
+ <param name="numTextureNames" type="GLsizei"/>
+ <param name="textureNames" type="const GLuint *"/>
+ </function>
+
+ <function name="VDPAUIsSurfaceNV" offset="assign">
+ <param name="surface" type="GLintptr"/>
+ </function>
+
+ <function name="VDPAUUnregisterSurfaceNV" offset="assign">
+ <param name="surface" type="GLintptr"/>
+ </function>
+
+ <function name="VDPAUGetSurfaceivNV" offset="assign">
+ <param name="surface" type="GLintptr"/>
+ <param name="pname" type="GLenum"/>
+ <param name="bufSize" type="GLsizei"/>
+ <param name="length" type="GLsizei *"/>
+ <param name="values" type="GLint *"/>
+ </function>
+
+ <function name="VDPAUSurfaceAccessNV" offset="assign">
+ <param name="surface" type="GLintptr"/>
+ <param name="access" type="GLenum"/>
+ </function>
+
+ <function name="VDPAUMapSurfacesNV" offset="assign">
+ <param name="numSurfaces" type="GLsizei"/>
+ <param name="surfaces" type="const GLintptr *"/>
+ </function>
+
+ <function name="VDPAUUnmapSurfacesNV" offset="assign">
+ <param name="numSurfaces" type="GLsizei"/>
+ <param name="surfaces" type="const GLintptr *"/>
+ </function>
+
+ <enum name="SURFACE_STATE_NV" value="0x86EB"/>
+ <enum name="SURFACE_REGISTERED_NV" value="0x86FD"/>
+ <enum name="SURFACE_MAPPED_NV" value="0x8700"/>
+ <enum name="WRITE_DISCARD_NV" value="0x88BE"/>
+
+</category>
+
+</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml
index 30ab9c9c1..45d69b40a 100644
--- a/mesalib/src/mapi/glapi/gen/gl_API.xml
+++ b/mesalib/src/mapi/glapi/gen/gl_API.xml
@@ -8308,6 +8308,8 @@
<enum name="MIN_MAP_BUFFER_ALIGNMENT" value="0x90BC" />
</category>
+<xi:include href="ARB_shader_atomic_counters.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
<xi:include href="ARB_texture_storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<!-- ARB extension #118 -->
@@ -13118,4 +13120,6 @@
<xi:include href="EXT_transform_feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<xi:include href="NV_vdpau_interop.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py
index a074c2348..3ce190fe3 100644
--- a/mesalib/src/mapi/glapi/gen/gl_genexec.py
+++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py
@@ -111,6 +111,7 @@ header = """/**
#include "main/syncobj.h"
#include "main/formatquery.h"
#include "main/dispatch.h"
+#include "main/vdpau.h"
#include "vbo/vbo.h"
diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources
index ff242b4ab..a84f8a788 100644
--- a/mesalib/src/mesa/Makefile.sources
+++ b/mesalib/src/mesa/Makefile.sources
@@ -108,6 +108,7 @@ MAIN_FILES = \
$(SRCDIR)main/uniforms.c \
$(SRCDIR)main/uniform_query.cpp \
$(SRCDIR)main/varray.c \
+ $(SRCDIR)main/vdpau.c \
$(SRCDIR)main/version.c \
$(SRCDIR)main/viewport.c \
$(SRCDIR)main/vtxfmt.c \
@@ -248,7 +249,8 @@ STATETRACKER_FILES = \
$(SRCDIR)state_tracker/st_manager.c \
$(SRCDIR)state_tracker/st_mesa_to_tgsi.c \
$(SRCDIR)state_tracker/st_program.c \
- $(SRCDIR)state_tracker/st_texture.c
+ $(SRCDIR)state_tracker/st_texture.c \
+ $(SRCDIR)state_tracker/st_vdpau.c
PROGRAM_FILES = \
$(SRCDIR)program/arbprogparse.c \
diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript
index 9b7712faf..42134983c 100644
--- a/mesalib/src/mesa/SConscript
+++ b/mesalib/src/mesa/SConscript
@@ -140,6 +140,7 @@ main_sources = [
'main/uniform_query.cpp',
'main/uniforms.c',
'main/varray.c',
+ 'main/vdpau.c',
'main/version.c',
'main/viewport.c',
'main/vtxfmt.c',
@@ -287,6 +288,7 @@ statetracker_sources = [
'state_tracker/st_mesa_to_tgsi.c',
'state_tracker/st_program.c',
'state_tracker/st_texture.c',
+ 'state_tracker/st_vdpau.c',
]
env.Append(YACCFLAGS = '-d -p "_mesa_program_"')
diff --git a/mesalib/src/mesa/drivers/dri/common/Makefile.am b/mesalib/src/mesa/drivers/dri/common/Makefile.am
index 9f49ff3ae..7f87ed6f5 100644
--- a/mesalib/src/mesa/drivers/dri/common/Makefile.am
+++ b/mesalib/src/mesa/drivers/dri/common/Makefile.am
@@ -27,6 +27,7 @@ AM_CFLAGS = \
-I$(top_srcdir)/src/mapi \
-I$(top_srcdir)/src/mesa/ \
$(DEFINES) \
+ $(EXPAT_CFLAGS) \
$(VISIBILITY_CFLAGS)
noinst_LTLIBRARIES = \
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 312ffb788..1f5506157 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -102,6 +102,11 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
return &ctx->UniformBuffer;
}
break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ if (ctx->Extensions.ARB_shader_atomic_counters) {
+ return &ctx->AtomicBuffer;
+ }
+ break;
default:
return NULL;
}
@@ -2119,6 +2124,51 @@ bind_buffer_base_uniform_buffer(struct gl_context *ctx,
set_ubo_binding(ctx, index, bufObj, 0, 0, GL_TRUE);
}
+static void
+set_atomic_buffer_binding(struct gl_context *ctx,
+ unsigned index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset,
+ GLsizeiptr size,
+ const char *name)
+{
+ struct gl_atomic_buffer_binding *binding;
+
+ if (index >= ctx->Const.MaxAtomicBufferBindings) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index);
+ return;
+ }
+
+ if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(offset misalgned %d/%d)", name, (int) offset,
+ ATOMIC_COUNTER_SIZE);
+ return;
+ }
+
+ _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
+
+ binding = &ctx->AtomicBufferBindings[index];
+ if (binding->BufferObject == bufObj &&
+ binding->Offset == offset &&
+ binding->Size == size) {
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, 0);
+ ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
+
+ _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
+
+ if (bufObj == ctx->Shared->NullBufferObj) {
+ binding->Offset = -1;
+ binding->Size = -1;
+ } else {
+ binding->Offset = offset;
+ binding->Size = size;
+ }
+}
+
void GLAPIENTRY
_mesa_BindBufferRange(GLenum target, GLuint index,
GLuint buffer, GLintptr offset, GLsizeiptr size)
@@ -2156,6 +2206,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
case GL_UNIFORM_BUFFER:
bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
return;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ set_atomic_buffer_binding(ctx, index, bufObj, offset, size,
+ "glBindBufferRange");
+ return;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
return;
@@ -2215,6 +2269,10 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
case GL_UNIFORM_BUFFER:
bind_buffer_base_uniform_buffer(ctx, index, bufObj);
return;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ set_atomic_buffer_binding(ctx, index, bufObj, 0, 0,
+ "glBindBufferBase");
+ return;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
return;
diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h
index 0f27d5a66..d806d5b9d 100644
--- a/mesalib/src/mesa/main/compiler.h
+++ b/mesalib/src/mesa/main/compiler.h
@@ -444,7 +444,29 @@ do { \
#define Elements(x) (sizeof(x)/sizeof(*(x)))
#endif
-
+#ifdef __cplusplus
+/**
+ * Macro function that evaluates to true if T is a trivially
+ * destructible type -- that is, if its (non-virtual) destructor
+ * performs no action and all member variables and base classes are
+ * trivially destructible themselves.
+ */
+# if defined(__GNUC__)
+# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))
+# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# endif
+# elif (defined(__clang__) && defined(__has_feature))
+# if __has_feature(has_trivial_destructor)
+# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# endif
+# endif
+# ifndef HAS_TRIVIAL_DESTRUCTOR
+ /* It's always safe (if inefficient) to assume that a
+ * destructor is non-trivial.
+ */
+# define HAS_TRIVIAL_DESTRUCTOR(T) (false)
+# endif
+#endif
#ifdef __cplusplus
}
diff --git a/mesalib/src/mesa/main/config.h b/mesalib/src/mesa/main/config.h
index 0bcf27c34..22bbfa0cf 100644
--- a/mesalib/src/mesa/main/config.h
+++ b/mesalib/src/mesa/main/config.h
@@ -170,6 +170,11 @@
#define MAX_UNIFORM_BUFFERS 15 /* + 1 default uniform buffer */
/* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */
#define MAX_COMBINED_UNIFORM_BUFFERS (MAX_UNIFORM_BUFFERS * 6)
+#define MAX_ATOMIC_COUNTERS 4096
+/* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */
+#define MAX_COMBINED_ATOMIC_BUFFERS (MAX_UNIFORM_BUFFERS * 6)
+/* Size of an atomic counter in bytes according to ARB_shader_atomic_counters */
+#define ATOMIC_COUNTER_SIZE 4
/*@}*/
/**
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 0d1f71c71..6cdeed19b 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -537,6 +537,9 @@ init_program_limits(struct gl_context *ctx, GLenum type,
prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents +
ctx->Const.MaxUniformBlockSize / 4 *
prog->MaxUniformBlocks);
+
+ prog->MaxAtomicBuffers = 0;
+ prog->MaxAtomicCounters = 0;
}
@@ -669,6 +672,12 @@ _mesa_init_constants(struct gl_context *ctx)
ctx->Const.MaxColorTextureSamples = 1;
ctx->Const.MaxDepthTextureSamples = 1;
ctx->Const.MaxIntegerSamples = 1;
+
+ /* GL_ARB_shader_atomic_counters */
+ ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS;
+ ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
+ ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
+ ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
}
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index 29469ce33..501192199 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -868,6 +868,20 @@ struct dd_function_table {
struct gl_framebuffer *fb,
GLuint index,
GLfloat *outValue);
+
+ /**
+ * \name NV_vdpau_interop interface
+ */
+ void (*VDPAUMapSurface)(struct gl_context *ctx, GLenum target,
+ GLenum access, GLboolean output,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ const GLvoid *vdpSurface, GLuint index);
+ void (*VDPAUUnmapSurface)(struct gl_context *ctx, GLenum target,
+ GLenum access, GLboolean output,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ const GLvoid *vdpSurface, GLuint index);
};
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index e8e0a20d8..285ec377c 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -120,6 +120,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_robustness", o(dummy_true), GL, 2010 },
{ "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 },
{ "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 },
+ { "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 },
{ "GL_ARB_shader_bit_encoding", o(ARB_shader_bit_encoding), GL, 2010 },
{ "GL_ARB_shader_objects", o(dummy_true), GL, 2002 },
{ "GL_ARB_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 },
@@ -335,6 +336,7 @@ static const struct extension extension_table[] = {
{ "GL_NV_texture_barrier", o(NV_texture_barrier), GL, 2009 },
{ "GL_NV_texture_env_combine4", o(NV_texture_env_combine4), GLL, 1999 },
{ "GL_NV_texture_rectangle", o(NV_texture_rectangle), GLL, 2000 },
+ { "GL_NV_vdpau_interop", o(NV_vdpau_interop), GL, 2010 },
{ "GL_S3_s3tc", o(ANGLE_texture_compression_dxt), GL, 1999 },
{ "GL_SGIS_generate_mipmap", o(dummy_true), GLL, 1997 },
{ "GL_SGIS_texture_border_clamp", o(ARB_texture_border_clamp), GLL, 1997 },
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 89b3bf09d..6e72ff5c2 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -143,6 +143,7 @@ enum value_extra {
EXTRA_FLUSH_CURRENT,
EXTRA_GLSL_130,
EXTRA_EXT_UBO_GS4,
+ EXTRA_EXT_ATOMICS_GS4,
};
#define NO_EXTRA NULL
@@ -331,6 +332,11 @@ static const int extra_MESA_texture_array_es3[] = {
EXTRA_END
};
+static const int extra_ARB_shader_atomic_counters_and_geometry_shader[] = {
+ EXTRA_EXT_ATOMICS_GS4,
+ EXTRA_END
+};
+
EXTRA_EXT(ARB_texture_cube_map);
EXTRA_EXT(MESA_texture_array);
EXTRA_EXT(NV_fog_distance);
@@ -367,6 +373,7 @@ EXTRA_EXT(ARB_texture_cube_map_array);
EXTRA_EXT(ARB_texture_buffer_range);
EXTRA_EXT(ARB_texture_multisample);
EXTRA_EXT(ARB_texture_gather);
+EXTRA_EXT(ARB_shader_atomic_counters);
static const int
extra_ARB_color_buffer_float_or_glcore[] = {
@@ -894,6 +901,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
_mesa_problem(ctx, "driver doesn't implement GetTimestamp");
}
break;
+ /* GL_ARB_shader_atomic_counters */
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ v->value_int = ctx->AtomicBuffer->Name;
+ break;
}
}
@@ -999,6 +1010,11 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d
api_found = (ctx->Extensions.ARB_uniform_buffer_object &&
_mesa_has_geometry_shaders(ctx));
break;
+ case EXTRA_EXT_ATOMICS_GS4:
+ api_check = GL_TRUE;
+ api_found = (ctx->Extensions.ARB_shader_atomic_counters &&
+ _mesa_has_geometry_shaders(ctx));
+ break;
case EXTRA_END:
break;
default: /* *e is a offset into the extension struct */
@@ -1692,6 +1708,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
goto invalid_enum;
v->value_int = ctx->Multisample.SampleMaskValue;
return TYPE_INT;
+
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ if (!ctx->Extensions.ARB_shader_atomic_counters)
+ goto invalid_enum;
+ if (index >= ctx->Const.MaxAtomicBufferBindings)
+ goto invalid_value;
+ v->value_int = ctx->AtomicBufferBindings[index].BufferObject->Name;
+ return TYPE_INT;
+
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ if (!ctx->Extensions.ARB_shader_atomic_counters)
+ goto invalid_enum;
+ if (index >= ctx->Const.MaxAtomicBufferBindings)
+ goto invalid_value;
+ v->value_int64 = ctx->AtomicBufferBindings[index].Offset;
+ return TYPE_INT64;
+
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ if (!ctx->Extensions.ARB_shader_atomic_counters)
+ goto invalid_enum;
+ if (index >= ctx->Const.MaxAtomicBufferBindings)
+ goto invalid_value;
+ v->value_int64 = ctx->AtomicBufferBindings[index].Size;
+ return TYPE_INT64;
}
invalid_enum:
diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py
index 9c54af094..9f79f3406 100644
--- a/mesalib/src/mesa/main/get_hash_params.py
+++ b/mesalib/src/mesa/main/get_hash_params.py
@@ -722,6 +722,18 @@ descriptor=[
[ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather"],
[ "MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB", "CONTEXT_INT(Const.MaxProgramTextureGatherComponents), extra_ARB_texture_gather"],
+# GL_ARB_shader_atomic_counters
+ [ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters" ],
+ [ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_geometry_shader" ],
+ [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ],
+ [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ],
+ [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ],
]},
# Enums restricted to OpenGL Core profile
diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h
index 53e40b445..d79e2a339 100644
--- a/mesalib/src/mesa/main/imports.h
+++ b/mesalib/src/mesa/main/imports.h
@@ -141,6 +141,7 @@ static inline float acoshf(float x) { return logf(x + sqrtf(x * x - 1.0f)); }
static inline float atanhf(float x) { return (logf(1.0f + x) - logf(1.0f - x)) / 2.0f; }
static inline int isblank(int ch) { return ch == ' ' || ch == '\t'; }
#define strtoll(p, e, b) _strtoi64(p, e, b)
+#define strcasecmp(s1, s2) _stricmp(s1, s2)
#endif
/*@}*/
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 97ed1bd6a..a1a5eb4bf 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -2375,6 +2375,25 @@ struct gl_uniform_block
enum gl_uniform_block_packing _Packing;
};
+/**
+ * Structure that represents a reference to an atomic buffer from some
+ * shader program.
+ */
+struct gl_active_atomic_buffer
+{
+ /** Uniform indices of the atomic counters declared within it. */
+ GLuint *Uniforms;
+ GLuint NumUniforms;
+
+ /** Binding point index associated with it. */
+ GLuint Binding;
+
+ /** Minimum reasonable size it is expected to have. */
+ GLuint MinimumSize;
+
+ /** Shader stages making use of it. */
+ GLboolean StageReferences[MESA_SHADER_TYPES];
+};
/**
* A GLSL program object.
@@ -2523,6 +2542,9 @@ struct gl_shader_program
*/
struct string_to_uint_map *UniformHash;
+ struct gl_active_atomic_buffer *AtomicBuffers;
+ unsigned NumAtomicBuffers;
+
GLboolean LinkStatus; /**< GL_LINK_STATUS */
GLboolean Validated;
GLboolean _Used; /**< Ever used for drawing? */
@@ -2960,6 +2982,9 @@ struct gl_program_constants
GLuint MaxUniformBlocks;
GLuint MaxCombinedUniformComponents;
GLuint MaxTextureImageUnits;
+ /* GL_ARB_shader_atomic_counters */
+ GLuint MaxAtomicBuffers;
+ GLuint MaxAtomicCounters;
};
@@ -3166,6 +3191,12 @@ struct gl_constants
GLint MaxColorTextureSamples;
GLint MaxDepthTextureSamples;
GLint MaxIntegerSamples;
+
+ /** GL_ARB_shader_atomic_counters */
+ GLuint MaxAtomicBufferBindings;
+ GLuint MaxAtomicBufferSize;
+ GLuint MaxCombinedAtomicBuffers;
+ GLuint MaxCombinedAtomicCounters;
};
@@ -3209,6 +3240,7 @@ struct gl_extensions
GLboolean ARB_occlusion_query2;
GLboolean ARB_point_sprite;
GLboolean ARB_seamless_cube_map;
+ GLboolean ARB_shader_atomic_counters;
GLboolean ARB_shader_bit_encoding;
GLboolean ARB_shader_stencil_export;
GLboolean ARB_shader_texture_lod;
@@ -3302,6 +3334,7 @@ struct gl_extensions
GLboolean NV_texture_barrier;
GLboolean NV_texture_env_combine4;
GLboolean NV_texture_rectangle;
+ GLboolean NV_vdpau_interop;
GLboolean TDFX_texture_compression_FXT1;
GLboolean OES_EGL_image;
GLboolean OES_draw_texture;
@@ -3581,6 +3614,11 @@ struct gl_driver_flags
* gl_shader_program::UniformBlocks
*/
GLbitfield NewUniformBuffer;
+
+ /**
+ * gl_context::AtomicBufferBindings
+ */
+ GLbitfield NewAtomicBuffer;
};
struct gl_uniform_buffer_binding
@@ -3598,6 +3636,16 @@ struct gl_uniform_buffer_binding
};
/**
+ * Binding point for an atomic counter buffer object.
+ */
+struct gl_atomic_buffer_binding
+{
+ struct gl_buffer_object *BufferObject;
+ GLintptr Offset;
+ GLsizeiptr Size;
+};
+
+/**
* Mesa rendering context.
*
* This is the central context data structure for Mesa. Almost all
@@ -3765,6 +3813,18 @@ struct gl_context
struct gl_uniform_buffer_binding
UniformBufferBindings[MAX_COMBINED_UNIFORM_BUFFERS];
+ /**
+ * Object currently associated with the GL_ATOMIC_COUNTER_BUFFER
+ * target.
+ */
+ struct gl_buffer_object *AtomicBuffer;
+
+ /**
+ * Array of atomic counter buffer binding points.
+ */
+ struct gl_atomic_buffer_binding
+ AtomicBufferBindings[MAX_COMBINED_ATOMIC_BUFFERS];
+
/*@}*/
struct gl_meta_state *Meta; /**< for "meta" operations */
@@ -3832,6 +3892,15 @@ struct gl_context
struct st_context *st;
void *aelt_context;
/*@}*/
+
+ /**
+ * \name NV_vdpau_interop
+ */
+ /*@{*/
+ const void *vdpDevice;
+ const void *vdpGetProcAddress;
+ struct set *vdpSurfaces;
+ /*@}*/
};
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index a18013369..86e7c3ad0 100644
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -202,13 +202,6 @@ _mesa_GenQueries(GLsizei n, GLuint *ids)
return;
}
- /* No query objects can be active at this time! */
- if (ctx->Query.CurrentOcclusionObject ||
- ctx->Query.CurrentTimerObject) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB");
- return;
- }
-
first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n);
if (first) {
GLsizei i;
@@ -241,18 +234,20 @@ _mesa_DeleteQueries(GLsizei n, const GLuint *ids)
return;
}
- /* No query objects can be active at this time! */
- if (ctx->Query.CurrentOcclusionObject ||
- ctx->Query.CurrentTimerObject) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
- return;
- }
-
for (i = 0; i < n; i++) {
if (ids[i] > 0) {
struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]);
if (q) {
- ASSERT(!q->Active); /* should be caught earlier */
+ if (q->Active) {
+ struct gl_query_object **bindpt;
+ bindpt = get_query_binding_point(ctx, q->Target);
+ assert(bindpt); /* Should be non-null for active q. */
+ if (bindpt) {
+ *bindpt = NULL;
+ }
+ q->Active = GL_FALSE;
+ ctx->Driver.EndQuery(ctx, q);
+ }
_mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
ctx->Driver.DeleteQuery(ctx, q);
}
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index f5c04b9f3..7da860ddf 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -648,6 +648,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param
case GL_PROGRAM_BINARY_LENGTH:
*params = 0;
return;
+ case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+ if (!ctx->Extensions.ARB_shader_atomic_counters)
+ break;
+
+ *params = shProg->NumAtomicBuffers;
+ return;
default:
break;
}
@@ -926,7 +932,7 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
/**
*/
-static bool
+static void
use_shader_program(struct gl_context *ctx, GLenum type,
struct gl_shader_program *shProg)
{
@@ -955,7 +961,7 @@ use_shader_program(struct gl_context *ctx, GLenum type,
}
break;
default:
- return false;
+ return;
}
if (*target != shProg) {
@@ -982,10 +988,8 @@ use_shader_program(struct gl_context *ctx, GLenum type,
}
_mesa_reference_shader_program(ctx, target, shProg);
- return true;
+ return;
}
-
- return false;
}
/**
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index c9d928f63..d56b7d9d7 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -23,7 +23,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-/**
+/**
* \file texparam.c
*
* glTexParameter-related functions
@@ -52,7 +52,7 @@
* Check if a coordinate wrap mode is supported for the texture target.
* \return GL_TRUE if legal, GL_FALSE otherwise
*/
-static GLboolean
+static GLboolean
validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap)
{
const struct gl_extensions * const e = & ctx->Extensions;
@@ -91,7 +91,7 @@ validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap)
break;
case GL_MIRROR_CLAMP_TO_EDGE_EXT:
- supported = is_desktop_gl
+ supported = is_desktop_gl
&& (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge)
&& (target != GL_TEXTURE_RECTANGLE_NV)
&& (target != GL_TEXTURE_EXTERNAL_OES);
@@ -1787,7 +1787,7 @@ _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
texObj = get_texobj(ctx, target, GL_TRUE);
if (!texObj)
return;
-
+
switch (pname) {
case GL_TEXTURE_BORDER_COLOR:
COPY_4V(params, texObj->Sampler.BorderColor.i);
@@ -1808,7 +1808,7 @@ _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
texObj = get_texobj(ctx, target, GL_TRUE);
if (!texObj)
return;
-
+
switch (pname) {
case GL_TEXTURE_BORDER_COLOR:
COPY_4V(params, texObj->Sampler.BorderColor.i);
@@ -1818,7 +1818,7 @@ _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
GLint ip[4];
_mesa_GetTexParameteriv(target, pname, ip);
params[0] = ip[0];
- if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
+ if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
pname == GL_TEXTURE_CROP_RECT_OES) {
params[1] = ip[1];
params[2] = ip[2];
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 3c460042e..88ad476ac 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -154,11 +154,21 @@ _mesa_GetActiveUniformsiv(GLuint program,
params[i] = uni->row_major;
break;
+ case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
+ if (!ctx->Extensions.ARB_shader_atomic_counters)
+ goto invalid_enum;
+ params[i] = uni->atomic_buffer_index;
+ break;
+
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
- return;
+ goto invalid_enum;
}
}
+
+ return;
+
+ invalid_enum:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
}
static bool
diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c
index 1e6f7f483..2e847fe31 100644
--- a/mesalib/src/mesa/main/uniforms.c
+++ b/mesalib/src/mesa/main/uniforms.c
@@ -535,7 +535,8 @@ _mesa_GetUniformLocation(GLhandleARB programObj, const GLcharARB *name)
* with a named uniform block, or if <name> starts with the reserved
* prefix "gl_"."
*/
- if (shProg->UniformStorage[index].block_index != -1)
+ if (shProg->UniformStorage[index].block_index != -1 ||
+ shProg->UniformStorage[index].atomic_buffer_index != -1)
return -1;
return _mesa_uniform_merge_location_offset(shProg, index, offset);
@@ -844,3 +845,68 @@ _mesa_get_uniform_name(const struct gl_uniform_storage *uni,
*length += i;
}
}
+
+void GLAPIENTRY
+_mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+ struct gl_active_atomic_buffer *ab;
+ int i;
+
+ if (!ctx->Extensions.ARB_shader_atomic_counters) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetActiveAtomicCounterBufferiv");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetActiveAtomicCounterBufferiv");
+ if (!shProg)
+ return;
+
+ if (bufferIndex >= shProg->NumAtomicBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetActiveAtomicCounterBufferiv(bufferIndex)");
+ return;
+ }
+
+ ab = &shProg->AtomicBuffers[bufferIndex];
+
+ switch (pname) {
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ params[0] = ab->Binding;
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
+ params[0] = ab->MinimumSize;
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
+ params[0] = ab->NumUniforms;
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
+ for (i = 0; i < ab->NumUniforms; ++i)
+ params[i] = ab->Uniforms[i];
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
+ params[0] = ab->StageReferences[MESA_SHADER_VERTEX];
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
+ params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY];
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
+ params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT];
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
+ params[0] = GL_FALSE;
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
+ params[0] = GL_FALSE;
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))",
+ pname, _mesa_lookup_enum_by_nr(pname));
+ return;
+ }
+}
diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h
index 92239176e..f7cac6328 100644
--- a/mesalib/src/mesa/main/uniforms.h
+++ b/mesalib/src/mesa/main/uniforms.h
@@ -142,6 +142,9 @@ _mesa_UniformBlockBinding(GLuint program,
GLuint uniformBlockIndex,
GLuint uniformBlockBinding);
void GLAPIENTRY
+_mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
+ GLenum pname, GLint *params);
+void GLAPIENTRY
_mesa_GetActiveUniformBlockiv(GLuint program,
GLuint uniformBlockIndex,
GLenum pname,
diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c
new file mode 100644
index 000000000..e21a26b43
--- /dev/null
+++ b/mesalib/src/mesa/main/vdpau.c
@@ -0,0 +1,424 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#include <stdbool.h>
+#include "context.h"
+#include "glformats.h"
+#include "hash_table.h"
+#include "set.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "vdpau.h"
+
+#define MAX_TEXTURES 4
+
+struct vdp_surface
+{
+ GLenum target;
+ struct gl_texture_object *textures[MAX_TEXTURES];
+ GLenum access, state;
+ GLboolean output;
+ const GLvoid *vdpSurface;
+};
+
+void GLAPIENTRY
+_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!vdpDevice) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice");
+ return;
+ }
+
+ if (!getProcAddress) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress");
+ return;
+ }
+
+ if (ctx->vdpDevice || ctx->vdpGetProcAddress || ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV");
+ return;
+ }
+
+ ctx->vdpDevice = vdpDevice;
+ ctx->vdpGetProcAddress = getProcAddress;
+ ctx->vdpSurfaces = _mesa_set_create(NULL, _mesa_key_pointer_equal);
+}
+
+static void
+unregister_surface(struct set_entry *entry)
+{
+ struct vdp_surface *surf = (struct vdp_surface *)entry->key;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (surf->state == GL_SURFACE_MAPPED_NV) {
+ GLintptr surfaces[] = { (GLintptr)surf };
+ _mesa_VDPAUUnmapSurfacesNV(1, surfaces);
+ }
+
+ _mesa_set_remove(ctx->vdpSurfaces, entry);
+ FREE(surf);
+}
+
+void GLAPIENTRY
+_mesa_VDPAUFiniNV(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV");
+ return;
+ }
+
+ _mesa_set_destroy(ctx->vdpSurfaces, unregister_surface);
+
+ ctx->vdpDevice = 0;
+ ctx->vdpGetProcAddress = 0;
+ ctx->vdpSurfaces = NULL;
+}
+
+static GLintptr
+register_surface(struct gl_context *ctx, GLboolean isOutput,
+ const GLvoid *vdpSurface, GLenum target,
+ GLsizei numTextureNames, const GLuint *textureNames)
+{
+ struct vdp_surface *surf;
+ int i;
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV");
+ return (GLintptr)NULL;
+ }
+
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
+ return (GLintptr)NULL;
+ }
+
+ if (target == GL_TEXTURE_RECTANGLE && !ctx->Extensions.NV_texture_rectangle) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
+ return (GLintptr)NULL;
+ }
+
+ surf = CALLOC_STRUCT( vdp_surface );
+ surf->vdpSurface = vdpSurface;
+ surf->target = target;
+ surf->access = GL_READ_WRITE;
+ surf->state = GL_SURFACE_REGISTERED_NV;
+ surf->output = isOutput;
+ for (i = 0; i < numTextureNames; ++i) {
+ struct gl_texture_object *tex;
+ tex = _mesa_lookup_texture(ctx, textureNames[i]);
+
+ _mesa_lock_texture(ctx, tex);
+
+ if (tex->Immutable) {
+ _mesa_unlock_texture(ctx, tex);
+ FREE(surf);
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "VDPAURegisterSurfaceNV(texture is immutable)");
+ return (GLintptr)NULL;
+ }
+
+ if (tex->Target == 0)
+ tex->Target = target;
+ else if (tex->Target != target) {
+ _mesa_unlock_texture(ctx, tex);
+ FREE(surf);
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "VDPAURegisterSurfaceNV(target mismatch)");
+ return (GLintptr)NULL;
+ }
+
+ /* This will disallow respecifying the storage. */
+ tex->Immutable = GL_TRUE;
+ _mesa_unlock_texture(ctx, tex);
+
+ _mesa_reference_texobj(&surf->textures[i], tex);
+ }
+
+ _mesa_set_add(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf);
+
+ return (GLintptr)surf;
+}
+
+GLintptr GLAPIENTRY
+_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+ GLsizei numTextureNames,
+ const GLuint *textureNames)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (numTextureNames != 4) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
+ return (GLintptr)NULL;
+ }
+
+ return register_surface(ctx, false, vdpSurface, target,
+ numTextureNames, textureNames);
+}
+
+GLintptr GLAPIENTRY
+_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+ GLsizei numTextureNames,
+ const GLuint *textureNames)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (numTextureNames != 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
+ return (GLintptr)NULL;
+ }
+
+ return register_surface(ctx, true, vdpSurface, target,
+ numTextureNames, textureNames);
+}
+
+void GLAPIENTRY
+_mesa_VDPAUIsSurfaceNV(GLintptr surface)
+{
+ struct vdp_surface *surf = (struct vdp_surface *)surface;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV");
+ return;
+ }
+
+ if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUIsSurfaceNV");
+ return;
+ }
+}
+
+void GLAPIENTRY
+_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface)
+{
+ struct vdp_surface *surf = (struct vdp_surface *)surface;
+ struct set_entry *entry;
+ int i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnregisterSurfaceNV");
+ return;
+ }
+
+ /* according to the spec it's ok when this is zero */
+ if (surface == 0)
+ return;
+
+ entry = _mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf);
+ if (!entry) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUUnregisterSurfaceNV");
+ return;
+ }
+
+ for (i = 0; i < MAX_TEXTURES; i++) {
+ if (surf->textures[i]) {
+ surf->textures[i]->Immutable = GL_FALSE;
+ _mesa_reference_texobj(&surf->textures[i], NULL);
+ }
+ }
+
+ _mesa_set_remove(ctx->vdpSurfaces, entry);
+ FREE(surf);
+}
+
+void GLAPIENTRY
+_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
+ GLsizei *length, GLint *values)
+{
+ struct vdp_surface *surf = (struct vdp_surface *)surface;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV");
+ return;
+ }
+
+ if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
+ return;
+ }
+
+ if (pname != GL_SURFACE_STATE_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "VDPAUGetSurfaceivNV");
+ return;
+ }
+
+ if (bufSize < 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
+ return;
+ }
+
+ values[0] = surf->state;
+
+ if (length != NULL)
+ *length = 1;
+}
+
+void GLAPIENTRY
+_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access)
+{
+ struct vdp_surface *surf = (struct vdp_surface *)surface;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+ return;
+ }
+
+ if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+ return;
+ }
+
+ if (access != GL_READ_ONLY && access != GL_WRITE_ONLY &&
+ access != GL_READ_WRITE) {
+
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+ return;
+ }
+
+ if (surf->state == GL_SURFACE_MAPPED_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+ return;
+ }
+
+ surf->access = access;
+}
+
+void GLAPIENTRY
+_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ int i, j;
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
+ return;
+ }
+
+ for (i = 0; i < numSurfaces; ++i) {
+ struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+
+ if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+ return;
+ }
+
+ if (surf->state == GL_SURFACE_MAPPED_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+ return;
+ }
+ }
+
+ for (i = 0; i < numSurfaces; ++i) {
+ struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+ unsigned numTextureNames = surf->output ? 1 : 4;
+
+ for (j = 0; j < numTextureNames; ++j) {
+ struct gl_texture_object *tex = surf->textures[j];
+ struct gl_texture_image *image;
+
+ _mesa_lock_texture(ctx, tex);
+ image = _mesa_get_tex_image(ctx, tex, surf->target, 0);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV");
+ _mesa_unlock_texture(ctx, tex);
+ return;
+ }
+
+ ctx->Driver.FreeTextureImageBuffer(ctx, image);
+
+ ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access,
+ surf->output, tex, image,
+ surf->vdpSurface, j);
+
+ _mesa_unlock_texture(ctx, tex);
+ }
+ surf->state = GL_SURFACE_MAPPED_NV;
+ }
+}
+
+void GLAPIENTRY
+_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ int i, j;
+
+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
+ return;
+ }
+
+ for (i = 0; i < numSurfaces; ++i) {
+ struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+
+ if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+ return;
+ }
+
+ if (surf->state != GL_SURFACE_MAPPED_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+ return;
+ }
+ }
+
+ for (i = 0; i < numSurfaces; ++i) {
+ struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+ unsigned numTextureNames = surf->output ? 1 : 4;
+
+ for (j = 0; j < numTextureNames; ++j) {
+ struct gl_texture_object *tex = surf->textures[j];
+ struct gl_texture_image *image;
+
+ _mesa_lock_texture(ctx, tex);
+
+ image = _mesa_select_tex_image(ctx, tex, surf->target, 0);
+
+ ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access,
+ surf->output, tex, image,
+ surf->vdpSurface, j);
+
+ if (image)
+ ctx->Driver.FreeTextureImageBuffer(ctx, image);
+
+ _mesa_unlock_texture(ctx, tex);
+ }
+ surf->state = GL_SURFACE_REGISTERED_NV;
+ }
+}
diff --git a/mesalib/src/mesa/main/vdpau.h b/mesalib/src/mesa/main/vdpau.h
new file mode 100644
index 000000000..f32d6dacb
--- /dev/null
+++ b/mesalib/src/mesa/main/vdpau.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#ifndef VDPAU_H
+#define VDPAU_H
+
+extern void GLAPIENTRY
+_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress);
+
+extern void GLAPIENTRY
+_mesa_VDPAUFiniNV(void);
+
+extern GLintptr GLAPIENTRY
+_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+ GLsizei numTextureNames,
+ const GLuint *textureNames);
+
+extern GLintptr GLAPIENTRY
+_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+ GLsizei numTextureNames,
+ const GLuint *textureNames);
+
+extern void GLAPIENTRY
+_mesa_VDPAUIsSurfaceNV(GLintptr surface);
+
+extern void GLAPIENTRY
+_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface);
+
+extern void GLAPIENTRY
+_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
+ GLsizei *length, GLint *values);
+
+extern void GLAPIENTRY
+_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access);
+
+extern void GLAPIENTRY
+_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces);
+
+extern void GLAPIENTRY
+_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces);
+
+#endif /* VDPAU_H */
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index cfad91bc4..c833a12f2 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -622,6 +622,7 @@ type_size(const struct glsl_type *type)
* at link time.
*/
return 1;
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
@@ -2601,6 +2602,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
format = uniform_native;
columns = 1;
break;
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_VOID:
case GLSL_TYPE_STRUCT:
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 4e0d98cc3..2cc3567e0 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -65,6 +65,7 @@
#include "st_extensions.h"
#include "st_gen_mipmap.h"
#include "st_program.h"
+#include "st_vdpau.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "util/u_upload_mgr.h"
@@ -360,5 +361,7 @@ void st_init_driver_functions(struct dd_function_table *functions)
st_init_xformfb_functions(functions);
st_init_syncobj_functions(functions);
+ st_init_vdpau_functions(functions);
+
functions->UpdateState = st_invalidate_state;
}
diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c
index c35723087..51bb23807 100644
--- a/mesalib/src/mesa/state_tracker/st_draw.c
+++ b/mesalib/src/mesa/state_tracker/st_draw.c
@@ -210,9 +210,6 @@ st_draw_vbo(struct gl_context *ctx,
if (st->dirty.st || ctx->NewDriverState) {
st_validate_state(st);
- if (st->vertex_array_out_of_memory)
- return;
-
#if 0
if (MESA_VERBOSE & VERBOSE_GLSL) {
check_uniforms(ctx);
@@ -222,6 +219,10 @@ st_draw_vbo(struct gl_context *ctx,
#endif
}
+ if (st->vertex_array_out_of_memory) {
+ return;
+ }
+
util_draw_init_info(&info);
if (ib) {
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c
index 231bb395a..97c5d55e1 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.c
+++ b/mesalib/src/mesa/state_tracker/st_extensions.c
@@ -445,8 +445,7 @@ void st_init_extensions(struct st_context *st)
{ PIPE_FORMAT_Z32_FLOAT,
PIPE_FORMAT_Z32_FLOAT_S8X24_UINT } },
- { { o(ARB_framebuffer_object),
- o(EXT_packed_depth_stencil) },
+ { { o(EXT_packed_depth_stencil) },
{ PIPE_FORMAT_S8_UINT_Z24_UNORM,
PIPE_FORMAT_Z24_UNORM_S8_UINT },
GL_TRUE }, /* at least one format must be supported */
@@ -565,6 +564,7 @@ void st_init_extensions(struct st_context *st)
ctx->Extensions.NV_fog_distance = GL_TRUE;
ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
ctx->Extensions.NV_texture_rectangle = GL_TRUE;
+ ctx->Extensions.NV_vdpau_interop = GL_TRUE;
ctx->Extensions.OES_EGL_image = GL_TRUE;
ctx->Extensions.OES_EGL_image_external = GL_TRUE;
@@ -760,6 +760,10 @@ void st_init_extensions(struct st_context *st)
PIPE_BUFFER, PIPE_BIND_SAMPLER_VIEW);
}
+ if (screen->get_param(screen, PIPE_CAP_MIXED_FRAMEBUFFER_SIZES) &&
+ ctx->Extensions.EXT_packed_depth_stencil) {
+ ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
+ }
/* Unpacking a varying in the fragment shader costs 1 texture indirection.
* If the number of available texture indirections is very limited, then we
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 3e11cce24..0eaf7467b 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -993,6 +993,7 @@ type_size(const struct glsl_type *type)
* at link time.
*/
return 1;
+ case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
diff --git a/mesalib/src/mesa/state_tracker/st_vdpau.c b/mesalib/src/mesa/state_tracker/st_vdpau.c
new file mode 100644
index 000000000..9b165ee39
--- /dev/null
+++ b/mesalib/src/mesa/state_tracker/st_vdpau.c
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#include "main/texobj.h"
+#include "main/teximage.h"
+#include "main/errors.h"
+#include "program/prog_instruction.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_video_codec.h"
+
+#include "state_tracker/vdpau_interop.h"
+
+#include "util/u_inlines.h"
+
+#include "st_vdpau.h"
+#include "st_context.h"
+#include "st_texture.h"
+#include "st_format.h"
+
+static void
+st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
+ GLboolean output, struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ const GLvoid *vdpSurface, GLuint index)
+{
+ int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
+ uint32_t device = (uintptr_t)ctx->vdpDevice;
+
+ struct st_context *st = st_context(ctx);
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct st_texture_image *stImage = st_texture_image(texImage);
+
+ struct pipe_resource *res;
+ struct pipe_sampler_view *sv, templ;
+ gl_format texFormat;
+
+ getProcAddr = ctx->vdpGetProcAddress;
+ if (output) {
+ VdpOutputSurfaceGallium *f;
+
+ if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ res = f((uintptr_t)vdpSurface);
+
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ } else {
+ VdpVideoSurfaceGallium *f;
+
+ struct pipe_video_buffer *buffer;
+ struct pipe_sampler_view **samplers;
+
+ if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ buffer = f((uintptr_t)vdpSurface);
+ if (!buffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ samplers = buffer->get_sampler_view_planes(buffer);
+ if (!samplers) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ sv = samplers[index >> 1];
+ if (!sv) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ res = sv->texture;
+ }
+
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ /* do we have different screen objects ? */
+ if (res->screen != st->pipe->screen) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+ return;
+ }
+
+ /* switch to surface based */
+ if (!stObj->surface_based) {
+ _mesa_clear_texture_object(ctx, texObj);
+ stObj->surface_based = GL_TRUE;
+ }
+
+ texFormat = st_pipe_format_to_mesa_format(res->format);
+
+ _mesa_init_teximage_fields(ctx, texImage,
+ res->width0, res->height0, 1, 0, GL_RGBA,
+ texFormat);
+
+ pipe_resource_reference(&stObj->pt, res);
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ pipe_resource_reference(&stImage->pt, res);
+
+ u_sampler_view_default_template(&templ, res, res->format);
+ templ.u.tex.first_layer = index & 1;
+ templ.u.tex.last_layer = index & 1;
+ templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0);
+ templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1);
+ templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
+ templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3);
+ stObj->sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ);
+
+ stObj->width0 = res->width0;
+ stObj->height0 = res->height0;
+ stObj->depth0 = 1;
+ stObj->surface_format = res->format;
+
+ _mesa_dirty_texobj(ctx, texObj);
+}
+
+static void
+st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
+ GLboolean output, struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ const GLvoid *vdpSurface, GLuint index)
+{
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct st_texture_image *stImage = st_texture_image(texImage);
+
+ pipe_resource_reference(&stObj->pt, NULL);
+ pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ pipe_resource_reference(&stImage->pt, NULL);
+
+ _mesa_dirty_texobj(ctx, texObj);
+}
+
+void
+st_init_vdpau_functions(struct dd_function_table *functions)
+{
+ functions->VDPAUMapSurface = st_vdpau_map_surface;
+ functions->VDPAUUnmapSurface = st_vdpau_unmap_surface;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_vdpau.h b/mesalib/src/mesa/state_tracker/st_vdpau.h
new file mode 100644
index 000000000..59c744305
--- /dev/null
+++ b/mesalib/src/mesa/state_tracker/st_vdpau.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#ifndef ST_VDPAU_H
+#define ST_VDPAU_H
+
+struct dd_function_table;
+
+extern void
+st_init_vdpau_functions(struct dd_function_table *functions);
+
+#endif /* ST_VDPAU_H */