softpipe: fix seamless cube filtering
[mesa.git] / src / glsl / opt_algebraic.cpp
index 5a9881dbebe7d118d51d28933bc59cc79dd6c4e8..d706a6ad13c44092b5e5498e93f58b2ce6cbd2db 100644 (file)
@@ -84,6 +84,12 @@ is_vec_one(ir_constant *ir)
    return (ir == NULL) ? false : ir->is_one();
 }
 
+static inline bool
+is_vec_basis(ir_constant *ir)
+{
+   return (ir == NULL) ? false : ir->is_basis();
+}
+
 static void
 update_type(ir_expression *ir)
 {
@@ -180,12 +186,12 @@ ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
 ir_rvalue *
 ir_algebraic_visitor::handle_expression(ir_expression *ir)
 {
-   ir_constant *op_const[2] = {NULL, NULL};
-   ir_expression *op_expr[2] = {NULL, NULL};
+   ir_constant *op_const[4] = {NULL, NULL, NULL, NULL};
+   ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL};
    ir_expression *temp;
    unsigned int i;
 
-   assert(ir->get_num_operands() <= 2);
+   assert(ir->get_num_operands() <= 4);
    for (i = 0; i < ir->get_num_operands(); i++) {
       if (ir->operands[i]->type->is_matrix())
         return ir;
@@ -314,6 +320,24 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
         this->progress = true;
         return ir_constant::zero(mem_ctx, ir->type);
       }
+      if (is_vec_basis(op_const[0])) {
+        this->progress = true;
+        unsigned component = 0;
+        for (unsigned c = 0; c < op_const[0]->type->vector_elements; c++) {
+           if (op_const[0]->value.f[c] == 1.0)
+              component = c;
+        }
+        return new(mem_ctx) ir_swizzle(ir->operands[1], component, 0, 0, 0, 1);
+      }
+      if (is_vec_basis(op_const[1])) {
+        this->progress = true;
+        unsigned component = 0;
+        for (unsigned c = 0; c < op_const[1]->type->vector_elements; c++) {
+           if (op_const[1]->value.f[c] == 1.0)
+              component = c;
+        }
+        return new(mem_ctx) ir_swizzle(ir->operands[0], component, 0, 0, 0, 1);
+      }
       break;
 
    case ir_binop_logic_and:
@@ -391,6 +415,17 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
 
       break;
 
+   case ir_triop_lrp:
+      /* Operands are (x, y, a). */
+      if (is_vec_zero(op_const[2])) {
+         this->progress = true;
+         return swizzle_if_required(ir, ir->operands[0]);
+      } else if (is_vec_one(op_const[2])) {
+         this->progress = true;
+         return swizzle_if_required(ir, ir->operands[1]);
+      }
+      break;
+
    default:
       break;
    }