/*
 Copyright (C) Intel Corp.  2006.  All Rights Reserved.
 Intel funded Tungsten Graphics to
 develop this 3D driver.

 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.

 **********************************************************************/
 /*
  * Authors:
  *   Keith Whitwell <keithw@vmware.com>
  */

#include "main/macros.h"
#include "main/enums.h"

#include "intel_batchbuffer.h"

#include "brw_defines.h"
#include "brw_context.h"
#include "brw_eu.h"
#include "brw_util.h"
#include "brw_state.h"
#include "brw_clip.h"

#include "util/ralloc.h"

#define FRONT_UNFILLED_BIT  0x1
#define BACK_UNFILLED_BIT   0x2


static void compile_clip_prog( struct brw_context *brw,
			     struct brw_clip_prog_key *key )
{
   struct brw_clip_compile c;
   const GLuint *program;
   void *mem_ctx;
   GLuint program_size;

   memset(&c, 0, sizeof(c));

   mem_ctx = ralloc_context(NULL);

   /* Begin the compilation:
    */
   brw_init_codegen(&brw->screen->devinfo, &c.func, mem_ctx);

   c.func.single_program_flow = 1;

   c.key = *key;
   c.vue_map = brw->vue_map_geom_out;

   /* nr_regs is the number of registers filled by reading data from the VUE.
    * This program accesses the entire VUE, so nr_regs needs to be the size of
    * the VUE (measured in pairs, since two slots are stored in each
    * register).
    */
   c.nr_regs = (c.vue_map.num_slots + 1)/2;

   c.prog_data.clip_mode = c.key.clip_mode; /* XXX */

   /* For some reason the thread is spawned with only 4 channels
    * unmasked.
    */
   brw_set_default_mask_control(&c.func, BRW_MASK_DISABLE);


   /* Would ideally have the option of producing a program which could
    * do all three:
    */
   switch (key->primitive) {
   case GL_TRIANGLES:
      if (key->do_unfilled)
	 brw_emit_unfilled_clip( &c );
      else
	 brw_emit_tri_clip( &c );
      break;
   case GL_LINES:
      brw_emit_line_clip( &c );
      break;
   case GL_POINTS:
      brw_emit_point_clip( &c );
      break;
   default:
      unreachable("not reached");
   }

   brw_compact_instructions(&c.func, 0, 0, NULL);

   /* get the program
    */
   program = brw_get_program(&c.func, &program_size);

   if (unlikely(INTEL_DEBUG & DEBUG_CLIP)) {
      fprintf(stderr, "clip:\n");
      brw_disassemble(&brw->screen->devinfo, c.func.store,
                      0, program_size, stderr);
      fprintf(stderr, "\n");
   }

   brw_upload_cache(&brw->cache,
		    BRW_CACHE_CLIP_PROG,
		    &c.key, sizeof(c.key),
		    program, program_size,
		    &c.prog_data, sizeof(c.prog_data),
		    &brw->clip.prog_offset, &brw->clip.prog_data);
   ralloc_free(mem_ctx);
}

/* Calculate interpolants for triangle and line rasterization.
 */
void
brw_upload_clip_prog(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   struct brw_clip_prog_key key;

   if (!brw_state_dirty(brw,
                        _NEW_BUFFERS |
                        _NEW_LIGHT |
                        _NEW_POLYGON |
                        _NEW_TRANSFORM,
                        BRW_NEW_BLORP |
                        BRW_NEW_FRAGMENT_PROGRAM |
                        BRW_NEW_REDUCED_PRIMITIVE |
                        BRW_NEW_VUE_MAP_GEOM_OUT))
      return;

   memset(&key, 0, sizeof(key));

   /* Populate the key:
    */

   const struct gl_program *fprog = brw->fragment_program;
   if (fprog) {
      assert(brw->gen < 6);
      struct gen4_fragment_program *p = (struct gen4_fragment_program *) fprog;

      /* BRW_NEW_FRAGMENT_PROGRAM */
      key.contains_flat_varying = p->contains_flat_varying;
      key.contains_noperspective_varying = p->contains_noperspective_varying;
      key.interp_mode = p->interp_mode;
   }

   /* BRW_NEW_REDUCED_PRIMITIVE */
   key.primitive = brw->reduced_primitive;
   /* BRW_NEW_VUE_MAP_GEOM_OUT */
   key.attrs = brw->vue_map_geom_out.slots_valid;

   /* _NEW_LIGHT */
   key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
   /* _NEW_TRANSFORM (also part of VUE map)*/
   if (ctx->Transform.ClipPlanesEnabled)
      key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;

   if (brw->gen == 5)
       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
   else
       key.clip_mode = BRW_CLIPMODE_NORMAL;

   /* _NEW_POLYGON */
   if (key.primitive == GL_TRIANGLES) {
      if (ctx->Polygon.CullFlag &&
	  ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
      else {
	 GLuint fill_front = CLIP_CULL;
	 GLuint fill_back = CLIP_CULL;
	 GLuint offset_front = 0;
	 GLuint offset_back = 0;

	 if (!ctx->Polygon.CullFlag ||
	     ctx->Polygon.CullFaceMode != GL_FRONT) {
	    switch (ctx->Polygon.FrontMode) {
	    case GL_FILL:
	       fill_front = CLIP_FILL;
	       offset_front = 0;
	       break;
	    case GL_LINE:
	       fill_front = CLIP_LINE;
	       offset_front = ctx->Polygon.OffsetLine;
	       break;
	    case GL_POINT:
	       fill_front = CLIP_POINT;
	       offset_front = ctx->Polygon.OffsetPoint;
	       break;
	    }
	 }

	 if (!ctx->Polygon.CullFlag ||
	     ctx->Polygon.CullFaceMode != GL_BACK) {
	    switch (ctx->Polygon.BackMode) {
	    case GL_FILL:
	       fill_back = CLIP_FILL;
	       offset_back = 0;
	       break;
	    case GL_LINE:
	       fill_back = CLIP_LINE;
	       offset_back = ctx->Polygon.OffsetLine;
	       break;
	    case GL_POINT:
	       fill_back = CLIP_POINT;
	       offset_back = ctx->Polygon.OffsetPoint;
	       break;
	    }
	 }

	 if (ctx->Polygon.BackMode != GL_FILL ||
	     ctx->Polygon.FrontMode != GL_FILL) {
	    key.do_unfilled = 1;

	    /* Most cases the fixed function units will handle.  Cases where
	     * one or more polygon faces are unfilled will require help:
	     */
	    key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;

	    if (offset_back || offset_front) {
	       /* _NEW_POLYGON, _NEW_BUFFERS */
	       key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2;
	       key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
	       key.offset_clamp = ctx->Polygon.OffsetClamp * ctx->DrawBuffer->_MRD;
	    }

	    if (!ctx->Polygon._FrontBit) {
	       key.fill_ccw = fill_front;
	       key.fill_cw = fill_back;
	       key.offset_ccw = offset_front;
	       key.offset_cw = offset_back;
	       if (ctx->Light.Model.TwoSide &&
		   key.fill_cw != CLIP_CULL)
		  key.copy_bfc_cw = 1;
	    } else {
	       key.fill_cw = fill_front;
	       key.fill_ccw = fill_back;
	       key.offset_cw = offset_front;
	       key.offset_ccw = offset_back;
	       if (ctx->Light.Model.TwoSide &&
		   key.fill_ccw != CLIP_CULL)
		  key.copy_bfc_ccw = 1;
	    }
	 }
      }
   }

   if (!brw_search_cache(&brw->cache, BRW_CACHE_CLIP_PROG,
			 &key, sizeof(key),
			 &brw->clip.prog_offset, &brw->clip.prog_data)) {
      compile_clip_prog( brw, &key );
   }
}
