Squashed commit of the following:
[mesa.git] / src / gallium / drivers / r300 / r300_state.c
index bf17d5d92036768eb45f39234c54dfc87db12130..52b89104b99935bfbd4773b22de1ccb37add81ac 100644 (file)
@@ -219,7 +219,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
             /* Enable reading from the colorbuffer. */
             blend->blend_control |= R300_READ_ENABLE;
 
-            if (r300_screen(r300_context(pipe)->context.screen)->caps->is_r500) {
+            if (r300screen->caps.is_r500) {
                 /* Optimization: Depending on incoming pixels, we can
                  * conditionally disable the reading in hardware... */
                 if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN &&
@@ -308,7 +308,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
 
     /* Color channel masks for all MRTs. */
     blend->color_channel_mask = bgra_cmask(state->rt[0].colormask);
-    if (r300screen->caps->is_r500 && state->independent_blend_enable) {
+    if (r300screen->caps.is_r500 && state->independent_blend_enable) {
         if (state->rt[1].blend_enable) {
             blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4;
         }
@@ -320,12 +320,17 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
         }
     }
 
+    /* Neither fglrx nor classic r300 ever set this, regardless of dithering
+     * state. Since it's an optional implementation detail, we can leave it
+     * out and never dither.
+     *
+     * This could be revisited if we ever get quality or conformance hints.
+     *
     if (state->dither) {
-       /* fglrx appears to never set this */
-       blend->dither = 0;
-        /* blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
-                           R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; */
+        blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
+                        R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
     }
+    */
 
     return (void*)blend;
 }
@@ -358,7 +363,6 @@ static void r300_set_blend_color(struct pipe_context* pipe,
                                  const struct pipe_blend_color* color)
 {
     struct r300_context* r300 = r300_context(pipe);
-    struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct r300_blend_color_state* state =
         (struct r300_blend_color_state*)r300->blend_color_state.state;
     union util_color uc;
@@ -374,7 +378,7 @@ static void r300_set_blend_color(struct pipe_context* pipe,
         float_to_fixed10(color->color[2]) |
         (float_to_fixed10(color->color[1]) << 16);
 
-    r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2;
+    r300->blend_color_state.size = r300->screen->caps.is_r500 ? 3 : 2;
     r300->blend_color_state.dirty = TRUE;
 }
 
@@ -385,7 +389,7 @@ static void r300_set_clip_state(struct pipe_context* pipe,
 
     r300->clip = *state;
 
-    if (r300_screen(pipe->screen)->caps->has_tcl) {
+    if (r300->screen->caps.has_tcl) {
         memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
         r300->clip_state.size = 29;
     } else {
@@ -406,8 +410,7 @@ static void*
         r300_create_dsa_state(struct pipe_context* pipe,
                               const struct pipe_depth_stencil_alpha_state* state)
 {
-    struct r300_capabilities *caps =
-        r300_screen(r300_context(pipe)->context.screen)->caps;
+    struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps;
     struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
 
     /* Depth test setup. */
@@ -441,6 +444,8 @@ static void*
                 (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT);
 
         if (state->stencil[1].enabled) {
+            dsa->two_sided = TRUE;
+
             dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK;
             dsa->z_stencil_control |=
             (r300_translate_depth_stencil_function(state->stencil[1].func) <<
@@ -452,14 +457,16 @@ static void*
             (r300_translate_stencil_op(state->stencil[1].zfail_op) <<
                 R300_S_BACK_ZFAIL_OP_SHIFT);
 
-            if (caps->is_r500)
-            {
+            dsa->stencil_ref_bf =
+                (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) |
+                (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT);
+
+            if (caps->is_r500) {
                 dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK;
-                dsa->stencil_ref_bf =
-                    (state->stencil[1].valuemask <<
-                    R300_STENCILMASK_SHIFT) |
-                    (state->stencil[1].writemask <<
-                    R300_STENCILWRITEMASK_SHIFT);
+            } else {
+                dsa->stencil_ref_bf_fallback =
+                  (state->stencil[0].valuemask != state->stencil[1].valuemask ||
+                   state->stencil[0].writemask != state->stencil[1].writemask);
             }
         }
     }
@@ -480,13 +487,33 @@ 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)
 {
     struct r300_context* r300 = r300_context(pipe);
 
+    if (!state) {
+        return;
+    }
+
     UPDATE_STATE(state, r300->dsa_state);
+
+    r300_update_stencil_ref_fallback_status(r300);
 }
 
 /* Free DSA state. */
@@ -500,8 +527,11 @@ static void r300_set_stencil_ref(struct pipe_context* pipe,
                                  const struct pipe_stencil_ref* sr)
 {
     struct r300_context* r300 = r300_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. */
@@ -524,7 +554,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
             continue;
         }
 
-        tex = (struct r300_texture*)old_state->cbufs[i]->texture;
+        tex = r300_texture(old_state->cbufs[i]->texture);
 
         if (tex) {
             r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
@@ -536,7 +566,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
     if (old_state->zsbuf &&
         (!new_state->zsbuf ||
          old_state->zsbuf->texture != new_state->zsbuf->texture)) {
-        tex = (struct r300_texture*)old_state->zsbuf->texture;
+        tex = r300_texture(old_state->zsbuf->texture);
 
         if (tex) {
             r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
@@ -548,7 +578,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
 
     /* Set tiling flags for new surfaces. */
     for (i = 0; i < new_state->nr_cbufs; i++) {
-        tex = (struct r300_texture*)new_state->cbufs[i]->texture;
+        tex = r300_texture(new_state->cbufs[i]->texture);
         level = new_state->cbufs[i]->level;
 
         r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
@@ -557,7 +587,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
                                         tex->mip_macrotile[level]);
     }
     if (new_state->zsbuf) {
-        tex = (struct r300_texture*)new_state->zsbuf->texture;
+        tex = r300_texture(new_state->zsbuf->texture);
         level = new_state->zsbuf->level;
 
         r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
@@ -572,7 +602,6 @@ static void
                                const struct pipe_framebuffer_state* state)
 {
     struct r300_context* r300 = r300_context(pipe);
-    struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct pipe_framebuffer_state *old_state = r300->fb_state.state;
     unsigned max_width, max_height;
     uint32_t zbuffer_bpp = 0;
@@ -583,9 +612,9 @@ static void
         return;
     }
 
-    if (r300screen->caps->is_r500) {
+    if (r300->screen->caps.is_r500) {
         max_width = max_height = 4096;
-    } else if (r300screen->caps->is_r400) {
+    } else if (r300->screen->caps.is_r400) {
         max_width = max_height = 4021;
     } else {
         max_width = max_height = 2560;
@@ -713,7 +742,6 @@ static void r300_set_polygon_stipple(struct pipe_context* pipe,
 static void* r300_create_rs_state(struct pipe_context* pipe,
                                   const struct pipe_rasterizer_state* state)
 {
-    struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
 
     /* Copy rasterizer state for Draw. */
@@ -726,7 +754,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 #endif
 
     /* If no TCL engine is present, turn off the HW TCL. */
-    if (!r300screen->caps->has_tcl) {
+    if (!r300_screen(pipe->screen)->caps.has_tcl) {
         rs->vap_control_status |= R300_VAP_TCL_BYPASS;
     }
 
@@ -850,7 +878,7 @@ static void*
 {
     struct r300_context* r300 = r300_context(pipe);
     struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state);
-    boolean is_r500 = r300_screen(pipe->screen)->caps->is_r500;
+    boolean is_r500 = r300->screen->caps.is_r500;
     int lod_bias;
     union util_color uc;
 
@@ -889,7 +917,7 @@ static void*
     sampler->border_color = uc.ui;
 
     /* R500-specific fixups and optimizations */
-    if (r300_screen(r300->context.screen)->caps->is_r500) {
+    if (r300->screen->caps.is_r500) {
         sampler->filter1 |= R500_BORDER_FIX;
     }
 
@@ -903,8 +931,9 @@ static void r300_bind_sampler_states(struct pipe_context* pipe,
     struct r300_context* r300 = r300_context(pipe);
     struct r300_textures_state* state =
         (struct r300_textures_state*)r300->textures_state.state;
+    unsigned tex_units = r300->screen->caps.num_tex_units;
 
-    if (count > 8) {
+    if (count > tex_units) {
         return;
     }
 
@@ -942,11 +971,11 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
         (struct r300_textures_state*)r300->textures_state.state;
     struct r300_texture *texture;
     unsigned i;
-    boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
+    unsigned tex_units = r300->screen->caps.num_tex_units;
+    boolean is_r500 = r300->screen->caps.is_r500;
     boolean dirty_tex = FALSE;
 
-    /* XXX magic num */
-    if (count > 8) {
+    if (count > tex_units) {
         return;
     }
 
@@ -963,8 +992,8 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
             dirty_tex = TRUE;
 
             /* R300-specific - set the texrect factor in the fragment shader */
-            texture = (struct r300_texture *)views[i]->texture;
-            if (!is_r500 && texture->is_npot) {
+            texture = r300_texture(views[i]->texture);
+            if (!is_r500 && texture->uses_pitch) {
                 /* XXX It would be nice to re-emit just 1 constant,
                  * XXX not all of them */
                 r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
@@ -972,7 +1001,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
         }
     }
 
-    for (i = count; i < 8; i++) {
+    for (i = count; i < tex_units; i++) {
         if (state->fragment_sampler_views[i]) {
             pipe_sampler_view_reference(&state->fragment_sampler_views[i],
                                         NULL);
@@ -990,7 +1019,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
 
 static struct pipe_sampler_view *
 r300_create_sampler_view(struct pipe_context *pipe,
-                         struct pipe_texture *texture,
+                         struct pipe_resource *texture,
                          const struct pipe_sampler_view *templ)
 {
    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
@@ -999,7 +1028,7 @@ r300_create_sampler_view(struct pipe_context *pipe,
       *view = *templ;
       view->reference.count = 1;
       view->texture = NULL;
-      pipe_texture_reference(&view->texture, texture);
+      pipe_resource_reference(&view->texture, texture);
       view->context = pipe;
    }
 
@@ -1010,7 +1039,7 @@ static void
 r300_sampler_view_destroy(struct pipe_context *pipe,
                           struct pipe_sampler_view *view)
 {
-   pipe_texture_reference(&view->texture, NULL);
+   pipe_resource_reference(&view->texture, NULL);
    FREE(view);
 }
 
@@ -1104,7 +1133,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
         vbo = (struct pipe_vertex_buffer*)&buffers[i];
 
         /* Reference our buffer. */
-        pipe_buffer_reference(&r300->vertex_buffer[i].buffer, vbo->buffer);
+        pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer);
 
         /* Skip NULL buffers */
         if (!buffers[i].buffer) {
@@ -1118,7 +1147,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
         if (vbo->max_index == ~0) {
             /* Bogus value from broken state tracker; hax it. */
             vbo->max_index =
-                (vbo->buffer->size - vbo->buffer_offset) / vbo->stride;
+                (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
         }
 
         max_index = MIN2(vbo->max_index, max_index);
@@ -1126,7 +1155,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
 
     for (; i < r300->vertex_buffer_count; i++) {
         /* Dereference any old buffers. */
-        pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL);
+        pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
     }
 
     memcpy(r300->vertex_buffer, buffers,
@@ -1185,7 +1214,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
                                                unsigned count,
                                                const struct pipe_vertex_element* attribs)
 {
-    struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct r300_vertex_element_state *velems;
     unsigned i, size;
 
@@ -1195,7 +1223,7 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
         velems->count = count;
         memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
 
-        if (r300screen->caps->has_tcl) {
+        if (r300_screen(pipe->screen)->caps.has_tcl) {
             /* Check if the format is aligned to the size of DWORD. */
             for (i = 0; i < count; i++) {
                 size = util_format_get_blocksize(attribs[i].src_format);
@@ -1250,7 +1278,7 @@ static void* r300_create_vs_state(struct pipe_context* pipe,
     struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
     r300_vertex_shader_common_init(vs, shader);
 
-    if (r300_screen(pipe->screen)->caps->has_tcl) {
+    if (r300->screen->caps.has_tcl) {
         r300_translate_vertex_shader(r300, vs);
     } else {
         vs->draw_vs = draw_create_vertex_shader(r300->draw, shader);
@@ -1284,7 +1312,7 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
     /* The majority of the RS block bits is dependent on the vertex shader. */
     r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
 
-    if (r300_screen(pipe->screen)->caps->has_tcl) {
+    if (r300->screen->caps.has_tcl) {
         r300->vs_state.dirty = TRUE;
         r300->vs_state.size = vs->code.length + 9;
 
@@ -1303,7 +1331,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
     struct r300_context* r300 = r300_context(pipe);
     struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
 
-    if (r300_screen(pipe->screen)->caps->has_tcl) {
+    if (r300->screen->caps.has_tcl) {
         rc_constants_destroy(&vs->code.constants);
     } else {
         draw_delete_vertex_shader(r300->draw,
@@ -1316,21 +1344,21 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
 
 static void r300_set_constant_buffer(struct pipe_context *pipe,
                                      uint shader, uint index,
-                                     struct pipe_buffer *buf)
+                                     struct pipe_resource *buf)
 {
     struct r300_context* r300 = r300_context(pipe);
-    struct r300_screen *r300screen = r300_screen(pipe->screen);
+    struct pipe_transfer *tr;
     void *mapped;
     int max_size = 0;
 
-    if (buf == NULL || buf->size == 0 ||
-        (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL)
+    if (buf == NULL || buf->width0 == 0 ||
+        (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL)
     {
         r300->shader_constants[shader].count = 0;
         return;
     }
 
-    assert((buf->size % 4 * sizeof(float)) == 0);
+    assert((buf->width0 % 4 * sizeof(float)) == 0);
 
     /* Check the size of the constant buffer. */
     switch (shader) {
@@ -1338,10 +1366,10 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
             max_size = 256;
             break;
         case PIPE_SHADER_FRAGMENT:
-            if (r300screen->caps->is_r500) {
+            if (r300->screen->caps.is_r500) {
                 max_size = 256;
             /* XXX Implement emission of r400's extended constant buffer. */
-            /*} else if (r300screen->caps->is_r400) {
+            /*} else if (r300->screen->caps.is_r400) {
                 max_size = 64;*/
             } else {
                 max_size = 32;
@@ -1352,24 +1380,24 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
     }
 
     /* XXX Subtract immediates and RC_STATE_* variables. */
-    if (buf->size > (sizeof(float) * 4 * max_size)) {
+    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();
     }
 
-    memcpy(r300->shader_constants[shader].constants, mapped, buf->size);
-    r300->shader_constants[shader].count = buf->size / (4 * sizeof(float));
-    pipe_buffer_unmap(pipe->screen, buf);
+    memcpy(r300->shader_constants[shader].constants, mapped, buf->width0);
+    r300->shader_constants[shader].count = buf->width0 / (4 * sizeof(float));
+    pipe_buffer_unmap(pipe, buf, tr);
 
     if (shader == PIPE_SHADER_VERTEX) {
-        if (r300screen->caps->has_tcl) {
+        if (r300->screen->caps.has_tcl) {
             r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
             r300->pvs_flush.dirty = TRUE;
         } else if (r300->draw) {
             draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX,
                 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants,
-                buf->size);
+                buf->width0);
         }
     } else if (shader == PIPE_SHADER_FRAGMENT) {
         r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;