/*
 * 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 lower_discard_flow.cpp
 *
 * Implements the GLSL 1.30 revision 9 rule for fragment shader
 * discard handling:
 *
 *     "Control flow exits the shader, and subsequent implicit or
 *      explicit derivatives are undefined when this control flow is
 *      non-uniform (meaning different fragments within the primitive
 *      take different control paths)."
 *
 * There seem to be two conflicting things here.  "Control flow exits
 * the shader" sounds like the discarded fragments should effectively
 * jump to the end of the shader, but that breaks derivatives in the
 * case of uniform control flow and causes rendering failure in the
 * bushes in Unigine Tropics.
 *
 * The question, then, is whether the intent was "loops stop at the
 * point that the only active channels left are discarded pixels" or
 * "discarded pixels become inactive at the point that control flow
 * returns to the top of a loop".  This implements the second
 * interpretation.
 */

#include "glsl_types.h"
#include "ir.h"
#include "program/hash_table.h"

class lower_discard_flow_visitor : public ir_hierarchical_visitor {
public:
   lower_discard_flow_visitor(ir_variable *discarded)
   : discarded(discarded)
   {
      mem_ctx = ralloc_parent(discarded);
   }

   ~lower_discard_flow_visitor()
   {
   }

   ir_visitor_status visit_enter(ir_discard *ir);
   ir_visitor_status visit_enter(ir_loop_jump *ir);
   ir_visitor_status visit_enter(ir_loop *ir);
   ir_visitor_status visit_enter(ir_function_signature *ir);

   ir_if *generate_discard_break();

   ir_variable *discarded;
   void *mem_ctx;
};

ir_visitor_status
lower_discard_flow_visitor::visit_enter(ir_loop_jump *ir)
{
   if (ir->mode != ir_loop_jump::jump_continue)
      return visit_continue;

   ir->insert_before(generate_discard_break());

   return visit_continue;
}

ir_visitor_status
lower_discard_flow_visitor::visit_enter(ir_discard *ir)
{
   ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded);
   ir_rvalue *rhs = new(mem_ctx) ir_constant(true);
   ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs);
   ir->insert_before(assign);

   return visit_continue;
}

ir_visitor_status
lower_discard_flow_visitor::visit_enter(ir_loop *ir)
{
   ir->body_instructions.push_tail(generate_discard_break());

   return visit_continue;
}

ir_visitor_status
lower_discard_flow_visitor::visit_enter(ir_function_signature *ir)
{
   if (strcmp(ir->function_name(), "main") != 0)
      return visit_continue;

   ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded);
   ir_rvalue *rhs = new(mem_ctx) ir_constant(false);
   ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs);
   ir->body.push_head(assign);

   return visit_continue;
}

ir_if *
lower_discard_flow_visitor::generate_discard_break()
{
   ir_rvalue *if_condition = new(mem_ctx) ir_dereference_variable(discarded);
   ir_if *if_inst = new(mem_ctx) ir_if(if_condition);

   ir_instruction *br = new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break);
   if_inst->then_instructions.push_tail(br);

   return if_inst;
}

void
lower_discard_flow(exec_list *ir)
{
   void *mem_ctx = ir;

   ir_variable *var = new(mem_ctx) ir_variable(glsl_type::bool_type,
					       "discarded",
					       ir_var_temporary);

   ir->push_head(var);

   lower_discard_flow_visitor v(var);

   visit_list_elements(&v, ir);
}
