gallium: change set_constant_buffer to be UBO-friendly
[mesa.git] / src / gallium / drivers / r300 / r300_state.c
index 2b0c8750554dfd1e0b995bf9dc27b95306e7d5c4..058e6f881f0fafbb0e832d756e76b07e568b549f 100644 (file)
@@ -45,7 +45,6 @@
 #include "r300_fs.h"
 #include "r300_texture.h"
 #include "r300_vs.h"
-#include "r300_winsys.h"
 
 /* r300_state: Functions used to intialize state context by translating
  * Gallium state objects into semi-native r300 state objects. */
@@ -188,13 +187,16 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
     struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state);
     uint32_t blend_control = 0;       /* R300_RB3D_CBLEND: 0x4e04 */
+    uint32_t blend_control_noclamp = 0;    /* R300_RB3D_CBLEND: 0x4e04 */
     uint32_t alpha_blend_control = 0; /* R300_RB3D_ABLEND: 0x4e08 */
+    uint32_t alpha_blend_control_noclamp = 0; /* R300_RB3D_ABLEND: 0x4e08 */
     uint32_t color_channel_mask = 0;  /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */
     uint32_t rop = 0;                 /* R300_RB3D_ROPCNTL: 0x4e18 */
     uint32_t dither = 0;              /* R300_RB3D_DITHER_CTL: 0x4e50 */
-    boolean clamp = TRUE;
     CB_LOCALS;
 
+    blend->state = *state;
+
     if (state->rt[0].blend_enable)
     {
         unsigned eqRGB = state->rt[0].rgb_func;
@@ -207,10 +209,14 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
 
         /* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha,
          * this is just the crappy D3D naming */
-        blend_control = R300_ALPHA_BLEND_ENABLE |
-            r300_translate_blend_function(eqRGB, clamp) |
+        blend_control = blend_control_noclamp =
+            R300_ALPHA_BLEND_ENABLE |
             ( r300_translate_blend_factor(srcRGB) << R300_SRC_BLEND_SHIFT) |
             ( r300_translate_blend_factor(dstRGB) << R300_DST_BLEND_SHIFT);
+        blend_control |=
+            r300_translate_blend_function(eqRGB, TRUE);
+        blend_control_noclamp |=
+            r300_translate_blend_function(eqRGB, FALSE);
 
         /* Optimization: some operations do not require the destination color.
          *
@@ -232,6 +238,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
             srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) {
             /* Enable reading from the colorbuffer. */
             blend_control |= R300_READ_ENABLE;
+            blend_control_noclamp |= R300_READ_ENABLE;
 
             if (r300screen->caps.is_r500) {
                 /* Optimization: Depending on incoming pixels, we can
@@ -269,8 +276,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
          *
          * Equations other than ADD are rarely used and therefore won't be
          * optimized. */
-        if (clamp &&
-            (eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) &&
+        if ((eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) &&
             (eqA == PIPE_BLEND_ADD || eqA == PIPE_BLEND_REVERSE_SUBTRACT)) {
             /* ADD: X+Y
              * REVERSE_SUBTRACT: Y-X
@@ -308,10 +314,14 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
         /* separate alpha */
         if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
             blend_control |= R300_SEPARATE_ALPHA_ENABLE;
-            alpha_blend_control =
-                r300_translate_blend_function(eqA, clamp) |
+            blend_control_noclamp |= R300_SEPARATE_ALPHA_ENABLE;
+            alpha_blend_control = alpha_blend_control_noclamp =
                 (r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) |
                 (r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT);
+            alpha_blend_control |=
+                r300_translate_blend_function(eqA, TRUE);
+            alpha_blend_control_noclamp |=
+                r300_translate_blend_function(eqA, FALSE);
         }
     }
 
@@ -348,7 +358,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
     */
 
     /* Build a command buffer. */
-    BEGIN_CB(blend->cb, 8);
+    BEGIN_CB(blend->cb_clamp, 8);
     OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
     OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
     OUT_CB(blend_control);
@@ -357,6 +367,16 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
     OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
     END_CB;
 
+    /* Build a command buffer. */
+    BEGIN_CB(blend->cb_noclamp, 8);
+    OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
+    OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
+    OUT_CB(blend_control_noclamp);
+    OUT_CB(alpha_blend_control_noclamp);
+    OUT_CB(color_channel_mask);
+    OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
+    END_CB;
+
     /* The same as above, but with no colorbuffer reads and writes. */
     BEGIN_CB(blend->cb_no_readwrite, 8);
     OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
@@ -473,21 +493,13 @@ static void r300_set_clip_state(struct pipe_context* pipe,
             (struct r300_clip_state*)r300->clip_state.state;
     CB_LOCALS;
 
-    clip->clip = *state;
-
     if (r300->screen->caps.has_tcl) {
-        r300->clip_state.size = 2 + !!state->nr * 3 + state->nr * 4;
-
         BEGIN_CB(clip->cb, r300->clip_state.size);
-        if (state->nr) {
-           OUT_CB_REG(R300_VAP_PVS_VECTOR_INDX_REG,
+        OUT_CB_REG(R300_VAP_PVS_VECTOR_INDX_REG,
                    (r300->screen->caps.is_r500 ?
                     R500_PVS_UCP_START : R300_PVS_UCP_START));
-           OUT_CB_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, state->nr * 4);
-           OUT_CB_TABLE(state->ucp, state->nr * 4);
-        }
-        OUT_CB_REG(R300_VAP_CLIP_CNTL, ((1 << state->nr) - 1) |
-                   R300_PS_UCP_MODE_CLIP_AS_TRIFAN);
+        OUT_CB_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4);
+        OUT_CB_TABLE(state->ucp, 6 * 4);
         END_CB;
 
         r300_mark_atom_dirty(r300, &r300->clip_state);
@@ -529,6 +541,10 @@ static void*
         dsa->z_stencil_control |=
             (r300_translate_depth_stencil_function(state->depth.func) <<
                 R300_Z_FUNC_SHIFT);
+    } else {
+        /* We must enable depth test, otherwise occlusion queries won't work. */
+        dsa->z_buffer_control |= R300_Z_ENABLE;
+        dsa->z_stencil_control |= R300_ZS_ALWAYS;
     }
 
     /* Stencil buffer setup. */
@@ -612,11 +628,13 @@ static void*
     OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value);
     END_CB;
 
+    /* We must enable depth test, otherwise occlusion queries won't work.
+     * We setup a dummy zbuffer to silent the CS checker, see emit_fb_state. */
     BEGIN_CB(dsa->cb_zb_no_readwrite, 10);
     OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
     OUT_CB_REG_SEQ(R300_ZB_CNTL, 3);
-    OUT_CB(0);
-    OUT_CB(0);
+    OUT_CB(R300_Z_ENABLE);
+    OUT_CB(R300_ZS_ALWAYS);
     OUT_CB(0);
     OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, 0);
     OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value);
@@ -625,8 +643,8 @@ static void*
     BEGIN_CB(dsa->cb_fp16_zb_no_readwrite, 10);
     OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function_fp16);
     OUT_CB_REG_SEQ(R300_ZB_CNTL, 3);
-    OUT_CB(0);
-    OUT_CB(0);
+    OUT_CB(R300_Z_ENABLE);
+    OUT_CB(R300_ZS_ALWAYS);
     OUT_CB(0);
     OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, 0);
     OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value);
@@ -730,7 +748,7 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
             "r300:   %s[%i] Dim: %ix%i, Firstlayer: %i, "
             "Lastlayer: %i, Level: %i, Format: %s\n"
 
-            "r300:     TEX: Macro: %s, Micro: %s, Pitch: %i, "
+            "r300:     TEX: Macro: %s, Micro: %s, "
             "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
 
             binding, index, surf->width, surf->height,
@@ -739,16 +757,14 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
 
             rtex->tex.macrotile[0] ? "YES" : " NO",
             rtex->tex.microtile ? "YES" : " NO",
-            rtex->tex.stride_in_pixels[0],
             tex->width0, tex->height0, tex->depth0,
-            tex->last_level, util_format_short_name(tex->format));
+            tex->last_level, util_format_short_name(surf->format));
 }
 
 void r300_mark_fb_state_dirty(struct r300_context *r300,
                               enum r300_fb_state_change change)
 {
     struct pipe_framebuffer_state *state = r300->fb_state.state;
-    boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
 
     r300_mark_atom_dirty(r300, &r300->gpu_flush);
     r300_mark_atom_dirty(r300, &r300->fb_state);
@@ -773,12 +789,14 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
     /* Now compute the fb_state atom size. */
     r300->fb_state.size = 2 + (8 * state->nr_cbufs);
 
-    if (r300->cbzb_clear)
+    if (r300->cbzb_clear) {
         r300->fb_state.size += 10;
-    else if (state->zsbuf) {
+    else if (state->zsbuf) {
         r300->fb_state.size += 10;
-        if (can_hyperz)
+        if (r300->hyperz_enabled)
             r300->fb_state.size += 8;
+    } else if (state->nr_cbufs) {
+        r300->fb_state.size += 10;
     }
 
     /* The size of the rest of atoms stays the same. */
@@ -793,6 +811,7 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
     struct pipe_framebuffer_state *old_state = r300->fb_state.state;
     unsigned max_width, max_height, i;
     uint32_t zbuffer_bpp = 0;
+    boolean unlock_zbuffer = FALSE;
 
     if (r300->screen->caps.is_r500) {
         max_width = max_height = 4096;
@@ -808,7 +827,7 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
         return;
     }
 
-    if (old_state->zsbuf && r300->zmask_in_use && !r300->hyperz_locked) {
+    if (old_state->zsbuf && r300->zmask_in_use && !r300->locked_zbuffer) {
         /* There is a zmask in use, what are we gonna do? */
         if (state->zsbuf) {
             if (!pipe_surface_equal(old_state->zsbuf, state->zsbuf)) {
@@ -818,10 +837,9 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
             }
         } else {
             /* We don't bind another zbuffer, so lock the current one. */
-            r300->hyperz_locked = TRUE;
             pipe_surface_reference(&r300->locked_zbuffer, old_state->zsbuf);
         }
-    } else if (r300->hyperz_locked && r300->locked_zbuffer) {
+    } else if (r300->locked_zbuffer) {
         /* We have a locked zbuffer now, what are we gonna do? */
         if (state->zsbuf) {
             if (!pipe_surface_equal(r300->locked_zbuffer, state->zsbuf)) {
@@ -831,33 +849,37 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
                 r300->hiz_in_use = FALSE;
             } else {
                 /* We are binding the locked zbuffer again, so unlock it. */
-                r300->hyperz_locked = FALSE;
+                unlock_zbuffer = TRUE;
             }
         }
     }
+    assert(state->zsbuf || (r300->locked_zbuffer && !unlock_zbuffer) || !r300->zmask_in_use);
+
+    /* Need to reset clamping or colormask. */
+    r300_mark_atom_dirty(r300, &r300->blend_state);
 
-    /* If nr_cbufs is changed from zero to non-zero or vice versa... */
-    if (!!old_state->nr_cbufs != !!state->nr_cbufs) {
-        r300_mark_atom_dirty(r300, &r300->blend_state);
-    }
     /* If zsbuf is set from NULL to non-NULL or vice versa.. */
     if (!!old_state->zsbuf != !!state->zsbuf) {
         r300_mark_atom_dirty(r300, &r300->dsa_state);
     }
 
-    /* The tiling flags are dependent on the surface miplevel, unfortunately. */
-    r300_fb_set_tiling_flags(r300, state);
+    if (r300->screen->info.drm_minor < 12) {
+       /* The tiling flags are dependent on the surface miplevel, unfortunately.
+        * This workarounds a bad design decision in old kernels which were
+        * rewriting tile fields in registers. */
+        r300_fb_set_tiling_flags(r300, state);
+    }
 
     util_copy_framebuffer_state(r300->fb_state.state, state);
 
-    if (!r300->hyperz_locked) {
+    if (unlock_zbuffer) {
         pipe_surface_reference(&r300->locked_zbuffer, NULL);
     }
 
     r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE);
 
     if (state->zsbuf) {
-        switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
+        switch (util_format_get_blocksize(state->zsbuf->format)) {
         case 2:
             zbuffer_bpp = 16;
             break;
@@ -949,24 +971,14 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
 {
     struct r300_context* r300 = r300_context(pipe);
     struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
-    struct pipe_framebuffer_state *fb = r300->fb_state.state;
-    boolean last_multi_write;
 
     if (fs == NULL) {
         r300->fs.state = NULL;
         return;
     }
 
-    last_multi_write = r300_fragment_shader_writes_all(r300_fs(r300));
-
     r300->fs.state = fs;
-    r300_pick_fragment_shader(r300);
-    r300_mark_fs_code_dirty(r300);
-
-    if (fb->nr_cbufs > 1 &&
-        last_multi_write != r300_fragment_shader_writes_all(fs)) {
-        r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE);
-    }
+    r300->fs_status = FRAGMENT_SHADER_DIRTY;
 
     r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */
 }
@@ -1005,8 +1017,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
                                   const struct pipe_rasterizer_state* state)
 {
     struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
-    float psiz;
     uint32_t vap_control_status;    /* R300_VAP_CNTL_STATUS: 0x2140 */
+    uint32_t vap_clip_cntl;         /* R300_VAP_CLIP_CNTL: 0x221C */
     uint32_t point_size;            /* R300_GA_POINT_SIZE: 0x421c */
     uint32_t point_minmax;          /* R300_GA_POINT_MINMAX: 0x4230 */
     uint32_t line_control;          /* R300_GA_LINE_CNTL: 0x4234 */
@@ -1023,7 +1035,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */
     float point_texcoord_right = 1; /* R300_GA_POINT_S1: 0x4208 */
     float point_texcoord_top = 0;   /* R300_GA_POINT_T1: 0x420c */
-    boolean vclamp = TRUE;
+    boolean vclamp = state->clamp_vertex_color ||
+                     !r300_context(pipe)->screen->caps.is_r500;
     CB_LOCALS;
 
     /* Copy rasterizer state. */
@@ -1035,6 +1048,10 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 
     /* Override some states for Draw. */
     rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */
+    rs->rs_draw.offset_point = 0;
+    rs->rs_draw.offset_line = 0;
+    rs->rs_draw.offset_tri = 0;
+    rs->rs_draw.offset_clamp = 0;
 
 #ifdef PIPE_ARCH_LITTLE_ENDIAN
     vap_control_status = R300_VC_NO_SWAP;
@@ -1056,14 +1073,16 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     if (state->point_size_per_vertex) {
         /* Per-vertex point size.
          * Clamp to [0, max FB size] */
-        psiz = pipe->screen->get_paramf(pipe->screen,
-                                        PIPE_CAP_MAX_POINT_WIDTH);
+        float min_psiz = util_get_min_point_size(state);
+        float max_psiz = pipe->screen->get_paramf(pipe->screen,
+                                        PIPE_CAPF_MAX_POINT_WIDTH);
         point_minmax =
-            pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT;
+            (pack_float_16_6x(min_psiz) << R300_GA_POINT_MINMAX_MIN_SHIFT) |
+            (pack_float_16_6x(max_psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT);
     } else {
         /* We cannot disable the point-size vertex output,
          * so clamp it. */
-        psiz = state->point_size;
+        float psiz = state->point_size;
         point_minmax =
             (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MIN_SHIFT) |
             (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT);
@@ -1146,6 +1165,13 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
         }
     }
 
+    if (r300_screen(pipe->screen)->caps.has_tcl) {
+       vap_clip_cntl = (state->clip_plane_enable & 63) |
+                       R300_PS_UCP_MODE_CLIP_AS_TRIFAN;
+    } else {
+       vap_clip_cntl = R300_CLIP_DISABLE;
+    }
+
     /* Vertex color clamping. FP20 means no clamping. */
     round_mode =
       R300_GA_ROUND_MODE_GEOMETRY_ROUND_NEAREST |
@@ -1155,13 +1181,14 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     /* Build the main command buffer. */
     BEGIN_CB(rs->cb_main, RS_STATE_MAIN_SIZE);
     OUT_CB_REG(R300_VAP_CNTL_STATUS, vap_control_status);
+    OUT_CB_REG(R300_VAP_CLIP_CNTL, vap_clip_cntl);
     OUT_CB_REG(R300_GA_POINT_SIZE, point_size);
     OUT_CB_REG_SEQ(R300_GA_POINT_MINMAX, 2);
     OUT_CB(point_minmax);
     OUT_CB(line_control);
     OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2);
     OUT_CB(polygon_offset_enable);
-    rs->cull_mode_index = 9;
+    rs->cull_mode_index = 11;
     OUT_CB(cull_mode);
     OUT_CB_REG(R300_GA_LINE_STIPPLE_CONFIG, line_stipple_config);
     OUT_CB_REG(R300_GA_LINE_STIPPLE_VALUE, line_stipple_value);
@@ -1282,7 +1309,7 @@ static void*
     sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter,
                                                    state->mag_img_filter,
                                                    state->min_mip_filter,
-                                                   state->max_anisotropy > 0);
+                                                   state->max_anisotropy > 1);
 
     sampler->filter0 |= r300_anisotropy(state->max_anisotropy);
 
@@ -1429,10 +1456,12 @@ 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_sampler_view *
+r300_create_sampler_view_custom(struct pipe_context *pipe,
                          struct pipe_resource *texture,
-                         const struct pipe_sampler_view *templ)
+                         const struct pipe_sampler_view *templ,
+                         unsigned width0_override,
+                         unsigned height0_override)
 {
     struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view);
     struct r300_resource *tex = r300_resource(texture);
@@ -1440,22 +1469,37 @@ r300_create_sampler_view(struct pipe_context *pipe,
     boolean dxtc_swizzle = r300_screen(pipe->screen)->caps.dxtc_swizzle;
 
     if (view) {
+        unsigned hwformat;
+
         view->base = *templ;
         view->base.reference.count = 1;
         view->base.context = pipe;
         view->base.texture = NULL;
         pipe_resource_reference(&view->base.texture, texture);
 
+       view->width0_override = width0_override;
+       view->height0_override = height0_override;
         view->swizzle[0] = templ->swizzle_r;
         view->swizzle[1] = templ->swizzle_g;
         view->swizzle[2] = templ->swizzle_b;
         view->swizzle[3] = templ->swizzle_a;
 
-        view->format = tex->tx_format;
-        view->format.format1 |= r300_translate_texformat(templ->format,
-                                                         view->swizzle,
-                                                         is_r500,
-                                                         dxtc_swizzle);
+        hwformat = r300_translate_texformat(templ->format,
+                                            view->swizzle,
+                                            is_r500,
+                                            dxtc_swizzle);
+
+        if (hwformat == ~0) {
+            fprintf(stderr, "r300: Ooops. Got unsupported format %s in %s.\n",
+                    util_format_short_name(templ->format), __func__);
+        }
+        assert(hwformat != ~0);
+
+       r300_texture_setup_format_state(r300_screen(pipe->screen), tex,
+                                       templ->format, 0,
+                                       width0_override, height0_override,
+                                       &view->format);
+        view->format.format1 |= hwformat;
         if (is_r500) {
             view->format.format2 |= r500_tx_format_msb_bit(templ->format);
         }
@@ -1464,6 +1508,17 @@ r300_create_sampler_view(struct pipe_context *pipe,
     return (struct pipe_sampler_view*)view;
 }
 
+static struct pipe_sampler_view *
+r300_create_sampler_view(struct pipe_context *pipe,
+                         struct pipe_resource *texture,
+                         const struct pipe_sampler_view *templ)
+{
+    return r300_create_sampler_view_custom(pipe, texture, templ,
+                                           r300_resource(texture)->tex.width0,
+                                           r300_resource(texture)->tex.height0);
+}
+
+
 static void
 r300_sampler_view_destroy(struct pipe_context *pipe,
                           struct pipe_sampler_view *view)
@@ -1527,7 +1582,8 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
     }
 
     r300_mark_atom_dirty(r300, &r300->viewport_state);
-    if (r300->fs.state && r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) {
+    if (r300->fs.state && r300_fs(r300)->shader &&
+        r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) {
         r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state);
     }
 }
@@ -1537,28 +1593,20 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
                                     const struct pipe_vertex_buffer* buffers)
 {
     struct r300_context* r300 = r300_context(pipe);
-    unsigned i;
-    struct pipe_vertex_buffer dummy_vb = {0};
 
     /* There must be at least one vertex buffer set, otherwise it locks up. */
     if (!count) {
-        dummy_vb.buffer = r300->dummy_vb;
-        buffers = &dummy_vb;
+        buffers = &r300->dummy_vb;
         count = 1;
     }
 
-    u_vbuf_mgr_set_vertex_buffers(r300->vbuf_mgr, count, buffers);
+    util_copy_vertex_buffers(r300->vertex_buffer,
+                             &r300->nr_vertex_buffers,
+                             buffers, count);
 
     if (r300->screen->caps.has_tcl) {
-        /* HW TCL. */
-        for (i = 0; i < count; i++) {
-            if (buffers[i].buffer &&
-               !r300_resource(buffers[i].buffer)->b.user_ptr) {
-            }
-        }
         r300->vertex_arrays_dirty = TRUE;
     } else {
-        /* SW TCL. */
         draw_set_vertex_buffers(r300->draw, count, buffers);
     }
 }
@@ -1568,16 +1616,11 @@ static void r300_set_index_buffer(struct pipe_context* pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
 
-    if (ib && ib->buffer) {
-        assert(ib->offset % ib->index_size == 0);
-
+    if (ib) {
         pipe_resource_reference(&r300->index_buffer.buffer, ib->buffer);
-        memcpy(&r300->index_buffer, ib, sizeof(r300->index_buffer));
-        r300->index_buffer.offset /= r300->index_buffer.index_size;
-    }
-    else {
+        memcpy(&r300->index_buffer, ib, sizeof(*ib));
+    } else {
         pipe_resource_reference(&r300->index_buffer.buffer, NULL);
-        memset(&r300->index_buffer, 0, sizeof(r300->index_buffer));
     }
 
     if (!r300->screen->caps.has_tcl) {
@@ -1593,12 +1636,6 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
     enum pipe_format format;
     unsigned i;
 
-    if (velems->count > 16) {
-        fprintf(stderr, "r300: More than 16 vertex elements are not supported,"
-                " requested %i, using 16.\n", velems->count);
-        velems->count = 16;
-    }
-
     /* Vertex shaders have no semantics on their inputs,
      * so PSC should just route stuff based on the vertex elements,
      * and not on attrib information. */
@@ -1639,7 +1676,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
                                                unsigned count,
                                                const struct pipe_vertex_element* attribs)
 {
-    struct r300_context *r300 = r300_context(pipe);
     struct r300_vertex_element_state *velems;
     unsigned i;
     struct pipe_vertex_element dummy_attrib = {0};
@@ -1649,17 +1685,18 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
         dummy_attrib.src_format = PIPE_FORMAT_R8G8B8A8_UNORM;
         attribs = &dummy_attrib;
         count = 1;
+    } else if (count > 16) {
+        fprintf(stderr, "r300: More than 16 vertex elements are not supported,"
+                " requested %i, using 16.\n", count);
+        count = 16;
     }
 
-    assert(count <= PIPE_MAX_ATTRIBS);
     velems = CALLOC_STRUCT(r300_vertex_element_state);
     if (!velems)
         return NULL;
 
     velems->count = count;
-    velems->vmgr_elements =
-        u_vbuf_mgr_create_vertex_elements(r300->vbuf_mgr, count, attribs,
-                                          velems->velem);
+    memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
 
     if (r300_screen(pipe->screen)->caps.has_tcl) {
         /* Setup PSC.
@@ -1688,8 +1725,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
 
     r300->velems = velems;
 
-    u_vbuf_mgr_bind_vertex_elements(r300->vbuf_mgr, state, velems->vmgr_elements);
-
     if (r300->draw) {
         draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
         return;
@@ -1702,10 +1737,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
 
 static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state)
 {
-    struct r300_context *r300 = r300_context(pipe);
-    struct r300_vertex_element_state *velems = state;
-
-    u_vbuf_mgr_destroy_vertex_elements(r300->vbuf_mgr, velems->vmgr_elements);
     FREE(state);
 }
 
@@ -1720,10 +1751,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_init_vs_outputs(vs);
+        r300_init_vs_outputs(r300, vs);
         r300_translate_vertex_shader(r300, vs);
     } else {
-        r300_draw_init_vertex_shader(r300->draw, vs);
+        r300_draw_init_vertex_shader(r300, vs);
     }
 
     return vs;
@@ -1749,9 +1780,8 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
     if (r300->screen->caps.has_tcl) {
         unsigned fc_op_dwords = r300->screen->caps.is_r500 ? 3 : 2;
         r300_mark_atom_dirty(r300, &r300->vs_state);
-        r300->vs_state.size =
-                vs->code.length + 9 +
-        (vs->code.num_fc_ops ? vs->code.num_fc_ops * fc_op_dwords + 4 : 0);
+        r300->vs_state.size = vs->code.length + 9 +
+                       (R300_VS_MAX_FC_OPS * fc_op_dwords + 4);
 
         r300_mark_atom_dirty(r300, &r300->vs_constants);
         r300->vs_constants.size =
@@ -1789,9 +1819,10 @@ 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_resource *buf)
+                                     struct pipe_constant_buffer *cb)
 {
     struct r300_context* r300 = r300_context(pipe);
+    struct pipe_resource *buf = cb ? cb->buffer : NULL;
     struct r300_constant_buffer *cbuf;
     struct r300_resource *rbuf = r300_resource(buf);
     uint32_t *mapped;
@@ -1810,8 +1841,8 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
     if (buf == NULL || buf->width0 == 0)
         return;
 
-    if (rbuf->b.user_ptr)
-        mapped = (uint32_t*)rbuf->b.user_ptr;
+    if (rbuf->b.b.user_ptr)
+        mapped = (uint32_t*)rbuf->b.b.user_ptr;
     else if (rbuf->constant_buffer)
         mapped = (uint32_t*)rbuf->constant_buffer;
     else
@@ -1849,6 +1880,14 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
     }
 }
 
+static void r300_texture_barrier(struct pipe_context *pipe)
+{
+    struct r300_context *r300 = r300_context(pipe);
+
+    r300_mark_atom_dirty(r300, &r300->gpu_flush);
+    r300_mark_atom_dirty(r300, &r300->texture_cache_inval);
+}
+
 void r300_init_state_functions(struct r300_context* r300)
 {
     r300->context.create_blend_state = r300_create_blend_state;
@@ -1904,4 +1943,6 @@ void r300_init_state_functions(struct r300_context* r300)
     r300->context.create_vs_state = r300_create_vs_state;
     r300->context.bind_vs_state = r300_bind_vs_state;
     r300->context.delete_vs_state = r300_delete_vs_state;
+
+    r300->context.texture_barrier = r300_texture_barrier;
 }