nv50: rasterizer stateobj
authorBen Skeggs <skeggsb@gmail.com>
Tue, 11 Mar 2008 17:29:58 +0000 (04:29 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Tue, 11 Mar 2008 17:29:58 +0000 (04:29 +1100)
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_state.c
src/gallium/drivers/nv50/nv50_state_validate.c

index 406ad2c..d839cf7 100644 (file)
@@ -28,6 +28,7 @@
 #define NV50_NEW_STIPPLE       (1 << 3)
 #define NV50_NEW_SCISSOR       (1 << 4)
 #define NV50_NEW_VIEWPORT      (1 << 5)
+#define NV50_NEW_RASTERIZER    (1 << 6)
 
 struct nv50_blend_stateobj {
        struct pipe_blend_state pipe;
@@ -39,6 +40,11 @@ struct nv50_zsa_stateobj {
        struct nouveau_stateobj *so;
 };
 
+struct nv50_rasterizer_stateobj {
+       struct pipe_rasterizer_state pipe;
+       struct nouveau_stateobj *so;
+};
+
 struct nv50_context {
        struct pipe_context pipe;
 
@@ -50,6 +56,7 @@ struct nv50_context {
        unsigned dirty;
        struct nv50_blend_stateobj *blend;
        struct nv50_zsa_stateobj *zsa;
+       struct nv50_rasterizer_stateobj *rasterizer;
        struct pipe_blend_color blend_colour;
        struct pipe_poly_stipple stipple;
        struct pipe_scissor_state scissor;
index 40e23f4..088df9e 100644 (file)
@@ -110,17 +110,135 @@ static void *
 nv50_rasterizer_state_create(struct pipe_context *pipe,
                             const struct pipe_rasterizer_state *cso)
 {
-       return NULL;
+       struct nouveau_stateobj *so = so_new(64, 0);
+       struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+       struct nv50_rasterizer_stateobj *rso =
+               CALLOC_STRUCT(nv50_rasterizer_stateobj);
+       unsigned i;
+
+       /*XXX: ignored
+        *      - light_twosize
+        *      - point_smooth
+        *      - multisample
+        *      - point_sprite / sprite_coord_mode
+        */
+
+       so_method(so, tesla, NV50TCL_SHADE_MODEL, 1);
+       so_data  (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT :
+                                      NV50TCL_SHADE_MODEL_SMOOTH);
+
+       so_method(so, tesla, NV50TCL_LINE_WIDTH, 1);
+       so_data  (so, fui(cso->line_width));
+       so_method(so, tesla, NV50TCL_LINE_SMOOTH_ENABLE, 1);
+       so_data  (so, cso->line_smooth ? 1 : 0);
+       if (cso->line_stipple_enable) {
+               so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
+               so_data  (so, 1);
+               so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1);
+               so_data  (so, (cso->line_stipple_pattern << 16) |
+                              cso->line_stipple_factor);
+       } else {
+               so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, tesla, NV50TCL_POINT_SIZE, 1);
+       so_data  (so, fui(cso->point_size));
+
+       so_method(so, tesla, NV50TCL_POLYGON_MODE_FRONT, 3);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+       } else {
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+       }
+       so_data(so, cso->poly_smooth ? 1 : 0);
+
+       so_method(so, tesla, NV50TCL_CULL_FACE_ENABLE, 3);
+       so_data  (so, cso->cull_mode != PIPE_WINDING_NONE);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, NV50TCL_FRONT_FACE_CCW);
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               }
+       } else {
+               so_data(so, NV50TCL_FRONT_FACE_CW);
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               }
+       }
+
+       so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_ENABLE, 1);
+       so_data  (so, cso->poly_stipple_enable ? 1 : 0);
+
+       so_method(so, tesla, NV50TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+
+       if (cso->offset_cw || cso->offset_ccw) {
+               so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1);
+               so_data  (so, fui(cso->offset_scale));
+               so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1);
+               so_data  (so, fui(cso->offset_units * 2));
+       }
+
+       rso->pipe = *cso;
+       so_ref(so, &rso->so);
+       return (void *)rso;
 }
 
 static void
 nv50_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->rasterizer = hwcso;
+       nv50->dirty |= NV50_NEW_RASTERIZER;
 }
 
 static void
 nv50_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_rasterizer_stateobj *rso = hwcso;
+
+       so_ref(NULL, &rso->so);
+       FREE(rso);
 }
 
 static void *
index 8920b6f..8921bfa 100644 (file)
@@ -15,6 +15,9 @@ nv50_state_validate(struct nv50_context *nv50)
        if (nv50->dirty & NV50_NEW_ZSA)
                so_emit(nvws, nv50->zsa->so);
 
+       if (nv50->dirty & NV50_NEW_RASTERIZER)
+               so_emit(nvws, nv50->rasterizer->so);
+
        if (nv50->dirty & NV50_NEW_BLEND_COLOUR) {
                so = so_new(5, 0);
                so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 8);