Squashed commit of the following:
[mesa.git] / src / gallium / drivers / i965 / brw_wm.c
index 764708f7df9d265dee366f3c8be5092d56a40888..5d66e61fbc1384e9ed9f62aad1ccb912b87957ef 100644 (file)
   * Authors:
   *   Keith Whitwell <keith@tungstengraphics.com>
   */
-             
+#include "tgsi/tgsi_info.h"
+
 #include "brw_context.h"
-#include "brw_util.h"
+#include "brw_screen.h"
 #include "brw_wm.h"
 #include "brw_state.h"
+#include "brw_debug.h"
+#include "brw_resource.h"
+#include "brw_pipe_rast.h"
 
 
 /** Return number of src args for given instruction */
@@ -52,9 +56,18 @@ GLuint brw_wm_nr_args( GLuint opcode )
    case WM_FB_WRITE:
    case WM_PINTERP:
       return 3;
+   case TGSI_OPCODE_TEX:
+   case TGSI_OPCODE_TXP:
+   case TGSI_OPCODE_TXB:
+   case TGSI_OPCODE_TXD:
+      /* sampler arg is held as a field in the instruction, not in an
+       * actual register:
+       */
+      return tgsi_get_opcode_info(opcode)->num_src - 1;
+
    default:
       assert(opcode < MAX_OPCODE);
-      return _mesa_num_inst_src_regs(opcode);
+      return tgsi_get_opcode_info(opcode)->num_src;
    }
 }
 
@@ -62,17 +75,17 @@ GLuint brw_wm_nr_args( GLuint opcode )
 GLuint brw_wm_is_scalar_result( GLuint opcode )
 {
    switch (opcode) {
-   case OPCODE_COS:
-   case OPCODE_EX2:
-   case OPCODE_LG2:
-   case OPCODE_POW:
-   case OPCODE_RCP:
-   case OPCODE_RSQ:
-   case OPCODE_SIN:
-   case OPCODE_DP3:
-   case OPCODE_DP4:
-   case OPCODE_DPH:
-   case OPCODE_DST:
+   case TGSI_OPCODE_COS:
+   case TGSI_OPCODE_EX2:
+   case TGSI_OPCODE_LG2:
+   case TGSI_OPCODE_POW:
+   case TGSI_OPCODE_RCP:
+   case TGSI_OPCODE_RSQ:
+   case TGSI_OPCODE_SIN:
+   case TGSI_OPCODE_DP3:
+   case TGSI_OPCODE_DP4:
+   case TGSI_OPCODE_DPH:
+   case TGSI_OPCODE_DST:
       return 1;
       
    default:
@@ -82,12 +95,12 @@ GLuint brw_wm_is_scalar_result( GLuint opcode )
 
 
 /**
- * Do GPU code generation for non-GLSL shader.  non-GLSL shaders have
- * no flow control instructions so we can more readily do SSA-style
- * optimizations.
+ * Do GPU code generation for shaders without flow control.  Shaders
+ * without flow control instructions can more readily be analysed for
+ * SSA-style optimizations.
  */
 static void
-brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
+brw_wm_linear_shader_emit(struct brw_context *brw, struct brw_wm_compile *c)
 {
    /* Augment fragment program.  Add instructions for pre- and
     * post-fragment-program tasks such as interpolation and fogging.
@@ -133,65 +146,67 @@ brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
  * Depending on the instructions used (i.e. flow control instructions)
  * we'll use one of two code generators.
  */
-static void do_wm_prog( struct brw_context *brw,
-                       struct brw_fragment_program *fp, 
-                       struct brw_wm_prog_key *key)
+static enum pipe_error do_wm_prog( struct brw_context *brw,
+                                   struct brw_fragment_shader *fp, 
+                                   struct brw_wm_prog_key *key,
+                                   struct brw_winsys_buffer **bo_out)
 {
+   enum pipe_error ret;
    struct brw_wm_compile *c;
    const GLuint *program;
    GLuint program_size;
 
-   c = brw->wm.compile_data;
-   if (c == NULL) {
-      brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
-      c = brw->wm.compile_data;
-      if (c == NULL) {
-         /* Ouch - big out of memory problem.  Can't continue
-          * without triggering a segfault, no way to signal,
-          * so just return.
-          */
-         return;
-      }
-   } else {
-      memset(c, 0, sizeof(*brw->wm.compile_data));
+   if (brw->wm.compile_data == NULL) {
+      brw->wm.compile_data = MALLOC(sizeof(*brw->wm.compile_data));
+      if (!brw->wm.compile_data) 
+         return PIPE_ERROR_OUT_OF_MEMORY;
    }
-   memcpy(&c->key, key, sizeof(*key));
 
+   c = brw->wm.compile_data;
+   memset(c, 0, sizeof *c);
+
+   c->key = *key;
    c->fp = fp;
    c->env_param = NULL; /*brw->intel.ctx.FragmentProgram.Parameters;*/
 
    brw_init_compile(brw, &c->func);
 
-   /* temporary sanity check assertion */
-   ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program));
-
    /*
     * Shader which use GLSL features such as flow control are handled
     * differently from "simple" shaders.
     */
-   if (fp->isGLSL) {
+   if (fp->has_flow_control) {
       c->dispatch_width = 8;
-      brw_wm_glsl_emit(brw, c);
+      /* XXX: GLSL support
+       */
+      exit(1);
+      /* brw_wm_branching_shader_emit(brw, c); */
    }
    else {
       c->dispatch_width = 16;
-      brw_wm_non_glsl_emit(brw, c);
+      brw_wm_linear_shader_emit(brw, c);
    }
 
-   if (INTEL_DEBUG & DEBUG_WM)
-      fprintf(stderr, "\n");
+   if (BRW_DEBUG & DEBUG_WM)
+      debug_printf("\n");
 
    /* get the program
     */
-   program = brw_get_program(&c->func, &program_size);
-
-   brw->sws->bo_unreference(brw->wm.prog_bo);
-   brw->wm.prog_bo = brw_upload_cache( &brw->cache, BRW_WM_PROG,
-                                      &c->key, sizeof(c->key),
-                                      NULL, 0,
-                                      program, program_size,
-                                      &c->prog_data,
-                                      &brw->wm.prog_data );
+   ret = brw_get_program(&c->func, &program, &program_size);
+   if (ret)
+      return ret;
+
+   ret = brw_upload_cache( &brw->cache, BRW_WM_PROG,
+                           &c->key, sizeof(c->key),
+                           NULL, 0,
+                           program, program_size,
+                           &c->prog_data,
+                           &brw->wm.prog_data,
+                           bo_out );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
@@ -199,157 +214,103 @@ static void do_wm_prog( struct brw_context *brw,
 static void brw_wm_populate_key( struct brw_context *brw,
                                 struct brw_wm_prog_key *key )
 {
-   /* BRW_NEW_FRAGMENT_PROGRAM */
-   const struct brw_fragment_program *fp = 
-      (struct brw_fragment_program *)brw->fragment_program;
-   GLboolean uses_depth = (fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0;
-   GLuint lookup = 0;
-   GLuint line_aa;
-   GLuint i;
+   unsigned lookup, line_aa;
+   unsigned i;
 
    memset(key, 0, sizeof(*key));
 
-   /* Build the index for table lookup
+   /* PIPE_NEW_FRAGMENT_SHADER
+    * PIPE_NEW_DEPTH_STENCIL_ALPHA
     */
-   /* _NEW_COLOR */
-   if (fp->program.UsesKill ||
-       ctx->Color.AlphaEnabled)
-      lookup |= IZ_PS_KILL_ALPHATEST_BIT;
-
-   if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPTH))
-      lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
-
-   /* _NEW_DEPTH */
-   if (ctx->Depth.Test)
-      lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
-
-   if (ctx->Depth.Test &&  
-       ctx->Depth.Mask) /* ?? */
-      lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
-
-   /* _NEW_STENCIL */
-   if (ctx->Stencil._Enabled) {
-      lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
+   lookup = (brw->curr.zstencil->iz_lookup |
+            brw->curr.fragment_shader->iz_lookup);
 
-      if (ctx->Stencil.WriteMask[0] ||
-         ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
-        lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
-   }
 
-   line_aa = AA_NEVER;
-
-   /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
-   if (ctx->Line.SmoothFlag) {
-      if (brw->intel.reduced_primitive == GL_LINES) {
-        line_aa = AA_ALWAYS;
-      }
-      else if (brw->intel.reduced_primitive == GL_TRIANGLES) {
-        if (ctx->Polygon.FrontMode == GL_LINE) {
-           line_aa = AA_SOMETIMES;
-
-           if (ctx->Polygon.BackMode == GL_LINE ||
-               (ctx->Polygon.CullFlag &&
-                ctx->Polygon.CullFaceMode == GL_BACK))
-              line_aa = AA_ALWAYS;
-        }
-        else if (ctx->Polygon.BackMode == GL_LINE) {
-           line_aa = AA_SOMETIMES;
-
-           if ((ctx->Polygon.CullFlag &&
-                ctx->Polygon.CullFaceMode == GL_FRONT))
-              line_aa = AA_ALWAYS;
-        }
-      }
+   /* PIPE_NEW_RAST
+    * BRW_NEW_REDUCED_PRIMITIVE 
+    */
+   switch (brw->reduced_primitive) {
+   case PIPE_PRIM_POINTS:
+      line_aa = AA_NEVER;
+      break;
+   case PIPE_PRIM_LINES:
+      line_aa = (brw->curr.rast->templ.line_smooth ? 
+                 AA_ALWAYS : AA_NEVER);
+      break;
+   default:
+      line_aa = brw->curr.rast->unfilled_aa_line;
+      break;
    }
         
    brw_wm_lookup_iz(line_aa,
                    lookup,
-                   uses_depth,
+                   brw->curr.fragment_shader->uses_depth,
                    key);
 
-   /* Revisit this, figure out if it's really useful, and either push
-    * it into the state tracker so that everyone benefits (use to
-    * create fs varients with TEX rather than TXP), or discard.
-    */
-   key->proj_attrib_mask = ~0; /*brw->wm.input_size_masks[4-1];*/
-
    /* PIPE_NEW_RAST */
-   key->flat_shade = brw->rast.flat_shade;
+   key->flat_shade = brw->curr.rast->templ.flatshade;
 
-   /* This can be determined by looking at the INTERP mode each input decl.
-    */
-   key->linear_color = 0;
-
-   /* _NEW_TEXTURE */
-   for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
-      if (i < brw->nr_textures) {
-        const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
-        const struct gl_texture_object *t = unit->_Current;
-        const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
-        
-        if (img->InternalFormat == GL_YCBCR_MESA) {
-           key->yuvtex_mask |= 1 << i;
-           if (img->TexFormat->MesaFormat == MESA_FORMAT_YCBCR)
-              key->yuvtex_swap_mask |= 1 << i;
-        }
 
-        key->tex_swizzles[i] = t->_Swizzle;
+   /* PIPE_NEW_BOUND_TEXTURES */
+   for (i = 0; i < brw->curr.num_fragment_sampler_views; i++) {
+      const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture);
         
-        if (0)
-           key->shadowtex_mask |= 1<<i;
-      }
-      else {
-         key->tex_swizzles[i] = SWIZZLE_NOOP;
-      }
-   }
+      if (tex->b.b.format == PIPE_FORMAT_UYVY)
+        key->yuvtex_mask |= 1 << i;
 
+      if (tex->b.b.format == PIPE_FORMAT_YUYV)
+        key->yuvtex_swap_mask |= 1 << i;
 
-   /* _NEW_FRAMEBUFFER */
-   if (brw->intel.driDrawable != NULL) {
-      key->drawable_height = brw->fb.cbufs[0].height;
+      /* XXX: shadow texture
+       */
+      /* key->shadowtex_mask |= 1<<i; */
    }
 
    /* CACHE_NEW_VS_PROG */
-   key->vp_nr_outputs_written = brw->vs.prog_data->nr_outputs_written;
+   key->vp_nr_outputs = brw->vs.prog_data->nr_outputs;
+
+   key->nr_cbufs = brw->curr.fb.nr_cbufs;
+
+   key->nr_inputs = brw->curr.fragment_shader->info.num_inputs;
 
    /* The unique fragment program ID */
-   key->program_string_id = fp->id;
+   key->program_string_id = brw->curr.fragment_shader->id;
 }
 
 
-static void brw_prepare_wm_prog(struct brw_context *brw)
+static enum pipe_error brw_prepare_wm_prog(struct brw_context *brw)
 {
    struct brw_wm_prog_key key;
-   struct brw_fragment_program *fp = (struct brw_fragment_program *)
-      brw->fragment_program;
+   struct brw_fragment_shader *fs = brw->curr.fragment_shader;
+   enum pipe_error ret;
      
    brw_wm_populate_key(brw, &key);
 
    /* Make an early check for the key.
     */
-   brw->sws->bo_unreference(brw->wm.prog_bo);
-   brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG,
-                                     &key, sizeof(key),
-                                     NULL, 0,
-                                     &brw->wm.prog_data);
-   if (brw->wm.prog_bo == NULL)
-      do_wm_prog(brw, fp, &key);
+   if (brw_search_cache(&brw->cache, BRW_WM_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->wm.prog_data,
+                        &brw->wm.prog_bo))
+      return PIPE_OK;
+
+   ret = do_wm_prog(brw, fs, &key, &brw->wm.prog_bo);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
 const struct brw_tracked_state brw_wm_prog = {
    .dirty = {
-      .mesa  = (_NEW_COLOR |
-               _NEW_DEPTH |
-                _NEW_HINT |
-               _NEW_STENCIL |
-               _NEW_POLYGON |
-               _NEW_LINE |
-               _NEW_LIGHT |
-               _NEW_BUFFERS |
-               _NEW_TEXTURE),
-      .brw   = (BRW_NEW_FRAGMENT_PROGRAM |
-               BRW_NEW_WM_INPUT_DIMENSIONS |
+      .mesa  = (PIPE_NEW_FRAGMENT_SHADER |
+               PIPE_NEW_DEPTH_STENCIL_ALPHA |
+               PIPE_NEW_RAST |
+               PIPE_NEW_NR_CBUFS |
+               PIPE_NEW_BOUND_TEXTURES),
+      .brw   = (BRW_NEW_WM_INPUT_DIMENSIONS |
                BRW_NEW_REDUCED_PRIMITIVE),
       .cache = CACHE_NEW_VS_PROG,
    },