diff options
Diffstat (limited to 'mesalib/src')
27 files changed, 926 insertions, 682 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 86bb8741b..e23718bdb 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -760,13 +760,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, ir_var_temporary); ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var); instructions->push_tail(var); - instructions->push_tail(new(ctx) ir_assignment(deref_var, - rhs, - NULL)); + instructions->push_tail(new(ctx) ir_assignment(deref_var, rhs)); deref_var = new(ctx) ir_dereference_variable(var); if (!error_emitted) - instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL)); + instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); return new(ctx) ir_dereference_variable(var); } @@ -783,7 +781,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) var->mode = ir_var_auto; instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), - lvalue, NULL)); + lvalue)); return new(ctx) ir_dereference_variable(var); } @@ -1223,12 +1221,12 @@ ast_expression::hir(exec_list *instructions, stmt->then_instructions.append_list(&rhs_instructions); ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const then_assign = - new(ctx) ir_assignment(then_deref, op[1], NULL); + new(ctx) ir_assignment(then_deref, op[1]); stmt->then_instructions.push_tail(then_assign); ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const else_assign = - new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false), NULL); + new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false)); stmt->else_instructions.push_tail(else_assign); result = new(ctx) ir_dereference_variable(tmp); @@ -1258,13 +1256,13 @@ ast_expression::hir(exec_list *instructions, ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const then_assign = - new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL); + new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true)); stmt->then_instructions.push_tail(then_assign); stmt->else_instructions.append_list(&rhs_instructions); ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const else_assign = - new(ctx) ir_assignment(else_deref, op[1], NULL); + new(ctx) ir_assignment(else_deref, op[1]); stmt->else_instructions.push_tail(else_assign); result = new(ctx) ir_dereference_variable(tmp); @@ -1452,14 +1450,14 @@ ast_expression::hir(exec_list *instructions, ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const then_assign = - new(ctx) ir_assignment(then_deref, op[1], NULL); + new(ctx) ir_assignment(then_deref, op[1]); stmt->then_instructions.push_tail(then_assign); else_instructions.move_nodes_to(& stmt->else_instructions); ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); ir_assignment *const else_assign = - new(ctx) ir_assignment(else_deref, op[2], NULL); + new(ctx) ir_assignment(else_deref, op[2]); stmt->else_instructions.push_tail(else_assign); result = new(ctx) ir_dereference_variable(tmp); @@ -3438,9 +3436,7 @@ ast_jump_statement::hir(exec_list *instructions, new(ctx) ir_dereference_variable(is_break_var); ir_constant *const true_val = new(ctx) ir_constant(true); ir_assignment *const set_break_var = - new(ctx) ir_assignment(deref_is_break_var, - true_val, - NULL); + new(ctx) ir_assignment(deref_is_break_var, true_val); instructions->push_tail(set_break_var); } @@ -3521,11 +3517,9 @@ ast_switch_statement::hir(exec_list *instructions, * * "The type of init-expression in a switch statement must be a * scalar integer." - * - * The checks are separated so that higher quality diagnostics can be - * generated for cases where the rule is violated. */ - if (!test_expression->type->is_integer()) { + if (!test_expression->type->is_scalar() || + !test_expression->type->is_integer()) { YYLTYPE loc = this->test_expression->get_location(); _mesa_glsl_error(& loc, @@ -3556,8 +3550,7 @@ ast_switch_statement::hir(exec_list *instructions, ir_dereference_variable *deref_is_fallthru_var = new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var, - is_fallthru_val, - NULL)); + is_fallthru_val)); /* Initalize is_break state to false. */ @@ -3570,13 +3563,12 @@ ast_switch_statement::hir(exec_list *instructions, ir_dereference_variable *deref_is_break_var = new(ctx) ir_dereference_variable(state->switch_state.is_break_var); instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var, - is_break_val, - NULL)); + is_break_val)); /* Cache test expression. */ test_to_hir(instructions, state); - + /* Emit code for body of switch stmt. */ body->hir(instructions, state); @@ -3585,290 +3577,267 @@ ast_switch_statement::hir(exec_list *instructions, state->switch_state = saved; - /* Switch statements do not have r-values. - */ - return NULL; - } - - - void - ast_switch_statement::test_to_hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - void *ctx = state; - - /* Cache value of test expression. - */ - ir_rvalue *const test_val = - test_expression->hir(instructions, - state); - - state->switch_state.test_var = new(ctx) ir_variable(glsl_type::int_type, - "switch_test_tmp", - ir_var_temporary); - ir_dereference_variable *deref_test_var = - new(ctx) ir_dereference_variable(state->switch_state.test_var); - - instructions->push_tail(state->switch_state.test_var); - instructions->push_tail(new(ctx) ir_assignment(deref_test_var, - test_val, - NULL)); - } - - - ir_rvalue * - ast_switch_body::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - if (stmts != NULL) - stmts->hir(instructions, state); - - /* Switch bodies do not have r-values. - */ - return NULL; - } - - - ir_rvalue * - ast_case_statement_list::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) - case_stmt->hir(instructions, state); - - /* Case statements do not have r-values. - */ - return NULL; - } - - - ir_rvalue * - ast_case_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - labels->hir(instructions, state); - - /* Conditionally set fallthru state based on break state. - */ - ir_constant *const false_val = new(state) ir_constant(false); - ir_dereference_variable *const deref_is_fallthru_var = - new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); - ir_dereference_variable *const deref_is_break_var = - new(state) ir_dereference_variable(state->switch_state.is_break_var); - ir_assignment *const reset_fallthru_on_break = - new(state) ir_assignment(deref_is_fallthru_var, - false_val, - deref_is_break_var); - instructions->push_tail(reset_fallthru_on_break); - - /* Guard case statements depending on fallthru state. - */ - ir_dereference_variable *const deref_fallthru_guard = - new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); - ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard); - - foreach_list_typed (ast_node, stmt, link, & this->stmts) - stmt->hir(& test_fallthru->then_instructions, state); - - instructions->push_tail(test_fallthru); - - /* Case statements do not have r-values. - */ - return NULL; - } - - - ir_rvalue * - ast_case_label_list::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - foreach_list_typed (ast_case_label, label, link, & this->labels) - label->hir(instructions, state); - - /* Case labels do not have r-values. - */ - return NULL; - } - - - ir_rvalue * - ast_case_label::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - void *ctx = state; - - ir_dereference_variable *deref_fallthru_var = - new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); - - ir_rvalue *const true_val = new(ctx) ir_constant(true); - - /* If not default case, ... - */ - if (this->test_value != NULL) { - /* Conditionally set fallthru state based on - * comparison of cached test expression value to case label. - */ - ir_rvalue *const label_rval = this->test_value->hir(instructions, state); - ir_constant *label_const = label_rval->constant_expression_value(); - - if (!label_const) { - YYLTYPE loc = this->test_value->get_location(); - - _mesa_glsl_error(& loc, state, - "switch statement case label must be a " - "constant expression"); - - /* Stuff a dummy value in to allow processing to continue. */ - label_const = new(ctx) ir_constant(0); - } else { - ast_expression *previous_label = (ast_expression *) - hash_table_find(state->switch_state.labels_ht, + /* Switch statements do not have r-values. */ + return NULL; +} + + +void +ast_switch_statement::test_to_hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + + /* Cache value of test expression. */ + ir_rvalue *const test_val = + test_expression->hir(instructions, + state); + + state->switch_state.test_var = new(ctx) ir_variable(test_val->type, + "switch_test_tmp", + ir_var_temporary); + ir_dereference_variable *deref_test_var = + new(ctx) ir_dereference_variable(state->switch_state.test_var); + + instructions->push_tail(state->switch_state.test_var); + instructions->push_tail(new(ctx) ir_assignment(deref_test_var, test_val)); +} + + +ir_rvalue * +ast_switch_body::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + if (stmts != NULL) + stmts->hir(instructions, state); + + /* Switch bodies do not have r-values. */ + return NULL; +} + +ir_rvalue * +ast_case_statement_list::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) + case_stmt->hir(instructions, state); + + /* Case statements do not have r-values. */ + return NULL; +} + +ir_rvalue * +ast_case_statement::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + labels->hir(instructions, state); + + /* Conditionally set fallthru state based on break state. */ + ir_constant *const false_val = new(state) ir_constant(false); + ir_dereference_variable *const deref_is_fallthru_var = + new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); + ir_dereference_variable *const deref_is_break_var = + new(state) ir_dereference_variable(state->switch_state.is_break_var); + ir_assignment *const reset_fallthru_on_break = + new(state) ir_assignment(deref_is_fallthru_var, + false_val, + deref_is_break_var); + instructions->push_tail(reset_fallthru_on_break); + + /* Guard case statements depending on fallthru state. */ + ir_dereference_variable *const deref_fallthru_guard = + new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); + ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard); + + foreach_list_typed (ast_node, stmt, link, & this->stmts) + stmt->hir(& test_fallthru->then_instructions, state); + + instructions->push_tail(test_fallthru); + + /* Case statements do not have r-values. */ + return NULL; +} + + +ir_rvalue * +ast_case_label_list::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + foreach_list_typed (ast_case_label, label, link, & this->labels) + label->hir(instructions, state); + + /* Case labels do not have r-values. */ + return NULL; +} + +ir_rvalue * +ast_case_label::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + + ir_dereference_variable *deref_fallthru_var = + new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); + + ir_rvalue *const true_val = new(ctx) ir_constant(true); + + /* If not default case, ... */ + if (this->test_value != NULL) { + /* Conditionally set fallthru state based on + * comparison of cached test expression value to case label. + */ + ir_rvalue *const label_rval = this->test_value->hir(instructions, state); + ir_constant *label_const = label_rval->constant_expression_value(); + + if (!label_const) { + YYLTYPE loc = this->test_value->get_location(); + + _mesa_glsl_error(& loc, state, + "switch statement case label must be a " + "constant expression"); + + /* Stuff a dummy value in to allow processing to continue. */ + label_const = new(ctx) ir_constant(0); + } else { + ast_expression *previous_label = (ast_expression *) + hash_table_find(state->switch_state.labels_ht, + (void *)(uintptr_t)label_const->value.u[0]); + + if (previous_label) { + YYLTYPE loc = this->test_value->get_location(); + _mesa_glsl_error(& loc, state, + "duplicate case value"); + + loc = previous_label->get_location(); + _mesa_glsl_error(& loc, state, + "this is the previous case label"); + } else { + hash_table_insert(state->switch_state.labels_ht, + this->test_value, (void *)(uintptr_t)label_const->value.u[0]); + } + } + + ir_dereference_variable *deref_test_var = + new(ctx) ir_dereference_variable(state->switch_state.test_var); + + ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal, + label_const, + deref_test_var); + + ir_assignment *set_fallthru_on_test = + new(ctx) ir_assignment(deref_fallthru_var, + true_val, + test_cond); + + instructions->push_tail(set_fallthru_on_test); + } else { /* default case */ + if (state->switch_state.previous_default) { + printf("a\n"); + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(& loc, state, + "multiple default labels in one switch"); + + printf("b\n"); + + loc = state->switch_state.previous_default->get_location(); + _mesa_glsl_error(& loc, state, + "this is the first default label"); + } + state->switch_state.previous_default = this; + + /* Set falltrhu state. */ + ir_assignment *set_fallthru = + new(ctx) ir_assignment(deref_fallthru_var, true_val); + + instructions->push_tail(set_fallthru); + } - if (previous_label) { - YYLTYPE loc = this->test_value->get_location(); - _mesa_glsl_error(& loc, state, - "duplicate case value"); - - loc = previous_label->get_location(); - _mesa_glsl_error(& loc, state, - "this is the previous case label"); - } else { - hash_table_insert(state->switch_state.labels_ht, - this->test_value, - (void *)(uintptr_t)label_const->value.u[0]); - } - } - - ir_dereference_variable *deref_test_var = - new(ctx) ir_dereference_variable(state->switch_state.test_var); - - ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal, - glsl_type::bool_type, - label_const, - deref_test_var); - - ir_assignment *set_fallthru_on_test = - new(ctx) ir_assignment(deref_fallthru_var, - true_val, - test_cond); - - instructions->push_tail(set_fallthru_on_test); - } else { /* default case */ - if (state->switch_state.previous_default) { - printf("a\n"); - YYLTYPE loc = this->get_location(); - _mesa_glsl_error(& loc, state, - "multiple default labels in one switch"); - - printf("b\n"); - - loc = state->switch_state.previous_default->get_location(); - _mesa_glsl_error(& loc, state, - "this is the first default label"); - } - state->switch_state.previous_default = this; - - /* Set falltrhu state. - */ - ir_assignment *set_fallthru = - new(ctx) ir_assignment(deref_fallthru_var, - true_val, - NULL); - - instructions->push_tail(set_fallthru); - } - - /* Case statements do not have r-values. - */ - return NULL; - } - - - void - ast_iteration_statement::condition_to_hir(ir_loop *stmt, - struct _mesa_glsl_parse_state *state) - { - void *ctx = state; - - if (condition != NULL) { - ir_rvalue *const cond = - condition->hir(& stmt->body_instructions, state); - - if ((cond == NULL) - || !cond->type->is_boolean() || !cond->type->is_scalar()) { - YYLTYPE loc = condition->get_location(); - - _mesa_glsl_error(& loc, state, - "loop condition must be scalar boolean"); - } else { - /* As the first code in the loop body, generate a block that looks - * like 'if (!condition) break;' as the loop termination condition. - */ - ir_rvalue *const not_cond = - new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond, - NULL); - - ir_if *const if_stmt = new(ctx) ir_if(not_cond); - - ir_jump *const break_stmt = - new(ctx) ir_loop_jump(ir_loop_jump::jump_break); - - if_stmt->then_instructions.push_tail(break_stmt); - stmt->body_instructions.push_tail(if_stmt); - } - } - } - - - ir_rvalue * - ast_iteration_statement::hir(exec_list *instructions, - struct _mesa_glsl_parse_state *state) - { - void *ctx = state; - - /* For-loops and while-loops start a new scope, but do-while loops do not. - */ - if (mode != ast_do_while) - state->symbols->push_scope(); - - if (init_statement != NULL) - init_statement->hir(instructions, state); - - ir_loop *const stmt = new(ctx) ir_loop(); - instructions->push_tail(stmt); - - /* Track the current loop nesting. - */ - ast_iteration_statement *nesting_ast = state->loop_nesting_ast; - - state->loop_nesting_ast = this; - - /* Likewise, indicate that following code is closest to a loop, - * NOT closest to a switch. - */ - bool saved_is_switch_innermost = state->switch_state.is_switch_innermost; - state->switch_state.is_switch_innermost = false; - - if (mode != ast_do_while) - condition_to_hir(stmt, state); - - if (body != NULL) - body->hir(& stmt->body_instructions, state); - - if (rest_expression != NULL) - rest_expression->hir(& stmt->body_instructions, state); + /* Case statements do not have r-values. */ + return NULL; +} + +void +ast_iteration_statement::condition_to_hir(ir_loop *stmt, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + + if (condition != NULL) { + ir_rvalue *const cond = + condition->hir(& stmt->body_instructions, state); + + if ((cond == NULL) + || !cond->type->is_boolean() || !cond->type->is_scalar()) { + YYLTYPE loc = condition->get_location(); + + _mesa_glsl_error(& loc, state, + "loop condition must be scalar boolean"); + } else { + /* As the first code in the loop body, generate a block that looks + * like 'if (!condition) break;' as the loop termination condition. + */ + ir_rvalue *const not_cond = + new(ctx) ir_expression(ir_unop_logic_not, cond); + + ir_if *const if_stmt = new(ctx) ir_if(not_cond); + + ir_jump *const break_stmt = + new(ctx) ir_loop_jump(ir_loop_jump::jump_break); + + if_stmt->then_instructions.push_tail(break_stmt); + stmt->body_instructions.push_tail(if_stmt); + } + } +} + + +ir_rvalue * +ast_iteration_statement::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + + /* For-loops and while-loops start a new scope, but do-while loops do not. + */ + if (mode != ast_do_while) + state->symbols->push_scope(); + + if (init_statement != NULL) + init_statement->hir(instructions, state); + + ir_loop *const stmt = new(ctx) ir_loop(); + instructions->push_tail(stmt); + + /* Track the current loop nesting. */ + ast_iteration_statement *nesting_ast = state->loop_nesting_ast; + + state->loop_nesting_ast = this; + + /* Likewise, indicate that following code is closest to a loop, + * NOT closest to a switch. + */ + bool saved_is_switch_innermost = state->switch_state.is_switch_innermost; + state->switch_state.is_switch_innermost = false; + + if (mode != ast_do_while) + condition_to_hir(stmt, state); + + if (body != NULL) + body->hir(& stmt->body_instructions, state); + + if (rest_expression != NULL) + rest_expression->hir(& stmt->body_instructions, state); + + if (mode == ast_do_while) + condition_to_hir(stmt, state); + + if (mode != ast_do_while) + state->symbols->pop_scope(); - if (mode == ast_do_while) - condition_to_hir(stmt, state); - - if (mode != ast_do_while) - state->symbols->pop_scope(); - - /* Restore previous nesting before returning. - */ - state->loop_nesting_ast = nesting_ast; - state->switch_state.is_switch_innermost = saved_is_switch_innermost; + /* Restore previous nesting before returning. */ + state->loop_nesting_ast = nesting_ast; + state->switch_state.is_switch_innermost = saved_is_switch_innermost; /* Loops do not have r-values. */ diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp index a81a38fff..4af78a72c 100644 --- a/mesalib/src/glsl/opt_dead_code_local.cpp +++ b/mesalib/src/glsl/opt_dead_code_local.cpp @@ -43,16 +43,20 @@ static bool debug = false; class assignment_entry : public exec_node { public: - assignment_entry(ir_variable *lhs, ir_instruction *ir) + assignment_entry(ir_variable *lhs, ir_assignment *ir) { assert(lhs); assert(ir); this->lhs = lhs; this->ir = ir; + this->available = ir->write_mask; } ir_variable *lhs; - ir_instruction *ir; + ir_assignment *ir; + + /* bitmask of xyzw channels written that haven't been used so far. */ + int available; }; class kill_for_derefs_visitor : public ir_hierarchical_visitor { @@ -62,23 +66,52 @@ public: this->assignments = assignments; } - virtual ir_visitor_status visit(ir_dereference_variable *ir) + void kill_channels(ir_variable *const var, int used) { - ir_variable *const var = ir->variable_referenced(); - foreach_iter(exec_list_iterator, iter, *this->assignments) { assignment_entry *entry = (assignment_entry *)iter.get(); if (entry->lhs == var) { - if (debug) - printf("kill %s\n", entry->lhs->name); - entry->remove(); + if (var->type->is_scalar() || var->type->is_vector()) { + if (debug) + printf("kill %s (0x%01x - 0x%01x)\n", entry->lhs->name, + entry->available, used); + entry->available &= ~used; + if (!entry->available) + entry->remove(); + } else { + if (debug) + printf("kill %s\n", entry->lhs->name); + entry->remove(); + } } } + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + kill_channels(ir->var, ~0); return visit_continue; } + virtual ir_visitor_status visit(ir_swizzle *ir) + { + ir_dereference_variable *deref = ir->val->as_dereference_variable(); + if (!deref) + return visit_continue; + + int used = 0; + used |= 1 << ir->mask.x; + used |= 1 << ir->mask.y; + used |= 1 << ir->mask.z; + used |= 1 << ir->mask.w; + + kill_channels(deref->var, used); + + return visit_continue_with_parent; + } + private: exec_list *assignments; }; @@ -130,21 +163,91 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments) assert(var); /* Now, check if we did a whole-variable assignment. */ - if (!ir->condition && (ir->whole_variable_written() != NULL)) { - /* We did a whole-variable assignment. So, any instruction in - * the assignment list with the same LHS is dead. - */ - if (debug) - printf("looking for %s to remove\n", var->name); - foreach_iter(exec_list_iterator, iter, *assignments) { - assignment_entry *entry = (assignment_entry *)iter.get(); + if (!ir->condition) { + ir_dereference_variable *deref_var = ir->lhs->as_dereference_variable(); - if (entry->lhs == var) { - if (debug) - printf("removing %s\n", var->name); - entry->ir->remove(); - entry->remove(); - progress = true; + /* If it's a vector type, we can do per-channel elimination of + * use of the RHS. + */ + if (deref_var && (deref_var->var->type->is_scalar() || + deref_var->var->type->is_vector())) { + + if (debug) + printf("looking for %s.0x%01x to remove\n", var->name, + ir->write_mask); + + foreach_iter(exec_list_iterator, iter, *assignments) { + assignment_entry *entry = (assignment_entry *)iter.get(); + + if (entry->lhs != var) + continue; + + int remove = entry->available & ir->write_mask; + if (debug) { + printf("%s 0x%01x - 0x%01x = 0x%01x\n", + var->name, + entry->ir->write_mask, + remove, entry->ir->write_mask & ~remove); + } + if (remove) { + progress = true; + + if (debug) { + printf("rewriting:\n "); + entry->ir->print(); + printf("\n"); + } + + entry->ir->write_mask &= ~remove; + entry->available &= ~remove; + if (entry->ir->write_mask == 0) { + /* Delete the dead assignment. */ + entry->ir->remove(); + entry->remove(); + } else { + void *mem_ctx = ralloc_parent(entry->ir); + /* Reswizzle the RHS arguments according to the new + * write_mask. + */ + unsigned components[4]; + unsigned channels = 0; + unsigned next = 0; + + for (int i = 0; i < 4; i++) { + if ((entry->ir->write_mask | remove) & (1 << i)) { + if (!(remove & (1 << i))) + components[channels++] = next; + next++; + } + } + + entry->ir->rhs = new(mem_ctx) ir_swizzle(entry->ir->rhs, + components, + channels); + if (debug) { + printf("to:\n "); + entry->ir->print(); + printf("\n"); + } + } + } + } + } else if (ir->whole_variable_written() != NULL) { + /* We did a whole-variable assignment. So, any instruction in + * the assignment list with the same LHS is dead. + */ + if (debug) + printf("looking for %s to remove\n", var->name); + foreach_iter(exec_list_iterator, iter, *assignments) { + assignment_entry *entry = (assignment_entry *)iter.get(); + + if (entry->lhs == var) { + if (debug) + printf("removing %s\n", var->name); + entry->ir->remove(); + entry->remove(); + progress = true; + } } } } @@ -160,7 +263,7 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments) foreach_iter(exec_list_iterator, iter, *assignments) { assignment_entry *entry = (assignment_entry *)iter.get(); - printf(" %s\n", entry->lhs->name); + printf(" %s (0x%01x)\n", entry->lhs->name, entry->available); } } diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index dc37a6730..d7932c7c9 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -215,6 +215,7 @@ vbo_sources = [ 'vbo/vbo_exec_draw.c', 'vbo/vbo_exec_eval.c', 'vbo/vbo_noop.c', + 'vbo/vbo_primitive_restart.c', 'vbo/vbo_rebase.c', 'vbo/vbo_split.c', 'vbo/vbo_split_copy.c', diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 25d981053..bfa06f37d 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -285,12 +285,6 @@ static INLINE GLuint CPU_TO_LE32(GLuint x) #endif -/* This is a macro on IRIX */ -#ifdef _P -#undef _P -#endif - - /* Turn off macro checking systems used by other libraries */ #ifdef CHECK #undef CHECK diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index bafd250a1..df0452cd1 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -662,6 +662,9 @@ _mesa_init_constants(struct gl_context *ctx) /* GL_ARB_robustness */ ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; + + /* PrimitiveRestart */ + ctx->Const.PrimitiveRestartInSoftware = GL_FALSE; } diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index b00e01236..c42bac19c 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -2929,7 +2929,7 @@ unpack_uint_z_Z32_FLOAT(const void *src, GLuint *dst, GLuint n) const float *s = (const float *)src; GLuint i; for (i = 0; i < n; i++) { - dst[i] = FLOAT_TO_UINT(IROUND(CLAMP((s[i]), 0.0F, 1.0F))); + dst[i] = FLOAT_TO_UINT(CLAMP(s[i], 0.0F, 1.0F)); } } @@ -2940,7 +2940,7 @@ unpack_uint_z_Z32_FLOAT_X24S8(const void *src, GLuint *dst, GLuint n) GLuint i; for (i = 0; i < n; i++) { - dst[i] = FLOAT_TO_UINT(IROUND(CLAMP((s[i].z), 0.0F, 1.0F))); + dst[i] = FLOAT_TO_UINT(CLAMP(s[i].z, 0.0F, 1.0F)); } } diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index aa5eb3200..c0b6cecea 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -285,19 +285,47 @@ static inline int GET_FLOAT_BITS( float x ) #endif -/*** - *** IROUND: return (as an integer) float rounded to nearest integer - ***/ +/** + * Convert float to int by rounding to nearest integer, away from zero. + */ +static inline int IROUND(float f) +{ + return (int) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F)); +} + + +/** + * Convert float to int64 by rounding to nearest integer. + */ +static inline GLint64 IROUND64(float f) +{ + return (GLint64) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F)); +} + + +/** + * Convert positive float to int by rounding to nearest integer. + */ +static inline int IROUND_POS(float f) +{ + assert(f >= 0.0F); + return (int) (f + 0.5F); +} + + +/** + * Convert float to int using a fast method. The rounding mode may vary. + * XXX We could use an x86-64/SSE2 version here. + */ #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) -static inline int iround(float f) +static inline int F_TO_I(float f) { int r; __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); return r; } -#define IROUND(x) iround(x) #elif defined(USE_X86_ASM) && defined(_MSC_VER) -static inline int iround(float f) +static inline int F_TO_I(float f) { int r; _asm { @@ -306,9 +334,8 @@ static inline int iround(float f) } return r; } -#define IROUND(x) iround(x) #elif defined(__WATCOMC__) && defined(__386__) -long iround(float f); +long F_TO_I(float f); #pragma aux iround = \ "push eax" \ "fistp dword ptr [esp]" \ @@ -316,20 +343,8 @@ long iround(float f); parm [8087] \ value [eax] \ modify exact [eax]; -#define IROUND(x) iround(x) -#else -#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F))) -#endif - -#define IROUND64(f) ((GLint64) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F))) - -/*** - *** IROUND_POS: return (as an integer) positive float rounded to nearest int - ***/ -#ifdef DEBUG -#define IROUND_POS(f) (assert((f) >= 0.0F), IROUND(f)) #else -#define IROUND_POS(f) (IROUND(f)) +#define F_TO_I(f) IROUND(f) #endif diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h index dbe5b867c..d1df2ce1b 100644 --- a/mesalib/src/mesa/main/macros.h +++ b/mesalib/src/mesa/main/macros.h @@ -129,12 +129,12 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256]; #define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15))) #define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) #define UNCLAMPED_FLOAT_TO_USHORT(us, f) \ - us = ( (GLushort) IROUND( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) + us = ( (GLushort) F_TO_I( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) #define CLAMPED_FLOAT_TO_USHORT(us, f) \ - us = ( (GLushort) IROUND( (f) * 65535.0F) ) + us = ( (GLushort) F_TO_I( (f) * 65535.0F) ) #define UNCLAMPED_FLOAT_TO_SHORT(s, f) \ - s = ( (GLshort) IROUND( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) + s = ( (GLshort) F_TO_I( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) /*** *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] @@ -166,9 +166,9 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256]; } while (0) #else #define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \ - ub = ((GLubyte) IROUND(CLAMP((f), 0.0F, 1.0F) * 255.0F)) + ub = ((GLubyte) F_TO_I(CLAMP((f), 0.0F, 1.0F) * 255.0F)) #define CLAMPED_FLOAT_TO_UBYTE(ub, f) \ - ub = ((GLubyte) IROUND((f) * 255.0F)) + ub = ((GLubyte) F_TO_I((f) * 255.0F)) #endif /*@}*/ diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index c306ac6b9..eefe5e7e9 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2355,6 +2355,7 @@ struct gl_shader_program #define GLSL_NOP_VERT 0x20 /**< Force no-op vertex shaders */ #define GLSL_NOP_FRAG 0x40 /**< Force no-op fragment shaders */ #define GLSL_USE_PROG 0x80 /**< Log glUseProgram calls */ +#define GLSL_REPORT_ERRORS 0x100 /**< Print compilation errors */ /** @@ -2845,6 +2846,11 @@ struct gl_constants */ GLboolean GLSLSkipStrictMaxVaryingLimitCheck; GLboolean GLSLSkipStrictMaxUniformLimitCheck; + + /** + * Force software support for primitive restart in the VBO module. + */ + GLboolean PrimitiveRestartInSoftware; }; diff --git a/mesalib/src/mesa/main/pack.c b/mesalib/src/mesa/main/pack.c index 4d4b4a825..c25a02e85 100644 --- a/mesalib/src/mesa/main/pack.c +++ b/mesalib/src/mesa/main/pack.c @@ -1726,9 +1726,9 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGB) { GLubyte *dst = (GLubyte *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 7.0F) << 5) - | (IROUND(rgba[i][GCOMP] * 7.0F) << 2) - | (IROUND(rgba[i][BCOMP] * 3.0F) ); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 7.0F) << 5) + | (F_TO_I(rgba[i][GCOMP] * 7.0F) << 2) + | (F_TO_I(rgba[i][BCOMP] * 3.0F) ); } } break; @@ -1736,9 +1736,9 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGB) { GLubyte *dst = (GLubyte *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 7.0F) ) - | (IROUND(rgba[i][GCOMP] * 7.0F) << 3) - | (IROUND(rgba[i][BCOMP] * 3.0F) << 6); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 7.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 7.0F) << 3) + | (F_TO_I(rgba[i][BCOMP] * 3.0F) << 6); } } break; @@ -1746,9 +1746,9 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGB) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) << 11) - | (IROUND(rgba[i][GCOMP] * 63.0F) << 5) - | (IROUND(rgba[i][BCOMP] * 31.0F) ); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 31.0F) << 11) + | (F_TO_I(rgba[i][GCOMP] * 63.0F) << 5) + | (F_TO_I(rgba[i][BCOMP] * 31.0F) ); } } break; @@ -1756,9 +1756,9 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGB) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) ) - | (IROUND(rgba[i][GCOMP] * 63.0F) << 5) - | (IROUND(rgba[i][BCOMP] * 31.0F) << 11); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 31.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 63.0F) << 5) + | (F_TO_I(rgba[i][BCOMP] * 31.0F) << 11); } } break; @@ -1766,28 +1766,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 15.0F) << 12) - | (IROUND(rgba[i][GCOMP] * 15.0F) << 8) - | (IROUND(rgba[i][BCOMP] * 15.0F) << 4) - | (IROUND(rgba[i][ACOMP] * 15.0F) ); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 15.0F) << 12) + | (F_TO_I(rgba[i][GCOMP] * 15.0F) << 8) + | (F_TO_I(rgba[i][BCOMP] * 15.0F) << 4) + | (F_TO_I(rgba[i][ACOMP] * 15.0F) ); } } else if (dstFormat == GL_BGRA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 15.0F) << 12) - | (IROUND(rgba[i][GCOMP] * 15.0F) << 8) - | (IROUND(rgba[i][RCOMP] * 15.0F) << 4) - | (IROUND(rgba[i][ACOMP] * 15.0F) ); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 15.0F) << 12) + | (F_TO_I(rgba[i][GCOMP] * 15.0F) << 8) + | (F_TO_I(rgba[i][RCOMP] * 15.0F) << 4) + | (F_TO_I(rgba[i][ACOMP] * 15.0F) ); } } else if (dstFormat == GL_ABGR_EXT) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 15.0F) << 12) - | (IROUND(rgba[i][BCOMP] * 15.0F) << 8) - | (IROUND(rgba[i][GCOMP] * 15.0F) << 4) - | (IROUND(rgba[i][RCOMP] * 15.0F) ); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 15.0F) << 12) + | (F_TO_I(rgba[i][BCOMP] * 15.0F) << 8) + | (F_TO_I(rgba[i][GCOMP] * 15.0F) << 4) + | (F_TO_I(rgba[i][RCOMP] * 15.0F) ); } } break; @@ -1795,28 +1795,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 15.0F) ) - | (IROUND(rgba[i][GCOMP] * 15.0F) << 4) - | (IROUND(rgba[i][BCOMP] * 15.0F) << 8) - | (IROUND(rgba[i][ACOMP] * 15.0F) << 12); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 15.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 15.0F) << 4) + | (F_TO_I(rgba[i][BCOMP] * 15.0F) << 8) + | (F_TO_I(rgba[i][ACOMP] * 15.0F) << 12); } } else if (dstFormat == GL_BGRA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 15.0F) ) - | (IROUND(rgba[i][GCOMP] * 15.0F) << 4) - | (IROUND(rgba[i][RCOMP] * 15.0F) << 8) - | (IROUND(rgba[i][ACOMP] * 15.0F) << 12); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 15.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 15.0F) << 4) + | (F_TO_I(rgba[i][RCOMP] * 15.0F) << 8) + | (F_TO_I(rgba[i][ACOMP] * 15.0F) << 12); } } else if (dstFormat == GL_ABGR_EXT) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 15.0F) ) - | (IROUND(rgba[i][BCOMP] * 15.0F) << 4) - | (IROUND(rgba[i][GCOMP] * 15.0F) << 8) - | (IROUND(rgba[i][RCOMP] * 15.0F) << 12); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 15.0F) ) + | (F_TO_I(rgba[i][BCOMP] * 15.0F) << 4) + | (F_TO_I(rgba[i][GCOMP] * 15.0F) << 8) + | (F_TO_I(rgba[i][RCOMP] * 15.0F) << 12); } } break; @@ -1824,28 +1824,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) << 11) - | (IROUND(rgba[i][GCOMP] * 31.0F) << 6) - | (IROUND(rgba[i][BCOMP] * 31.0F) << 1) - | (IROUND(rgba[i][ACOMP] * 1.0F) ); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 31.0F) << 11) + | (F_TO_I(rgba[i][GCOMP] * 31.0F) << 6) + | (F_TO_I(rgba[i][BCOMP] * 31.0F) << 1) + | (F_TO_I(rgba[i][ACOMP] * 1.0F) ); } } else if (dstFormat == GL_BGRA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 31.0F) << 11) - | (IROUND(rgba[i][GCOMP] * 31.0F) << 6) - | (IROUND(rgba[i][RCOMP] * 31.0F) << 1) - | (IROUND(rgba[i][ACOMP] * 1.0F) ); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 31.0F) << 11) + | (F_TO_I(rgba[i][GCOMP] * 31.0F) << 6) + | (F_TO_I(rgba[i][RCOMP] * 31.0F) << 1) + | (F_TO_I(rgba[i][ACOMP] * 1.0F) ); } } else if (dstFormat == GL_ABGR_EXT) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 31.0F) << 11) - | (IROUND(rgba[i][BCOMP] * 31.0F) << 6) - | (IROUND(rgba[i][GCOMP] * 31.0F) << 1) - | (IROUND(rgba[i][RCOMP] * 1.0F) ); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 31.0F) << 11) + | (F_TO_I(rgba[i][BCOMP] * 31.0F) << 6) + | (F_TO_I(rgba[i][GCOMP] * 31.0F) << 1) + | (F_TO_I(rgba[i][RCOMP] * 1.0F) ); } } break; @@ -1853,28 +1853,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) ) - | (IROUND(rgba[i][GCOMP] * 31.0F) << 5) - | (IROUND(rgba[i][BCOMP] * 31.0F) << 10) - | (IROUND(rgba[i][ACOMP] * 1.0F) << 15); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 31.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 31.0F) << 5) + | (F_TO_I(rgba[i][BCOMP] * 31.0F) << 10) + | (F_TO_I(rgba[i][ACOMP] * 1.0F) << 15); } } else if (dstFormat == GL_BGRA) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 31.0F) ) - | (IROUND(rgba[i][GCOMP] * 31.0F) << 5) - | (IROUND(rgba[i][RCOMP] * 31.0F) << 10) - | (IROUND(rgba[i][ACOMP] * 1.0F) << 15); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 31.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 31.0F) << 5) + | (F_TO_I(rgba[i][RCOMP] * 31.0F) << 10) + | (F_TO_I(rgba[i][ACOMP] * 1.0F) << 15); } } else if (dstFormat == GL_ABGR_EXT) { GLushort *dst = (GLushort *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 31.0F) ) - | (IROUND(rgba[i][BCOMP] * 31.0F) << 5) - | (IROUND(rgba[i][GCOMP] * 31.0F) << 10) - | (IROUND(rgba[i][RCOMP] * 1.0F) << 15); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 31.0F) ) + | (F_TO_I(rgba[i][BCOMP] * 31.0F) << 5) + | (F_TO_I(rgba[i][GCOMP] * 31.0F) << 10) + | (F_TO_I(rgba[i][RCOMP] * 1.0F) << 15); } } break; @@ -1882,28 +1882,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 255.F) << 24) - | (IROUND(rgba[i][GCOMP] * 255.F) << 16) - | (IROUND(rgba[i][BCOMP] * 255.F) << 8) - | (IROUND(rgba[i][ACOMP] * 255.F) ); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 255.F) << 24) + | (F_TO_I(rgba[i][GCOMP] * 255.F) << 16) + | (F_TO_I(rgba[i][BCOMP] * 255.F) << 8) + | (F_TO_I(rgba[i][ACOMP] * 255.F) ); } } else if (dstFormat == GL_BGRA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 255.F) << 24) - | (IROUND(rgba[i][GCOMP] * 255.F) << 16) - | (IROUND(rgba[i][RCOMP] * 255.F) << 8) - | (IROUND(rgba[i][ACOMP] * 255.F) ); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 255.F) << 24) + | (F_TO_I(rgba[i][GCOMP] * 255.F) << 16) + | (F_TO_I(rgba[i][RCOMP] * 255.F) << 8) + | (F_TO_I(rgba[i][ACOMP] * 255.F) ); } } else if (dstFormat == GL_ABGR_EXT) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 255.F) << 24) - | (IROUND(rgba[i][BCOMP] * 255.F) << 16) - | (IROUND(rgba[i][GCOMP] * 255.F) << 8) - | (IROUND(rgba[i][RCOMP] * 255.F) ); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 255.F) << 24) + | (F_TO_I(rgba[i][BCOMP] * 255.F) << 16) + | (F_TO_I(rgba[i][GCOMP] * 255.F) << 8) + | (F_TO_I(rgba[i][RCOMP] * 255.F) ); } } break; @@ -1911,28 +1911,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 255.0F) ) - | (IROUND(rgba[i][GCOMP] * 255.0F) << 8) - | (IROUND(rgba[i][BCOMP] * 255.0F) << 16) - | (IROUND(rgba[i][ACOMP] * 255.0F) << 24); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 255.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 255.0F) << 8) + | (F_TO_I(rgba[i][BCOMP] * 255.0F) << 16) + | (F_TO_I(rgba[i][ACOMP] * 255.0F) << 24); } } else if (dstFormat == GL_BGRA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 255.0F) ) - | (IROUND(rgba[i][GCOMP] * 255.0F) << 8) - | (IROUND(rgba[i][RCOMP] * 255.0F) << 16) - | (IROUND(rgba[i][ACOMP] * 255.0F) << 24); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 255.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 255.0F) << 8) + | (F_TO_I(rgba[i][RCOMP] * 255.0F) << 16) + | (F_TO_I(rgba[i][ACOMP] * 255.0F) << 24); } } else if (dstFormat == GL_ABGR_EXT) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 255.0F) ) - | (IROUND(rgba[i][BCOMP] * 255.0F) << 8) - | (IROUND(rgba[i][GCOMP] * 255.0F) << 16) - | (IROUND(rgba[i][RCOMP] * 255.0F) << 24); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 255.0F) ) + | (F_TO_I(rgba[i][BCOMP] * 255.0F) << 8) + | (F_TO_I(rgba[i][GCOMP] * 255.0F) << 16) + | (F_TO_I(rgba[i][RCOMP] * 255.0F) << 24); } } break; @@ -1940,28 +1940,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 1023.0F) << 22) - | (IROUND(rgba[i][GCOMP] * 1023.0F) << 12) - | (IROUND(rgba[i][BCOMP] * 1023.0F) << 2) - | (IROUND(rgba[i][ACOMP] * 3.0F) ); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 1023.0F) << 22) + | (F_TO_I(rgba[i][GCOMP] * 1023.0F) << 12) + | (F_TO_I(rgba[i][BCOMP] * 1023.0F) << 2) + | (F_TO_I(rgba[i][ACOMP] * 3.0F) ); } } else if (dstFormat == GL_BGRA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 1023.0F) << 22) - | (IROUND(rgba[i][GCOMP] * 1023.0F) << 12) - | (IROUND(rgba[i][RCOMP] * 1023.0F) << 2) - | (IROUND(rgba[i][ACOMP] * 3.0F) ); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 1023.0F) << 22) + | (F_TO_I(rgba[i][GCOMP] * 1023.0F) << 12) + | (F_TO_I(rgba[i][RCOMP] * 1023.0F) << 2) + | (F_TO_I(rgba[i][ACOMP] * 3.0F) ); } } else if (dstFormat == GL_ABGR_EXT) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 1023.0F) << 22) - | (IROUND(rgba[i][BCOMP] * 1023.0F) << 12) - | (IROUND(rgba[i][GCOMP] * 1023.0F) << 2) - | (IROUND(rgba[i][RCOMP] * 3.0F) ); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 1023.0F) << 22) + | (F_TO_I(rgba[i][BCOMP] * 1023.0F) << 12) + | (F_TO_I(rgba[i][GCOMP] * 1023.0F) << 2) + | (F_TO_I(rgba[i][RCOMP] * 3.0F) ); } } break; @@ -1969,28 +1969,28 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], if (dstFormat == GL_RGBA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][RCOMP] * 1023.0F) ) - | (IROUND(rgba[i][GCOMP] * 1023.0F) << 10) - | (IROUND(rgba[i][BCOMP] * 1023.0F) << 20) - | (IROUND(rgba[i][ACOMP] * 3.0F) << 30); + dst[i] = (F_TO_I(rgba[i][RCOMP] * 1023.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 1023.0F) << 10) + | (F_TO_I(rgba[i][BCOMP] * 1023.0F) << 20) + | (F_TO_I(rgba[i][ACOMP] * 3.0F) << 30); } } else if (dstFormat == GL_BGRA) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][BCOMP] * 1023.0F) ) - | (IROUND(rgba[i][GCOMP] * 1023.0F) << 10) - | (IROUND(rgba[i][RCOMP] * 1023.0F) << 20) - | (IROUND(rgba[i][ACOMP] * 3.0F) << 30); + dst[i] = (F_TO_I(rgba[i][BCOMP] * 1023.0F) ) + | (F_TO_I(rgba[i][GCOMP] * 1023.0F) << 10) + | (F_TO_I(rgba[i][RCOMP] * 1023.0F) << 20) + | (F_TO_I(rgba[i][ACOMP] * 3.0F) << 30); } } else if (dstFormat == GL_ABGR_EXT) { GLuint *dst = (GLuint *) dstAddr; for (i=0;i<n;i++) { - dst[i] = (IROUND(rgba[i][ACOMP] * 1023.0F) ) - | (IROUND(rgba[i][BCOMP] * 1023.0F) << 10) - | (IROUND(rgba[i][GCOMP] * 1023.0F) << 20) - | (IROUND(rgba[i][RCOMP] * 3.0F) << 30); + dst[i] = (F_TO_I(rgba[i][ACOMP] * 1023.0F) ) + | (F_TO_I(rgba[i][BCOMP] * 1023.0F) << 10) + | (F_TO_I(rgba[i][GCOMP] * 1023.0F) << 20) + | (F_TO_I(rgba[i][RCOMP] * 3.0F) << 30); } } break; @@ -3005,7 +3005,7 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], static inline GLuint clamp_float_to_uint(GLfloat f) { - return f < 0.0F ? 0 : IROUND(f); + return f < 0.0F ? 0 : F_TO_I(f); } @@ -3013,7 +3013,7 @@ static inline GLuint clamp_half_to_uint(GLhalfARB h) { GLfloat f = _mesa_half_to_float(h); - return f < 0.0F ? 0 : IROUND(f); + return f < 0.0F ? 0 : F_TO_I(f); } diff --git a/mesalib/src/mesa/main/pixeltransfer.c b/mesalib/src/mesa/main/pixeltransfer.c index c6172b9fd..fa355eb4a 100644 --- a/mesalib/src/mesa/main/pixeltransfer.c +++ b/mesalib/src/mesa/main/pixeltransfer.c @@ -93,10 +93,10 @@ _mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] ) GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); - rgba[i][RCOMP] = rMap[IROUND(r * rscale)]; - rgba[i][GCOMP] = gMap[IROUND(g * gscale)]; - rgba[i][BCOMP] = bMap[IROUND(b * bscale)]; - rgba[i][ACOMP] = aMap[IROUND(a * ascale)]; + rgba[i][RCOMP] = rMap[F_TO_I(r * rscale)]; + rgba[i][GCOMP] = gMap[F_TO_I(g * gscale)]; + rgba[i][BCOMP] = bMap[F_TO_I(b * bscale)]; + rgba[i][ACOMP] = aMap[F_TO_I(a * ascale)]; } } @@ -235,7 +235,7 @@ _mesa_apply_ci_transfer_ops(const struct gl_context *ctx, GLuint i; for (i = 0; i < n; i++) { const GLuint j = indexes[i] & mask; - indexes[i] = IROUND(ctx->PixelMaps.ItoI.Map[j]); + indexes[i] = F_TO_I(ctx->PixelMaps.ItoI.Map[j]); } } } diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index 31acfcbf1..138111049 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -701,6 +701,12 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, return; } + if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glReadPixels(incomplete framebuffer)" ); + return; + } + /* Check that the destination format and source buffer are both * integer-valued or both non-integer-valued. */ @@ -715,12 +721,6 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, } } - if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glReadPixels(incomplete framebuffer)" ); - return; - } - if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); return; diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index fd793a7ab..6927368de 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -83,6 +83,8 @@ get_shader_flags(void) flags |= GLSL_UNIFORMS; if (strstr(env, "useprog")) flags |= GLSL_USE_PROG; + if (strstr(env, "errors")) + flags |= GLSL_REPORT_ERRORS; } return flags; @@ -627,7 +629,8 @@ get_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength, /** - * Set/replace shader source code. + * Set/replace shader source code. A helper function used by + * glShaderSource[ARB] and glCreateShaderProgramEXT. */ static void shader_source(struct gl_context *ctx, GLuint shader, const GLchar *source) @@ -672,6 +675,12 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) * compilation was successful. */ _mesa_glsl_compile_shader(ctx, sh); + + if (sh->CompileStatus == GL_FALSE && + (ctx->Shader.Flags & GLSL_REPORT_ERRORS)) { + _mesa_debug(ctx, "Error compiling shader %u:\n%s\n", + sh->Name, sh->InfoLog); + } } @@ -702,6 +711,12 @@ link_program(struct gl_context *ctx, GLuint program) _mesa_glsl_link_shader(ctx, shProg); + if (shProg->LinkStatus == GL_FALSE && + (ctx->Shader.Flags & GLSL_REPORT_ERRORS)) { + _mesa_debug(ctx, "Error linking program %u:\n%s\n", + shProg->Name, shProg->InfoLog); + } + /* debug code */ if (0) { GLuint i; @@ -1534,6 +1549,10 @@ _mesa_use_shader_program(struct gl_context *ctx, GLenum type, ctx->Driver.UseProgram(ctx, shProg); } + +/** + * For GL_EXT_separate_shader_objects + */ void GLAPIENTRY _mesa_UseShaderProgramEXT(GLenum type, GLuint program) { @@ -1570,6 +1589,10 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program) _mesa_use_shader_program(ctx, type, shProg); } + +/** + * For GL_EXT_separate_shader_objects + */ void GLAPIENTRY _mesa_ActiveProgramEXT(GLuint program) { @@ -1582,6 +1605,10 @@ _mesa_ActiveProgramEXT(GLuint program) return; } + +/** + * For GL_EXT_separate_shader_objects + */ GLuint GLAPIENTRY _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) { diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 365169ddd..a471bad22 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -558,7 +558,8 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, GLuint face; assert(baseImage->Width2 == baseImage->Height); for (face = 1; face < 6; face++) { - assert(t->Image[face][baseLevel]->Width2 == + assert(t->Image[face][baseLevel] == NULL || + t->Image[face][baseLevel]->Width2 == t->Image[face][baseLevel]->Height2); if (t->Image[face][baseLevel] == NULL || t->Image[face][baseLevel]->Width2 != baseImage->Width2) { diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 08d330a52..f5d998ffb 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -46,6 +46,8 @@ _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index, struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); + ASSERT_OUTSIDE_BEGIN_END(ctx); + if (!shProg) return; diff --git a/mesalib/src/mesa/program/prog_execute.c b/mesalib/src/mesa/program/prog_execute.c index 848c2fec1..dd1706e14 100644 --- a/mesalib/src/mesa/program/prog_execute.c +++ b/mesalib/src/mesa/program/prog_execute.c @@ -1308,8 +1308,8 @@ _mesa_execute_program(struct gl_context * ctx, fetch_vector4(&inst->SrcReg[0], machine, a); a[0] = CLAMP(a[0], 0.0F, 1.0F); a[1] = CLAMP(a[1], 0.0F, 1.0F); - usx = IROUND(a[0] * 65535.0F); - usy = IROUND(a[1] * 65535.0F); + usx = F_TO_I(a[0] * 65535.0F); + usy = F_TO_I(a[1] * 65535.0F); result[0] = result[1] = result[2] = @@ -1326,10 +1326,10 @@ _mesa_execute_program(struct gl_context * ctx, a[1] = CLAMP(a[1], -128.0F / 127.0F, 1.0F); a[2] = CLAMP(a[2], -128.0F / 127.0F, 1.0F); a[3] = CLAMP(a[3], -128.0F / 127.0F, 1.0F); - ubx = IROUND(127.0F * a[0] + 128.0F); - uby = IROUND(127.0F * a[1] + 128.0F); - ubz = IROUND(127.0F * a[2] + 128.0F); - ubw = IROUND(127.0F * a[3] + 128.0F); + ubx = F_TO_I(127.0F * a[0] + 128.0F); + uby = F_TO_I(127.0F * a[1] + 128.0F); + ubz = F_TO_I(127.0F * a[2] + 128.0F); + ubw = F_TO_I(127.0F * a[3] + 128.0F); result[0] = result[1] = result[2] = @@ -1346,10 +1346,10 @@ _mesa_execute_program(struct gl_context * ctx, a[1] = CLAMP(a[1], 0.0F, 1.0F); a[2] = CLAMP(a[2], 0.0F, 1.0F); a[3] = CLAMP(a[3], 0.0F, 1.0F); - ubx = IROUND(255.0F * a[0]); - uby = IROUND(255.0F * a[1]); - ubz = IROUND(255.0F * a[2]); - ubw = IROUND(255.0F * a[3]); + ubx = F_TO_I(255.0F * a[0]); + uby = F_TO_I(255.0F * a[1]); + ubz = F_TO_I(255.0F * a[2]); + ubw = F_TO_I(255.0F * a[3]); result[0] = result[1] = result[2] = diff --git a/mesalib/src/mesa/sources.mak b/mesalib/src/mesa/sources.mak index c746b8afa..19a05ecc8 100644 --- a/mesalib/src/mesa/sources.mak +++ b/mesalib/src/mesa/sources.mak @@ -184,6 +184,7 @@ VBO_SOURCES = \ vbo/vbo_exec_draw.c \ vbo/vbo_exec_eval.c \ vbo/vbo_noop.c \ + vbo/vbo_primitive_restart.c \ vbo/vbo_rebase.c \ vbo/vbo_split.c \ vbo/vbo_split_copy.c \ diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index 6534a4347..b47a2d87f 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -195,6 +195,9 @@ st_bufferobj_data(struct gl_context *ctx, case GL_ELEMENT_ARRAY_BUFFER_ARB: bind = PIPE_BIND_INDEX_BUFFER; break; + case GL_TRANSFORM_FEEDBACK_BUFFER: + bind = PIPE_BIND_STREAM_OUTPUT; + break; default: bind = 0; } diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index b44976525..132dcc02f 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -247,7 +247,7 @@ static void st_destroy_context_priv( struct st_context *st ) st_destroy_drawtex(st); for (i = 0; i < Elements(st->state.sampler_views); i++) { - pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); + pipe_sampler_view_release(st->pipe, &st->state.sampler_views[i]); } if (st->default_texture) { diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 00a405b69..55ae65b3c 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -79,7 +79,6 @@ struct st_context struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */ struct draw_stage *rastpos_stage; /**< For glRasterPos */ - GLboolean sw_primitive_restart; GLboolean clamp_frag_color_in_shader; GLboolean clamp_vert_color_in_shader; diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index a8c20f45a..0a06e9995 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -638,175 +638,6 @@ check_uniforms(struct gl_context *ctx) } -/* - * Notes on primitive restart: - * The code below is used when the gallium driver does not support primitive - * restart itself. We map the index buffer, find the restart indexes, unmap - * the index buffer then draw the sub-primitives delineated by the restarts. - * A couple possible optimizations: - * 1. Save the list of sub-primitive (start, count) values in a list attached - * to the index buffer for re-use in subsequent draws. The list would be - * invalidated when the contents of the buffer changed. - * 2. If drawing triangle strips or quad strips, create a new index buffer - * that uses duplicated vertices to render the disjoint strips as one - * long strip. We'd have to be careful to avoid using too much memory - * for this. - * Finally, some apps might perform better if they don't use primitive restart - * at all rather than this fallback path. Set MESA_EXTENSION_OVERRIDE to - * "-GL_NV_primitive_restart" to test that. - */ - - -struct sub_primitive -{ - unsigned start, count; -}; - - -/** - * Scan the elements array to find restart indexes. Return a list - * of primitive (start,count) pairs to indicate how to draw the sub- - * primitives delineated by the restart index. - */ -static struct sub_primitive * -find_sub_primitives(const void *elements, unsigned element_size, - unsigned start, unsigned end, unsigned restart_index, - unsigned *num_sub_prims) -{ - const unsigned max_prims = end - start; - struct sub_primitive *sub_prims; - unsigned i, cur_start, cur_count, num; - - sub_prims = (struct sub_primitive *) - malloc(max_prims * sizeof(struct sub_primitive)); - - if (!sub_prims) { - *num_sub_prims = 0; - return NULL; - } - - cur_start = start; - cur_count = 0; - num = 0; - -#define SCAN_ELEMENTS(TYPE) \ - for (i = start; i < end; i++) { \ - if (((const TYPE *) elements)[i] == restart_index) { \ - if (cur_count > 0) { \ - assert(num < max_prims); \ - sub_prims[num].start = cur_start; \ - sub_prims[num].count = cur_count; \ - num++; \ - } \ - cur_start = i + 1; \ - cur_count = 0; \ - } \ - else { \ - cur_count++; \ - } \ - } \ - if (cur_count > 0) { \ - assert(num < max_prims); \ - sub_prims[num].start = cur_start; \ - sub_prims[num].count = cur_count; \ - num++; \ - } - - switch (element_size) { - case 1: - SCAN_ELEMENTS(ubyte); - break; - case 2: - SCAN_ELEMENTS(ushort); - break; - case 4: - SCAN_ELEMENTS(uint); - break; - default: - assert(0 && "bad index_size in find_sub_primitives()"); - } - -#undef SCAN_ELEMENTS - - *num_sub_prims = num; - - return sub_prims; -} - - -/** - * For gallium drivers that don't support the primitive restart - * feature, handle it here by breaking up the indexed primitive into - * sub-primitives. - */ -static void -handle_fallback_primitive_restart(struct cso_context *cso, - struct pipe_context *pipe, - const struct _mesa_index_buffer *ib, - struct pipe_index_buffer *ibuffer, - struct pipe_draw_info *orig_info) -{ - const unsigned start = orig_info->start; - const unsigned count = orig_info->count; - struct pipe_draw_info info = *orig_info; - struct pipe_transfer *transfer = NULL; - unsigned instance, i; - const void *ptr = NULL; - struct sub_primitive *sub_prims; - unsigned num_sub_prims; - - assert(info.indexed); - assert(ibuffer->buffer || ibuffer->user_buffer); - assert(ib); - - if (!ibuffer->buffer || !ibuffer->user_buffer || !ib) - return; - - info.primitive_restart = FALSE; - info.instance_count = 1; - - if (_mesa_is_bufferobj(ib->obj)) { - ptr = pipe_buffer_map_range(pipe, ibuffer->buffer, - start * ibuffer->index_size, /* start */ - count * ibuffer->index_size, /* length */ - PIPE_TRANSFER_READ, &transfer); - if (!ptr) - return; - - ptr = (uint8_t*)ptr + (ibuffer->offset - start * ibuffer->index_size); - } - else { - ptr = ib->ptr; - if (!ptr) - return; - } - - sub_prims = find_sub_primitives(ptr, ibuffer->index_size, - 0, count, orig_info->restart_index, - &num_sub_prims); - - if (transfer) - pipe_buffer_unmap(pipe, transfer); - - /* Now draw the sub primitives. - * Need to loop over instances as well to preserve draw order. - */ - for (instance = 0; instance < orig_info->instance_count; instance++) { - info.start_instance = instance + orig_info->start_instance; - for (i = 0; i < num_sub_prims; i++) { - info.start = sub_prims[i].start; - info.count = sub_prims[i].count; - if (u_trim_pipe_prim(info.mode, &info.count)) { - cso_draw_vbo(cso, &info); - } - } - } - - if (sub_prims) - free(sub_prims); -} - - /** * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to * the corresponding Gallium type. @@ -901,7 +732,6 @@ st_draw_vbo(struct gl_context *ctx, struct gl_transform_feedback_object *tfb_vertcount) { struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; struct pipe_index_buffer ibuffer = {0}; struct pipe_draw_info info; const struct gl_client_array **arrays = ctx->Array._DrawArrays; @@ -994,15 +824,8 @@ st_draw_vbo(struct gl_context *ctx, cso_draw_vbo(st->cso_context, &info); } else if (info.primitive_restart) { - if (st->sw_primitive_restart) { - /* Handle primitive restart for drivers that doesn't support it */ - handle_fallback_primitive_restart(st->cso_context, pipe, ib, - &ibuffer, &info); - } - else { - /* don't trim, restarts might be inside index list */ - cso_draw_vbo(st->cso_context, &info); - } + /* don't trim, restarts might be inside index list */ + cso_draw_vbo(st->cso_context, &info); } else if (u_trim_pipe_prim(info.mode, &info.count)) cso_draw_vbo(st->cso_context, &info); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 1b4bca681..953155f36 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -601,7 +601,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.NV_primitive_restart = GL_TRUE; if (!screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { - st->sw_primitive_restart = GL_TRUE; + ctx->Const.PrimitiveRestartInSoftware = GL_TRUE; } if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index deee722cf..e6664fb7c 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -1285,3 +1285,26 @@ st_destroy_program_variants(struct st_context *st) _mesa_HashWalk(st->ctx->Shared->ShaderObjects, destroy_shader_program_variants_cb, st); } + + +/** + * For debugging, print/dump the current vertex program. + */ +void +st_print_current_vertex_program(void) +{ + GET_CURRENT_CONTEXT(ctx); + + if (ctx->VertexProgram._Current) { + struct st_vertex_program *stvp = + (struct st_vertex_program *) ctx->VertexProgram._Current; + struct st_vp_variant *stv; + + debug_printf("Vertex program %u\n", stvp->Base.Base.Id); + + for (stv = stvp->variants; stv; stv = stv->next) { + debug_printf("variant %p\n", stv); + tgsi_dump(stv->tgsi.tokens, 0); + } + } +} diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h index 6c4b4f6c3..23a262ccc 100644 --- a/mesalib/src/mesa/state_tracker/st_program.h +++ b/mesalib/src/mesa/state_tracker/st_program.h @@ -315,4 +315,8 @@ extern void st_destroy_program_variants(struct st_context *st); +extern void +st_print_current_vertex_program(void); + + #endif diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h index 3cff8987e..4387e10b7 100644 --- a/mesalib/src/mesa/vbo/vbo.h +++ b/mesalib/src/mesa/vbo/vbo.h @@ -157,6 +157,12 @@ void vbo_bind_arrays(struct gl_context *ctx); size_t count_tessellated_primitives(const struct _mesa_prim *prim); +void +vbo_sw_primitive_restart(struct gl_context *ctx, + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib); + void GLAPIENTRY _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 9303ad719..3fb7c6480 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -543,6 +543,37 @@ vbo_bind_arrays(struct gl_context *ctx) /** + * Handle a draw case that potentially has primitive restart enabled. + * + * If primitive restart is enabled, and PrimitiveRestartInSoftware is + * set, then vbo_sw_primitive_restart is used to handle the primitive + * restart case in software. + */ +static void +vbo_handle_primitive_restart(struct gl_context *ctx, + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index) +{ + struct vbo_context *vbo = vbo_context(ctx); + + if ((ib != NULL) && + ctx->Const.PrimitiveRestartInSoftware && + ctx->Array.PrimitiveRestart) { + /* Handle primitive restart in software */ + vbo_sw_primitive_restart(ctx, prim, nr_prims, ib); + } else { + /* Call driver directly for draw_prims */ + vbo->draw_prims(ctx, prim, nr_prims, ib, + index_bounds_valid, min_index, max_index, NULL); + } +} + + +/** * Helper function called by the other DrawArrays() functions below. * This is where we handle primitive restart for drawing non-indexed * arrays. If primitive restart is enabled, it typically means @@ -805,8 +836,8 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, */ check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims( ctx, prim, 1, &ib, - index_bounds_valid, start, end, NULL ); + vbo_handle_primitive_restart(ctx, prim, 1, &ib, + index_bounds_valid, start, end); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); @@ -1104,8 +1135,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, } check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, primcount, &ib, - GL_FALSE, ~0, ~0, NULL); + vbo_handle_primitive_restart(ctx, prim, primcount, &ib, + GL_FALSE, ~0, ~0); } else { /* render one prim at a time */ for (i = 0; i < primcount; i++) { @@ -1129,8 +1160,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, prim[0].basevertex = 0; check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, 1, &ib, - GL_FALSE, ~0, ~0, NULL); + vbo_handle_primitive_restart(ctx, prim, 1, &ib, + GL_FALSE, ~0, ~0); } } diff --git a/mesalib/src/mesa/vbo/vbo_primitive_restart.c b/mesalib/src/mesa/vbo/vbo_primitive_restart.c new file mode 100644 index 000000000..18d851c1e --- /dev/null +++ b/mesalib/src/mesa/vbo/vbo_primitive_restart.c @@ -0,0 +1,233 @@ +/* + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Copyright © 2012 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. + * + * Authors: + * Jordan Justen <jordan.l.justen@intel.com> + * + */ + +#include "main/imports.h" +#include "main/bufferobj.h" +#include "main/macros.h" + +#include "vbo.h" +#include "vbo_context.h" + +#define UPDATE_MIN2(a, b) (a) = MIN2((a), (b)) +#define UPDATE_MAX2(a, b) (a) = MAX2((a), (b)) + +/* + * Notes on primitive restart: + * The code below is used when the driver does not support primitive + * restart itself. (ctx->Const.PrimitiveRestartInSoftware == GL_TRUE) + * + * We map the index buffer, find the restart indexes, unmap + * the index buffer then draw the sub-primitives delineated by the restarts. + * + * A couple possible optimizations: + * 1. Save the list of sub-primitive (start, count) values in a list attached + * to the index buffer for re-use in subsequent draws. The list would be + * invalidated when the contents of the buffer changed. + * 2. If drawing triangle strips or quad strips, create a new index buffer + * that uses duplicated vertices to render the disjoint strips as one + * long strip. We'd have to be careful to avoid using too much memory + * for this. + * + * Finally, some apps might perform better if they don't use primitive restart + * at all rather than this fallback path. Set MESA_EXTENSION_OVERRIDE to + * "-GL_NV_primitive_restart" to test that. + */ + + +struct sub_primitive +{ + GLuint start; + GLuint count; + GLuint min_index; + GLuint max_index; +}; + + +/** + * Scan the elements array to find restart indexes. Return an array + * of struct sub_primitive to indicate how to draw the sub-primitives + * are delineated by the restart index. + */ +static struct sub_primitive * +find_sub_primitives(const void *elements, unsigned element_size, + unsigned start, unsigned end, unsigned restart_index, + unsigned *num_sub_prims) +{ + const unsigned max_prims = end - start; + struct sub_primitive *sub_prims; + unsigned i, cur_start, cur_count; + GLuint scan_index; + unsigned scan_num; + + sub_prims = (struct sub_primitive *) + malloc(max_prims * sizeof(struct sub_primitive)); + + if (!sub_prims) { + *num_sub_prims = 0; + return NULL; + } + + cur_start = start; + cur_count = 0; + scan_num = 0; + +#define IB_INDEX_READ(TYPE, INDEX) (((const GL##TYPE *) elements)[INDEX]) + +#define SCAN_ELEMENTS(TYPE) \ + sub_prims[scan_num].min_index = (GL##TYPE) 0xffffffff; \ + sub_prims[scan_num].max_index = 0; \ + for (i = start; i < end; i++) { \ + scan_index = IB_INDEX_READ(TYPE, i); \ + if (scan_index == restart_index) { \ + if (cur_count > 0) { \ + assert(scan_num < max_prims); \ + sub_prims[scan_num].start = cur_start; \ + sub_prims[scan_num].count = cur_count; \ + scan_num++; \ + sub_prims[scan_num].min_index = (GL##TYPE) 0xffffffff; \ + sub_prims[scan_num].max_index = 0; \ + } \ + cur_start = i + 1; \ + cur_count = 0; \ + } \ + else { \ + UPDATE_MIN2(sub_prims[scan_num].min_index, scan_index); \ + UPDATE_MAX2(sub_prims[scan_num].max_index, scan_index); \ + cur_count++; \ + } \ + } \ + if (cur_count > 0) { \ + assert(scan_num < max_prims); \ + sub_prims[scan_num].start = cur_start; \ + sub_prims[scan_num].count = cur_count; \ + scan_num++; \ + } + + switch (element_size) { + case 1: + SCAN_ELEMENTS(ubyte); + break; + case 2: + SCAN_ELEMENTS(ushort); + break; + case 4: + SCAN_ELEMENTS(uint); + break; + default: + assert(0 && "bad index_size in find_sub_primitives()"); + } + +#undef SCAN_ELEMENTS + + *num_sub_prims = scan_num; + + return sub_prims; +} + + +/** + * Handle primitive restart in software. + * + * This function breaks up calls into the driver so primitive restart + * support is not required in the driver. + */ +void +vbo_sw_primitive_restart(struct gl_context *ctx, + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib) +{ + GLuint prim_num; + struct sub_primitive *sub_prims; + struct sub_primitive *sub_prim; + GLuint num_sub_prims; + GLuint sub_prim_num; + GLuint end_index; + GLuint sub_end_index; + GLuint restart_index = ctx->Array.RestartIndex; + struct _mesa_prim temp_prim; + struct vbo_context *vbo = vbo_context(ctx); + vbo_draw_func draw_prims_func = vbo->draw_prims; + GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + void *ptr; + + /* Find the sub-primitives. These are regions in the index buffer which + * are split based on the primitive restart index value. + */ + if (map_ib) { + ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT, + ib->obj); + } + + ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + + sub_prims = find_sub_primitives(ptr, vbo_sizeof_ib_type(ib->type), + 0, ib->count, restart_index, + &num_sub_prims); + + if (map_ib) { + ctx->Driver.UnmapBuffer(ctx, ib->obj); + } + + /* Loop over the primitives, and use the located sub-primitives to draw + * each primitive with a break to implement each primitive restart. + */ + for (prim_num = 0; prim_num < nr_prims; prim_num++) { + end_index = prims[prim_num].start + prims[prim_num].count; + memcpy(&temp_prim, &prims[prim_num], sizeof (temp_prim)); + /* Loop over the sub-primitives drawing sub-ranges of the primitive. */ + for (sub_prim_num = 0; sub_prim_num < num_sub_prims; sub_prim_num++) { + sub_prim = &sub_prims[sub_prim_num]; + sub_end_index = sub_prim->start + sub_prim->count; + if (prims[prim_num].start <= sub_prim->start) { + temp_prim.start = MAX2(prims[prim_num].start, sub_prim->start); + temp_prim.count = MIN2(sub_end_index, end_index) - temp_prim.start; + if ((temp_prim.start == sub_prim->start) && + (temp_prim.count == sub_prim->count)) { + draw_prims_func(ctx, &temp_prim, 1, ib, + GL_TRUE, sub_prim->min_index, sub_prim->max_index, + NULL); + } else { + draw_prims_func(ctx, &temp_prim, 1, ib, + GL_FALSE, -1, -1, + NULL); + } + } + if (sub_end_index >= end_index) { + break; + } + } + } + + if (sub_prims) { + free(sub_prims); + } +} + |