r300g: better describe another flush and move it closer to the real problem
[mesa.git] / src / gallium / drivers / r300 / r300_state.c
index 399099785c68cd5e5f3ab2a471a4f0ca752c1242..cfec8ac2b7ea587c8a29a7c504baf1aee94ffc7d 100644 (file)
@@ -395,15 +395,22 @@ static void r300_set_clip_state(struct pipe_context* pipe,
     if (r300->screen->caps.has_tcl) {
         memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
         r300->clip_state.size = 29;
+
+        r300->clip_state.dirty = TRUE;
     } else {
         draw_flush(r300->draw);
         draw_set_clip_state(r300->draw, state);
         r300->clip_state.size = 2;
     }
+}
 
-    r300->clip_state.dirty = TRUE;
+static void
+r300_set_sample_mask(struct pipe_context *pipe,
+                     unsigned sample_mask)
+{
 }
 
+
 /* Create a new depth, stencil, and alpha state based on the CSO dsa state.
  *
  * This contains the depth buffer, stencil buffer, alpha test, and such.
@@ -467,7 +474,7 @@ static void*
             if (caps->is_r500) {
                 dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK;
             } else {
-                dsa->stencil_ref_bf_fallback =
+                dsa->two_sided_stencil_ref =
                   (state->stencil[0].valuemask != state->stencil[1].valuemask ||
                    state->stencil[0].writemask != state->stencil[1].writemask);
             }
@@ -490,20 +497,6 @@ static void*
     return (void*)dsa;
 }
 
-static void r300_update_stencil_ref_fallback_status(struct r300_context *r300)
-{
-    struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
-
-    if (r300->screen->caps.is_r500) {
-        return;
-    }
-
-    r300->stencil_ref_bf_fallback =
-        dsa->stencil_ref_bf_fallback ||
-        (dsa->two_sided &&
-         r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]);
-}
-
 /* Bind DSA state. */
 static void r300_bind_dsa_state(struct pipe_context* pipe,
                                 void* state)
@@ -515,8 +508,6 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
     }
 
     UPDATE_STATE(state, r300->dsa_state);
-
-    r300_update_stencil_ref_fallback_status(r300);
 }
 
 /* Free DSA state. */
@@ -533,8 +524,6 @@ static void r300_set_stencil_ref(struct pipe_context* pipe,
 
     r300->stencil_ref = *sr;
     r300->dsa_state.dirty = TRUE;
-
-    r300_update_stencil_ref_fallback_status(r300);
 }
 
 /* This switcheroo is needed just because of goddamned MACRO_SWITCH. */
@@ -551,28 +540,50 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300,
         level = new_state->cbufs[i]->level;
 
         r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
-                                        tex->pitch[0],
-                                        tex->microtile,
-                                        tex->mip_macrotile[level]);
+                tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
+                tex->microtile,
+                tex->mip_macrotile[level]);
     }
     if (new_state->zsbuf) {
         tex = r300_texture(new_state->zsbuf->texture);
         level = new_state->zsbuf->level;
 
         r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
-                                        tex->pitch[0],
-                                        tex->microtile,
-                                        tex->mip_macrotile[level]);
+                tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
+                tex->microtile,
+                tex->mip_macrotile[level]);
     }
 }
 
+static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
+                                    const char *binding)
+{
+    struct pipe_resource *tex = surf->texture;
+    struct r300_texture *rtex = r300_texture(tex);
+
+    fprintf(stderr,
+            "r300:   %s[%i] Dim: %ix%i, Offset: %i, ZSlice: %i, "
+            "Face: %i, Level: %i, Format: %s\n"
+
+            "r300:     TEX: Macro: %s, Micro: %s, Pitch: %i, "
+            "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
+
+            binding, index, surf->width, surf->height, surf->offset,
+            surf->zslice, surf->face, surf->level,
+            util_format_short_name(surf->format),
+
+            rtex->macrotile ? "YES" : " NO", rtex->microtile ? "YES" : " NO",
+            rtex->hwpitch[0], tex->width0, tex->height0, tex->depth0,
+            tex->last_level, util_format_short_name(tex->format));
+}
+
 static void
     r300_set_framebuffer_state(struct pipe_context* pipe,
                                const struct pipe_framebuffer_state* state)
 {
     struct r300_context* r300 = r300_context(pipe);
     struct pipe_framebuffer_state *old_state = r300->fb_state.state;
-    unsigned max_width, max_height;
+    unsigned max_width, max_height, i;
     uint32_t zbuffer_bpp = 0;
 
     if (state->nr_cbufs > 4) {
@@ -634,6 +645,16 @@ static void
             r300->rs_state.dirty = TRUE;
         }
     }
+
+    if (DBG_ON(r300, DBG_FB)) {
+        fprintf(stderr, "r300: set_framebuffer_state:\n");
+        for (i = 0; i < state->nr_cbufs; i++) {
+            r300_print_fb_surf_info(state->cbufs[i], i, "CB");
+        }
+        if (state->zsbuf) {
+            r300_print_fb_surf_info(state->zsbuf, 0, "ZB");
+        }
+    }
 }
 
 /* Create fragment shader state. */
@@ -724,8 +745,12 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     int i;
     float psiz;
 
-    /* Copy rasterizer state for Draw. */
+    /* Copy rasterizer state. */
     rs->rs = *state;
+    rs->rs_draw = *state;
+
+    /* Override some states for Draw. */
+    rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */
 
 #ifdef PIPE_ARCH_LITTLE_ENDIAN
     rs->vap_control_status = R300_VC_NO_SWAP;
@@ -765,53 +790,37 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
         R300_GA_LINE_CNTL_END_TYPE_COMP;
 
     /* Enable polygon mode */
-    if (state->fill_cw != PIPE_POLYGON_MODE_FILL ||
-        state->fill_ccw != PIPE_POLYGON_MODE_FILL) {
+    if (state->fill_front != PIPE_POLYGON_MODE_FILL ||
+        state->fill_back != PIPE_POLYGON_MODE_FILL) {
         rs->polygon_mode = R300_GA_POLY_MODE_DUAL;
     }
 
-    /* Radeons don't think in "CW/CCW", they think in "front/back". */
-    if (state->front_winding == PIPE_WINDING_CW) {
-        rs->cull_mode = R300_FRONT_FACE_CW;
-
-        /* Polygon offset */
-        if (state->offset_cw) {
-            rs->polygon_offset_enable |= R300_FRONT_ENABLE;
-        }
-        if (state->offset_ccw) {
-            rs->polygon_offset_enable |= R300_BACK_ENABLE;
-        }
-
-        /* Polygon mode */
-        if (rs->polygon_mode) {
-            rs->polygon_mode |=
-                r300_translate_polygon_mode_front(state->fill_cw);
-            rs->polygon_mode |=
-                r300_translate_polygon_mode_back(state->fill_ccw);
-        }
-    } else {
+    /* Front face */
+    if (state->front_ccw) 
         rs->cull_mode = R300_FRONT_FACE_CCW;
+    else
+        rs->cull_mode = R300_FRONT_FACE_CW;
 
-        /* Polygon offset */
-        if (state->offset_ccw) {
-            rs->polygon_offset_enable |= R300_FRONT_ENABLE;
-        }
-        if (state->offset_cw) {
-            rs->polygon_offset_enable |= R300_BACK_ENABLE;
-        }
+    /* Polygon offset */
+    if (util_get_offset(state, state->fill_front)) {
+       rs->polygon_offset_enable |= R300_FRONT_ENABLE;
+    }
+    if (util_get_offset(state, state->fill_back)) {
+       rs->polygon_offset_enable |= R300_BACK_ENABLE;
+    }
 
-        /* Polygon mode */
-        if (rs->polygon_mode) {
-            rs->polygon_mode |=
-                r300_translate_polygon_mode_front(state->fill_ccw);
-            rs->polygon_mode |=
-                r300_translate_polygon_mode_back(state->fill_cw);
-        }
+    /* Polygon mode */
+    if (rs->polygon_mode) {
+       rs->polygon_mode |=
+          r300_translate_polygon_mode_front(state->fill_front);
+       rs->polygon_mode |=
+          r300_translate_polygon_mode_back(state->fill_back);
     }
-    if (state->front_winding & state->cull_mode) {
+
+    if (state->cull_face & PIPE_FACE_FRONT) {
         rs->cull_mode |= R300_CULL_FRONT;
     }
-    if (~(state->front_winding) & state->cull_mode) {
+    if (state->cull_face & PIPE_FACE_BACK) {
         rs->cull_mode |= R300_CULL_BACK;
     }
 
@@ -872,13 +881,15 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
     int last_sprite_coord_enable = r300->sprite_coord_enable;
     boolean last_two_sided_color = r300->two_sided_color;
 
-    if (r300->draw) {
+    if (r300->draw && rs) {
         draw_flush(r300->draw);
-        draw_set_rasterizer_state(r300->draw, &rs->rs, state);
+        draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state);
     }
 
     if (rs) {
-        r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
+        r300->polygon_offset_enabled = (rs->rs.offset_point ||
+                                        rs->rs.offset_line ||
+                                        rs->rs.offset_tri);
         r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
         r300->two_sided_color = rs->rs.light_twoside;
     } else {
@@ -1098,6 +1109,13 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
 
     r300->viewport = *state;
 
+    if (r300->draw) {
+        draw_flush(r300->draw);
+        draw_set_viewport_state(r300->draw, state);
+        viewport->vte_control = R300_VTX_XY_FMT | R300_VTX_Z_FMT;
+        return;
+    }
+
     /* Do the transform in HW. */
     viewport->vte_control = R300_VTX_W0_FMT;
 
@@ -1147,48 +1165,61 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
         return;
     }
 
-    /* Check if the stride is aligned to the size of DWORD. */
-    for (i = 0; i < count; i++) {
-        if (buffers[i].buffer) {
-            if (buffers[i].stride % 4 != 0) {
-                // XXX Shouldn't we align the buffer?
-                fprintf(stderr, "r300: set_vertex_buffers: "
-                        "Unaligned buffer stride %i isn't supported.\n",
-                        buffers[i].stride);
-                abort();
+    if (r300->screen->caps.has_tcl) {
+        /* HW TCL. */
+        /* Check if the stride is aligned to the size of DWORD. */
+        for (i = 0; i < count; i++) {
+            if (buffers[i].buffer) {
+                if (buffers[i].stride % 4 != 0) {
+                    // XXX Shouldn't we align the buffer?
+                    fprintf(stderr, "r300: set_vertex_buffers: "
+                            "Unaligned buffer stride %i isn't supported.\n",
+                            buffers[i].stride);
+                    abort();
+                }
             }
         }
-    }
 
-    for (i = 0; i < count; i++) {
-        /* Why, yes, I AM casting away constness. How did you know? */
-        vbo = (struct pipe_vertex_buffer*)&buffers[i];
+        for (i = 0; i < count; i++) {
+            /* Why, yes, I AM casting away constness. How did you know? */
+            vbo = (struct pipe_vertex_buffer*)&buffers[i];
 
-        /* Reference our buffer. */
-        pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer);
+            /* Skip NULL buffers */
+            if (!buffers[i].buffer) {
+                continue;
+            }
 
-        /* Skip NULL buffers */
-        if (!buffers[i].buffer) {
-            continue;
-        }
+            if (r300_buffer_is_user_buffer(vbo->buffer)) {
+                any_user_buffer = TRUE;
+            }
 
-        if (r300_buffer_is_user_buffer(vbo->buffer)) {
-            any_user_buffer = TRUE;
-        }
+            if (vbo->max_index == ~0) {
+                /* if no VBO stride then only one vertex value so max index is 1 */
+                /* should think about converting to VS constants like svga does */
+                if (!vbo->stride)
+                    vbo->max_index = 1;
+                else
+                    vbo->max_index =
+                             (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
+            }
 
-        if (vbo->max_index == ~0) {
-           /* if no VBO stride then only one vertex value so max index is 1 */
-           /* should think about converting to VS constants like svga does */
-           if (!vbo->stride)
-               vbo->max_index = 1;
-           else
-               vbo->max_index =
-                                (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
+            max_index = MIN2(vbo->max_index, max_index);
         }
 
-        max_index = MIN2(vbo->max_index, max_index);
+        r300->any_user_vbs = any_user_buffer;
+        r300->vertex_buffer_max_index = max_index;
+
+    } else {
+        /* SW TCL. */
+        draw_flush(r300->draw);
+        draw_set_vertex_buffers(r300->draw, count, buffers);
     }
 
+    /* Common code. */
+    for (i = 0; i < count; i++) {
+        /* Reference our buffer. */
+        pipe_resource_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer);
+    }
     for (; i < r300->vertex_buffer_count; i++) {
         /* Dereference any old buffers. */
         pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
@@ -1196,18 +1227,10 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
 
     memcpy(r300->vertex_buffer, buffers,
         sizeof(struct pipe_vertex_buffer) * count);
-
     r300->vertex_buffer_count = count;
-    r300->vertex_buffer_max_index = max_index;
-    r300->any_user_vbs = any_user_buffer;
-
-    if (r300->draw) {
-        draw_flush(r300->draw);
-        draw_set_vertex_buffers(r300->draw, count, buffers);
-    }
 }
 
-/* Update the PSC tables. */
+/* Initialize the PSC tables. */
 static void r300_vertex_psc(struct r300_vertex_element_state *velems)
 {
     struct r300_vertex_stream_state *vstream = &velems->vertex_stream;
@@ -1227,8 +1250,15 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
     for (i = 0; i < velems->count; i++) {
         format = velems->velem[i].src_format;
 
-        type = r300_translate_vertex_data_type(format) |
-            (i << R300_DST_VEC_LOC_SHIFT);
+        type = r300_translate_vertex_data_type(format);
+        if (type == R300_INVALID_FORMAT) {
+            fprintf(stderr, "r300: Bad vertex format %s.\n",
+                    util_format_short_name(format));
+            assert(0);
+            abort();
+        }
+
+        type |= i << R300_DST_VEC_LOC_SHIFT;
         swizzle = r300_translate_vertex_data_swizzle(format);
 
         if (i & 1) {
@@ -1346,7 +1376,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
                     abort();
                 }
             }
-
         }
     }
     return velems;
@@ -1367,6 +1396,7 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
     if (r300->draw) {
         draw_flush(r300->draw);
         draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
+        return;
     }
 
     UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state);
@@ -1390,9 +1420,10 @@ static void* r300_create_vs_state(struct pipe_context* pipe,
     vs->state.tokens = tgsi_dup_tokens(shader->tokens);
 
     if (r300->screen->caps.has_tcl) {
-        r300_translate_vertex_shader(r300, vs, vs->state.tokens);
+        r300_init_vs_outputs(vs);
+        r300_translate_vertex_shader(r300, vs);
     } else {
-        vs->draw_vs = draw_create_vertex_shader(r300->draw, shader);
+        r300_draw_init_vertex_shader(r300->draw, vs);
     }
 
     return vs;
@@ -1460,7 +1491,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
     struct r300_constant_buffer *cbuf;
     struct pipe_transfer *tr;
     void *mapped;
-    int max_size = 0;
+    int max_size = 0, max_size_bytes = 0, clamped_size = 0;
 
     switch (shader) {
         case PIPE_SHADER_VERTEX:
@@ -1479,6 +1510,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
             assert(0);
             return;
     }
+    max_size_bytes = max_size * 4 * sizeof(float);
 
     if (buf == NULL || buf->width0 == 0 ||
         (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL)
@@ -1487,19 +1519,21 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
         return;
     }
 
-    assert((buf->width0 % 4 * sizeof(float)) == 0);
+    if (shader == PIPE_SHADER_FRAGMENT ||
+        (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) {
+        assert((buf->width0 % (4 * sizeof(float))) == 0);
 
-    /* Check the size of the constant buffer. */
-    /* XXX Subtract immediates and RC_STATE_* variables. */
-    if (buf->width0 > (sizeof(float) * 4 * max_size)) {
-        fprintf(stderr, "r300: Max size of the constant buffer is "
-                      "%i*4 floats.\n", max_size);
-        abort();
-    }
+        /* Check the size of the constant buffer. */
+        /* XXX Subtract immediates and RC_STATE_* variables. */
+        if (buf->width0 > max_size_bytes) {
+            fprintf(stderr, "r300: Max size of the constant buffer is "
+                          "%i*4 floats.\n", max_size);
+        }
+        clamped_size = MIN2(buf->width0, max_size_bytes);
 
-    memcpy(cbuf->constants, mapped, buf->width0);
-    cbuf->count = buf->width0 / (4 * sizeof(float));
-    pipe_buffer_unmap(pipe, buf, tr);
+        memcpy(cbuf->constants, mapped, clamped_size);
+        cbuf->count = clamped_size / (4 * sizeof(float));
+    }
 
     if (shader == PIPE_SHADER_VERTEX) {
         if (r300->screen->caps.has_tcl) {
@@ -1509,12 +1543,13 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
             r300->pvs_flush.dirty = TRUE;
         } else if (r300->draw) {
             draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX,
-                0, cbuf->constants,
-                buf->width0);
+                0, mapped, buf->width0);
         }
     } else if (shader == PIPE_SHADER_FRAGMENT) {
         r300->fs_constants.dirty = TRUE;
     }
+
+    pipe_buffer_unmap(pipe, buf, tr);
 }
 
 void r300_init_state_functions(struct r300_context* r300)
@@ -1526,6 +1561,7 @@ void r300_init_state_functions(struct r300_context* r300)
     r300->context.set_blend_color = r300_set_blend_color;
 
     r300->context.set_clip_state = r300_set_clip_state;
+    r300->context.set_sample_mask = r300_set_sample_mask;
 
     r300->context.set_constant_buffer = r300_set_constant_buffer;