aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp146
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp2
-rw-r--r--mesalib/src/glsl/opt_copy_propagation_elements.cpp925
-rw-r--r--mesalib/src/mesa/main/context.c10
-rw-r--r--mesalib/src/mesa/main/context.h12
-rw-r--r--mesalib/src/mesa/main/extensions.c1
-rw-r--r--mesalib/src/mesa/main/samplerobj.c2710
-rw-r--r--mesalib/src/mesa/main/shared.c6
-rw-r--r--mesalib/src/mesa/main/shared.h3
-rw-r--r--mesalib/src/mesa/program/program_parse.y29
-rw-r--r--mesalib/src/mesa/program/program_parse_extra.c520
-rw-r--r--mesalib/src/mesa/program/program_parser.h1
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_texture.c12
13 files changed, 2208 insertions, 2169 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 5e1851c11..d7e54d823 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -848,6 +848,36 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
return cmp;
}
+/* For logical operations, we want to ensure that the operands are
+ * scalar booleans. If it isn't, emit an error and return a constant
+ * boolean to avoid triggering cascading error messages.
+ */
+ir_rvalue *
+get_scalar_boolean_operand(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state,
+ ast_expression *parent_expr,
+ int operand,
+ const char *operand_name,
+ bool *error_emitted)
+{
+ ast_expression *expr = parent_expr->subexpressions[operand];
+ void *ctx = state;
+ ir_rvalue *val = expr->hir(instructions, state);
+
+ if (val->type->is_boolean() && val->type->is_scalar())
+ return val;
+
+ if (!*error_emitted) {
+ YYLTYPE loc = expr->get_location();
+ _mesa_glsl_error(&loc, state, "%s of `%s' must be scalar boolean",
+ operand_name,
+ parent_expr->operator_string(parent_expr->oper));
+ *error_emitted = true;
+ }
+
+ return new(ctx) ir_constant(true);
+}
+
ir_rvalue *
ast_expression::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
@@ -1043,10 +1073,14 @@ ast_expression::hir(exec_list *instructions,
error_emitted = true;
}
- result = do_comparison(ctx, operations[this->oper], op[0], op[1]);
- type = glsl_type::bool_type;
+ if (error_emitted) {
+ result = new(ctx) ir_constant(false);
+ } else {
+ result = do_comparison(ctx, operations[this->oper], op[0], op[1]);
+ assert(result->type == glsl_type::bool_type);
+ type = glsl_type::bool_type;
+ }
- assert(error_emitted || (result->type == glsl_type::bool_type));
break;
case ast_bit_and:
@@ -1079,29 +1113,16 @@ ast_expression::hir(exec_list *instructions,
break;
case ast_logic_and: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
+ exec_list rhs_instructions;
+ op[0] = get_scalar_boolean_operand(instructions, state, this, 0,
+ "LHS", &error_emitted);
+ op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1,
+ "RHS", &error_emitted);
ir_constant *op0_const = op[0]->constant_expression_value();
if (op0_const) {
if (op0_const->value.b[0]) {
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
+ instructions->append_list(&rhs_instructions);
result = op[1];
} else {
result = op0_const;
@@ -1116,17 +1137,7 @@ ast_expression::hir(exec_list *instructions,
ir_if *const stmt = new(ctx) ir_if(op[0]);
instructions->push_tail(stmt);
- op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
-
+ 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);
@@ -1144,31 +1155,17 @@ ast_expression::hir(exec_list *instructions,
}
case ast_logic_or: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
+ exec_list rhs_instructions;
+ op[0] = get_scalar_boolean_operand(instructions, state, this, 0,
+ "LHS", &error_emitted);
+ op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1,
+ "RHS", &error_emitted);
ir_constant *op0_const = op[0]->constant_expression_value();
if (op0_const) {
if (op0_const->value.b[0]) {
result = op0_const;
} else {
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
result = op[1];
}
type = glsl_type::bool_type;
@@ -1181,21 +1178,12 @@ ast_expression::hir(exec_list *instructions,
ir_if *const stmt = new(ctx) ir_if(op[0]);
instructions->push_tail(stmt);
- op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state);
-
- if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[1]->get_location();
-
- _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
- operator_string(this->oper));
- error_emitted = true;
- }
-
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);
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);
@@ -1208,9 +1196,16 @@ ast_expression::hir(exec_list *instructions,
}
case ast_logic_xor:
- op[0] = this->subexpressions[0]->hir(instructions, state);
- op[1] = this->subexpressions[1]->hir(instructions, state);
-
+ /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "The logical binary operators and (&&), or ( | | ), and
+ * exclusive or (^^). They operate only on two Boolean
+ * expressions and result in a Boolean expression."
+ */
+ op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS",
+ &error_emitted);
+ op[1] = get_scalar_boolean_operand(instructions, state, this, 1, "RHS",
+ &error_emitted);
result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
op[0], op[1]);
@@ -1218,15 +1213,8 @@ ast_expression::hir(exec_list *instructions,
break;
case ast_logic_not:
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state,
- "operand of `!' must be scalar boolean");
- error_emitted = true;
- }
+ op[0] = get_scalar_boolean_operand(instructions, state, this, 0,
+ "operand", &error_emitted);
result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
op[0], NULL);
@@ -1313,20 +1301,14 @@ ast_expression::hir(exec_list *instructions,
}
case ast_conditional: {
- op[0] = this->subexpressions[0]->hir(instructions, state);
-
/* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
*
* "The ternary selection operator (?:). It operates on three
* expressions (exp1 ? exp2 : exp3). This operator evaluates the
* first expression, which must result in a scalar Boolean."
*/
- if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
- YYLTYPE loc = this->subexpressions[0]->get_location();
-
- _mesa_glsl_error(& loc, state, "?: condition must be scalar boolean");
- error_emitted = true;
- }
+ op[0] = get_scalar_boolean_operand(instructions, state, this, 0,
+ "condition", &error_emitted);
/* The :? operator is implemented by generating an anonymous temporary
* followed by an if-statement. The last instruction in each branch of
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 1e8123491..823e75167 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -768,7 +768,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration
progress = do_if_simplification(ir) || progress;
progress = do_discard_simplification(ir) || progress;
progress = do_copy_propagation(ir) || progress;
- /*progress = do_copy_propagation_elements(ir) || progress;*/
+ progress = do_copy_propagation_elements(ir) || progress;
if (linked)
progress = do_dead_code(ir) || progress;
else
diff --git a/mesalib/src/glsl/opt_copy_propagation_elements.cpp b/mesalib/src/glsl/opt_copy_propagation_elements.cpp
index 8541d9a8e..580c10f27 100644
--- a/mesalib/src/glsl/opt_copy_propagation_elements.cpp
+++ b/mesalib/src/glsl/opt_copy_propagation_elements.cpp
@@ -1,458 +1,467 @@
-/*
- * Copyright © 2010 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_copy_propagation_elements.cpp
- *
- * Replaces usage of recently-copied components of variables with the
- * previous copy of the variable.
- *
- * This pass can be compared with opt_copy_propagation, which operands
- * on arbitrary whole-variable copies. However, in order to handle
- * the copy propagation of swizzled variables or writemasked writes,
- * we want to track things on a channel-wise basis. I found that
- * trying to mix the swizzled/writemasked support here with the
- * whole-variable stuff in opt_copy_propagation.cpp just made a mess,
- * so this is separate despite the ACP handling being somewhat
- * similar.
- *
- * This should reduce the number of MOV instructions in the generated
- * programs unless copy propagation is also done on the LIR, and may
- * help anyway by triggering other optimizations that live in the HIR.
- */
-
-#include "ir.h"
-#include "ir_rvalue_visitor.h"
-#include "ir_basic_block.h"
-#include "ir_optimization.h"
-#include "glsl_types.h"
-
-static bool debug = false;
-
-class acp_entry : public exec_node
-{
-public:
- acp_entry(ir_variable *lhs, ir_variable *rhs, int write_mask, int swizzle[4])
- {
- this->lhs = lhs;
- this->rhs = rhs;
- this->write_mask = write_mask;
- memcpy(this->swizzle, swizzle, sizeof(this->swizzle));
- }
-
- acp_entry(acp_entry *a)
- {
- this->lhs = a->lhs;
- this->rhs = a->rhs;
- this->write_mask = a->write_mask;
- memcpy(this->swizzle, a->swizzle, sizeof(this->swizzle));
- }
-
- ir_variable *lhs;
- ir_variable *rhs;
- unsigned int write_mask;
- int swizzle[4];
-};
-
-
-class kill_entry : public exec_node
-{
-public:
- kill_entry(ir_variable *var, int write_mask)
- {
- this->var = var;
- this->write_mask = write_mask;
- }
-
- ir_variable *var;
- unsigned int write_mask;
-};
-
-class ir_copy_propagation_elements_visitor : public ir_rvalue_visitor {
-public:
- ir_copy_propagation_elements_visitor()
- {
- this->progress = false;
- this->mem_ctx = ralloc_context(NULL);
- this->shader_mem_ctx = NULL;
- this->acp = new(mem_ctx) exec_list;
- this->kills = new(mem_ctx) exec_list;
- }
- ~ir_copy_propagation_elements_visitor()
- {
- ralloc_free(mem_ctx);
- }
-
- virtual ir_visitor_status visit_enter(class ir_loop *);
- virtual ir_visitor_status visit_enter(class ir_function_signature *);
- virtual ir_visitor_status visit_leave(class ir_assignment *);
- virtual ir_visitor_status visit_enter(class ir_call *);
- virtual ir_visitor_status visit_enter(class ir_if *);
-
- void handle_rvalue(ir_rvalue **rvalue);
-
- void add_copy(ir_assignment *ir);
- void kill(kill_entry *k);
- void handle_if_block(exec_list *instructions);
-
- /** List of acp_entry: The available copies to propagate */
- exec_list *acp;
- /**
- * List of kill_entry: The variables whose values were killed in this
- * block.
- */
- exec_list *kills;
-
- bool progress;
-
- bool killed_all;
-
- /* Context for our local data structures. */
- void *mem_ctx;
- /* Context for allocating new shader nodes. */
- void *shader_mem_ctx;
-};
-
-ir_visitor_status
-ir_copy_propagation_elements_visitor::visit_enter(ir_function_signature *ir)
-{
- /* Treat entry into a function signature as a completely separate
- * block. Any instructions at global scope will be shuffled into
- * main() at link time, so they're irrelevant to us.
- */
- exec_list *orig_acp = this->acp;
- exec_list *orig_kills = this->kills;
- bool orig_killed_all = this->killed_all;
-
- this->acp = new(mem_ctx) exec_list;
- this->kills = new(mem_ctx) exec_list;
- this->killed_all = false;
-
- visit_list_elements(this, &ir->body);
-
- this->kills = orig_kills;
- this->acp = orig_acp;
- this->killed_all = orig_killed_all;
-
- return visit_continue_with_parent;
-}
-
-ir_visitor_status
-ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir)
-{
- ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
-
- if (lhs && (lhs->type->is_scalar() || lhs->type->is_vector())) {
- kill_entry *k = new(mem_ctx) kill_entry(lhs->var, ir->write_mask);
- kill(k);
- }
-
- add_copy(ir);
-
- return visit_continue;
-}
-
-/**
- * Replaces dereferences of ACP RHS variables with ACP LHS variables.
- *
- * This is where the actual copy propagation occurs. Note that the
- * rewriting of ir_dereference means that the ir_dereference instance
- * must not be shared by multiple IR operations!
- */
-void
-ir_copy_propagation_elements_visitor::handle_rvalue(ir_rvalue **ir)
-{
- int swizzle_chan[4];
- ir_dereference_variable *deref_var;
- ir_variable *source[4] = {NULL, NULL, NULL, NULL};
- int source_chan[4];
- int chans;
-
- if (!*ir)
- return;
-
- ir_swizzle *swizzle = (*ir)->as_swizzle();
- if (swizzle) {
- deref_var = swizzle->val->as_dereference_variable();
- if (!deref_var)
- return;
-
- swizzle_chan[0] = swizzle->mask.x;
- swizzle_chan[1] = swizzle->mask.y;
- swizzle_chan[2] = swizzle->mask.z;
- swizzle_chan[3] = swizzle->mask.w;
- chans = swizzle->type->vector_elements;
- } else {
- deref_var = (*ir)->as_dereference_variable();
- if (!deref_var)
- return;
-
- swizzle_chan[0] = 0;
- swizzle_chan[1] = 1;
- swizzle_chan[2] = 2;
- swizzle_chan[3] = 3;
- chans = deref_var->type->vector_elements;
- }
-
- if (this->in_assignee)
- return;
-
- ir_variable *var = deref_var->var;
-
- /* Try to find ACP entries covering swizzle_chan[], hoping they're
- * the same source variable.
- */
- foreach_iter(exec_list_iterator, iter, *this->acp) {
- acp_entry *entry = (acp_entry *)iter.get();
-
- if (var == entry->lhs) {
- for (int c = 0; c < chans; c++) {
- if (entry->write_mask & (1 << swizzle_chan[c])) {
- source[c] = entry->rhs;
- source_chan[c] = entry->swizzle[swizzle_chan[c]];
- }
- }
- }
- }
-
- /* Make sure all channels are copying from the same source variable. */
- if (!source[0])
- return;
- for (int c = 1; c < chans; c++) {
- if (source[c] != source[0])
- return;
- }
-
- if (!shader_mem_ctx)
- shader_mem_ctx = ralloc_parent(deref_var);
-
- if (debug) {
- printf("Copy propagation from:\n");
- (*ir)->print();
- }
-
- deref_var = new(shader_mem_ctx) ir_dereference_variable(source[0]);
- *ir = new(shader_mem_ctx) ir_swizzle(deref_var,
- source_chan[0],
- source_chan[1],
- source_chan[2],
- source_chan[3],
- chans);
-
- if (debug) {
- printf("to:\n");
- (*ir)->print();
- printf("\n");
- }
-}
-
-
-ir_visitor_status
-ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir)
-{
- /* Do copy propagation on call parameters, but skip any out params */
- exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
- foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
- ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
- ir_instruction *ir = (ir_instruction *)iter.get();
- if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
- ir->accept(this);
- }
- sig_param_iter.next();
- }
-
- /* Since we're unlinked, we don't (necessarily) know the side effects of
- * this call. So kill all copies.
- */
- acp->make_empty();
- this->killed_all = true;
-
- return visit_continue_with_parent;
-}
-
-void
-ir_copy_propagation_elements_visitor::handle_if_block(exec_list *instructions)
-{
- exec_list *orig_acp = this->acp;
- exec_list *orig_kills = this->kills;
- bool orig_killed_all = this->killed_all;
-
- this->acp = new(mem_ctx) exec_list;
- this->kills = new(mem_ctx) exec_list;
- this->killed_all = false;
-
- /* Populate the initial acp with a copy of the original */
- foreach_iter(exec_list_iterator, iter, *orig_acp) {
- acp_entry *a = (acp_entry *)iter.get();
- this->acp->push_tail(new(this->mem_ctx) acp_entry(a));
- }
-
- visit_list_elements(this, instructions);
-
- if (this->killed_all) {
- orig_acp->make_empty();
- }
-
- exec_list *new_kills = this->kills;
- this->kills = orig_kills;
- this->acp = orig_acp;
- this->killed_all = this->killed_all || orig_killed_all;
-
- /* Move the new kills into the parent block's list, removing them
- * from the parent's ACP list in the process.
- */
- foreach_list_safe(node, new_kills) {
- kill_entry *k = (kill_entry *)node;
- kill(k);
- }
-}
-
-ir_visitor_status
-ir_copy_propagation_elements_visitor::visit_enter(ir_if *ir)
-{
- ir->condition->accept(this);
-
- handle_if_block(&ir->then_instructions);
- handle_if_block(&ir->else_instructions);
-
- /* handle_if_block() already descended into the children. */
- return visit_continue_with_parent;
-}
-
-ir_visitor_status
-ir_copy_propagation_elements_visitor::visit_enter(ir_loop *ir)
-{
- exec_list *orig_acp = this->acp;
- exec_list *orig_kills = this->kills;
- bool orig_killed_all = this->killed_all;
-
- /* FINISHME: For now, the initial acp for loops is totally empty.
- * We could go through once, then go through again with the acp
- * cloned minus the killed entries after the first run through.
- */
- this->acp = new(mem_ctx) exec_list;
- this->kills = new(mem_ctx) exec_list;
- this->killed_all = false;
-
- visit_list_elements(this, &ir->body_instructions);
-
- if (this->killed_all) {
- orig_acp->make_empty();
- }
-
- exec_list *new_kills = this->kills;
- this->kills = orig_kills;
- this->acp = orig_acp;
- this->killed_all = this->killed_all || orig_killed_all;
-
- foreach_list_safe(node, new_kills) {
- kill_entry *k = (kill_entry *)node;
- kill(k);
- }
-
- /* already descended into the children. */
- return visit_continue_with_parent;
-}
-
-/* Remove any entries currently in the ACP for this kill. */
-void
-ir_copy_propagation_elements_visitor::kill(kill_entry *k)
-{
- foreach_list_safe(node, acp) {
- acp_entry *entry = (acp_entry *)node;
-
- if (entry->lhs == k->var) {
- entry->write_mask = entry->write_mask & ~k->write_mask;
- if (entry->write_mask == 0)
- entry->remove();
- }
- if (entry->rhs == k->var) {
- entry->remove();
- }
- }
-
- /* If we were on a list, remove ourselves before inserting */
- if (k->next)
- k->remove();
-
- this->kills->push_tail(k);
-}
-
-/**
- * Adds directly-copied channels between vector variables to the available
- * copy propagation list.
- */
-void
-ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
-{
- acp_entry *entry;
- int orig_swizzle[4] = {0, 1, 2, 3};
- int swizzle[4];
-
- if (ir->condition)
- return;
-
- ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
- if (!lhs || !(lhs->type->is_scalar() || lhs->type->is_vector()))
- return;
-
- ir_dereference_variable *rhs = ir->rhs->as_dereference_variable();
- if (!rhs) {
- ir_swizzle *swiz = ir->rhs->as_swizzle();
- if (!swiz)
- return;
-
- rhs = swiz->val->as_dereference_variable();
- if (!rhs)
- return;
-
- orig_swizzle[0] = swiz->mask.x;
- orig_swizzle[1] = swiz->mask.y;
- orig_swizzle[2] = swiz->mask.z;
- orig_swizzle[3] = swiz->mask.w;
- }
-
- /* Move the swizzle channels out to the positions they match in the
- * destination. We don't want to have to rewrite the swizzle[]
- * array every time we clear a bit of the write_mask.
- */
- int j = 0;
- for (int i = 0; i < 4; i++) {
- if (ir->write_mask & (1 << i))
- swizzle[i] = orig_swizzle[j++];
- }
-
- entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask,
- swizzle);
- this->acp->push_tail(entry);
-}
-
-bool
-do_copy_propagation_elements(exec_list *instructions)
-{
- ir_copy_propagation_elements_visitor v;
-
- visit_list_elements(&v, instructions);
-
- return v.progress;
-}
+/*
+ * Copyright © 2010 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_copy_propagation_elements.cpp
+ *
+ * Replaces usage of recently-copied components of variables with the
+ * previous copy of the variable.
+ *
+ * This pass can be compared with opt_copy_propagation, which operands
+ * on arbitrary whole-variable copies. However, in order to handle
+ * the copy propagation of swizzled variables or writemasked writes,
+ * we want to track things on a channel-wise basis. I found that
+ * trying to mix the swizzled/writemasked support here with the
+ * whole-variable stuff in opt_copy_propagation.cpp just made a mess,
+ * so this is separate despite the ACP handling being somewhat
+ * similar.
+ *
+ * This should reduce the number of MOV instructions in the generated
+ * programs unless copy propagation is also done on the LIR, and may
+ * help anyway by triggering other optimizations that live in the HIR.
+ */
+
+#include "ir.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class acp_entry : public exec_node
+{
+public:
+ acp_entry(ir_variable *lhs, ir_variable *rhs, int write_mask, int swizzle[4])
+ {
+ this->lhs = lhs;
+ this->rhs = rhs;
+ this->write_mask = write_mask;
+ memcpy(this->swizzle, swizzle, sizeof(this->swizzle));
+ }
+
+ acp_entry(acp_entry *a)
+ {
+ this->lhs = a->lhs;
+ this->rhs = a->rhs;
+ this->write_mask = a->write_mask;
+ memcpy(this->swizzle, a->swizzle, sizeof(this->swizzle));
+ }
+
+ ir_variable *lhs;
+ ir_variable *rhs;
+ unsigned int write_mask;
+ int swizzle[4];
+};
+
+
+class kill_entry : public exec_node
+{
+public:
+ kill_entry(ir_variable *var, int write_mask)
+ {
+ this->var = var;
+ this->write_mask = write_mask;
+ }
+
+ ir_variable *var;
+ unsigned int write_mask;
+};
+
+class ir_copy_propagation_elements_visitor : public ir_rvalue_visitor {
+public:
+ ir_copy_propagation_elements_visitor()
+ {
+ this->progress = false;
+ this->mem_ctx = ralloc_context(NULL);
+ this->shader_mem_ctx = NULL;
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ }
+ ~ir_copy_propagation_elements_visitor()
+ {
+ ralloc_free(mem_ctx);
+ }
+
+ virtual ir_visitor_status visit_enter(class ir_loop *);
+ virtual ir_visitor_status visit_enter(class ir_function_signature *);
+ virtual ir_visitor_status visit_leave(class ir_assignment *);
+ virtual ir_visitor_status visit_enter(class ir_call *);
+ virtual ir_visitor_status visit_enter(class ir_if *);
+
+ void handle_rvalue(ir_rvalue **rvalue);
+
+ void add_copy(ir_assignment *ir);
+ void kill(kill_entry *k);
+ void handle_if_block(exec_list *instructions);
+
+ /** List of acp_entry: The available copies to propagate */
+ exec_list *acp;
+ /**
+ * List of kill_entry: The variables whose values were killed in this
+ * block.
+ */
+ exec_list *kills;
+
+ bool progress;
+
+ bool killed_all;
+
+ /* Context for our local data structures. */
+ void *mem_ctx;
+ /* Context for allocating new shader nodes. */
+ void *shader_mem_ctx;
+};
+
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_enter(ir_function_signature *ir)
+{
+ /* Treat entry into a function signature as a completely separate
+ * block. Any instructions at global scope will be shuffled into
+ * main() at link time, so they're irrelevant to us.
+ */
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ visit_list_elements(this, &ir->body);
+
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = orig_killed_all;
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir)
+{
+ ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
+ ir_variable *var = ir->lhs->variable_referenced();
+
+ if (var->type->is_scalar() || var->type->is_vector()) {
+ kill_entry *k;
+
+ if (lhs)
+ k = new(mem_ctx) kill_entry(var, ir->write_mask);
+ else
+ k = new(mem_ctx) kill_entry(var, ~0);
+
+ kill(k);
+ }
+
+ add_copy(ir);
+
+ return visit_continue;
+}
+
+/**
+ * Replaces dereferences of ACP RHS variables with ACP LHS variables.
+ *
+ * This is where the actual copy propagation occurs. Note that the
+ * rewriting of ir_dereference means that the ir_dereference instance
+ * must not be shared by multiple IR operations!
+ */
+void
+ir_copy_propagation_elements_visitor::handle_rvalue(ir_rvalue **ir)
+{
+ int swizzle_chan[4];
+ ir_dereference_variable *deref_var;
+ ir_variable *source[4] = {NULL, NULL, NULL, NULL};
+ int source_chan[4];
+ int chans;
+
+ if (!*ir)
+ return;
+
+ ir_swizzle *swizzle = (*ir)->as_swizzle();
+ if (swizzle) {
+ deref_var = swizzle->val->as_dereference_variable();
+ if (!deref_var)
+ return;
+
+ swizzle_chan[0] = swizzle->mask.x;
+ swizzle_chan[1] = swizzle->mask.y;
+ swizzle_chan[2] = swizzle->mask.z;
+ swizzle_chan[3] = swizzle->mask.w;
+ chans = swizzle->type->vector_elements;
+ } else {
+ deref_var = (*ir)->as_dereference_variable();
+ if (!deref_var)
+ return;
+
+ swizzle_chan[0] = 0;
+ swizzle_chan[1] = 1;
+ swizzle_chan[2] = 2;
+ swizzle_chan[3] = 3;
+ chans = deref_var->type->vector_elements;
+ }
+
+ if (this->in_assignee)
+ return;
+
+ ir_variable *var = deref_var->var;
+
+ /* Try to find ACP entries covering swizzle_chan[], hoping they're
+ * the same source variable.
+ */
+ foreach_iter(exec_list_iterator, iter, *this->acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
+
+ if (var == entry->lhs) {
+ for (int c = 0; c < chans; c++) {
+ if (entry->write_mask & (1 << swizzle_chan[c])) {
+ source[c] = entry->rhs;
+ source_chan[c] = entry->swizzle[swizzle_chan[c]];
+ }
+ }
+ }
+ }
+
+ /* Make sure all channels are copying from the same source variable. */
+ if (!source[0])
+ return;
+ for (int c = 1; c < chans; c++) {
+ if (source[c] != source[0])
+ return;
+ }
+
+ if (!shader_mem_ctx)
+ shader_mem_ctx = ralloc_parent(deref_var);
+
+ if (debug) {
+ printf("Copy propagation from:\n");
+ (*ir)->print();
+ }
+
+ deref_var = new(shader_mem_ctx) ir_dereference_variable(source[0]);
+ *ir = new(shader_mem_ctx) ir_swizzle(deref_var,
+ source_chan[0],
+ source_chan[1],
+ source_chan[2],
+ source_chan[3],
+ chans);
+
+ if (debug) {
+ printf("to:\n");
+ (*ir)->print();
+ printf("\n");
+ }
+}
+
+
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir)
+{
+ /* Do copy propagation on call parameters, but skip any out params */
+ exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
+ foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
+ ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
+ ir->accept(this);
+ }
+ sig_param_iter.next();
+ }
+
+ /* Since we're unlinked, we don't (necessarily) know the side effects of
+ * this call. So kill all copies.
+ */
+ acp->make_empty();
+ this->killed_all = true;
+
+ return visit_continue_with_parent;
+}
+
+void
+ir_copy_propagation_elements_visitor::handle_if_block(exec_list *instructions)
+{
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ /* Populate the initial acp with a copy of the original */
+ foreach_iter(exec_list_iterator, iter, *orig_acp) {
+ acp_entry *a = (acp_entry *)iter.get();
+ this->acp->push_tail(new(this->mem_ctx) acp_entry(a));
+ }
+
+ visit_list_elements(this, instructions);
+
+ if (this->killed_all) {
+ orig_acp->make_empty();
+ }
+
+ exec_list *new_kills = this->kills;
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = this->killed_all || orig_killed_all;
+
+ /* Move the new kills into the parent block's list, removing them
+ * from the parent's ACP list in the process.
+ */
+ foreach_list_safe(node, new_kills) {
+ kill_entry *k = (kill_entry *)node;
+ kill(k);
+ }
+}
+
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_enter(ir_if *ir)
+{
+ ir->condition->accept(this);
+
+ handle_if_block(&ir->then_instructions);
+ handle_if_block(&ir->else_instructions);
+
+ /* handle_if_block() already descended into the children. */
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_enter(ir_loop *ir)
+{
+ exec_list *orig_acp = this->acp;
+ exec_list *orig_kills = this->kills;
+ bool orig_killed_all = this->killed_all;
+
+ /* FINISHME: For now, the initial acp for loops is totally empty.
+ * We could go through once, then go through again with the acp
+ * cloned minus the killed entries after the first run through.
+ */
+ this->acp = new(mem_ctx) exec_list;
+ this->kills = new(mem_ctx) exec_list;
+ this->killed_all = false;
+
+ visit_list_elements(this, &ir->body_instructions);
+
+ if (this->killed_all) {
+ orig_acp->make_empty();
+ }
+
+ exec_list *new_kills = this->kills;
+ this->kills = orig_kills;
+ this->acp = orig_acp;
+ this->killed_all = this->killed_all || orig_killed_all;
+
+ foreach_list_safe(node, new_kills) {
+ kill_entry *k = (kill_entry *)node;
+ kill(k);
+ }
+
+ /* already descended into the children. */
+ return visit_continue_with_parent;
+}
+
+/* Remove any entries currently in the ACP for this kill. */
+void
+ir_copy_propagation_elements_visitor::kill(kill_entry *k)
+{
+ foreach_list_safe(node, acp) {
+ acp_entry *entry = (acp_entry *)node;
+
+ if (entry->lhs == k->var) {
+ entry->write_mask = entry->write_mask & ~k->write_mask;
+ if (entry->write_mask == 0) {
+ entry->remove();
+ continue;
+ }
+ }
+ if (entry->rhs == k->var) {
+ entry->remove();
+ }
+ }
+
+ /* If we were on a list, remove ourselves before inserting */
+ if (k->next)
+ k->remove();
+
+ this->kills->push_tail(k);
+}
+
+/**
+ * Adds directly-copied channels between vector variables to the available
+ * copy propagation list.
+ */
+void
+ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
+{
+ acp_entry *entry;
+ int orig_swizzle[4] = {0, 1, 2, 3};
+ int swizzle[4];
+
+ if (ir->condition)
+ return;
+
+ ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
+ if (!lhs || !(lhs->type->is_scalar() || lhs->type->is_vector()))
+ return;
+
+ ir_dereference_variable *rhs = ir->rhs->as_dereference_variable();
+ if (!rhs) {
+ ir_swizzle *swiz = ir->rhs->as_swizzle();
+ if (!swiz)
+ return;
+
+ rhs = swiz->val->as_dereference_variable();
+ if (!rhs)
+ return;
+
+ orig_swizzle[0] = swiz->mask.x;
+ orig_swizzle[1] = swiz->mask.y;
+ orig_swizzle[2] = swiz->mask.z;
+ orig_swizzle[3] = swiz->mask.w;
+ }
+
+ /* Move the swizzle channels out to the positions they match in the
+ * destination. We don't want to have to rewrite the swizzle[]
+ * array every time we clear a bit of the write_mask.
+ */
+ int j = 0;
+ for (int i = 0; i < 4; i++) {
+ if (ir->write_mask & (1 << i))
+ swizzle[i] = orig_swizzle[j++];
+ }
+
+ entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask,
+ swizzle);
+ this->acp->push_tail(entry);
+}
+
+bool
+do_copy_propagation_elements(exec_list *instructions)
+{
+ ir_copy_propagation_elements_visitor v;
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 4f6712a10..56a60fb12 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -191,7 +191,8 @@ _mesa_notifySwapBuffers(struct gl_context *ctx)
* is acceptable but the actual depth type will be GLushort or GLuint as
* needed.
* \param stencilBits requested minimum bits per stencil buffer value
- * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number of bits per color component in accum buffer.
+ * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number
+ * of bits per color component in accum buffer.
* \param indexBits number of bits per pixel if \p rgbFlag is GL_FALSE
* \param redBits number of bits per color component in frame buffer for RGB(A)
* mode. We always use 8 in core Mesa though.
@@ -200,8 +201,8 @@ _mesa_notifySwapBuffers(struct gl_context *ctx)
* \param alphaBits same as above.
* \param numSamples not really used.
*
- * \return pointer to new struct gl_config or NULL if requested parameters can't be
- * met.
+ * \return pointer to new struct gl_config or NULL if requested parameters
+ * can't be met.
*
* \note Need to add params for level and numAuxBuffers (at least)
*/
@@ -1186,7 +1187,8 @@ _mesa_destroy_context( struct gl_context *ctx )
* structures.
*/
void
-_mesa_copy_context( const struct gl_context *src, struct gl_context *dst, GLuint mask )
+_mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
+ GLuint mask )
{
if (mask & GL_ACCUM_BUFFER_BIT) {
/* OK to memcpy */
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index ae4d6f7da..2e9fbc77a 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -30,16 +30,16 @@
* There are three large Mesa data types/classes which are meant to be
* used by device drivers:
* - struct gl_context: this contains the Mesa rendering state
- * - struct gl_config: this describes the color buffer (RGB vs. ci), whether or not
- * there's a depth buffer, stencil buffer, etc.
- * - struct gl_framebuffer: contains pointers to the depth buffer, stencil buffer,
- * accum buffer and alpha buffers.
+ * - struct gl_config: this describes the color buffer (RGB vs. ci), whether
+ * or not there's a depth buffer, stencil buffer, etc.
+ * - struct gl_framebuffer: contains pointers to the depth buffer, stencil
+ * buffer, accum buffer and alpha buffers.
*
* These types should be encapsulated by corresponding device driver
* data types. See xmesa.h and xmesaP.h for an example.
*
- * In OOP terms, struct gl_context, struct gl_config, and struct gl_framebuffer are base classes
- * which the device driver must derive from.
+ * In OOP terms, struct gl_context, struct gl_config, and struct gl_framebuffer
+ * are base classes which the device driver must derive from.
*
* The following functions create and destroy these data types.
*/
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 6d098788b..da55c61f9 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -262,6 +262,7 @@ static const struct extension extension_table[] = {
{ "GL_APPLE_packed_pixels", o(APPLE_packed_pixels), GL, 2002 },
{ "GL_APPLE_vertex_array_object", o(APPLE_vertex_array_object), GL, 2002 },
{ "GL_ATI_blend_equation_separate", o(EXT_blend_equation_separate), GL, 2003 },
+ { "GL_ATI_draw_buffers", o(ARB_draw_buffers), GL, 2002 },
{ "GL_ATI_envmap_bumpmap", o(ATI_envmap_bumpmap), GL, 2001 },
{ "GL_ATI_fragment_shader", o(ATI_fragment_shader), GL, 2001 },
{ "GL_ATI_separate_stencil", o(ATI_separate_stencil), GL, 2006 },
diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c
index 55acb6d1f..2561f04bd 100644
--- a/mesalib/src/mesa/main/samplerobj.c
+++ b/mesalib/src/mesa/main/samplerobj.c
@@ -1,1355 +1,1355 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2011 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, 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
- * BRIAN PAUL 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 samplerobj.c
- * \brief Functions for the GL_ARB_sampler_objects extension.
- * \author Brian Paul
- */
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/dispatch.h"
-#include "main/enums.h"
-#include "main/hash.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "main/mtypes.h"
-#include "main/samplerobj.h"
-
-
-static struct gl_sampler_object *
-_mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
-{
- if (name == 0)
- return NULL;
- else
- return (struct gl_sampler_object *)
- _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
-}
-
-
-/**
- * Handle reference counting.
- */
-void
-_mesa_reference_sampler_object(struct gl_context *ctx,
- struct gl_sampler_object **ptr,
- struct gl_sampler_object *samp)
-{
- if (*ptr == samp)
- return;
-
- if (*ptr) {
- /* Unreference the old buffer */
- GLboolean deleteFlag = GL_FALSE;
- struct gl_sampler_object *oldSamp = *ptr;
-
- /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/
- ASSERT(oldSamp->RefCount > 0);
- oldSamp->RefCount--;
-#if 0
- printf("SamplerObj %p %d DECR to %d\n",
- (void *) oldSamp, oldSamp->Name, oldSamp->RefCount);
-#endif
- deleteFlag = (oldSamp->RefCount == 0);
- /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/
-
- if (deleteFlag) {
- ASSERT(ctx->Driver.DeleteSamplerObject);
- ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
- }
-
- *ptr = NULL;
- }
- ASSERT(!*ptr);
-
- if (samp) {
- /* reference new sampler */
- /*_glthread_LOCK_MUTEX(samp->Mutex);*/
- if (samp->RefCount == 0) {
- /* this buffer's being deleted (look just above) */
- /* Not sure this can every really happen. Warn if it does. */
- _mesa_problem(NULL, "referencing deleted buffer object");
- *ptr = NULL;
- }
- else {
- samp->RefCount++;
-#if 0
- printf("SamplerObj %p %d INCR to %d\n",
- (void *) samp, samp->Name, samp->RefCount);
-#endif
- *ptr = samp;
- }
- /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/
- }
-}
-
-
-/**
- * Initialize the fields of the given sampler object.
- */
-void
-_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
-{
- sampObj->Name = name;
- sampObj->RefCount = 1;
- sampObj->WrapS = GL_REPEAT;
- sampObj->WrapT = GL_REPEAT;
- sampObj->WrapR = GL_REPEAT;
- sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
- sampObj->MagFilter = GL_LINEAR;
- sampObj->BorderColor.f[0] = 0.0;
- sampObj->BorderColor.f[1] = 0.0;
- sampObj->BorderColor.f[2] = 0.0;
- sampObj->BorderColor.f[3] = 0.0;
- sampObj->MinLod = -1000.0F;
- sampObj->MaxLod = 1000.0F;
- sampObj->LodBias = 0.0F;
- sampObj->MaxAnisotropy = 1.0F;
- sampObj->CompareMode = GL_NONE;
- sampObj->CompareFunc = GL_LEQUAL;
- sampObj->CompareFailValue = 0.0;
- sampObj->sRGBDecode = GL_FALSE;
- sampObj->DepthMode = 0;
-}
-
-
-/**
- * Fallback for ctx->Driver.NewSamplerObject();
- */
-struct gl_sampler_object *
-_mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
-{
- struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
- if (sampObj) {
- _mesa_init_sampler_object(sampObj, name);
- }
- return sampObj;
-}
-
-
-/**
- * Fallback for ctx->Driver.DeleteSamplerObject();
- */
-void
-_mesa_delete_sampler_object(struct gl_context *ctx,
- struct gl_sampler_object *sampObj)
-{
- FREE(sampObj);
-}
-
-
-static void GLAPIENTRY
-_mesa_GenSamplers(GLsizei count, GLuint *samplers)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLuint first;
- GLint i;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
-
- if (count < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
- return;
- }
-
- if (!samplers)
- return;
-
- first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
-
- /* Insert the ID and pointer to new sampler object into hash table */
- for (i = 0; i < count; i++) {
- struct gl_sampler_object *sampObj =
- ctx->Driver.NewSamplerObject(ctx, first + i);
- _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj);
- samplers[i] = first + i;
- }
-}
-
-
-static void GLAPIENTRY
-_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
-{
- GET_CURRENT_CONTEXT(ctx);
- GLsizei i;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, 0);
-
- if (count < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
- return;
- }
-
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
-
- for (i = 0; i < count; i++) {
- if (samplers[i]) {
- struct gl_sampler_object *sampObj =
- _mesa_lookup_samplerobj(ctx, samplers[i]);
- if (sampObj) {
- /* The ID is immediately freed for re-use */
- _mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]);
- /* But the object exists until its reference count goes to zero */
- _mesa_reference_sampler_object(ctx, &sampObj, NULL);
- }
- }
- }
-
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
-}
-
-
-static GLboolean GLAPIENTRY
-_mesa_IsSampler(GLuint sampler)
-{
- struct gl_sampler_object *sampObj;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
- if (sampler == 0)
- return GL_FALSE;
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
-
- return sampObj != NULL;
-}
-
-
-static void GLAPIENTRY
-_mesa_BindSampler(GLuint unit, GLuint sampler)
-{
- struct gl_sampler_object *sampObj;
- GET_CURRENT_CONTEXT(ctx);
-
- if (unit >= ctx->Const.MaxTextureImageUnits) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
- return;
- }
-
- if (sampler == 0) {
- /* Use the default sampler object, the one contained in the texture
- * object.
- */
- sampObj = NULL;
- }
- else {
- /* user-defined sampler object */
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
- return;
- }
- }
-
- if (ctx->Texture.Unit[unit].Sampler != sampObj) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- }
-
- /* bind new sampler */
- _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
- sampObj);
-}
-
-
-/**
- * Check if a coordinate wrap mode is supported for the texture target.
- * \return GL_TRUE if legal, GL_FALSE otherwise
- */
-static GLboolean
-validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
-{
- const struct gl_extensions * const e = &ctx->Extensions;
-
- switch (wrap) {
- case GL_CLAMP:
- case GL_CLAMP_TO_EDGE:
- case GL_REPEAT:
- return GL_TRUE;
- case GL_CLAMP_TO_BORDER:
- return e->ARB_texture_border_clamp;
- case GL_MIRRORED_REPEAT:
- return e->ARB_texture_mirrored_repeat;
- case GL_MIRROR_CLAMP_EXT:
- return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
- case GL_MIRROR_CLAMP_TO_EDGE_EXT:
- return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
- case GL_MIRROR_CLAMP_TO_BORDER_EXT:
- return e->EXT_texture_mirror_clamp;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * This is called just prior to changing any sampler object state.
- */
-static INLINE void
-flush(struct gl_context *ctx)
-{
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-}
-
-
-#define INVALID_PARAM 0x100
-#define INVALID_PNAME 0x101
-#define INVALID_VALUE 0x102
-
-static GLuint
-set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLint param)
-{
- if (samp->WrapS == param)
- return GL_FALSE;
- if (validate_texture_wrap_mode(ctx, param)) {
- flush(ctx);
- samp->WrapS = param;
- return GL_TRUE;
- }
- return INVALID_PARAM;
-}
-
-
-static GLuint
-set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLint param)
-{
- if (samp->WrapT == param)
- return GL_FALSE;
- if (validate_texture_wrap_mode(ctx, param)) {
- flush(ctx);
- samp->WrapT = param;
- return GL_TRUE;
- }
- return INVALID_PARAM;
-}
-
-
-static GLuint
-set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLint param)
-{
- if (samp->WrapR == param)
- return GL_FALSE;
- if (validate_texture_wrap_mode(ctx, param)) {
- flush(ctx);
- samp->WrapR = param;
- return GL_TRUE;
- }
- return INVALID_PARAM;
-}
-
-
-static GLuint
-set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLint param)
-{
- if (samp->MinFilter == param)
- return GL_FALSE;
-
- switch (param) {
- case GL_NEAREST:
- case GL_LINEAR:
- case GL_NEAREST_MIPMAP_NEAREST:
- case GL_LINEAR_MIPMAP_NEAREST:
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
- flush(ctx);
- samp->MinFilter = param;
- return GL_TRUE;
- default:
- return INVALID_PARAM;
- }
-}
-
-
-static GLuint
-set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLint param)
-{
- if (samp->MagFilter == param)
- return GL_FALSE;
-
- switch (param) {
- case GL_NEAREST:
- case GL_LINEAR:
- flush(ctx);
- samp->MagFilter = param;
- return GL_TRUE;
- default:
- return INVALID_PARAM;
- }
-}
-
-
-static GLuint
-set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLfloat param)
-{
- if (samp->LodBias == param)
- return GL_FALSE;
-
- flush(ctx);
- samp->LodBias = param;
- return GL_TRUE;
-}
-
-
-static GLuint
-set_sampler_border_colorf(struct gl_context *ctx,
- struct gl_sampler_object *samp,
- const GLfloat params[4])
-{
- flush(ctx);
- samp->BorderColor.f[RCOMP] = params[0];
- samp->BorderColor.f[GCOMP] = params[1];
- samp->BorderColor.f[BCOMP] = params[2];
- samp->BorderColor.f[ACOMP] = params[3];
- return GL_TRUE;
-}
-
-
-static GLuint
-set_sampler_border_colori(struct gl_context *ctx,
- struct gl_sampler_object *samp,
- const GLint params[4])
-{
- flush(ctx);
- samp->BorderColor.i[RCOMP] = params[0];
- samp->BorderColor.i[GCOMP] = params[1];
- samp->BorderColor.i[BCOMP] = params[2];
- samp->BorderColor.i[ACOMP] = params[3];
- return GL_TRUE;
-}
-
-
-static GLuint
-set_sampler_border_colorui(struct gl_context *ctx,
- struct gl_sampler_object *samp,
- const GLuint params[4])
-{
- flush(ctx);
- samp->BorderColor.ui[RCOMP] = params[0];
- samp->BorderColor.ui[GCOMP] = params[1];
- samp->BorderColor.ui[BCOMP] = params[2];
- samp->BorderColor.ui[ACOMP] = params[3];
- return GL_TRUE;
-}
-
-
-static GLuint
-set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLfloat param)
-{
- if (samp->MinLod == param)
- return GL_FALSE;
-
- flush(ctx);
- samp->MinLod = param;
- return GL_TRUE;
-}
-
-
-static GLuint
-set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
- GLint param)
-{
- if (samp->MaxLod == param)
- return GL_FALSE;
-
- flush(ctx);
- samp->MaxLod = param;
- return GL_TRUE;
-}
-
-
-static GLuint
-set_sampler_compare_mode(struct gl_context *ctx,
- struct gl_sampler_object *samp, GLint param)
-{
- if (!ctx->Extensions.ARB_shadow)
- return INVALID_PNAME;
-
- if (samp->CompareMode == param)
- return GL_FALSE;
-
- if (param == GL_NONE ||
- param == GL_COMPARE_R_TO_TEXTURE_ARB) {
- flush(ctx);
- samp->CompareMode = param;
- return GL_TRUE;
- }
-
- return INVALID_PARAM;
-}
-
-
-static GLuint
-set_sampler_compare_func(struct gl_context *ctx,
- struct gl_sampler_object *samp, GLint param)
-{
- if (!ctx->Extensions.ARB_shadow)
- return INVALID_PNAME;
-
- if (samp->CompareFunc == param)
- return GL_FALSE;
-
- switch (param) {
- case GL_LEQUAL:
- case GL_GEQUAL:
- flush(ctx);
- samp->CompareFunc = param;
- return GL_TRUE;
- case GL_EQUAL:
- case GL_NOTEQUAL:
- case GL_LESS:
- case GL_GREATER:
- case GL_ALWAYS:
- case GL_NEVER:
- if (ctx->Extensions.EXT_shadow_funcs) {
- flush(ctx);
- samp->CompareFunc = param;
- return GL_TRUE;
- }
- /* fall-through */
- default:
- return INVALID_PARAM;
- }
-}
-
-
-static GLuint
-set_sampler_max_anisotropy(struct gl_context *ctx,
- struct gl_sampler_object *samp, GLfloat param)
-{
- if (!ctx->Extensions.EXT_texture_filter_anisotropic)
- return INVALID_PNAME;
-
- if (samp->MaxAnisotropy == param)
- return GL_FALSE;
-
- if (param < 1.0)
- return INVALID_VALUE;
-
- flush(ctx);
- /* clamp to max, that's what NVIDIA does */
- samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
- return GL_TRUE;
-}
-
-
-static void GLAPIENTRY
-_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
-{
- struct gl_sampler_object *sampObj;
- GLuint res;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- res = set_sampler_wrap_s(ctx, sampObj, param);
- break;
- case GL_TEXTURE_WRAP_T:
- res = set_sampler_wrap_t(ctx, sampObj, param);
- break;
- case GL_TEXTURE_WRAP_R:
- res = set_sampler_wrap_r(ctx, sampObj, param);
- break;
- case GL_TEXTURE_MIN_FILTER:
- res = set_sampler_min_filter(ctx, sampObj, param);
- break;
- case GL_TEXTURE_MAG_FILTER:
- res = set_sampler_mag_filter(ctx, sampObj, param);
- break;
- case GL_TEXTURE_MIN_LOD:
- res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
- break;
- case GL_TEXTURE_MAX_LOD:
- res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
- break;
- case GL_TEXTURE_LOD_BIAS:
- res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
- break;
- case GL_TEXTURE_COMPARE_MODE:
- res = set_sampler_compare_mode(ctx, sampObj, param);
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- res = set_sampler_compare_func(ctx, sampObj, param);
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
- break;
- case GL_TEXTURE_BORDER_COLOR:
- /* fall-through */
- default:
- res = INVALID_PNAME;
- }
-
- switch (res) {
- case GL_FALSE:
- /* no change */
- break;
- case GL_TRUE:
- /* state change - we do nothing special at this time */
- break;
- case INVALID_PNAME:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
- _mesa_lookup_enum_by_nr(pname));
- break;
- case INVALID_PARAM:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
- param);
- break;
- case INVALID_VALUE:
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
- param);
- break;
- default:
- ;
- }
-}
-
-
-static void GLAPIENTRY
-_mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
-{
- struct gl_sampler_object *sampObj;
- GLuint res;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_WRAP_T:
- res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_WRAP_R:
- res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_MIN_FILTER:
- res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_MAG_FILTER:
- res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_MIN_LOD:
- res = set_sampler_min_lod(ctx, sampObj, param);
- break;
- case GL_TEXTURE_MAX_LOD:
- res = set_sampler_max_lod(ctx, sampObj, param);
- break;
- case GL_TEXTURE_LOD_BIAS:
- res = set_sampler_lod_bias(ctx, sampObj, param);
- break;
- case GL_TEXTURE_COMPARE_MODE:
- res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- res = set_sampler_max_anisotropy(ctx, sampObj, param);
- break;
- case GL_TEXTURE_BORDER_COLOR:
- /* fall-through */
- default:
- res = INVALID_PNAME;
- }
-
- switch (res) {
- case GL_FALSE:
- /* no change */
- break;
- case GL_TRUE:
- /* state change - we do nothing special at this time */
- break;
- case INVALID_PNAME:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
- _mesa_lookup_enum_by_nr(pname));
- break;
- case INVALID_PARAM:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
- param);
- break;
- case INVALID_VALUE:
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
- param);
- break;
- default:
- ;
- }
-}
-
-static void GLAPIENTRY
-_mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
-{
- struct gl_sampler_object *sampObj;
- GLuint res;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- res = set_sampler_wrap_s(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_WRAP_T:
- res = set_sampler_wrap_t(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_WRAP_R:
- res = set_sampler_wrap_r(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MIN_FILTER:
- res = set_sampler_min_filter(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAG_FILTER:
- res = set_sampler_mag_filter(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MIN_LOD:
- res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_MAX_LOD:
- res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_LOD_BIAS:
- res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_COMPARE_MODE:
- res = set_sampler_compare_mode(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- res = set_sampler_compare_func(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_BORDER_COLOR:
- {
- GLfloat c[4];
- c[0] = INT_TO_FLOAT(params[0]);
- c[1] = INT_TO_FLOAT(params[1]);
- c[2] = INT_TO_FLOAT(params[2]);
- c[3] = INT_TO_FLOAT(params[3]);
- res = set_sampler_border_colorf(ctx, sampObj, c);
- }
- break;
- default:
- res = INVALID_PNAME;
- }
-
- switch (res) {
- case GL_FALSE:
- /* no change */
- break;
- case GL_TRUE:
- /* state change - we do nothing special at this time */
- break;
- case INVALID_PNAME:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
- _mesa_lookup_enum_by_nr(pname));
- break;
- case INVALID_PARAM:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
- params[0]);
- break;
- case INVALID_VALUE:
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
- params[0]);
- break;
- default:
- ;
- }
-}
-
-static void GLAPIENTRY
-_mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
-{
- struct gl_sampler_object *sampObj;
- GLuint res;
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_WRAP_T:
- res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_WRAP_R:
- res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_MIN_FILTER:
- res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_MAG_FILTER:
- res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_MIN_LOD:
- res = set_sampler_min_lod(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAX_LOD:
- res = set_sampler_max_lod(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_LOD_BIAS:
- res = set_sampler_lod_bias(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_COMPARE_MODE:
- res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_BORDER_COLOR:
- res = set_sampler_border_colorf(ctx, sampObj, params);
- break;
- default:
- res = INVALID_PNAME;
- }
-
- switch (res) {
- case GL_FALSE:
- /* no change */
- break;
- case GL_TRUE:
- /* state change - we do nothing special at this time */
- break;
- case INVALID_PNAME:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
- _mesa_lookup_enum_by_nr(pname));
- break;
- case INVALID_PARAM:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
- params[0]);
- break;
- case INVALID_VALUE:
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
- params[0]);
- break;
- default:
- ;
- }
-}
-
-static void GLAPIENTRY
-_mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
-{
- struct gl_sampler_object *sampObj;
- GLuint res;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- res = set_sampler_wrap_s(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_WRAP_T:
- res = set_sampler_wrap_t(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_WRAP_R:
- res = set_sampler_wrap_r(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MIN_FILTER:
- res = set_sampler_min_filter(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAG_FILTER:
- res = set_sampler_mag_filter(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MIN_LOD:
- res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_MAX_LOD:
- res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_LOD_BIAS:
- res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_COMPARE_MODE:
- res = set_sampler_compare_mode(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- res = set_sampler_compare_func(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_BORDER_COLOR:
- res = set_sampler_border_colori(ctx, sampObj, params);
- break;
- default:
- res = INVALID_PNAME;
- }
-
- switch (res) {
- case GL_FALSE:
- /* no change */
- break;
- case GL_TRUE:
- /* state change - we do nothing special at this time */
- break;
- case INVALID_PNAME:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
- _mesa_lookup_enum_by_nr(pname));
- break;
- case INVALID_PARAM:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
- params[0]);
- break;
- case INVALID_VALUE:
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
- params[0]);
- break;
- default:
- ;
- }
-}
-
-
-static void GLAPIENTRY
-_mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
-{
- struct gl_sampler_object *sampObj;
- GLuint res;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- res = set_sampler_wrap_s(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_WRAP_T:
- res = set_sampler_wrap_t(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_WRAP_R:
- res = set_sampler_wrap_r(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MIN_FILTER:
- res = set_sampler_min_filter(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAG_FILTER:
- res = set_sampler_mag_filter(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MIN_LOD:
- res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_MAX_LOD:
- res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_LOD_BIAS:
- res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_COMPARE_MODE:
- res = set_sampler_compare_mode(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- res = set_sampler_compare_func(ctx, sampObj, params[0]);
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
- break;
- case GL_TEXTURE_BORDER_COLOR:
- res = set_sampler_border_colorui(ctx, sampObj, params);
- break;
- default:
- res = INVALID_PNAME;
- }
-
- switch (res) {
- case GL_FALSE:
- /* no change */
- break;
- case GL_TRUE:
- /* state change - we do nothing special at this time */
- break;
- case INVALID_PNAME:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
- _mesa_lookup_enum_by_nr(pname));
- break;
- case INVALID_PARAM:
- _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
- params[0]);
- break;
- case INVALID_VALUE:
- _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
- params[0]);
- break;
- default:
- ;
- }
-}
-
-
-static void GLAPIENTRY
-_mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
-{
- struct gl_sampler_object *sampObj;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- *params = sampObj->WrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = sampObj->WrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- *params = sampObj->WrapR;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = sampObj->MinFilter;
- break;
- case GL_TEXTURE_MAG_FILTER:
- *params = sampObj->MagFilter;
- break;
- case GL_TEXTURE_MIN_LOD:
- *params = (GLint) sampObj->MinLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- *params = (GLint) sampObj->MaxLod;
- break;
- case GL_TEXTURE_LOD_BIAS:
- *params = (GLint) sampObj->LodBias;
- break;
- case GL_TEXTURE_COMPARE_MODE:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = sampObj->CompareMode;
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = sampObj->CompareFunc;
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- *params = (GLint) sampObj->MaxAnisotropy;
- break;
- case GL_TEXTURE_BORDER_COLOR:
- params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
- params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
- params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
- params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
- break;
- default:
- goto invalid_pname;
- }
- return;
-
-invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
- _mesa_lookup_enum_by_nr(pname));
-}
-
-
-static void GLAPIENTRY
-_mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
-{
- struct gl_sampler_object *sampObj;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- *params = (GLfloat) sampObj->WrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = (GLfloat) sampObj->WrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- *params = (GLfloat) sampObj->WrapR;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = (GLfloat) sampObj->MinFilter;
- break;
- case GL_TEXTURE_MAG_FILTER:
- *params = (GLfloat) sampObj->MagFilter;
- break;
- case GL_TEXTURE_MIN_LOD:
- *params = sampObj->MinLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- *params = sampObj->MaxLod;
- break;
- case GL_TEXTURE_LOD_BIAS:
- *params = sampObj->LodBias;
- break;
- case GL_TEXTURE_COMPARE_MODE:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = (GLfloat) sampObj->CompareMode;
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = (GLfloat) sampObj->CompareFunc;
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- *params = sampObj->MaxAnisotropy;
- break;
- case GL_TEXTURE_BORDER_COLOR:
- params[0] = sampObj->BorderColor.f[0];
- params[1] = sampObj->BorderColor.f[1];
- params[2] = sampObj->BorderColor.f[2];
- params[3] = sampObj->BorderColor.f[3];
- break;
- default:
- goto invalid_pname;
- }
- return;
-
-invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
- _mesa_lookup_enum_by_nr(pname));
-}
-
-
-static void GLAPIENTRY
-_mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
-{
- struct gl_sampler_object *sampObj;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetSamplerParameterIiv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- *params = sampObj->WrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = sampObj->WrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- *params = sampObj->WrapR;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = sampObj->MinFilter;
- break;
- case GL_TEXTURE_MAG_FILTER:
- *params = sampObj->MagFilter;
- break;
- case GL_TEXTURE_MIN_LOD:
- *params = (GLint) sampObj->MinLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- *params = (GLint) sampObj->MaxLod;
- break;
- case GL_TEXTURE_LOD_BIAS:
- *params = (GLint) sampObj->LodBias;
- break;
- case GL_TEXTURE_COMPARE_MODE:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = sampObj->CompareMode;
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = sampObj->CompareFunc;
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- *params = (GLint) sampObj->MaxAnisotropy;
- break;
- case GL_TEXTURE_BORDER_COLOR:
- params[0] = sampObj->BorderColor.i[0];
- params[1] = sampObj->BorderColor.i[1];
- params[2] = sampObj->BorderColor.i[2];
- params[3] = sampObj->BorderColor.i[3];
- break;
- default:
- goto invalid_pname;
- }
- return;
-
-invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
- _mesa_lookup_enum_by_nr(pname));
-}
-
-
-static void GLAPIENTRY
-_mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
-{
- struct gl_sampler_object *sampObj;
- GET_CURRENT_CONTEXT(ctx);
-
- sampObj = _mesa_lookup_samplerobj(ctx, sampler);
- if (!sampObj) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetSamplerParameterIuiv(sampler %u)",
- sampler);
- return;
- }
-
- switch (pname) {
- case GL_TEXTURE_WRAP_S:
- *params = sampObj->WrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = sampObj->WrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- *params = sampObj->WrapR;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = sampObj->MinFilter;
- break;
- case GL_TEXTURE_MAG_FILTER:
- *params = sampObj->MagFilter;
- break;
- case GL_TEXTURE_MIN_LOD:
- *params = (GLuint) sampObj->MinLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- *params = (GLuint) sampObj->MaxLod;
- break;
- case GL_TEXTURE_LOD_BIAS:
- *params = (GLuint) sampObj->LodBias;
- break;
- case GL_TEXTURE_COMPARE_MODE:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = sampObj->CompareMode;
- break;
- case GL_TEXTURE_COMPARE_FUNC:
- if (!ctx->Extensions.ARB_shadow)
- goto invalid_pname;
- *params = sampObj->CompareFunc;
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- *params = (GLuint) sampObj->MaxAnisotropy;
- break;
- case GL_TEXTURE_BORDER_COLOR:
- params[0] = sampObj->BorderColor.ui[0];
- params[1] = sampObj->BorderColor.ui[1];
- params[2] = sampObj->BorderColor.ui[2];
- params[3] = sampObj->BorderColor.ui[3];
- break;
- default:
- goto invalid_pname;
- }
- return;
-
-invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
- _mesa_lookup_enum_by_nr(pname));
-}
-
-
-void
-_mesa_init_sampler_object_functions(struct dd_function_table *driver)
-{
- driver->NewSamplerObject = _mesa_new_sampler_object;
- driver->DeleteSamplerObject = _mesa_delete_sampler_object;
-}
-
-
-void
-_mesa_init_sampler_object_dispatch(struct _glapi_table *disp)
-{
- SET_GenSamplers(disp, _mesa_GenSamplers);
- SET_DeleteSamplers(disp, _mesa_DeleteSamplers);
- SET_IsSampler(disp, _mesa_IsSampler);
- SET_BindSampler(disp, _mesa_BindSampler);
- SET_SamplerParameteri(disp, _mesa_SamplerParameteri);
- SET_SamplerParameterf(disp, _mesa_SamplerParameterf);
- SET_SamplerParameteriv(disp, _mesa_SamplerParameteriv);
- SET_SamplerParameterfv(disp, _mesa_SamplerParameterfv);
- SET_SamplerParameterIiv(disp, _mesa_SamplerParameterIiv);
- SET_SamplerParameterIuiv(disp, _mesa_SamplerParameterIuiv);
- SET_GetSamplerParameteriv(disp, _mesa_GetSamplerParameteriv);
- SET_GetSamplerParameterfv(disp, _mesa_GetSamplerParameterfv);
- SET_GetSamplerParameterIiv(disp, _mesa_GetSamplerParameterIiv);
- SET_GetSamplerParameterIuiv(disp, _mesa_GetSamplerParameterIuiv);
-}
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2011 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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
+ * BRIAN PAUL 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 samplerobj.c
+ * \brief Functions for the GL_ARB_sampler_objects extension.
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/dispatch.h"
+#include "main/enums.h"
+#include "main/hash.h"
+#include "main/macros.h"
+#include "main/mfeatures.h"
+#include "main/mtypes.h"
+#include "main/samplerobj.h"
+
+
+static struct gl_sampler_object *
+_mesa_lookup_samplerobj(struct gl_context *ctx, GLuint name)
+{
+ if (name == 0)
+ return NULL;
+ else
+ return (struct gl_sampler_object *)
+ _mesa_HashLookup(ctx->Shared->SamplerObjects, name);
+}
+
+
+/**
+ * Handle reference counting.
+ */
+void
+_mesa_reference_sampler_object(struct gl_context *ctx,
+ struct gl_sampler_object **ptr,
+ struct gl_sampler_object *samp)
+{
+ if (*ptr == samp)
+ return;
+
+ if (*ptr) {
+ /* Unreference the old sampler */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_sampler_object *oldSamp = *ptr;
+
+ /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/
+ ASSERT(oldSamp->RefCount > 0);
+ oldSamp->RefCount--;
+#if 0
+ printf("SamplerObj %p %d DECR to %d\n",
+ (void *) oldSamp, oldSamp->Name, oldSamp->RefCount);
+#endif
+ deleteFlag = (oldSamp->RefCount == 0);
+ /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/
+
+ if (deleteFlag) {
+ ASSERT(ctx->Driver.DeleteSamplerObject);
+ ctx->Driver.DeleteSamplerObject(ctx, oldSamp);
+ }
+
+ *ptr = NULL;
+ }
+ ASSERT(!*ptr);
+
+ if (samp) {
+ /* reference new sampler */
+ /*_glthread_LOCK_MUTEX(samp->Mutex);*/
+ if (samp->RefCount == 0) {
+ /* this sampler's being deleted (look just above) */
+ /* Not sure this can every really happen. Warn if it does. */
+ _mesa_problem(NULL, "referencing deleted sampler object");
+ *ptr = NULL;
+ }
+ else {
+ samp->RefCount++;
+#if 0
+ printf("SamplerObj %p %d INCR to %d\n",
+ (void *) samp, samp->Name, samp->RefCount);
+#endif
+ *ptr = samp;
+ }
+ /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/
+ }
+}
+
+
+/**
+ * Initialize the fields of the given sampler object.
+ */
+void
+_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
+{
+ sampObj->Name = name;
+ sampObj->RefCount = 1;
+ sampObj->WrapS = GL_REPEAT;
+ sampObj->WrapT = GL_REPEAT;
+ sampObj->WrapR = GL_REPEAT;
+ sampObj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
+ sampObj->MagFilter = GL_LINEAR;
+ sampObj->BorderColor.f[0] = 0.0;
+ sampObj->BorderColor.f[1] = 0.0;
+ sampObj->BorderColor.f[2] = 0.0;
+ sampObj->BorderColor.f[3] = 0.0;
+ sampObj->MinLod = -1000.0F;
+ sampObj->MaxLod = 1000.0F;
+ sampObj->LodBias = 0.0F;
+ sampObj->MaxAnisotropy = 1.0F;
+ sampObj->CompareMode = GL_NONE;
+ sampObj->CompareFunc = GL_LEQUAL;
+ sampObj->CompareFailValue = 0.0;
+ sampObj->sRGBDecode = GL_FALSE;
+ sampObj->DepthMode = 0;
+}
+
+
+/**
+ * Fallback for ctx->Driver.NewSamplerObject();
+ */
+struct gl_sampler_object *
+_mesa_new_sampler_object(struct gl_context *ctx, GLuint name)
+{
+ struct gl_sampler_object *sampObj = CALLOC_STRUCT(gl_sampler_object);
+ if (sampObj) {
+ _mesa_init_sampler_object(sampObj, name);
+ }
+ return sampObj;
+}
+
+
+/**
+ * Fallback for ctx->Driver.DeleteSamplerObject();
+ */
+void
+_mesa_delete_sampler_object(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj)
+{
+ FREE(sampObj);
+}
+
+
+static void GLAPIENTRY
+_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
+
+ if (count < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
+ return;
+ }
+
+ if (!samplers)
+ return;
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count);
+
+ /* Insert the ID and pointer to new sampler object into hash table */
+ for (i = 0; i < count; i++) {
+ struct gl_sampler_object *sampObj =
+ ctx->Driver.NewSamplerObject(ctx, first + i);
+ _mesa_HashInsert(ctx->Shared->SamplerObjects, first + i, sampObj);
+ samplers[i] = first + i;
+ }
+}
+
+
+static void GLAPIENTRY
+_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLsizei i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, 0);
+
+ if (count < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
+ return;
+ }
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+ for (i = 0; i < count; i++) {
+ if (samplers[i]) {
+ struct gl_sampler_object *sampObj =
+ _mesa_lookup_samplerobj(ctx, samplers[i]);
+ if (sampObj) {
+ /* The ID is immediately freed for re-use */
+ _mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]);
+ /* But the object exists until its reference count goes to zero */
+ _mesa_reference_sampler_object(ctx, &sampObj, NULL);
+ }
+ }
+ }
+
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+static GLboolean GLAPIENTRY
+_mesa_IsSampler(GLuint sampler)
+{
+ struct gl_sampler_object *sampObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (sampler == 0)
+ return GL_FALSE;
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+
+ return sampObj != NULL;
+}
+
+
+static void GLAPIENTRY
+_mesa_BindSampler(GLuint unit, GLuint sampler)
+{
+ struct gl_sampler_object *sampObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (unit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit);
+ return;
+ }
+
+ if (sampler == 0) {
+ /* Use the default sampler object, the one contained in the texture
+ * object.
+ */
+ sampObj = NULL;
+ }
+ else {
+ /* user-defined sampler object */
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSampler(sampler)");
+ return;
+ }
+ }
+
+ if (ctx->Texture.Unit[unit].Sampler != sampObj) {
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ }
+
+ /* bind new sampler */
+ _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler,
+ sampObj);
+}
+
+
+/**
+ * Check if a coordinate wrap mode is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise
+ */
+static GLboolean
+validate_texture_wrap_mode(struct gl_context *ctx, GLenum wrap)
+{
+ const struct gl_extensions * const e = &ctx->Extensions;
+
+ switch (wrap) {
+ case GL_CLAMP:
+ case GL_CLAMP_TO_EDGE:
+ case GL_REPEAT:
+ return GL_TRUE;
+ case GL_CLAMP_TO_BORDER:
+ return e->ARB_texture_border_clamp;
+ case GL_MIRRORED_REPEAT:
+ return e->ARB_texture_mirrored_repeat;
+ case GL_MIRROR_CLAMP_EXT:
+ return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
+ case GL_MIRROR_CLAMP_TO_EDGE_EXT:
+ return e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp;
+ case GL_MIRROR_CLAMP_TO_BORDER_EXT:
+ return e->EXT_texture_mirror_clamp;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * This is called just prior to changing any sampler object state.
+ */
+static INLINE void
+flush(struct gl_context *ctx)
+{
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+}
+
+
+#define INVALID_PARAM 0x100
+#define INVALID_PNAME 0x101
+#define INVALID_VALUE 0x102
+
+static GLuint
+set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLint param)
+{
+ if (samp->WrapS == param)
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, param)) {
+ flush(ctx);
+ samp->WrapS = param;
+ return GL_TRUE;
+ }
+ return INVALID_PARAM;
+}
+
+
+static GLuint
+set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLint param)
+{
+ if (samp->WrapT == param)
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, param)) {
+ flush(ctx);
+ samp->WrapT = param;
+ return GL_TRUE;
+ }
+ return INVALID_PARAM;
+}
+
+
+static GLuint
+set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLint param)
+{
+ if (samp->WrapR == param)
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, param)) {
+ flush(ctx);
+ samp->WrapR = param;
+ return GL_TRUE;
+ }
+ return INVALID_PARAM;
+}
+
+
+static GLuint
+set_sampler_min_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLint param)
+{
+ if (samp->MinFilter == param)
+ return GL_FALSE;
+
+ switch (param) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ flush(ctx);
+ samp->MinFilter = param;
+ return GL_TRUE;
+ default:
+ return INVALID_PARAM;
+ }
+}
+
+
+static GLuint
+set_sampler_mag_filter(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLint param)
+{
+ if (samp->MagFilter == param)
+ return GL_FALSE;
+
+ switch (param) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ flush(ctx);
+ samp->MagFilter = param;
+ return GL_TRUE;
+ default:
+ return INVALID_PARAM;
+ }
+}
+
+
+static GLuint
+set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLfloat param)
+{
+ if (samp->LodBias == param)
+ return GL_FALSE;
+
+ flush(ctx);
+ samp->LodBias = param;
+ return GL_TRUE;
+}
+
+
+static GLuint
+set_sampler_border_colorf(struct gl_context *ctx,
+ struct gl_sampler_object *samp,
+ const GLfloat params[4])
+{
+ flush(ctx);
+ samp->BorderColor.f[RCOMP] = params[0];
+ samp->BorderColor.f[GCOMP] = params[1];
+ samp->BorderColor.f[BCOMP] = params[2];
+ samp->BorderColor.f[ACOMP] = params[3];
+ return GL_TRUE;
+}
+
+
+static GLuint
+set_sampler_border_colori(struct gl_context *ctx,
+ struct gl_sampler_object *samp,
+ const GLint params[4])
+{
+ flush(ctx);
+ samp->BorderColor.i[RCOMP] = params[0];
+ samp->BorderColor.i[GCOMP] = params[1];
+ samp->BorderColor.i[BCOMP] = params[2];
+ samp->BorderColor.i[ACOMP] = params[3];
+ return GL_TRUE;
+}
+
+
+static GLuint
+set_sampler_border_colorui(struct gl_context *ctx,
+ struct gl_sampler_object *samp,
+ const GLuint params[4])
+{
+ flush(ctx);
+ samp->BorderColor.ui[RCOMP] = params[0];
+ samp->BorderColor.ui[GCOMP] = params[1];
+ samp->BorderColor.ui[BCOMP] = params[2];
+ samp->BorderColor.ui[ACOMP] = params[3];
+ return GL_TRUE;
+}
+
+
+static GLuint
+set_sampler_min_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLfloat param)
+{
+ if (samp->MinLod == param)
+ return GL_FALSE;
+
+ flush(ctx);
+ samp->MinLod = param;
+ return GL_TRUE;
+}
+
+
+static GLuint
+set_sampler_max_lod(struct gl_context *ctx, struct gl_sampler_object *samp,
+ GLint param)
+{
+ if (samp->MaxLod == param)
+ return GL_FALSE;
+
+ flush(ctx);
+ samp->MaxLod = param;
+ return GL_TRUE;
+}
+
+
+static GLuint
+set_sampler_compare_mode(struct gl_context *ctx,
+ struct gl_sampler_object *samp, GLint param)
+{
+ if (!ctx->Extensions.ARB_shadow)
+ return INVALID_PNAME;
+
+ if (samp->CompareMode == param)
+ return GL_FALSE;
+
+ if (param == GL_NONE ||
+ param == GL_COMPARE_R_TO_TEXTURE_ARB) {
+ flush(ctx);
+ samp->CompareMode = param;
+ return GL_TRUE;
+ }
+
+ return INVALID_PARAM;
+}
+
+
+static GLuint
+set_sampler_compare_func(struct gl_context *ctx,
+ struct gl_sampler_object *samp, GLint param)
+{
+ if (!ctx->Extensions.ARB_shadow)
+ return INVALID_PNAME;
+
+ if (samp->CompareFunc == param)
+ return GL_FALSE;
+
+ switch (param) {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ flush(ctx);
+ samp->CompareFunc = param;
+ return GL_TRUE;
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ if (ctx->Extensions.EXT_shadow_funcs) {
+ flush(ctx);
+ samp->CompareFunc = param;
+ return GL_TRUE;
+ }
+ /* fall-through */
+ default:
+ return INVALID_PARAM;
+ }
+}
+
+
+static GLuint
+set_sampler_max_anisotropy(struct gl_context *ctx,
+ struct gl_sampler_object *samp, GLfloat param)
+{
+ if (!ctx->Extensions.EXT_texture_filter_anisotropic)
+ return INVALID_PNAME;
+
+ if (samp->MaxAnisotropy == param)
+ return GL_FALSE;
+
+ if (param < 1.0)
+ return INVALID_VALUE;
+
+ flush(ctx);
+ /* clamp to max, that's what NVIDIA does */
+ samp->MaxAnisotropy = MIN2(param, ctx->Const.MaxTextureMaxAnisotropy);
+ return GL_TRUE;
+}
+
+
+static void GLAPIENTRY
+_mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+ struct gl_sampler_object *sampObj;
+ GLuint res;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ res = set_sampler_wrap_s(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ res = set_sampler_wrap_t(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_WRAP_R:
+ res = set_sampler_wrap_r(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ res = set_sampler_min_filter(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ res = set_sampler_mag_filter(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ res = set_sampler_min_lod(ctx, sampObj, (GLfloat) param);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ res = set_sampler_max_lod(ctx, sampObj, (GLfloat) param);
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) param);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ res = set_sampler_compare_mode(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ res = set_sampler_compare_func(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) param);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ /* fall-through */
+ default:
+ res = INVALID_PNAME;
+ }
+
+ switch (res) {
+ case GL_FALSE:
+ /* no change */
+ break;
+ case GL_TRUE:
+ /* state change - we do nothing special at this time */
+ break;
+ case INVALID_PNAME:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(pname=%s)\n",
+ _mesa_lookup_enum_by_nr(pname));
+ break;
+ case INVALID_PARAM:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteri(param=%d)\n",
+ param);
+ break;
+ case INVALID_VALUE:
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(param=%d)\n",
+ param);
+ break;
+ default:
+ ;
+ }
+}
+
+
+static void GLAPIENTRY
+_mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+ struct gl_sampler_object *sampObj;
+ GLuint res;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ res = set_sampler_wrap_t(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_WRAP_R:
+ res = set_sampler_wrap_r(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ res = set_sampler_min_filter(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ res = set_sampler_mag_filter(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ res = set_sampler_min_lod(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ res = set_sampler_max_lod(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ res = set_sampler_lod_bias(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ res = set_sampler_compare_mode(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ res = set_sampler_compare_func(ctx, sampObj, (GLint) param);
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ res = set_sampler_max_anisotropy(ctx, sampObj, param);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ /* fall-through */
+ default:
+ res = INVALID_PNAME;
+ }
+
+ switch (res) {
+ case GL_FALSE:
+ /* no change */
+ break;
+ case GL_TRUE:
+ /* state change - we do nothing special at this time */
+ break;
+ case INVALID_PNAME:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(pname=%s)\n",
+ _mesa_lookup_enum_by_nr(pname));
+ break;
+ case INVALID_PARAM:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterf(param=%f)\n",
+ param);
+ break;
+ case INVALID_VALUE:
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterf(param=%f)\n",
+ param);
+ break;
+ default:
+ ;
+ }
+}
+
+static void GLAPIENTRY
+_mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
+{
+ struct gl_sampler_object *sampObj;
+ GLuint res;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ res = set_sampler_wrap_s(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ res = set_sampler_wrap_t(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_WRAP_R:
+ res = set_sampler_wrap_r(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ res = set_sampler_min_filter(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ res = set_sampler_mag_filter(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ res = set_sampler_compare_mode(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ res = set_sampler_compare_func(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ {
+ GLfloat c[4];
+ c[0] = INT_TO_FLOAT(params[0]);
+ c[1] = INT_TO_FLOAT(params[1]);
+ c[2] = INT_TO_FLOAT(params[2]);
+ c[3] = INT_TO_FLOAT(params[3]);
+ res = set_sampler_border_colorf(ctx, sampObj, c);
+ }
+ break;
+ default:
+ res = INVALID_PNAME;
+ }
+
+ switch (res) {
+ case GL_FALSE:
+ /* no change */
+ break;
+ case GL_TRUE:
+ /* state change - we do nothing special at this time */
+ break;
+ case INVALID_PNAME:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(pname=%s)\n",
+ _mesa_lookup_enum_by_nr(pname));
+ break;
+ case INVALID_PARAM:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameteriv(param=%d)\n",
+ params[0]);
+ break;
+ case INVALID_VALUE:
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(param=%d)\n",
+ params[0]);
+ break;
+ default:
+ ;
+ }
+}
+
+static void GLAPIENTRY
+_mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
+{
+ struct gl_sampler_object *sampObj;
+ GLuint res;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ res = set_sampler_wrap_t(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_WRAP_R:
+ res = set_sampler_wrap_r(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ res = set_sampler_min_filter(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ res = set_sampler_mag_filter(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ res = set_sampler_min_lod(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ res = set_sampler_max_lod(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ res = set_sampler_lod_bias(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ res = set_sampler_compare_mode(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ res = set_sampler_compare_func(ctx, sampObj, (GLint) params[0]);
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ res = set_sampler_max_anisotropy(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ res = set_sampler_border_colorf(ctx, sampObj, params);
+ break;
+ default:
+ res = INVALID_PNAME;
+ }
+
+ switch (res) {
+ case GL_FALSE:
+ /* no change */
+ break;
+ case GL_TRUE:
+ /* state change - we do nothing special at this time */
+ break;
+ case INVALID_PNAME:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(pname=%s)\n",
+ _mesa_lookup_enum_by_nr(pname));
+ break;
+ case INVALID_PARAM:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterfv(param=%f)\n",
+ params[0]);
+ break;
+ case INVALID_VALUE:
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterfv(param=%f)\n",
+ params[0]);
+ break;
+ default:
+ ;
+ }
+}
+
+static void GLAPIENTRY
+_mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
+{
+ struct gl_sampler_object *sampObj;
+ GLuint res;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ res = set_sampler_wrap_s(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ res = set_sampler_wrap_t(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_WRAP_R:
+ res = set_sampler_wrap_r(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ res = set_sampler_min_filter(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ res = set_sampler_mag_filter(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ res = set_sampler_compare_mode(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ res = set_sampler_compare_func(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ res = set_sampler_border_colori(ctx, sampObj, params);
+ break;
+ default:
+ res = INVALID_PNAME;
+ }
+
+ switch (res) {
+ case GL_FALSE:
+ /* no change */
+ break;
+ case GL_TRUE:
+ /* state change - we do nothing special at this time */
+ break;
+ case INVALID_PNAME:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(pname=%s)\n",
+ _mesa_lookup_enum_by_nr(pname));
+ break;
+ case INVALID_PARAM:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIiv(param=%d)\n",
+ params[0]);
+ break;
+ case INVALID_VALUE:
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(param=%d)\n",
+ params[0]);
+ break;
+ default:
+ ;
+ }
+}
+
+
+static void GLAPIENTRY
+_mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
+{
+ struct gl_sampler_object *sampObj;
+ GLuint res;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ res = set_sampler_wrap_s(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ res = set_sampler_wrap_t(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_WRAP_R:
+ res = set_sampler_wrap_r(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ res = set_sampler_min_filter(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ res = set_sampler_mag_filter(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ res = set_sampler_min_lod(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ res = set_sampler_max_lod(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ res = set_sampler_lod_bias(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ res = set_sampler_compare_mode(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ res = set_sampler_compare_func(ctx, sampObj, params[0]);
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ res = set_sampler_max_anisotropy(ctx, sampObj, (GLfloat) params[0]);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ res = set_sampler_border_colorui(ctx, sampObj, params);
+ break;
+ default:
+ res = INVALID_PNAME;
+ }
+
+ switch (res) {
+ case GL_FALSE:
+ /* no change */
+ break;
+ case GL_TRUE:
+ /* state change - we do nothing special at this time */
+ break;
+ case INVALID_PNAME:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(pname=%s)\n",
+ _mesa_lookup_enum_by_nr(pname));
+ break;
+ case INVALID_PARAM:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSamplerParameterIuiv(param=%u)\n",
+ params[0]);
+ break;
+ case INVALID_VALUE:
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(param=%u)\n",
+ params[0]);
+ break;
+ default:
+ ;
+ }
+}
+
+
+static void GLAPIENTRY
+_mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
+{
+ struct gl_sampler_object *sampObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ *params = sampObj->WrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = sampObj->WrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = sampObj->WrapR;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = sampObj->MinFilter;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = sampObj->MagFilter;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLint) sampObj->MinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLint) sampObj->MaxLod;
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ *params = (GLint) sampObj->LodBias;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = sampObj->CompareMode;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = sampObj->CompareFunc;
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = (GLint) sampObj->MaxAnisotropy;
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]);
+ params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]);
+ params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]);
+ params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]);
+ break;
+ default:
+ goto invalid_pname;
+ }
+ return;
+
+invalid_pname:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
+}
+
+
+static void GLAPIENTRY
+_mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+ struct gl_sampler_object *sampObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLfloat) sampObj->WrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLfloat) sampObj->WrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = (GLfloat) sampObj->WrapR;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLfloat) sampObj->MinFilter;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLfloat) sampObj->MagFilter;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = sampObj->MinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = sampObj->MaxLod;
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ *params = sampObj->LodBias;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = (GLfloat) sampObj->CompareMode;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = (GLfloat) sampObj->CompareFunc;
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = sampObj->MaxAnisotropy;
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = sampObj->BorderColor.f[0];
+ params[1] = sampObj->BorderColor.f[1];
+ params[2] = sampObj->BorderColor.f[2];
+ params[3] = sampObj->BorderColor.f[3];
+ break;
+ default:
+ goto invalid_pname;
+ }
+ return;
+
+invalid_pname:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterfv(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
+}
+
+
+static void GLAPIENTRY
+_mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params)
+{
+ struct gl_sampler_object *sampObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetSamplerParameterIiv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ *params = sampObj->WrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = sampObj->WrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = sampObj->WrapR;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = sampObj->MinFilter;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = sampObj->MagFilter;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLint) sampObj->MinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLint) sampObj->MaxLod;
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ *params = (GLint) sampObj->LodBias;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = sampObj->CompareMode;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = sampObj->CompareFunc;
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = (GLint) sampObj->MaxAnisotropy;
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = sampObj->BorderColor.i[0];
+ params[1] = sampObj->BorderColor.i[1];
+ params[2] = sampObj->BorderColor.i[2];
+ params[3] = sampObj->BorderColor.i[3];
+ break;
+ default:
+ goto invalid_pname;
+ }
+ return;
+
+invalid_pname:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIiv(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
+}
+
+
+static void GLAPIENTRY
+_mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params)
+{
+ struct gl_sampler_object *sampObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetSamplerParameterIuiv(sampler %u)",
+ sampler);
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WRAP_S:
+ *params = sampObj->WrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = sampObj->WrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = sampObj->WrapR;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = sampObj->MinFilter;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = sampObj->MagFilter;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLuint) sampObj->MinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLuint) sampObj->MaxLod;
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ *params = (GLuint) sampObj->LodBias;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = sampObj->CompareMode;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ctx->Extensions.ARB_shadow)
+ goto invalid_pname;
+ *params = sampObj->CompareFunc;
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = (GLuint) sampObj->MaxAnisotropy;
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = sampObj->BorderColor.ui[0];
+ params[1] = sampObj->BorderColor.ui[1];
+ params[2] = sampObj->BorderColor.ui[2];
+ params[3] = sampObj->BorderColor.ui[3];
+ break;
+ default:
+ goto invalid_pname;
+ }
+ return;
+
+invalid_pname:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameterIuiv(pname=%s)",
+ _mesa_lookup_enum_by_nr(pname));
+}
+
+
+void
+_mesa_init_sampler_object_functions(struct dd_function_table *driver)
+{
+ driver->NewSamplerObject = _mesa_new_sampler_object;
+ driver->DeleteSamplerObject = _mesa_delete_sampler_object;
+}
+
+
+void
+_mesa_init_sampler_object_dispatch(struct _glapi_table *disp)
+{
+ SET_GenSamplers(disp, _mesa_GenSamplers);
+ SET_DeleteSamplers(disp, _mesa_DeleteSamplers);
+ SET_IsSampler(disp, _mesa_IsSampler);
+ SET_BindSampler(disp, _mesa_BindSampler);
+ SET_SamplerParameteri(disp, _mesa_SamplerParameteri);
+ SET_SamplerParameterf(disp, _mesa_SamplerParameterf);
+ SET_SamplerParameteriv(disp, _mesa_SamplerParameteriv);
+ SET_SamplerParameterfv(disp, _mesa_SamplerParameterfv);
+ SET_SamplerParameterIiv(disp, _mesa_SamplerParameterIiv);
+ SET_SamplerParameterIuiv(disp, _mesa_SamplerParameterIuiv);
+ SET_GetSamplerParameteriv(disp, _mesa_GetSamplerParameteriv);
+ SET_GetSamplerParameterfv(disp, _mesa_GetSamplerParameterfv);
+ SET_GetSamplerParameterIiv(disp, _mesa_GetSamplerParameterIiv);
+ SET_GetSamplerParameterIuiv(disp, _mesa_GetSamplerParameterIuiv);
+}
diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c
index 8937e5a5f..a36083a37 100644
--- a/mesalib/src/mesa/main/shared.c
+++ b/mesalib/src/mesa/main/shared.c
@@ -27,8 +27,6 @@
* Shared-context state
*/
-
-
#include "imports.h"
#include "mfeatures.h"
#include "mtypes.h"
@@ -46,6 +44,7 @@
#include "shaderobj.h"
#include "syncobj.h"
+
/**
* Allocate and initialize a shared context state structure.
* Initializes the display list, texture objects and vertex programs hash
@@ -403,7 +402,8 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
* \sa free_shared_state().
*/
void
-_mesa_release_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
+_mesa_release_shared_state(struct gl_context *ctx,
+ struct gl_shared_state *shared)
{
GLint RefCount;
diff --git a/mesalib/src/mesa/main/shared.h b/mesalib/src/mesa/main/shared.h
index 870aadeb2..4e0ca2203 100644
--- a/mesalib/src/mesa/main/shared.h
+++ b/mesalib/src/mesa/main/shared.h
@@ -32,7 +32,8 @@ _mesa_alloc_shared_state(struct gl_context *ctx);
void
-_mesa_release_shared_state(struct gl_context *ctx, struct gl_shared_state *shared);
+_mesa_release_shared_state(struct gl_context *ctx,
+ struct gl_shared_state *shared);
#endif
diff --git a/mesalib/src/mesa/program/program_parse.y b/mesalib/src/mesa/program/program_parse.y
index e63a9f1e1..292cd5ac1 100644
--- a/mesalib/src/mesa/program/program_parse.y
+++ b/mesalib/src/mesa/program/program_parse.y
@@ -2064,6 +2064,34 @@ optResultFaceType:
? VERT_RESULT_COL0
: FRAG_RESULT_COLOR;
}
+ | '[' INTEGER ']'
+ {
+ if (state->mode == ARB_vertex) {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ } else {
+ if (!state->option.DrawBuffers) {
+ /* From the ARB_draw_buffers spec (same text exists
+ * for ATI_draw_buffers):
+ *
+ * If this option is not specified, a fragment
+ * program that attempts to bind
+ * "result.color[n]" will fail to load, and only
+ * "result.color" will be allowed.
+ */
+ yyerror(& @1, state,
+ "result.color[] used without "
+ "`OPTION ARB_draw_buffers' or "
+ "`OPTION ATI_draw_buffers'");
+ YYERROR;
+ } else if ($2 >= state->MaxDrawBuffers) {
+ yyerror(& @1, state,
+ "result.color[] exceeds MAX_DRAW_BUFFERS_ARB");
+ YYERROR;
+ }
+ $$ = FRAG_RESULT_DATA0 + $2;
+ }
+ }
| FRONT
{
if (state->mode == ARB_vertex) {
@@ -2681,6 +2709,7 @@ _mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *st
state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
state->MaxLights = ctx->Const.MaxLights;
state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+ state->MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
diff --git a/mesalib/src/mesa/program/program_parse_extra.c b/mesalib/src/mesa/program/program_parse_extra.c
index ae98b782b..67ab9b99d 100644
--- a/mesalib/src/mesa/program/program_parse_extra.c
+++ b/mesalib/src/mesa/program/program_parse_extra.c
@@ -1,255 +1,265 @@
-/*
- * Copyright © 2009 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.
- */
-
-#include <string.h>
-#include "main/mtypes.h"
-#include "prog_instruction.h"
-#include "program_parser.h"
-
-
-/**
- * Extra assembly-level parser routines
- *
- * \author Ian Romanick <ian.d.romanick@intel.com>
- */
-
-int
-_mesa_parse_instruction_suffix(const struct asm_parser_state *state,
- const char *suffix,
- struct prog_instruction *inst)
-{
- inst->CondUpdate = 0;
- inst->CondDst = 0;
- inst->SaturateMode = SATURATE_OFF;
- inst->Precision = FLOAT32;
-
-
- /* The first possible suffix element is the precision specifier from
- * NV_fragment_program_option.
- */
- if (state->option.NV_fragment) {
- switch (suffix[0]) {
- case 'H':
- inst->Precision = FLOAT16;
- suffix++;
- break;
- case 'R':
- inst->Precision = FLOAT32;
- suffix++;
- break;
- case 'X':
- inst->Precision = FIXED12;
- suffix++;
- break;
- default:
- break;
- }
- }
-
- /* The next possible suffix element is the condition code modifier selection
- * from NV_fragment_program_option.
- */
- if (state->option.NV_fragment) {
- if (suffix[0] == 'C') {
- inst->CondUpdate = 1;
- suffix++;
- }
- }
-
-
- /* The final possible suffix element is the saturation selector from
- * ARB_fragment_program.
- */
- if (state->mode == ARB_fragment) {
- if (strcmp(suffix, "_SAT") == 0) {
- inst->SaturateMode = SATURATE_ZERO_ONE;
- suffix += 4;
- }
- }
-
-
- /* It is an error for all of the suffix string not to be consumed.
- */
- return suffix[0] == '\0';
-}
-
-
-int
-_mesa_parse_cc(const char *s)
-{
- int cond = 0;
-
- switch (s[0]) {
- case 'E':
- if (s[1] == 'Q') {
- cond = COND_EQ;
- }
- break;
-
- case 'F':
- if (s[1] == 'L') {
- cond = COND_FL;
- }
- break;
-
- case 'G':
- if (s[1] == 'E') {
- cond = COND_GE;
- } else if (s[1] == 'T') {
- cond = COND_GT;
- }
- break;
-
- case 'L':
- if (s[1] == 'E') {
- cond = COND_LE;
- } else if (s[1] == 'T') {
- cond = COND_LT;
- }
- break;
-
- case 'N':
- if (s[1] == 'E') {
- cond = COND_NE;
- }
- break;
-
- case 'T':
- if (s[1] == 'R') {
- cond = COND_TR;
- }
- break;
-
- default:
- break;
- }
-
- return ((cond == 0) || (s[2] != '\0')) ? 0 : cond;
-}
-
-
-int
-_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
-{
- if (strcmp(option, "ARB_position_invariant") == 0) {
- state->option.PositionInvariant = 1;
- return 1;
- }
-
- return 0;
-}
-
-
-int
-_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
-{
- /* All of the options currently supported start with "ARB_". The code is
- * currently structured with nested if-statements because eventually options
- * that start with "NV_" will be supported. This structure will result in
- * less churn when those options are added.
- */
- if (strncmp(option, "ARB_", 4) == 0) {
- /* Advance the pointer past the "ARB_" prefix.
- */
- option += 4;
-
-
- if (strncmp(option, "fog_", 4) == 0) {
- option += 4;
-
- if (state->option.Fog == OPTION_NONE) {
- if (strcmp(option, "exp") == 0) {
- state->option.Fog = OPTION_FOG_EXP;
- return 1;
- } else if (strcmp(option, "exp2") == 0) {
- state->option.Fog = OPTION_FOG_EXP2;
- return 1;
- } else if (strcmp(option, "linear") == 0) {
- state->option.Fog = OPTION_FOG_LINEAR;
- return 1;
- }
- }
-
- return 0;
- } else if (strncmp(option, "precision_hint_", 15) == 0) {
- option += 15;
-
- if (state->option.PrecisionHint == OPTION_NONE) {
- if (strcmp(option, "nicest") == 0) {
- state->option.PrecisionHint = OPTION_NICEST;
- return 1;
- } else if (strcmp(option, "fastest") == 0) {
- state->option.PrecisionHint = OPTION_FASTEST;
- return 1;
- }
- }
-
- return 0;
- } else if (strcmp(option, "draw_buffers") == 0) {
- /* Don't need to check extension availability because all Mesa-based
- * drivers support GL_ARB_draw_buffers.
- */
- state->option.DrawBuffers = 1;
- return 1;
- } else if (strcmp(option, "fragment_program_shadow") == 0) {
- if (state->ctx->Extensions.ARB_fragment_program_shadow) {
- state->option.Shadow = 1;
- return 1;
- }
- } else if (strncmp(option, "fragment_coord_", 15) == 0) {
- option += 15;
- if (state->ctx->Extensions.ARB_fragment_coord_conventions) {
- if (strcmp(option, "origin_upper_left") == 0) {
- state->option.OriginUpperLeft = 1;
- return 1;
- }
- else if (strcmp(option, "pixel_center_integer") == 0) {
- state->option.PixelCenterInteger = 1;
- return 1;
- }
- }
- }
- } else if (strncmp(option, "NV_fragment_program", 19) == 0) {
- option += 19;
-
- /* Other NV_fragment_program strings may be supported later.
- */
- if (option[0] == '\0') {
- if (state->ctx->Extensions.NV_fragment_program_option) {
- state->option.NV_fragment = 1;
- return 1;
- }
- }
- } else if (strncmp(option, "MESA_", 5) == 0) {
- option += 5;
-
- if (strcmp(option, "texture_array") == 0) {
- if (state->ctx->Extensions.MESA_texture_array) {
- state->option.TexArray = 1;
- return 1;
- }
- }
- }
-
- return 0;
-}
+/*
+ * Copyright © 2009 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.
+ */
+
+#include <string.h>
+#include "main/mtypes.h"
+#include "prog_instruction.h"
+#include "program_parser.h"
+
+
+/**
+ * Extra assembly-level parser routines
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+int
+_mesa_parse_instruction_suffix(const struct asm_parser_state *state,
+ const char *suffix,
+ struct prog_instruction *inst)
+{
+ inst->CondUpdate = 0;
+ inst->CondDst = 0;
+ inst->SaturateMode = SATURATE_OFF;
+ inst->Precision = FLOAT32;
+
+
+ /* The first possible suffix element is the precision specifier from
+ * NV_fragment_program_option.
+ */
+ if (state->option.NV_fragment) {
+ switch (suffix[0]) {
+ case 'H':
+ inst->Precision = FLOAT16;
+ suffix++;
+ break;
+ case 'R':
+ inst->Precision = FLOAT32;
+ suffix++;
+ break;
+ case 'X':
+ inst->Precision = FIXED12;
+ suffix++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* The next possible suffix element is the condition code modifier selection
+ * from NV_fragment_program_option.
+ */
+ if (state->option.NV_fragment) {
+ if (suffix[0] == 'C') {
+ inst->CondUpdate = 1;
+ suffix++;
+ }
+ }
+
+
+ /* The final possible suffix element is the saturation selector from
+ * ARB_fragment_program.
+ */
+ if (state->mode == ARB_fragment) {
+ if (strcmp(suffix, "_SAT") == 0) {
+ inst->SaturateMode = SATURATE_ZERO_ONE;
+ suffix += 4;
+ }
+ }
+
+
+ /* It is an error for all of the suffix string not to be consumed.
+ */
+ return suffix[0] == '\0';
+}
+
+
+int
+_mesa_parse_cc(const char *s)
+{
+ int cond = 0;
+
+ switch (s[0]) {
+ case 'E':
+ if (s[1] == 'Q') {
+ cond = COND_EQ;
+ }
+ break;
+
+ case 'F':
+ if (s[1] == 'L') {
+ cond = COND_FL;
+ }
+ break;
+
+ case 'G':
+ if (s[1] == 'E') {
+ cond = COND_GE;
+ } else if (s[1] == 'T') {
+ cond = COND_GT;
+ }
+ break;
+
+ case 'L':
+ if (s[1] == 'E') {
+ cond = COND_LE;
+ } else if (s[1] == 'T') {
+ cond = COND_LT;
+ }
+ break;
+
+ case 'N':
+ if (s[1] == 'E') {
+ cond = COND_NE;
+ }
+ break;
+
+ case 'T':
+ if (s[1] == 'R') {
+ cond = COND_TR;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ((cond == 0) || (s[2] != '\0')) ? 0 : cond;
+}
+
+
+int
+_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
+{
+ if (strcmp(option, "ARB_position_invariant") == 0) {
+ state->option.PositionInvariant = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int
+_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
+{
+ /* All of the options currently supported start with "ARB_". The code is
+ * currently structured with nested if-statements because eventually options
+ * that start with "NV_" will be supported. This structure will result in
+ * less churn when those options are added.
+ */
+ if (strncmp(option, "ARB_", 4) == 0) {
+ /* Advance the pointer past the "ARB_" prefix.
+ */
+ option += 4;
+
+
+ if (strncmp(option, "fog_", 4) == 0) {
+ option += 4;
+
+ if (state->option.Fog == OPTION_NONE) {
+ if (strcmp(option, "exp") == 0) {
+ state->option.Fog = OPTION_FOG_EXP;
+ return 1;
+ } else if (strcmp(option, "exp2") == 0) {
+ state->option.Fog = OPTION_FOG_EXP2;
+ return 1;
+ } else if (strcmp(option, "linear") == 0) {
+ state->option.Fog = OPTION_FOG_LINEAR;
+ return 1;
+ }
+ }
+
+ return 0;
+ } else if (strncmp(option, "precision_hint_", 15) == 0) {
+ option += 15;
+
+ if (state->option.PrecisionHint == OPTION_NONE) {
+ if (strcmp(option, "nicest") == 0) {
+ state->option.PrecisionHint = OPTION_NICEST;
+ return 1;
+ } else if (strcmp(option, "fastest") == 0) {
+ state->option.PrecisionHint = OPTION_FASTEST;
+ return 1;
+ }
+ }
+
+ return 0;
+ } else if (strcmp(option, "draw_buffers") == 0) {
+ /* Don't need to check extension availability because all Mesa-based
+ * drivers support GL_ARB_draw_buffers.
+ */
+ state->option.DrawBuffers = 1;
+ return 1;
+ } else if (strcmp(option, "fragment_program_shadow") == 0) {
+ if (state->ctx->Extensions.ARB_fragment_program_shadow) {
+ state->option.Shadow = 1;
+ return 1;
+ }
+ } else if (strncmp(option, "fragment_coord_", 15) == 0) {
+ option += 15;
+ if (state->ctx->Extensions.ARB_fragment_coord_conventions) {
+ if (strcmp(option, "origin_upper_left") == 0) {
+ state->option.OriginUpperLeft = 1;
+ return 1;
+ }
+ else if (strcmp(option, "pixel_center_integer") == 0) {
+ state->option.PixelCenterInteger = 1;
+ return 1;
+ }
+ }
+ }
+ } else if (strncmp(option, "ATI_", 4) == 0) {
+ option += 4;
+
+ if (strcmp(option, "draw_buffers") == 0) {
+ /* Don't need to check extension availability because all Mesa-based
+ * drivers support GL_ATI_draw_buffers.
+ */
+ state->option.DrawBuffers = 1;
+ return 1;
+ }
+ } else if (strncmp(option, "NV_fragment_program", 19) == 0) {
+ option += 19;
+
+ /* Other NV_fragment_program strings may be supported later.
+ */
+ if (option[0] == '\0') {
+ if (state->ctx->Extensions.NV_fragment_program_option) {
+ state->option.NV_fragment = 1;
+ return 1;
+ }
+ }
+ } else if (strncmp(option, "MESA_", 5) == 0) {
+ option += 5;
+
+ if (strcmp(option, "texture_array") == 0) {
+ if (state->ctx->Extensions.MESA_texture_array) {
+ state->option.TexArray = 1;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/mesalib/src/mesa/program/program_parser.h b/mesalib/src/mesa/program/program_parser.h
index ff2f4f25f..cbbb2677d 100644
--- a/mesalib/src/mesa/program/program_parser.h
+++ b/mesalib/src/mesa/program/program_parser.h
@@ -173,6 +173,7 @@ struct asm_parser_state {
unsigned MaxClipPlanes;
unsigned MaxLights;
unsigned MaxProgramMatrices;
+ unsigned MaxDrawBuffers;
/*@}*/
/**
diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c
index 532e9b5a3..4277a24b0 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c
@@ -251,13 +251,15 @@ update_textures(struct st_context *st)
st->state.num_textures = su + 1;
/* if sampler view has changed dereference it */
- if (stObj->sampler_view)
+ if (stObj->sampler_view) {
if (check_sampler_swizzle(stObj->sampler_view,
stObj->base._Swizzle,
samp->DepthMode) ||
(st_view_format != stObj->sampler_view->format) ||
- stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level)
+ stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+ }
+ }
sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
samp,
@@ -269,10 +271,12 @@ update_textures(struct st_context *st)
cso_set_fragment_sampler_views(st->cso_context,
st->state.num_textures,
st->state.sampler_views);
+
if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
+ GLuint numUnits = MIN2(st->state.num_textures,
+ st->ctx->Const.MaxVertexTextureImageUnits);
cso_set_vertex_sampler_views(st->cso_context,
- MIN2(st->state.num_textures,
- st->ctx->Const.MaxVertexTextureImageUnits),
+ numUnits,
st->state.sampler_views);
}
}