diff options
Diffstat (limited to 'mesalib/src')
26 files changed, 762 insertions, 98 deletions
diff --git a/mesalib/src/gallium/auxiliary/Android.mk b/mesalib/src/gallium/auxiliary/Android.mk index 11fc2256a..8046943c1 100644 --- a/mesalib/src/gallium/auxiliary/Android.mk +++ b/mesalib/src/gallium/auxiliary/Android.mk @@ -30,7 +30,9 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(C_SOURCES) -LOCAL_C_INCLUDES := $(GALLIUM_TOP)/auxiliary/util +LOCAL_C_INCLUDES := \ + $(GALLIUM_TOP)/auxiliary/util \ + $(MESA_TOP)/src LOCAL_MODULE := libmesa_gallium diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 58d8af71f..f6621ef99 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -75,6 +75,7 @@ C_SOURCES := \ tgsi/tgsi_exec.c \ tgsi/tgsi_info.c \ tgsi/tgsi_iterate.c \ + tgsi/tgsi_lowering.c \ tgsi/tgsi_parse.c \ tgsi/tgsi_sanity.c \ tgsi/tgsi_scan.c \ diff --git a/mesalib/src/gallium/auxiliary/hud/hud_context.c b/mesalib/src/gallium/auxiliary/hud/hud_context.c index b6e018423..18a878118 100644 --- a/mesalib/src/gallium/auxiliary/hud/hud_context.c +++ b/mesalib/src/gallium/auxiliary/hud/hud_context.c @@ -44,6 +44,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" #include "util/u_simple_shaders.h" #include "util/u_string.h" #include "util/u_upload_mgr.h" @@ -1050,12 +1051,8 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso) } /* sampler view */ - memset(&view_templ, 0, sizeof(view_templ)); - view_templ.format = hud->font.texture->format; - view_templ.swizzle_r = PIPE_SWIZZLE_RED; - view_templ.swizzle_g = PIPE_SWIZZLE_GREEN; - view_templ.swizzle_b = PIPE_SWIZZLE_BLUE; - view_templ.swizzle_a = PIPE_SWIZZLE_ALPHA; + u_sampler_view_default_template( + &view_templ, hud->font.texture, hud->font.texture->format); hud->font_sampler_view = pipe->create_sampler_view(pipe, hud->font.texture, &view_templ); diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h index 39bd40fa1..f95c11166 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.h +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -727,6 +727,18 @@ util_bitcount(unsigned n) #endif } + +static INLINE unsigned +util_bitcount64(uint64_t n) +{ +#ifdef HAVE___BUILTIN_POPCOUNTLL + return __builtin_popcountll(n); +#else + return util_bitcount(n) + util_bitcount(n >> 32); +#endif +} + + /** * Reverse bits in n * Algorithm taken from: diff --git a/mesalib/src/gallium/auxiliary/util/u_pstipple.c b/mesalib/src/gallium/auxiliary/util/u_pstipple.c index 4f2e70234..509f815c5 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pstipple.c +++ b/mesalib/src/gallium/auxiliary/util/u_pstipple.c @@ -407,7 +407,6 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe, struct pipe_shader_state *new_fs; struct pstip_transform_context transform; const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS; - unsigned i; new_fs = MALLOC(sizeof(*new_fs)); if (!new_fs) @@ -433,11 +432,8 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe, tgsi_scan_shader(fs->tokens, &transform.info); - /* find fragment coordinate origin property */ - for (i = 0; i < transform.info.num_properties; i++) { - if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN) - transform.coordOrigin = transform.info.properties[i].data[0]; - } + transform.coordOrigin = + transform.info.properties[TGSI_PROPERTY_FS_COORD_ORIGIN]; tgsi_transform_shader(fs->tokens, (struct tgsi_token *) new_fs->tokens, diff --git a/mesalib/src/glsl/Android.mk b/mesalib/src/glsl/Android.mk index 7b1fa7e53..1cbc5c6d2 100644 --- a/mesalib/src/glsl/Android.mk +++ b/mesalib/src/glsl/Android.mk @@ -39,6 +39,7 @@ LOCAL_SRC_FILES := \ $(LIBGLSL_FILES) LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/mapi \ $(MESA_TOP)/src/mesa @@ -59,10 +60,11 @@ LOCAL_SRC_FILES := \ $(GLSL_COMPILER_CXX_FILES) LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/mapi \ $(MESA_TOP)/src/mesa -LOCAL_STATIC_LIBRARIES := libmesa_glsl libmesa_glsl_utils +LOCAL_STATIC_LIBRARIES := libmesa_glsl libmesa_glsl_utils libmesa_util LOCAL_MODULE_TAGS := eng LOCAL_MODULE := glsl_compiler diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index bfb699353..0c55327d6 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -96,6 +96,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_flip_matrices.cpp \ $(GLSL_SRCDIR)/opt_function_inlining.cpp \ $(GLSL_SRCDIR)/opt_if_simplification.cpp \ + $(GLSL_SRCDIR)/opt_minmax.cpp \ $(GLSL_SRCDIR)/opt_noop_swizzle.cpp \ $(GLSL_SRCDIR)/opt_rebalance_tree.cpp \ $(GLSL_SRCDIR)/opt_redundant_jumps.cpp \ diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 5a024cb43..bb7fbcdc1 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -442,6 +442,7 @@ private: ir_swizzle *matrix_elt(ir_variable *var, int col, int row); ir_expression *asin_expr(ir_variable *x); + void do_atan(ir_factory &body, const glsl_type *type, ir_variable *res, operand y_over_x); /** * Call function \param f with parameters specified as the linked @@ -2684,11 +2685,7 @@ builtin_builder::_atan2(const glsl_type *type) ir_factory outer_then(&outer_if->then_instructions, mem_ctx); /* Then...call atan(y/x) */ - ir_variable *y_over_x = outer_then.make_temp(glsl_type::float_type, "y_over_x"); - outer_then.emit(assign(y_over_x, div(y, x))); - outer_then.emit(assign(r, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x), - imm(1.0f)))))); - outer_then.emit(assign(r, asin_expr(r))); + do_atan(body, glsl_type::float_type, r, div(y, x)); /* ...and fix it up: */ ir_if *inner_if = new(mem_ctx) ir_if(less(x, imm(0.0f))); @@ -2711,17 +2708,65 @@ builtin_builder::_atan2(const glsl_type *type) return sig; } +void +builtin_builder::do_atan(ir_factory &body, const glsl_type *type, ir_variable *res, operand y_over_x) +{ + /* + * range-reduction, first step: + * + * / y_over_x if |y_over_x| <= 1.0; + * x = < + * \ 1.0 / y_over_x otherwise + */ + ir_variable *x = body.make_temp(type, "atan_x"); + body.emit(assign(x, div(min2(abs(y_over_x), + imm(1.0f)), + max2(abs(y_over_x), + imm(1.0f))))); + + /* + * approximate atan by evaluating polynomial: + * + * x * 0.9999793128310355 - x^3 * 0.3326756418091246 + + * x^5 * 0.1938924977115610 - x^7 * 0.1173503194786851 + + * x^9 * 0.0536813784310406 - x^11 * 0.0121323213173444 + */ + ir_variable *tmp = body.make_temp(type, "atan_tmp"); + body.emit(assign(tmp, mul(x, x))); + body.emit(assign(tmp, mul(add(mul(sub(mul(add(mul(sub(mul(add(mul(imm(-0.0121323213173444f), + tmp), + imm(0.0536813784310406f)), + tmp), + imm(0.1173503194786851f)), + tmp), + imm(0.1938924977115610f)), + tmp), + imm(0.3326756418091246f)), + tmp), + imm(0.9999793128310355f)), + x))); + + /* range-reduction fixup */ + body.emit(assign(tmp, add(tmp, + mul(b2f(greater(abs(y_over_x), + imm(1.0f, type->components()))), + add(mul(tmp, + imm(-2.0f)), + imm(M_PI_2f)))))); + + /* sign fixup */ + body.emit(assign(res, mul(tmp, sign(y_over_x)))); +} + ir_function_signature * builtin_builder::_atan(const glsl_type *type) { ir_variable *y_over_x = in_var(type, "y_over_x"); MAKE_SIG(type, always_available, 1, y_over_x); - ir_variable *t = body.make_temp(type, "t"); - body.emit(assign(t, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x), - imm(1.0f)))))); - - body.emit(ret(asin_expr(t))); + ir_variable *tmp = body.make_temp(type, "tmp"); + do_atan(body, type, tmp, y_over_x); + body.emit(ret(tmp)); return sig; } @@ -4465,9 +4510,11 @@ builtin_builder::_image_prototype(const glsl_type *image_type, sig->parameters.push_tail(in_var(glsl_type::int_type, "sample")); /* Data arguments. */ - for (unsigned i = 0; i < num_arguments; ++i) - sig->parameters.push_tail(in_var(data_type, - ralloc_asprintf(NULL, "arg%d", i))); + for (unsigned i = 0; i < num_arguments; ++i) { + char *arg_name = ralloc_asprintf(NULL, "arg%d", i); + sig->parameters.push_tail(in_var(data_type, arg_name)); + ralloc_free(arg_name); + } /* Set the maximal set of qualifiers allowed for this image * built-in. Function calls with arguments having fewer diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index cc7d2d746..79f849465 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -1613,6 +1613,7 @@ do_common_optimization(exec_list *ir, bool linked, else progress = do_constant_variable_unlinked(ir) || progress; progress = do_constant_folding(ir) || progress; + progress = do_minmax_prune(ir) || progress; progress = do_cse(ir) || progress; progress = do_rebalance_tree(ir) || progress; progress = do_algebraic(ir, native_integers, options) || progress; diff --git a/mesalib/src/glsl/glsl_symbol_table.h b/mesalib/src/glsl/glsl_symbol_table.h index 25282641f..e32b88b86 100644 --- a/mesalib/src/glsl/glsl_symbol_table.h +++ b/mesalib/src/glsl/glsl_symbol_table.h @@ -43,37 +43,8 @@ struct glsl_type; * type safe and some symbol table invariants. */ struct glsl_symbol_table { -private: - static void - _glsl_symbol_table_destructor (glsl_symbol_table *table) - { - table->~glsl_symbol_table(); - } - -public: - /* Callers of this ralloc-based new need not call delete. It's - * easier to just ralloc_free 'ctx' (or any of its ancestors). */ - static void* operator new(size_t size, void *ctx) - { - void *table; - - table = ralloc_size(ctx, size); - assert(table != NULL); - - ralloc_set_destructor(table, (void (*)(void*)) _glsl_symbol_table_destructor); - - return table; - } - - /* If the user *does* call delete, that's OK, we will just - * ralloc_free in that case. Here, C++ will have already called the - * destructor so tell ralloc not to do that again. */ - static void operator delete(void *table) - { - ralloc_set_destructor(table, NULL); - ralloc_free(table); - } - + DECLARE_RALLOC_CXX_OPERATORS(glsl_symbol_table) + glsl_symbol_table(); ~glsl_symbol_table(); diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 0c3a63831..e25857ac5 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -99,6 +99,7 @@ bool opt_flatten_nested_if_blocks(exec_list *instructions); bool do_discard_simplification(exec_list *instructions); bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth = 0); bool do_mat_op_to_vec(exec_list *instructions); +bool do_minmax_prune(exec_list *instructions); bool do_noop_swizzle(exec_list *instructions); bool do_structure_splitting(exec_list *instructions); bool do_swizzle_swizzle(exec_list *instructions); diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index a738e2f38..1866ab265 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -1456,7 +1456,22 @@ assign_varying_locations(struct gl_context *ctx, if (var && var->data.mode == ir_var_shader_in && var->data.is_unmatched_generic_inout) { - if (prog->Version <= 120) { + if (prog->IsES) { + /* + * On Page 91 (Page 97 of the PDF) of the GLSL ES 1.0 spec: + * + * If the vertex shader declares but doesn't write to a + * varying and the fragment shader declares and reads it, + * is this an error? + * + * RESOLUTION: No. + */ + linker_warning(prog, "%s shader varying %s not written " + "by %s shader\n.", + _mesa_shader_stage_to_string(consumer->Stage), + var->name, + _mesa_shader_stage_to_string(producer->Stage)); + } else if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * * Only those varying variables used (i.e. read) in @@ -1469,7 +1484,6 @@ assign_varying_locations(struct gl_context *ctx, * write the variable for the FS to read it. See * "glsl1-varying read but not written" in piglit. */ - linker_error(prog, "%s shader varying %s not written " "by %s shader\n.", _mesa_shader_stage_to_string(consumer->Stage), diff --git a/mesalib/src/glsl/loop_analysis.h b/mesalib/src/glsl/loop_analysis.h index 31be4f3cf..3b1971d7e 100644 --- a/mesalib/src/glsl/loop_analysis.h +++ b/mesalib/src/glsl/loop_analysis.h @@ -140,22 +140,7 @@ public: hash_table_dtor(this->var_hash); } - static void* operator new(size_t size, void *ctx) - { - void *lvs = ralloc_size(ctx, size); - assert(lvs != NULL); - - ralloc_set_destructor(lvs, (void (*)(void*)) destructor); - - return lvs; - } - -private: - static void - destructor(loop_variable_state *lvs) - { - lvs->~loop_variable_state(); - } + DECLARE_RALLOC_CXX_OPERATORS(loop_variable_state) }; diff --git a/mesalib/src/glsl/opt_minmax.cpp b/mesalib/src/glsl/opt_minmax.cpp new file mode 100644 index 000000000..32fb2d7ea --- /dev/null +++ b/mesalib/src/glsl/opt_minmax.cpp @@ -0,0 +1,475 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_minmax.cpp + * + * Drop operands from an expression tree of only min/max operations if they + * can be proven to not contribute to the final result. + * + * The algorithm is similar to alpha-beta pruning on a minmax search. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_rvalue_visitor.h" +#include "ir_optimization.h" +#include "ir_builder.h" +#include "program/prog_instruction.h" +#include "glsl_types.h" +#include "main/macros.h" + +using namespace ir_builder; + +namespace { + +enum compare_components_result { + LESS, + LESS_OR_EQUAL, + EQUAL, + GREATER_OR_EQUAL, + GREATER, + MIXED +}; + +class minmax_range { +public: + minmax_range(ir_constant *low = NULL, ir_constant *high = NULL) + { + this->low = low; + this->high = high; + } + + /* low is the lower limit of the range, high is the higher limit. NULL on + * low means negative infinity (unlimited) and on high positive infinity + * (unlimited). Because of the two interpretations of the value NULL, + * arbitrary comparison between ir_constants is impossible. + */ + ir_constant *low; + ir_constant *high; +}; + +class ir_minmax_visitor : public ir_rvalue_enter_visitor { +public: + ir_minmax_visitor() + : progress(false) + { + } + + ir_rvalue *prune_expression(ir_expression *expr, minmax_range baserange); + + void handle_rvalue(ir_rvalue **rvalue); + + bool progress; +}; + +/* + * Returns LESS if all vector components of `a' are strictly lower than of `b', + * GREATER if all vector components of `a' are strictly greater than of `b', + * MIXED if some vector components of `a' are strictly lower than of `b' while + * others are strictly greater, or EQUAL otherwise. + */ +static enum compare_components_result +compare_components(ir_constant *a, ir_constant *b) +{ + assert(a != NULL); + assert(b != NULL); + + assert(a->type->base_type == b->type->base_type); + + unsigned a_inc = a->type->is_scalar() ? 0 : 1; + unsigned b_inc = b->type->is_scalar() ? 0 : 1; + unsigned components = MAX2(a->type->components(), b->type->components()); + + bool foundless = false; + bool foundgreater = false; + bool foundequal = false; + + for (unsigned i = 0, c0 = 0, c1 = 0; + i < components; + c0 += a_inc, c1 += b_inc, ++i) { + switch (a->type->base_type) { + case GLSL_TYPE_UINT: + if (a->value.u[c0] < b->value.u[c1]) + foundless = true; + else if (a->value.u[c0] > b->value.u[c1]) + foundgreater = true; + else + foundequal = true; + break; + case GLSL_TYPE_INT: + if (a->value.i[c0] < b->value.i[c1]) + foundless = true; + else if (a->value.i[c0] > b->value.i[c1]) + foundgreater = true; + else + foundequal = true; + break; + case GLSL_TYPE_FLOAT: + if (a->value.f[c0] < b->value.f[c1]) + foundless = true; + else if (a->value.f[c0] > b->value.f[c1]) + foundgreater = true; + else + foundequal = true; + break; + default: + unreachable("not reached"); + } + } + + if (foundless && foundgreater) { + /* Some components are strictly lower, others are strictly greater */ + return MIXED; + } + + if (foundequal) { + /* It is not mixed, but it is not strictly lower or greater */ + if (foundless) + return LESS_OR_EQUAL; + if (foundgreater) + return GREATER_OR_EQUAL; + return EQUAL; + } + + /* All components are strictly lower or strictly greater */ + return foundless ? LESS : GREATER; +} + +static ir_constant * +combine_constant(bool ismin, ir_constant *a, ir_constant *b) +{ + void *mem_ctx = ralloc_parent(a); + ir_constant *c = a->clone(mem_ctx, NULL); + for (unsigned i = 0; i < c->type->components(); i++) { + switch (c->type->base_type) { + case GLSL_TYPE_UINT: + if ((ismin && b->value.u[i] < c->value.u[i]) || + (!ismin && b->value.u[i] > c->value.u[i])) + c->value.u[i] = b->value.u[i]; + break; + case GLSL_TYPE_INT: + if ((ismin && b->value.i[i] < c->value.i[i]) || + (!ismin && b->value.i[i] > c->value.i[i])) + c->value.i[i] = b->value.i[i]; + break; + case GLSL_TYPE_FLOAT: + if ((ismin && b->value.f[i] < c->value.f[i]) || + (!ismin && b->value.f[i] > c->value.f[i])) + c->value.f[i] = b->value.f[i]; + break; + default: + assert(!"not reached"); + } + } + return c; +} + +static ir_constant * +smaller_constant(ir_constant *a, ir_constant *b) +{ + assert(a != NULL); + assert(b != NULL); + + enum compare_components_result ret = compare_components(a, b); + if (ret == MIXED) + return combine_constant(true, a, b); + else if (ret < EQUAL) + return a; + else + return b; +} + +static ir_constant * +larger_constant(ir_constant *a, ir_constant *b) +{ + assert(a != NULL); + assert(b != NULL); + + enum compare_components_result ret = compare_components(a, b); + if (ret == MIXED) + return combine_constant(false, a, b); + else if (ret < EQUAL) + return b; + else + return a; +} + +/* Combines two ranges by doing an element-wise min() / max() depending on the + * operation. + */ +static minmax_range +combine_range(minmax_range r0, minmax_range r1, bool ismin) +{ + minmax_range ret; + + if (!r0.low) { + ret.low = ismin ? r0.low : r1.low; + } else if (!r1.low) { + ret.low = ismin ? r1.low : r0.low; + } else { + ret.low = ismin ? smaller_constant(r0.low, r1.low) : + larger_constant(r0.low, r1.low); + } + + if (!r0.high) { + ret.high = ismin ? r1.high : r0.high; + } else if (!r1.high) { + ret.high = ismin ? r0.high : r1.high; + } else { + ret.high = ismin ? smaller_constant(r0.high, r1.high) : + larger_constant(r0.high, r1.high); + } + + return ret; +} + +/* Returns a range so that lower limit is the larger of the two lower limits, + * and higher limit is the smaller of the two higher limits. + */ +static minmax_range +range_intersection(minmax_range r0, minmax_range r1) +{ + minmax_range ret; + + if (!r0.low) + ret.low = r1.low; + else if (!r1.low) + ret.low = r0.low; + else + ret.low = larger_constant(r0.low, r1.low); + + if (!r0.high) + ret.high = r1.high; + else if (!r1.high) + ret.high = r0.high; + else + ret.high = smaller_constant(r0.high, r1.high); + + return ret; +} + +static minmax_range +get_range(ir_rvalue *rval) +{ + ir_expression *expr = rval->as_expression(); + if (expr && (expr->operation == ir_binop_min || + expr->operation == ir_binop_max)) { + minmax_range r0 = get_range(expr->operands[0]); + minmax_range r1 = get_range(expr->operands[1]); + return combine_range(r0, r1, expr->operation == ir_binop_min); + } + + ir_constant *c = rval->as_constant(); + if (c) { + return minmax_range(c, c); + } + + return minmax_range(); +} + +/** + * Prunes a min/max expression considering the base range of the parent + * min/max expression. + * + * @param baserange the range that the parents of this min/max expression + * in the min/max tree will clamp its value to. + */ +ir_rvalue * +ir_minmax_visitor::prune_expression(ir_expression *expr, minmax_range baserange) +{ + assert(expr->operation == ir_binop_min || + expr->operation == ir_binop_max); + + bool ismin = expr->operation == ir_binop_min; + minmax_range limits[2]; + + /* Recurse to get the ranges for each of the subtrees of this + * expression. We need to do this as a separate step because we need to + * know the ranges of each of the subtrees before we prune either one. + * Consider something like this: + * + * max + * / \ + * max max + * / \ / \ + * 3 a b 2 + * + * We would like to prune away the max on the bottom-right, but to do so + * we need to know the range of the expression on the left beforehand, + * and there's no guarantee that we will visit either subtree in a + * particular order. + */ + for (unsigned i = 0; i < 2; ++i) + limits[i] = get_range(expr->operands[i]); + + for (unsigned i = 0; i < 2; ++i) { + bool is_redundant = false; + + enum compare_components_result cr = LESS; + if (ismin) { + /* If this operand will always be greater than the other one, it's + * redundant. + */ + if (limits[i].low && limits[1 - i].high) { + cr = compare_components(limits[i].low, limits[1 - i].high); + if (cr >= EQUAL && cr != MIXED) + is_redundant = true; + } + /* If this operand is always greater than baserange, then even if + * it's smaller than the other one it'll get clamped, so it's + * redundant. + */ + if (!is_redundant && limits[i].low && baserange.high) { + cr = compare_components(limits[i].low, baserange.high); + if (cr >= EQUAL && cr != MIXED) + is_redundant = true; + } + } else { + /* If this operand will always be lower than the other one, it's + * redundant. + */ + if (limits[i].high && limits[1 - i].low) { + cr = compare_components(limits[i].high, limits[1 - i].low); + if (cr <= EQUAL) + is_redundant = true; + } + /* If this operand is always lower than baserange, then even if + * it's greater than the other one it'll get clamped, so it's + * redundant. + */ + if (!is_redundant && limits[i].high && baserange.low) { + cr = compare_components(limits[i].high, baserange.low); + if (cr <= EQUAL) + is_redundant = true; + } + } + + if (is_redundant) { + progress = true; + + /* Recurse if necessary. */ + ir_expression *op_expr = expr->operands[1 - i]->as_expression(); + if (op_expr && (op_expr->operation == ir_binop_min || + op_expr->operation == ir_binop_max)) { + return prune_expression(op_expr, baserange); + } + + return expr->operands[1 - i]; + } else if (cr == MIXED) { + /* If we have mixed vector operands, we can try to resolve the minmax + * expression by doing a component-wise minmax: + * + * min min + * / \ / \ + * min a ===> [1,1] a + * / \ + * [1,3] [3,1] + * + */ + ir_constant *a = expr->operands[0]->as_constant(); + ir_constant *b = expr->operands[1]->as_constant(); + if (a && b) + return combine_constant(ismin, a, b); + } + } + + /* Now recurse to operands giving them the proper baserange. The baserange + * to pass is the intersection of our baserange and the other operand's + * limit with one of the ranges unlimited. If we can't compute a valid + * intersection, we use the current baserange. + */ + for (unsigned i = 0; i < 2; ++i) { + ir_expression *op_expr = expr->operands[i]->as_expression(); + if (op_expr && (op_expr->operation == ir_binop_min || + op_expr->operation == ir_binop_max)) { + /* We can only compute a new baserange for this operand if we managed + * to compute a valid range for the other operand. + */ + if (ismin) + limits[1 - i].low = NULL; + else + limits[1 - i].high = NULL; + minmax_range base = range_intersection(limits[1 - i], baserange); + expr->operands[i] = prune_expression(op_expr, base); + } + } + + /* If we got here we could not discard any of the operands of the minmax + * expression, but we can still try to resolve the expression if both + * operands are constant. We do this after the loop above, to make sure + * that if our operands are minmax expressions we have tried to prune them + * first (hopefully reducing them to constants). + */ + ir_constant *a = expr->operands[0]->as_constant(); + ir_constant *b = expr->operands[1]->as_constant(); + if (a && b) + return combine_constant(ismin, a, b); + + return expr; +} + +static ir_rvalue * +swizzle_if_required(ir_expression *expr, ir_rvalue *rval) +{ + if (expr->type->is_vector() && rval->type->is_scalar()) { + return swizzle(rval, SWIZZLE_XXXX, expr->type->vector_elements); + } else { + return rval; + } +} + +void +ir_minmax_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + ir_expression *expr = (*rvalue)->as_expression(); + if (!expr || (expr->operation != ir_binop_min && + expr->operation != ir_binop_max)) + return; + + ir_rvalue *new_rvalue = prune_expression(expr, minmax_range()); + if (new_rvalue == *rvalue) + return; + + /* If the expression type is a vector and the optimization leaves a scalar + * as the result, we need to turn it into a vector. + */ + *rvalue = swizzle_if_required(expr, new_rvalue); + + progress = true; +} + +} + +bool +do_minmax_prune(exec_list *instructions) +{ + ir_minmax_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/mesalib/src/mesa/Android.gen.mk b/mesalib/src/mesa/Android.gen.mk index c6280f5cb..c7b7f7edf 100644 --- a/mesalib/src/mesa/Android.gen.mk +++ b/mesalib/src/mesa/Android.gen.mk @@ -115,3 +115,12 @@ GET_HASH_GEN := $(LOCAL_PATH)/main/get_hash_generator.py $(intermediates)/main/get_hash.h: $(glapi)/gl_and_es_API.xml \ $(LOCAL_PATH)/main/get_hash_params.py $(GET_HASH_GEN) @$(MESA_PYTHON2) $(GET_HASH_GEN) -f $< > $@ + +FORMAT_INFO := $(LOCAL_PATH)/main/format_info.py +format_info_deps := \ + $(LOCAL_PATH)/main/formats.csv \ + $(LOCAL_PATH)/main/format_parser.py \ + $(FORMAT_INFO) + +$(intermediates)/main/format_info.c: $(format_info_deps) + @$(MESA_PYTHON2) $(FORMAT_INFO) $< > $@ diff --git a/mesalib/src/mesa/Android.libmesa_dricore.mk b/mesalib/src/mesa/Android.libmesa_dricore.mk index 28d6feb35..1e6d94872 100644 --- a/mesalib/src/mesa/Android.libmesa_dricore.mk +++ b/mesalib/src/mesa/Android.libmesa_dricore.mk @@ -32,6 +32,8 @@ LOCAL_PATH := $(call my-dir) # MESA_FILES # X86_FILES include $(LOCAL_PATH)/Makefile.sources +SRCDIR := +BUILDDIR := include $(CLEAR_VARS) @@ -55,6 +57,7 @@ endif LOCAL_C_INCLUDES := \ $(call intermediates-dir-for STATIC_LIBRARIES,libmesa_program,,) \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/mapi \ $(MESA_TOP)/src/glsl \ $(MESA_TOP)/src/gallium/auxiliary diff --git a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk index e93891f07..a9f6ff59a 100644 --- a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk +++ b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk @@ -36,11 +36,11 @@ include $(CLEAR_VARS) LOCAL_MODULE := libmesa_glsl_utils LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/glsl \ $(MESA_TOP)/src/mapi LOCAL_SRC_FILES := \ - main/hash_table.c \ main/imports.c \ program/prog_hash_table.c \ program/symbol_table.c @@ -59,11 +59,11 @@ LOCAL_IS_HOST_MODULE := true LOCAL_CFLAGS := -D_POSIX_C_SOURCE=199309L LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/glsl \ $(MESA_TOP)/src/mapi LOCAL_SRC_FILES := \ - main/hash_table.c \ main/imports.c \ program/prog_hash_table.c \ program/symbol_table.c diff --git a/mesalib/src/mesa/Android.libmesa_st_mesa.mk b/mesalib/src/mesa/Android.libmesa_st_mesa.mk index e6374a6d8..8b8d652a3 100644 --- a/mesalib/src/mesa/Android.libmesa_st_mesa.mk +++ b/mesalib/src/mesa/Android.libmesa_st_mesa.mk @@ -32,6 +32,8 @@ LOCAL_PATH := $(call my-dir) # MESA_GALLIUM_FILES. # X86_FILES include $(LOCAL_PATH)/Makefile.sources +SRCDIR := +BUILDDIR := include $(CLEAR_VARS) @@ -50,6 +52,7 @@ LOCAL_C_INCLUDES := \ $(call intermediates-dir-for STATIC_LIBRARIES,libmesa_program,,) \ $(MESA_TOP)/src/gallium/auxiliary \ $(MESA_TOP)/src/gallium/include \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/glsl \ $(MESA_TOP)/src/mapi diff --git a/mesalib/src/mesa/drivers/common/meta_blit.c b/mesalib/src/mesa/drivers/common/meta_blit.c index d78300b80..c6616d93d 100644 --- a/mesalib/src/mesa/drivers/common/meta_blit.c +++ b/mesalib/src/mesa/drivers/common/meta_blit.c @@ -45,6 +45,7 @@ #include "main/texenv.h" #include "main/teximage.h" #include "main/texparam.h" +#include "main/uniforms.h" #include "main/varray.h" #include "main/viewport.h" #include "swrast/swrast.h" @@ -69,7 +70,7 @@ setup_glsl_msaa_blit_scaled_shader(struct gl_context *ctx, const uint8_t *sample_map; char *sample_map_str = rzalloc_size(mem_ctx, 1); char *sample_map_expr = rzalloc_size(mem_ctx, 1); - char *texel_fetch_macro = rzalloc_size(mem_ctx, 1);; + char *texel_fetch_macro = rzalloc_size(mem_ctx, 1); const char *vs_source; const char *sampler_array_suffix = ""; const char *texcoord_type = "vec2"; @@ -105,11 +106,11 @@ setup_glsl_msaa_blit_scaled_shader(struct gl_context *ctx, _mesa_UseProgram(blit->msaa_shaders[shader_index]); /* Update the uniform values. */ loc_src_width = - glGetUniformLocation(blit->msaa_shaders[shader_index], "src_width"); + _mesa_GetUniformLocation(blit->msaa_shaders[shader_index], "src_width"); loc_src_height = - glGetUniformLocation(blit->msaa_shaders[shader_index], "src_height"); - glUniform1f(loc_src_width, src_rb->Width); - glUniform1f(loc_src_height, src_rb->Height); + _mesa_GetUniformLocation(blit->msaa_shaders[shader_index], "src_height"); + _mesa_Uniform1f(loc_src_width, src_rb->Width); + _mesa_Uniform1f(loc_src_height, src_rb->Height); return; } @@ -218,11 +219,11 @@ setup_glsl_msaa_blit_scaled_shader(struct gl_context *ctx, _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, name, &blit->msaa_shaders[shader_index]); loc_src_width = - glGetUniformLocation(blit->msaa_shaders[shader_index], "src_width"); + _mesa_GetUniformLocation(blit->msaa_shaders[shader_index], "src_width"); loc_src_height = - glGetUniformLocation(blit->msaa_shaders[shader_index], "src_height"); - glUniform1f(loc_src_width, src_rb->Width); - glUniform1f(loc_src_height, src_rb->Height); + _mesa_GetUniformLocation(blit->msaa_shaders[shader_index], "src_height"); + _mesa_Uniform1f(loc_src_width, src_rb->Width); + _mesa_Uniform1f(loc_src_height, src_rb->Height); ralloc_free(mem_ctx); } diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index 51a3d1f01..9b80600de 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -112,9 +112,8 @@ check_valid_to_render(struct gl_context *ctx, const char *function) switch (ctx->API) { case API_OPENGLES2: - /* For ES2, we can draw if any vertex array is enabled (and we - * should always have a vertex program/shader). */ - if (ctx->Array.VAO->_Enabled == 0x0 || !ctx->VertexProgram._Current) + /* For ES2, we can draw if we have a vertex program/shader). */ + if (!ctx->VertexProgram._Current) return GL_FALSE; break; diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 0edd66d6f..5a8f7184a 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -891,10 +891,24 @@ _mesa_generic_nop(void) /** - * Allocate and initialize a new dispatch table. + * Special no-op glFlush, see below. + */ +#if defined(_WIN32) +static void GLAPIENTRY +nop_glFlush(void) +{ + /* don't record an error like we do in _mesa_generic_nop() */ +} +#endif + + +/** + * Allocate and initialize a new dispatch table. All the dispatch + * function pointers will point at the _mesa_generic_nop() function + * which raises GL_INVALID_OPERATION. */ struct _glapi_table * -_mesa_alloc_dispatch_table() +_mesa_alloc_dispatch_table(void) { /* Find the larger of Mesa's dispatch table and libGL's dispatch table. * In practice, this'll be the same for stand-alone Mesa. But for DRI @@ -911,6 +925,26 @@ _mesa_alloc_dispatch_table() for (i = 0; i < numEntries; i++) { entry[i] = (_glapi_proc) _mesa_generic_nop; } + +#if defined(_WIN32) + /* This is a special case for Windows in the event that + * wglGetProcAddress is called between glBegin/End(). + * + * The MS opengl32.dll library apparently calls glFlush from + * wglGetProcAddress(). If we're inside glBegin/End(), glFlush + * will dispatch to _mesa_generic_nop() and we'll generate a + * GL_INVALID_OPERATION error. + * + * The specific case which hits this is piglit's primitive-restart + * test which calls glPrimitiveRestartNV() inside glBegin/End. The + * first time we call glPrimitiveRestartNV() Piglit's API dispatch + * code will try to resolve the function by calling wglGetProcAddress. + * This raises GL_INVALID_OPERATION and an assert(glGetError()==0) + * will fail causing the test to fail. By suppressing the error, the + * assertion passes and the test continues. + */ + SET_Flush(table, nop_glFlush); +#endif } return table; } diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 2c54e4a35..cb5f7936c 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -78,8 +78,8 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, struct gl_texture_image *texImage) { const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; + GLint height = texImage->Height; + GLint depth = texImage->Depth; GLint img, row; GLfloat *depthRow = malloc(width * sizeof(GLfloat)); @@ -88,6 +88,11 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, return; } + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + depth = height; + height = 1; + } + for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint srcRowStride; diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 647d28ab3..c0298af8e 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -2449,7 +2449,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, /* level check */ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(level=%d)", + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%uD(level=%d)", dimensions, level); return GL_TRUE; } diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index 09bf52c42..96c2b26f7 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -1907,10 +1907,10 @@ static void print_array(const char *name, GLint index, const struct gl_client_array *array) { if (index >= 0) - printf(" %s[%d]: ", name, index); + fprintf(stderr, " %s[%d]: ", name, index); else - printf(" %s: ", name); - printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu)\n", + fprintf(stderr, " %s: ", name); + fprintf(stderr, "Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu)\n", array->Ptr, array->Type, array->Size, array->_ElementSize, array->StrideB, array->BufferObj->Name, (unsigned long) array->BufferObj->Size); diff --git a/mesalib/src/mesa/program/Android.mk b/mesalib/src/mesa/program/Android.mk index e85afe672..19c4be0fe 100644 --- a/mesalib/src/mesa/program/Android.mk +++ b/mesalib/src/mesa/program/Android.mk @@ -39,6 +39,8 @@ endef # Import the following variables: # PROGRAM_FILES include $(MESA_TOP)/src/mesa/Makefile.sources +SRCDIR := +BUILDDIR := include $(CLEAR_VARS) @@ -71,6 +73,7 @@ $(intermediates)/program/lex.yy.c: $(LOCAL_PATH)/program_lexer.l LOCAL_C_INCLUDES := \ $(intermediates) \ + $(MESA_TOP)/src \ $(MESA_TOP)/src/mapi \ $(MESA_TOP)/src/mesa \ $(MESA_TOP)/src/glsl diff --git a/mesalib/src/util/Android.mk b/mesalib/src/util/Android.mk new file mode 100644 index 000000000..6b38cf9af --- /dev/null +++ b/mesalib/src/util/Android.mk @@ -0,0 +1,102 @@ +# Mesa 3-D graphics library +# +# Copyright (C) 2014 Tomasz Figa <tomasz.figa@gmail.com> +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +LOCAL_PATH := $(call my-dir) + +include $(LOCAL_PATH)/Makefile.sources + +# --------------------------------------- +# Build libmesa_util +# --------------------------------------- + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + $(MESA_UTIL_FILES) + +LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src/mesa \ + $(MESA_TOP)/src/mapi \ + $(MESA_TOP)/src + +LOCAL_MODULE := libmesa_util + +# Generated sources + +ifeq ($(LOCAL_MODULE_CLASS),) +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +endif + +intermediates := $(call local-intermediates-dir) + +# This is the list of auto-generated files: sources and headers +sources := $(addprefix $(intermediates)/, $(MESA_UTIL_GENERATED_FILES)) + +LOCAL_GENERATED_SOURCES += $(sources) + +FORMAT_SRGB := $(LOCAL_PATH)/format_srgb.py + +$(intermediates)/format_srgb.c: $(FORMAT_SRGB) + @$(MESA_PYTHON2) $(FORMAT_SRGB) $< > $@ + +include $(MESA_COMMON_MK) +include $(BUILD_STATIC_LIBRARY) + +# --------------------------------------- +# Build host libmesa_util +# --------------------------------------- + +include $(CLEAR_VARS) + +LOCAL_IS_HOST_MODULE := true +LOCAL_CFLAGS := -D_POSIX_C_SOURCE=199309L + +LOCAL_SRC_FILES := \ + $(MESA_UTIL_FILES) + +LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src/mesa \ + $(MESA_TOP)/src/mapi \ + $(MESA_TOP)/src + +LOCAL_MODULE := libmesa_util + +# Generated sources + +ifeq ($(LOCAL_MODULE_CLASS),) +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +endif + +intermediates := $(call local-intermediates-dir) + +# This is the list of auto-generated files: sources and headers +sources := $(addprefix $(intermediates)/, $(MESA_UTIL_GENERATED_FILES)) + +LOCAL_GENERATED_SOURCES += $(sources) + +FORMAT_SRGB := $(LOCAL_PATH)/format_srgb.py + +$(intermediates)/format_srgb.c: $(FORMAT_SRGB) + @$(MESA_PYTHON2) $(FORMAT_SRGB) $< > $@ + +include $(MESA_COMMON_MK) +include $(BUILD_HOST_STATIC_LIBRARY) |