include surface.offset in address calculations
[mesa.git] / src / mesa / pipe / softpipe / sp_state_derived.c
index dd8a490f3b5ba86a70ccb56e535529e3d749d483..e1faaed93ce759cef26962eb03b54b3b1a32d42a 100644 (file)
@@ -28,7 +28,6 @@
 #include "main/glheader.h"
 #include "main/macros.h"
 #include "main/enums.h"
-#include "shader/program.h"
 
 #include "vf/vf.h"
 #include "pipe/draw/draw_context.h"
 #include "sp_state.h"
 
 
-#define EMIT_ATTR( ATTR, FRAG_ATTR, INTERP )                   \
-do {                                                   \
-   slot_to_vf_attr[softpipe->nr_attrs] = ATTR; \
-   softpipe->vf_attr_to_slot[ATTR] = softpipe->nr_attrs;       \
+#define EMIT_ATTR( VF_ATTR, FRAG_ATTR, INTERP )                        \
+do {                                                           \
+   slot_to_vf_attr[softpipe->nr_attrs] = VF_ATTR;              \
+   softpipe->vf_attr_to_slot[VF_ATTR] = softpipe->nr_attrs;    \
    softpipe->fp_attr_to_slot[FRAG_ATTR] = softpipe->nr_attrs;  \
-   softpipe->interp[softpipe->nr_attrs] = INTERP;      \
-   softpipe->nr_attrs++;       \
-   attr_mask |= (1<<ATTR);     \
+   softpipe->interp[softpipe->nr_attrs] = INTERP;              \
+   softpipe->nr_attrs++;                                       \
+   attr_mask |= (1 << (VF_ATTR));                              \
 } while (0)
 
 
-static GLuint frag_to_vf[FRAG_ATTRIB_MAX] = 
+static const GLuint frag_to_vf[FRAG_ATTRIB_MAX] = 
 {
    VF_ATTRIB_POS,
    VF_ATTRIB_COLOR0,
@@ -61,19 +60,47 @@ static GLuint frag_to_vf[FRAG_ATTRIB_MAX] =
    VF_ATTRIB_TEX5,
    VF_ATTRIB_TEX6,
    VF_ATTRIB_TEX7,
+   VF_ATTRIB_VAR0,
+   VF_ATTRIB_VAR1,
+   VF_ATTRIB_VAR2,
+   VF_ATTRIB_VAR3,
+   VF_ATTRIB_VAR4,
+   VF_ATTRIB_VAR5,
+   VF_ATTRIB_VAR6,
+   VF_ATTRIB_VAR7,
 };
 
 
-/* Derived from:  fs, setup states.
+/**
+ * Determine which post-transform / pre-rasterization vertex attributes
+ * we need.
+ * Derived from:  fs, setup states.
  */
 static void calculate_vertex_layout( struct softpipe_context *softpipe )
 {
-   struct gl_fragment_program *fp = softpipe->fs.fp;
-   const GLuint inputsRead = fp->Base.InputsRead;
+   const GLbitfield inputsRead = softpipe->fs.inputs_read;
    GLuint slot_to_vf_attr[VF_ATTRIB_MAX];
-   GLuint attr_mask = 0;
+   GLbitfield attr_mask = 0x0;
    GLuint i;
 
+   /* Need Z if depth test is enabled or the fragment program uses the
+    * fragment position (XYZW).
+    */
+   if (softpipe->depth_test.enabled ||
+       (inputsRead & FRAG_ATTRIB_WPOS))
+      softpipe->need_z = GL_TRUE;
+   else
+      softpipe->need_z = GL_FALSE;
+
+   /* Need W if we do any perspective-corrected interpolation or the
+    * fragment program uses the fragment position.
+    */
+   if (inputsRead & FRAG_ATTRIB_WPOS)
+      softpipe->need_w = GL_TRUE;
+   else
+      softpipe->need_w = GL_FALSE;
+
+
    softpipe->nr_attrs = 0;
    memset(slot_to_vf_attr, 0, sizeof(slot_to_vf_attr));
 
@@ -89,14 +116,21 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe )
     * as fixed point or ubyte format.
     */
    for (i = 1; i < FRAG_ATTRIB_TEX0; i++) {
-      if (inputsRead & (i << i)) {
-        EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR);
+      if (inputsRead & (1 << i)) {
+         assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0]));
+         if (softpipe->setup.flatshade
+             && (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1))
+            EMIT_ATTR(frag_to_vf[i], i, INTERP_CONSTANT);
+         else
+            EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR);
       }
    }
 
    for (i = FRAG_ATTRIB_TEX0; i < FRAG_ATTRIB_MAX; i++) {
-      if (inputsRead & (i << i)) {
-        EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE);
+      if (inputsRead & (1 << i)) {
+         assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0]));
+         EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE);
+         softpipe->need_w = GL_TRUE;
       }
    }
 
@@ -116,6 +150,9 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe )
       }
    }
 
+   /* If the attributes have changed, tell the draw module (which in turn
+    * tells the vf module) about the new vertex layout.
+    */
    if (attr_mask != softpipe->attr_mask) {
       softpipe->attr_mask = attr_mask;
 
@@ -126,6 +163,41 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe )
 }
 
 
+/**
+ * Recompute cliprect from scissor bounds, scissor enable and surface size.
+ */
+static void
+compute_cliprect(struct softpipe_context *sp)
+{
+   GLint surfWidth, surfHeight;
+
+   if (sp->framebuffer.num_cbufs > 0) {
+      surfWidth = sp->framebuffer.cbufs[0]->width;
+      surfHeight = sp->framebuffer.cbufs[0]->height;
+   }
+   else {
+      /* no surface? */
+      surfWidth = sp->scissor.maxx;
+      surfHeight = sp->scissor.maxy;
+   }
+
+   if (sp->setup.scissor) {
+      /* clip to scissor rect */
+      sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
+      sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
+      sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
+      sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
+   }
+   else {
+      /* clip to surface bounds */
+      sp->cliprect.minx = 0;
+      sp->cliprect.miny = 0;
+      sp->cliprect.maxx = surfWidth;
+      sp->cliprect.maxy = surfHeight;
+   }
+}
+
+
 /* Hopefully this will remain quite simple, otherwise need to pull in
  * something like the state tracker mechanism.
  */
@@ -134,7 +206,18 @@ void softpipe_update_derived( struct softpipe_context *softpipe )
    if (softpipe->dirty & (SP_NEW_SETUP | SP_NEW_FS))
       calculate_vertex_layout( softpipe );
 
-   if (softpipe->dirty & (SP_NEW_BLEND | SP_NEW_DEPTH_TEST | SP_NEW_ALPHA_TEST | SP_NEW_FS))
+   if (softpipe->dirty & (SP_NEW_SCISSOR |
+                          SP_NEW_STENCIL |
+                          SP_NEW_FRAMEBUFFER))
+      compute_cliprect(softpipe);
+
+   if (softpipe->dirty & (SP_NEW_BLEND |
+                          SP_NEW_DEPTH_TEST |
+                          SP_NEW_ALPHA_TEST |
+                          SP_NEW_FRAMEBUFFER |
+                          SP_NEW_STENCIL |
+                          SP_NEW_SETUP |
+                          SP_NEW_FS))
       sp_build_quad_pipeline(softpipe);
 
    softpipe->dirty = 0;