summaryrefslogtreecommitdiff
path: root/src/glsl/ir.cpp
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-11-19 18:27:41 +0800
committerEric Anholt <eric@anholt.net>2010-11-19 19:09:18 -0800
commit02939d643f878ce3a3dcd2e7b2c6f035c64ecda7 (patch)
treef68a3826a9a8a3b68286303f48008200f2b49301 /src/glsl/ir.cpp
parent602ae2441aaca6a652d3fc78114bb60852132f98 (diff)
glsl: Add a helper function for determining if an rvalue could be a saturate.
Hardware pretty commonly has saturate modifiers on instructions, and this can be used in codegen to produce those, without everyone else needing to understand clamping other than min and max.
Diffstat (limited to 'src/glsl/ir.cpp')
-rw-r--r--src/glsl/ir.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 741e3cb177..2abb95394f 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1335,3 +1335,59 @@ reparent_ir(exec_list *list, void *mem_ctx)
visit_tree((ir_instruction *) node, steal_memory, mem_ctx);
}
}
+
+
+static ir_rvalue *
+try_min_one(ir_rvalue *ir)
+{
+ ir_expression *expr = ir->as_expression();
+
+ if (!expr || expr->operation != ir_binop_min)
+ return NULL;
+
+ if (expr->operands[0]->is_one())
+ return expr->operands[1];
+
+ if (expr->operands[1]->is_one())
+ return expr->operands[0];
+
+ return NULL;
+}
+
+static ir_rvalue *
+try_max_zero(ir_rvalue *ir)
+{
+ ir_expression *expr = ir->as_expression();
+
+ if (!expr || expr->operation != ir_binop_max)
+ return NULL;
+
+ if (expr->operands[0]->is_zero())
+ return expr->operands[1];
+
+ if (expr->operands[1]->is_zero())
+ return expr->operands[0];
+
+ return NULL;
+}
+
+ir_rvalue *
+ir_rvalue::as_rvalue_to_saturate()
+{
+ ir_expression *expr = this->as_expression();
+
+ if (!expr)
+ return NULL;
+
+ ir_rvalue *max_zero = try_max_zero(expr);
+ if (max_zero) {
+ return try_min_one(max_zero);
+ } else {
+ ir_rvalue *min_one = try_min_one(expr);
+ if (min_one) {
+ return try_max_zero(min_one);
+ }
+ }
+
+ return NULL;
+}