r300g: add generating texture coordinates for point sprites (WIP)
[mesa.git] / src / gallium / drivers / r300 / r300_state.c
index d4b7376f126c969b9efd5039673e995f812cbc4e..db7844eef0e5378f98126f2f4c3939a561d6b8b8 100644 (file)
@@ -34,6 +34,7 @@
 #include "r300_context.h"
 #include "r300_reg.h"
 #include "r300_screen.h"
+#include "r300_screen_buffer.h"
 #include "r300_state_inlines.h"
 #include "r300_fs.h"
 #include "r300_vs.h"
@@ -525,7 +526,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
         tex = (struct r300_texture*)old_state->cbufs[i]->texture;
 
         if (tex) {
-            r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+            r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
                                             tex->pitch[0],
                                             tex->microtile != 0,
                                             tex->macrotile != 0);
@@ -537,7 +538,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
         tex = (struct r300_texture*)old_state->zsbuf->texture;
 
         if (tex) {
-            r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+            r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
                                             tex->pitch[0],
                                             tex->microtile != 0,
                                             tex->macrotile != 0);
@@ -549,7 +550,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
         tex = (struct r300_texture*)new_state->cbufs[i]->texture;
         level = new_state->cbufs[i]->level;
 
-        r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+        r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
                                         tex->pitch[level],
                                         tex->microtile != 0,
                                         tex->mip_macrotile[level] != 0);
@@ -558,7 +559,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300,
         tex = (struct r300_texture*)new_state->zsbuf->texture;
         level = new_state->zsbuf->level;
 
-        r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer,
+        r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
                                         tex->pitch[level],
                                         tex->microtile != 0,
                                         tex->mip_macrotile[level] != 0);
@@ -714,6 +715,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 {
     struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
+    unsigned coord_index;
 
     /* Copy rasterizer state for Draw. */
     rs->rs = *state;
@@ -806,6 +808,32 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
         rs->color_control = R300_SHADE_MODEL_SMOOTH;
     }
 
+    /* Point sprites */
+    if (state->sprite_coord_enable) {
+        coord_index = ffs(state->sprite_coord_enable)-1;
+
+        SCREEN_DBG(r300screen, DBG_DRAW,
+                   "r300: point sprite: shader coord=%d\n", coord_index);
+
+        rs->stuffing_enable =
+            R300_GB_POINT_STUFF_ENABLE |
+            R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (coord_index*2));
+
+        rs->point_texcoord_left = 0.0f;
+        rs->point_texcoord_right = 1.0f;
+
+        switch (state->sprite_coord_mode) {
+            case PIPE_SPRITE_COORD_UPPER_LEFT:
+                rs->point_texcoord_top = 0.0f;
+                rs->point_texcoord_bottom = 1.0f;
+                break;
+            case PIPE_SPRITE_COORD_LOWER_LEFT:
+                rs->point_texcoord_top = 1.0f;
+                rs->point_texcoord_bottom = 0.0f;
+                break;
+        }
+    }
+
     return (void*)rs;
 }
 
@@ -815,6 +843,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
     struct r300_context* r300 = r300_context(pipe);
     struct r300_rs_state* rs = (struct r300_rs_state*)state;
     boolean scissor_was_enabled = r300->scissor_enabled;
+    int last_sprite_coord_index = r300->sprite_coord_index;
 
     if (r300->draw) {
         draw_flush(r300->draw);
@@ -824,17 +853,22 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
     if (rs) {
         r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
         r300->scissor_enabled = rs->rs.scissor;
+        r300->sprite_coord_index = ffs(rs->rs.sprite_coord_enable)-1;
     } else {
         r300->polygon_offset_enabled = FALSE;
         r300->scissor_enabled = FALSE;
+        r300->sprite_coord_index = -1;
     }
 
     UPDATE_STATE(state, r300->rs_state);
-    r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0);
+    r300->rs_state.size = 24 + (r300->polygon_offset_enabled ? 5 : 0);
 
     if (scissor_was_enabled != r300->scissor_enabled) {
         r300->scissor_state.dirty = TRUE;
     }
+    if (last_sprite_coord_index != r300->sprite_coord_index) {
+        r300->rs_block_state.dirty = TRUE;
+    }
 }
 
 /* Free rasterizer state. */
@@ -849,6 +883,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;
     int lod_bias;
     union util_color uc;
 
@@ -864,6 +899,8 @@ static void*
                                                    state->min_mip_filter,
                                                    state->max_anisotropy > 0);
 
+    sampler->filter0 |= r300_anisotropy(state->max_anisotropy);
+
     /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */
     /* We must pass these to the merge function to clamp them properly. */
     sampler->min_lod = MAX2((unsigned)state->min_lod, 0);
@@ -873,7 +910,13 @@ static void*
 
     sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT;
 
-    sampler->filter1 |= r300_anisotropy(state->max_anisotropy);
+    /* This is very high quality anisotropic filtering for R5xx.
+     * It's good for benchmarking the performance of texturing but
+     * in practice we don't want to slow down the driver because it's
+     * a pretty good performance killer. Feel free to play with it. */
+    if (DBG_ON(r300, DBG_ANISOHQ) && is_r500) {
+        sampler->filter1 |= r500_anisotropy(state->max_anisotropy);
+    }
 
     util_pack_color(state->border_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
     sampler->border_color = uc.ui;
@@ -928,6 +971,8 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
                                             struct pipe_sampler_view** views)
 {
     struct r300_context* r300 = r300_context(pipe);
+    struct r300_textures_state* state =
+        (struct r300_textures_state*)r300->textures_state.state;
     unsigned i;
     boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
     boolean dirty_tex = FALSE;
@@ -938,16 +983,16 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
     }
 
     for (i = 0; i < count; i++) {
-        if (r300->fragment_sampler_views[i] != views[i]) {
+        if (state->fragment_sampler_views[i] != views[i]) {
             struct r300_texture *texture;
-
-            pipe_sampler_view_reference(&r300->fragment_sampler_views[i],
-                views[i]);
+            pipe_sampler_view_reference(&state->fragment_sampler_views[i],
+                                        views[i]);
             dirty_tex = TRUE;
 
             texture = (struct r300_texture *)views[i]->texture;
 
-            /* R300-specific - set the texrect factor in a fragment shader */
+            /* R300-specific - set the texrect factor in the fragment shader */
             if (!is_r500 && texture->is_npot) {
                 /* XXX It would be nice to re-emit just 1 constant,
                  * XXX not all of them */
@@ -957,13 +1002,13 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
     }
 
     for (i = count; i < 8; i++) {
-        if (r300->fragment_sampler_views[i]) {
-            pipe_sampler_view_reference(&r300->fragment_sampler_views[i],
-                NULL);
+        if (state->fragment_sampler_views[i]) {
+            pipe_sampler_view_reference(&state->fragment_sampler_views[i],
+                                        NULL);
         }
     }
 
-    r300->fragment_sampler_view_count = count;
+    state->texture_count = count;
 
     r300->textures_state.dirty = TRUE;
 
@@ -977,7 +1022,6 @@ r300_create_sampler_view(struct pipe_context *pipe,
                          struct pipe_texture *texture,
                          const struct pipe_sampler_view *templ)
 {
-   struct r300_context *r300 = r300_context(pipe);
    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
 
    if (view) {
@@ -1061,17 +1105,30 @@ 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, max_index = (1 << 24) - 1;
+    int i;
+    unsigned max_index = (1 << 24) - 1;
+    boolean any_user_buffer = false;
 
-    memcpy(r300->vertex_buffer, buffers,
-        sizeof(struct pipe_vertex_buffer) * count);
+    if (count == r300->vertex_buffer_count &&
+       memcmp(r300->vertex_buffer, buffers, count * sizeof(buffers[0])) == 0)
+        return;
 
     for (i = 0; i < count; i++) {
+       pipe_buffer_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer);
+       if (r300_buffer_is_user_buffer(buffers[i].buffer))
+           any_user_buffer = true;
         max_index = MIN2(buffers[i].max_index, max_index);
     }
 
+    for ( ; i < r300->vertex_buffer_count; i++)
+       pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL);
+
+    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);