+ if (!ir->type->is_array())
+ return false;
+ if (ir->type->fields.array != glsl_type::float_type)
+ return false;
+
+ if (this->old_clip_distance_out_var) {
+ if (ir->variable_referenced() == this->old_clip_distance_out_var)
+ return true;
+ }
+ if (this->old_clip_distance_in_var) {
+ assert(this->shader_stage == MESA_SHADER_TESS_CTRL ||
+ this->shader_stage == MESA_SHADER_TESS_EVAL ||
+ this->shader_stage == MESA_SHADER_GEOMETRY ||
+ this->shader_stage == MESA_SHADER_FRAGMENT);
+
+ if (ir->variable_referenced() == this->old_clip_distance_in_var)
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * If the given ir satisfies is_clip_distance_vec8(), return new ir
+ * representing its lowered equivalent. That is, map:
+ *
+ * - gl_ClipDistance => gl_ClipDistanceMESA (if gl_ClipDistance is 1D)
+ * - gl_ClipDistance[i] => gl_ClipDistanceMESA[i] (if gl_ClipDistance is 2D)
+ *
+ * Otherwise return NULL.
+ */
+ir_rvalue *
+lower_clip_distance_visitor::lower_clip_distance_vec8(ir_rvalue *ir)
+{
+ if (!ir->type->is_array())
+ return NULL;
+ if (ir->type->fields.array != glsl_type::float_type)
+ return NULL;
+
+ ir_variable **new_var = NULL;
+ if (this->old_clip_distance_out_var) {
+ if (ir->variable_referenced() == this->old_clip_distance_out_var)
+ new_var = &this->new_clip_distance_out_var;
+ }
+ if (this->old_clip_distance_in_var) {
+ if (ir->variable_referenced() == this->old_clip_distance_in_var)
+ new_var = &this->new_clip_distance_in_var;
+ }
+ if (new_var == NULL)
+ return NULL;
+
+ if (ir->as_dereference_variable()) {
+ return new(ralloc_parent(ir)) ir_dereference_variable(*new_var);
+ } else {
+ ir_dereference_array *array_ref = ir->as_dereference_array();
+ assert(array_ref);
+ assert(array_ref->array->as_dereference_variable());
+
+ return new(ralloc_parent(ir))
+ ir_dereference_array(*new_var, array_ref->array_index);
+ }
+}
+
+
+void
+lower_clip_distance_visitor::handle_rvalue(ir_rvalue **rv)
+{
+ if (*rv == NULL)
+ return;
+
+ ir_dereference_array *const array_deref = (*rv)->as_dereference_array();
+ if (array_deref == NULL)
+ return;
+
+ /* Replace any expression that indexes one of the floats in gl_ClipDistance
+ * with an expression that indexes into one of the vec4's in
+ * gl_ClipDistanceMESA and accesses the appropriate component.
+ */
+ ir_rvalue *lowered_vec8 =
+ this->lower_clip_distance_vec8(array_deref->array);
+ if (lowered_vec8 != NULL) {