r300g: turn rasterizer state into a command buffer
authorMarek Olšák <maraeo@gmail.com>
Fri, 25 Jun 2010 02:48:02 +0000 (04:48 +0200)
committerMarek Olšák <maraeo@gmail.com>
Sun, 27 Jun 2010 13:13:13 +0000 (15:13 +0200)
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_render_stencilref.c
src/gallium/drivers/r300/r300_state.c

index 5e35d8907122ec78ec970d73bfc0f80199e0c37e..760336cc3036df2eb76b87beb7d39496f48e6304 100644 (file)
@@ -115,31 +115,19 @@ struct r300_rs_state {
     /* Draw-specific rasterizer state. */
     struct pipe_rasterizer_state rs_draw;
 
-    uint32_t vap_control_status;    /* R300_VAP_CNTL_STATUS: 0x2140 */
-    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 */
-    float depth_scale;            /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */
-                                  /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */
-    float depth_offset;           /* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */
-                                  /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */
-    uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */
-    uint32_t cull_mode;             /* R300_SU_CULL_MODE: 0x42b8 */
-    uint32_t line_stipple_config;   /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */
-    uint32_t line_stipple_value;    /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
+    /* Command buffers. */
+    uint32_t cb_main[25];
+    uint32_t cb_poly_offset_zb16[5];
+    uint32_t cb_poly_offset_zb24[5];
+
+    /* The index to cb_main where the cull_mode register value resides. */
+    unsigned cull_mode_index;
+
+    /* Whether polygon offset is enabled. */
+    boolean polygon_offset_enable;
+
+    /* This is emitted in the draw function. */
     uint32_t color_control;         /* R300_GA_COLOR_CONTROL: 0x4278 */
-    uint32_t polygon_mode;          /* R300_GA_POLY_MODE: 0x4288 */
-    uint32_t clip_rule;             /* R300_SC_CLIP_RULE: 0x43D0 */
-
-    /* Specifies top of Raster pipe specific enable controls,
-     * i.e. texture coordinates stuffing for points, lines, triangles */
-    uint32_t stuffing_enable;       /* R300_GB_ENABLE: 0x4008 */
-
-    /* Point sprites texture coordinates, 0: lower left, 1: upper right */
-    float point_texcoord_left;      /* R300_GA_POINT_S0: 0x4200 */
-    float point_texcoord_bottom;    /* R300_GA_POINT_T0: 0x4204 */
-    float point_texcoord_right;     /* R300_GA_POINT_S1: 0x4208 */
-    float point_texcoord_top;       /* R300_GA_POINT_T1: 0x420c */
 };
 
 struct r300_rs_block {
index 65cddc88481c5646829d460f0f8246ec5a40b41e..5effb61200e845a0d51cb6277026ea1844bd6335 100644 (file)
@@ -565,49 +565,17 @@ void r300_emit_invariant_state(struct r300_context *r300,
 void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state)
 {
     struct r300_rs_state* rs = state;
-    float scale, offset;
     CS_LOCALS(r300);
 
     BEGIN_CS(size);
-    OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status);
-    OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size);
-    OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2);
-    OUT_CS(rs->point_minmax);
-    OUT_CS(rs->line_control);
-
+    OUT_CS_TABLE(rs->cb_main, 25);
     if (rs->polygon_offset_enable) {
-        scale = rs->depth_scale * 12;
-        offset = rs->depth_offset;
-
-        switch (r300->zbuffer_bpp) {
-            case 16:
-                offset *= 4;
-                break;
-            case 24:
-                offset *= 2;
-                break;
+        if (r300->zbuffer_bpp == 16) {
+            OUT_CS_TABLE(rs->cb_poly_offset_zb16, 5);
+        } else {
+            OUT_CS_TABLE(rs->cb_poly_offset_zb24, 5);
         }
-
-        OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
-        OUT_CS_32F(scale);
-        OUT_CS_32F(offset);
-        OUT_CS_32F(scale);
-        OUT_CS_32F(offset);
     }
-
-    OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2);
-    OUT_CS(rs->polygon_offset_enable);
-    OUT_CS(rs->cull_mode);
-    OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config);
-    OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value);
-    OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode);
-    OUT_CS_REG(R300_SC_CLIP_RULE, rs->clip_rule);
-    OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable);
-    OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
-    OUT_CS_32F(rs->point_texcoord_left);
-    OUT_CS_32F(rs->point_texcoord_bottom);
-    OUT_CS_32F(rs->point_texcoord_right);
-    OUT_CS_32F(rs->point_texcoord_top);
     END_CS;
 }
 
index d509ded3ec8a4c06ad053a10e11121e606b2f705..9a6b4e12ff1ed0c135c91d8b8a23ef5cc4e20cc7 100644 (file)
@@ -64,12 +64,12 @@ static void r300_stencilref_begin(struct r300_context *r300)
     struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
 
     /* Save state. */
-    sr->rs_cull_mode = rs->cull_mode;
+    sr->rs_cull_mode = rs->cb_main[rs->cull_mode_index];
     sr->zb_stencilrefmask = dsa->stencil_ref_mask;
     sr->ref_value_front = r300->stencil_ref.ref_value[0];
 
     /* We *cull* pixels, therefore no need to mask out the bits. */
-    rs->cull_mode |= R300_CULL_BACK;
+    rs->cb_main[rs->cull_mode_index] |= R300_CULL_BACK;
 
     r300->rs_state.dirty = TRUE;
 }
@@ -81,7 +81,7 @@ static void r300_stencilref_switch_side(struct r300_context *r300)
     struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
     struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
 
-    rs->cull_mode = sr->rs_cull_mode | R300_CULL_FRONT;
+    rs->cb_main[rs->cull_mode_index] = sr->rs_cull_mode | R300_CULL_FRONT;
     dsa->stencil_ref_mask = dsa->stencil_ref_bf;
     r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1];
 
@@ -97,7 +97,7 @@ static void r300_stencilref_end(struct r300_context *r300)
     struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
 
     /* Restore state. */
-    rs->cull_mode = sr->rs_cull_mode;
+    rs->cb_main[rs->cull_mode_index] = sr->rs_cull_mode;
     dsa->stencil_ref_mask = sr->zb_stencilrefmask;
     r300->stencil_ref.ref_value[0] = sr->ref_value_front;
 
index ea1210fcb482ab435f70e86113039f1841b0a5ab..09e694f041ae59c3f3b141135c851b09dcfb54c5 100644 (file)
@@ -850,6 +850,27 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
     int i;
     float psiz;
+    uint32_t vap_control_status;    /* R300_VAP_CNTL_STATUS: 0x2140 */
+    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 */
+    uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */
+    uint32_t cull_mode;             /* R300_SU_CULL_MODE: 0x42b8 */
+    uint32_t line_stipple_config;   /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */
+    uint32_t line_stipple_value;    /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
+    uint32_t polygon_mode;          /* R300_GA_POLY_MODE: 0x4288 */
+    uint32_t clip_rule;             /* R300_SC_CLIP_RULE: 0x43D0 */
+
+    /* Specifies top of Raster pipe specific enable controls,
+     * i.e. texture coordinates stuffing for points, lines, triangles */
+    uint32_t stuffing_enable;       /* R300_GB_ENABLE: 0x4008 */
+
+    /* Point sprites texture coordinates, 0: lower left, 1: upper right */
+    float point_texcoord_left;      /* R300_GA_POINT_S0: 0x4200 */
+    float point_texcoord_bottom;    /* R300_GA_POINT_T0: 0x4204 */
+    float point_texcoord_right;     /* R300_GA_POINT_S1: 0x4208 */
+    float point_texcoord_top;       /* R300_GA_POINT_T1: 0x420c */
+    CB_LOCALS;
 
     /* Copy rasterizer state. */
     rs->rs = *state;
@@ -859,18 +880,18 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     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;
+    vap_control_status = R300_VC_NO_SWAP;
 #else
-    rs->vap_control_status = R300_VC_32BIT_SWAP;
+    vap_control_status = R300_VC_32BIT_SWAP;
 #endif
 
     /* If no TCL engine is present, turn off the HW TCL. */
     if (!r300_screen(pipe->screen)->caps.has_tcl) {
-        rs->vap_control_status |= R300_VAP_TCL_BYPASS;
+        vap_control_status |= R300_VAP_TCL_BYPASS;
     }
 
     /* Point size width and height. */
-    rs->point_size =
+    point_size =
         pack_float_16_6x(state->point_size) |
         (pack_float_16_6x(state->point_size) << R300_POINTSIZE_X_SHIFT);
 
@@ -880,68 +901,67 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
          * Clamp to [0, max FB size] */
         psiz = pipe->screen->get_paramf(pipe->screen,
                                         PIPE_CAP_MAX_POINT_WIDTH);
-        rs->point_minmax =
+        point_minmax =
             pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT;
     } else {
         /* We cannot disable the point-size vertex output,
          * so clamp it. */
         psiz = state->point_size;
-        rs->point_minmax =
+        point_minmax =
             (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MIN_SHIFT) |
             (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT);
     }
 
     /* Line control. */
-    rs->line_control = pack_float_16_6x(state->line_width) |
+    line_control = pack_float_16_6x(state->line_width) |
         R300_GA_LINE_CNTL_END_TYPE_COMP;
 
     /* Enable polygon mode */
+    polygon_mode = 0;
     if (state->fill_front != PIPE_POLYGON_MODE_FILL ||
         state->fill_back != PIPE_POLYGON_MODE_FILL) {
-        rs->polygon_mode = R300_GA_POLY_MODE_DUAL;
+        polygon_mode = R300_GA_POLY_MODE_DUAL;
     }
 
     /* Front face */
     if (state->front_ccw) 
-        rs->cull_mode = R300_FRONT_FACE_CCW;
+        cull_mode = R300_FRONT_FACE_CCW;
     else
-        rs->cull_mode = R300_FRONT_FACE_CW;
+        cull_mode = R300_FRONT_FACE_CW;
 
     /* Polygon offset */
+    polygon_offset_enable = 0;
     if (util_get_offset(state, state->fill_front)) {
-       rs->polygon_offset_enable |= R300_FRONT_ENABLE;
+       polygon_offset_enable |= R300_FRONT_ENABLE;
     }
     if (util_get_offset(state, state->fill_back)) {
-       rs->polygon_offset_enable |= R300_BACK_ENABLE;
+       polygon_offset_enable |= R300_BACK_ENABLE;
     }
 
+    rs->polygon_offset_enable = polygon_offset_enable != 0;
+
     /* Polygon mode */
-    if (rs->polygon_mode) {
-       rs->polygon_mode |=
+    if (polygon_mode) {
+       polygon_mode |=
           r300_translate_polygon_mode_front(state->fill_front);
-       rs->polygon_mode |=
+       polygon_mode |=
           r300_translate_polygon_mode_back(state->fill_back);
     }
 
     if (state->cull_face & PIPE_FACE_FRONT) {
-        rs->cull_mode |= R300_CULL_FRONT;
+        cull_mode |= R300_CULL_FRONT;
     }
     if (state->cull_face & PIPE_FACE_BACK) {
-        rs->cull_mode |= R300_CULL_BACK;
-    }
-
-    if (rs->polygon_offset_enable) {
-        rs->depth_offset = state->offset_units;
-        rs->depth_scale = state->offset_scale;
+        cull_mode |= R300_CULL_BACK;
     }
 
     if (state->line_stipple_enable) {
-        rs->line_stipple_config =
+        line_stipple_config =
             R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_LINE |
             (fui((float)state->line_stipple_factor) &
                 R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_MASK);
         /* XXX this might need to be scaled up */
-        rs->line_stipple_value = state->line_stipple_pattern;
+        line_stipple_value = state->line_stipple_pattern;
     }
 
     if (state->flatshade) {
@@ -950,32 +970,80 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
         rs->color_control = R300_SHADE_MODEL_SMOOTH;
     }
 
-    rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
+    clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
 
     /* Point sprites */
+    stuffing_enable = 0;
     if (state->sprite_coord_enable) {
-        rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
+        stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
        for (i = 0; i < 8; i++) {
            if (state->sprite_coord_enable & (1 << i))
-               rs->stuffing_enable |=
+                stuffing_enable |=
                    R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
        }
 
-        rs->point_texcoord_left = 0.0f;
-        rs->point_texcoord_right = 1.0f;
+        point_texcoord_left = 0.0f;
+        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;
+                point_texcoord_top = 0.0f;
+                point_texcoord_bottom = 1.0f;
                 break;
             case PIPE_SPRITE_COORD_LOWER_LEFT:
-                rs->point_texcoord_top = 1.0f;
-                rs->point_texcoord_bottom = 0.0f;
+                point_texcoord_top = 1.0f;
+                point_texcoord_bottom = 0.0f;
                 break;
         }
     }
 
+    /* Build the main command buffer. */
+    BEGIN_CB(rs->cb_main, 25);
+    OUT_CB_REG(R300_VAP_CNTL_STATUS, vap_control_status);
+    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 = 25 - cs_count;
+    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);
+    OUT_CB_REG(R300_GA_POLY_MODE, polygon_mode);
+    OUT_CB_REG(R300_SC_CLIP_RULE, clip_rule);
+    OUT_CB_REG(R300_GB_ENABLE, stuffing_enable);
+    OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4);
+    OUT_CB_32F(point_texcoord_left);
+    OUT_CB_32F(point_texcoord_bottom);
+    OUT_CB_32F(point_texcoord_right);
+    OUT_CB_32F(point_texcoord_top);
+    END_CB;
+
+    /* Build the two command buffers for polygon offset setup. */
+    if (polygon_offset_enable) {
+        float scale = state->offset_scale * 12;
+        float offset = state->offset_units * 4;
+
+        BEGIN_CB(rs->cb_poly_offset_zb16, 5);
+        OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
+        OUT_CB_32F(scale);
+        OUT_CB_32F(offset);
+        OUT_CB_32F(scale);
+        OUT_CB_32F(offset);
+        END_CB;
+
+        offset = state->offset_units * 2;
+
+        BEGIN_CB(rs->cb_poly_offset_zb24, 5);
+        OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
+        OUT_CB_32F(scale);
+        OUT_CB_32F(offset);
+        OUT_CB_32F(scale);
+        OUT_CB_32F(offset);
+        END_CB;
+    }
+
     return (void*)rs;
 }