NV30/NV40 CMP and SCS src == dst handling
[mesa.git] / src / gallium / drivers / i965 / brw_clip.c
index d82ebeb9a9b2507aad7082b924bb9e53df5a3311..d67a1a62633e03fcc7d5935202b73a63b85f49bb 100644 (file)
 
 #include "util/u_math.h"
 
-#include "intel_batchbuffer.h"
-
+#include "brw_screen.h"
+#include "brw_batchbuffer.h"
 #include "brw_defines.h"
 #include "brw_context.h"
 #include "brw_eu.h"
 #include "brw_util.h"
 #include "brw_state.h"
+#include "brw_pipe_rast.h"
 #include "brw_clip.h"
 
 
 #define BACK_UNFILLED_BIT   0x2
 
 
-static void compile_clip_prog( struct brw_context *brw,
-                            struct brw_clip_prog_key *key )
+static enum pipe_error
+compile_clip_prog( struct brw_context *brw,
+                   struct brw_clip_prog_key *key,
+                   struct brw_winsys_buffer **bo_out )
 {
+   enum pipe_error ret;
    struct brw_clip_compile c;
    const GLuint *program;
    GLuint program_size;
    GLuint delta;
-   GLuint i;
 
    memset(&c, 0, sizeof(c));
    
@@ -64,31 +67,41 @@ static void compile_clip_prog( struct brw_context *brw,
 
    c.func.single_program_flow = 1;
 
+   c.chipset = brw->chipset;
    c.key = *key;
-   c.need_ff_sync = BRW_IS_IGDNG(brw);
+   c.need_ff_sync = c.chipset.is_igdng;
 
    /* Need to locate the two positions present in vertex + header.
     * These are currently hardcoded:
     */
    c.header_position_offset = ATTR_SIZE;
 
-   if (BRW_IS_IGDNG(brw))
+   if (c.chipset.is_igdng)
        delta = 3 * REG_SIZE;
    else
        delta = REG_SIZE;
 
-   for (i = 0; i < VERT_RESULT_MAX; i++)
-      if (c.key.attrs & (1<<i)) {
-        c.offset[i] = delta;
-        delta += ATTR_SIZE;
-      }
+   c.offset_hpos = delta + c.key.output_hpos * ATTR_SIZE;
+
+   if (c.key.output_color0 != BRW_OUTPUT_NOT_PRESENT)
+      c.offset_color0 = delta + c.key.output_color0 * ATTR_SIZE;
+
+   if (c.key.output_color1 != BRW_OUTPUT_NOT_PRESENT)
+      c.offset_color1 = delta + c.key.output_color1 * ATTR_SIZE;
+
+   if (c.key.output_bfc0 != BRW_OUTPUT_NOT_PRESENT)
+      c.offset_bfc0 = delta + c.key.output_bfc0 * ATTR_SIZE;
 
-   c.nr_attrs = util_count_bits(c.key.attrs);
+   if (c.key.output_bfc1 != BRW_OUTPUT_NOT_PRESENT)
+      c.offset_bfc1 = delta + c.key.output_bfc1 * ATTR_SIZE;
+
+   if (c.key.output_edgeflag != BRW_OUTPUT_NOT_PRESENT)
+      c.offset_edgeflag = delta + c.key.output_edgeflag * ATTR_SIZE;
    
    if (BRW_IS_IGDNG(brw))
-       c.nr_regs = (c.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
+       c.nr_regs = (c.key.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
    else
-       c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
+       c.nr_regs = (c.key.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
 
    c.nr_bytes = c.nr_regs * REG_SIZE;
 
@@ -118,101 +131,92 @@ static void compile_clip_prog( struct brw_context *brw,
       break;
    default:
       assert(0);
-      return;
+      return PIPE_ERROR_BAD_INPUT;
    }
 
         
 
    /* get the program
     */
-   program = brw_get_program(&c.func, &program_size);
+   ret = brw_get_program(&c.func, &program, &program_size);
+   if (ret)
+      return ret;
 
    /* Upload
     */
-   brw->sws->bo_unreference(brw->clip.prog_bo);
-   brw->clip.prog_bo = brw_upload_cache( &brw->cache,
-                                        BRW_CLIP_PROG,
-                                        &c.key, sizeof(c.key),
-                                        NULL, 0,
-                                        program, program_size,
-                                        &c.prog_data,
-                                        &brw->clip.prog_data );
+   ret = brw_upload_cache( &brw->cache,
+                           BRW_CLIP_PROG,
+                           &c.key, sizeof(c.key),
+                           NULL, 0,
+                           program, program_size,
+                           &c.prog_data,
+                           &brw->clip.prog_data,
+                           bo_out );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 /* Calculate interpolants for triangle and line rasterization.
  */
-static void upload_clip_prog(struct brw_context *brw)
+static enum pipe_error
+upload_clip_prog(struct brw_context *brw)
 {
+   const struct brw_vertex_shader *vs = brw->curr.vertex_shader;
    struct brw_clip_prog_key key;
+   enum pipe_error ret;
 
-   memset(&key, 0, sizeof(key));
-
-   /* Populate the key:
+   /* Populate the key, starting from the almost-complete version from
+    * the rast state. 
     */
+
+   /* PIPE_NEW_RAST */
+   key = brw->curr.rast->clip_key;
+   
    /* BRW_NEW_REDUCED_PRIMITIVE */
    key.primitive = brw->reduced_primitive;
+
+   /* XXX: if edgeflag is moved to a proper TGSI vs output, can remove
+    * dependency on CACHE_NEW_VS_PROG
+    */
    /* CACHE_NEW_VS_PROG */
-   key.attrs = brw->vs.prog_data->outputs_written;
-   /* PIPE_NEW_RAST */
-   key.do_flat_shading = brw->rast.base.flatshade;
-   /* PIPE_NEW_UCP */
-   key.nr_userclip = brw->nr_ucp;
+   key.nr_attrs        = brw->vs.prog_data->nr_outputs;
 
-   if (BRW_IS_IGDNG(brw))
-       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
-   else
-       key.clip_mode = BRW_CLIPMODE_NORMAL;
+   /* PIPE_NEW_VS */
+   key.output_hpos     = vs->output_hpos;
+   key.output_color0   = vs->output_color0;
+   key.output_color1   = vs->output_color1;
+   key.output_bfc0     = vs->output_bfc0;
+   key.output_bfc1     = vs->output_bfc1;
+   key.output_edgeflag = vs->output_edgeflag;
 
-   /* PIPE_NEW_RAST */
-   if (key.primitive == PIPE_PRIM_TRIANGLES) {
-      if (brw->rast->cull_mode = PIPE_WINDING_BOTH)
-        key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
-      else {
-        key.fill_ccw = CLIP_CULL;
-        key.fill_cw = CLIP_CULL;
-
-        if (!(brw->rast->cull_mode & PIPE_WINDING_CCW)) {
-           key.fill_ccw = translate_fill(brw->rast.fill_ccw);
-        }
-
-        if (!(brw->rast->cull_mode & PIPE_WINDING_CW)) {
-           key.fill_cw = translate_fill(brw->rast.fill_cw);
-        }
-
-        if (key.fill_cw != CLIP_FILL ||
-            key.fill_ccw != CLIP_FILL) {
-           key.do_unfilled = 1;
-           key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
-        }
-
-        key.offset_ccw = brw->rast.offset_ccw;
-        key.offset_cw = brw->rast.offset_cw;
-
-        if (brw->rast.light_twoside &&
-            key.fill_cw != CLIP_CULL) 
-           key.copy_bfc_cw = 1;
-
-        if (brw->rast.light_twoside &&
-            key.fill_ccw != CLIP_CULL) 
-           key.copy_bfc_ccw = 1;
-        }
-      }
-   }
+   /* PIPE_NEW_CLIP */
+   key.nr_userclip = brw->curr.ucp.nr;
+
+   /* Already cached?
+    */
+   if (brw_search_cache(&brw->cache, BRW_CLIP_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->clip.prog_data,
+                        &brw->clip.prog_bo))
+      return PIPE_OK;
+
+   /* Compile new program:
+    */
+   ret = compile_clip_prog( brw, &key, &brw->clip.prog_bo );
+   if (ret)
+      return ret;
 
-   brw->sws->bo_unreference(brw->clip.prog_bo);
-   brw->clip.prog_bo = brw_search_cache(&brw->cache, BRW_CLIP_PROG,
-                                       &key, sizeof(key),
-                                       NULL, 0,
-                                       &brw->clip.prog_data);
-   if (brw->clip.prog_bo == NULL)
-      compile_clip_prog( brw, &key );
+   return PIPE_OK;
 }
 
 
 const struct brw_tracked_state brw_clip_prog = {
    .dirty = {
       .mesa  = (PIPE_NEW_RAST | 
-               PIPE_NEW_UCP),
+               PIPE_NEW_CLIP),
       .brw   = (BRW_NEW_REDUCED_PRIMITIVE),
       .cache = CACHE_NEW_VS_PROG
    },