Implement line stippling.
authorBrian <brian.paul@tungstengraphics.com>
Wed, 25 Jul 2007 21:48:09 +0000 (15:48 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Wed, 25 Jul 2007 21:48:09 +0000 (15:48 -0600)
Also added draw_stage::reset_line_stipple().  There may be a better way
of doing that though.

src/mesa/pipe/draw/draw_clip.c
src/mesa/pipe/draw/draw_cull.c
src/mesa/pipe/draw/draw_flatshade.c
src/mesa/pipe/draw/draw_offset.c
src/mesa/pipe/draw/draw_private.h
src/mesa/pipe/draw/draw_twoside.c
src/mesa/pipe/draw/draw_unfilled.c
src/mesa/pipe/draw/draw_vb.c
src/mesa/pipe/softpipe/sp_context.h
src/mesa/pipe/softpipe/sp_prim_setup.c

index b220cc3643fdcdfdc164cab6c652202ea3395a06..f8bacf8a8187574ddd1687548366f6fd8ab97ff6 100644 (file)
@@ -433,6 +433,12 @@ static void clip_end( struct draw_stage *stage )
 }
 
 
+static void clip_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
 /**
  * Allocate a new clipper stage.
  * \return pointer to new stage object
@@ -449,6 +455,7 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw )
    clipper->stage.line = clip_line;
    clipper->stage.tri = clip_tri;
    clipper->stage.end = clip_end;
+   clipper->stage.reset_stipple_counter = clip_reset_stipple_counter;
 
    clipper->plane = draw->plane;
 
index e563f9f45f6de92e6fa5a0144230fbe4ff20c9ef..8b2ac5ea5f9685ec3a36be999b22dcbdc1e78699 100644 (file)
@@ -111,6 +111,11 @@ static void cull_end( struct draw_stage *stage )
 }
 
 
+static void cull_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
 /**
  * Create a new polygon culling stage.
  */
@@ -127,6 +132,7 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw )
    cull->stage.line = cull_line;
    cull->stage.tri = cull_tri;
    cull->stage.end = cull_end;
+   cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
 
    return &cull->stage;
 }
index 09547865fadc653c29e26229c497e20a4ff1b02e..cf5e762079adbfe94815db95a6d9ec56e56d5d24 100644 (file)
@@ -130,6 +130,12 @@ static void flatshade_end( struct draw_stage *stage )
 }
 
 
+static void flatshade_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
 /**
  * Create flatshading drawing stage.
  */
@@ -146,6 +152,7 @@ struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
    flatshade->stage.line = flatshade_line;
    flatshade->stage.tri = flatshade_tri;
    flatshade->stage.end = flatshade_end;
+   flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
 
    flatshade->lookup = draw->vf_attr_to_slot;
 
index 1a7f56d0c51392c381bd096dd8dbf2f5fcf876fa..9f6656635386677124116a3981e680dae28b1e0a 100644 (file)
@@ -145,6 +145,12 @@ static void offset_end( struct draw_stage *stage )
 }
 
 
+static void offset_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
 /**
  * Create polygon offset drawing stage.
  */
@@ -161,6 +167,7 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw )
    offset->stage.line = offset_line;
    offset->stage.tri = offset_tri;
    offset->stage.end = offset_end;
+   offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
 
    return &offset->stage;
 }
index 573b5bf58881a851d88226d90812adbbcbc907e1..3dfaa0581db61f3bacebb1858e0079f45ae52d0e 100644 (file)
@@ -98,6 +98,8 @@ struct draw_stage
                struct prim_header * );
    
    void (*end)( struct draw_stage * );
+
+   void (*reset_stipple_counter)( struct draw_stage * );
 };
 
 
index 9f26335fb6530a6c28940cdeb7d07d574e34bf29..fdda6b362fa5c4f23d6ee0126f367e2be11bf9ae 100644 (file)
@@ -139,6 +139,12 @@ static void twoside_end( struct draw_stage *stage )
 }
 
 
+static void twoside_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
 /**
  * Create twoside pipeline stage.
  */
@@ -155,6 +161,7 @@ struct draw_stage *draw_twoside_stage( struct draw_context *draw )
    twoside->stage.line = twoside_line;
    twoside->stage.tri = twoside_tri;
    twoside->stage.end = twoside_end;
+   twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
 
    twoside->lookup = draw->vf_attr_to_slot;
 
index f0aee583330710fc71d948b4435b10ccaf1b8766..82e8775f59f1d6c3faaa5a1baa0429f1a1e60a3c 100644 (file)
@@ -156,6 +156,12 @@ static void unfilled_end( struct draw_stage *stage )
 }
 
 
+static void unfilled_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
 /**
  * Create unfilled triangle stage.
  */
@@ -173,6 +179,7 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
    unfilled->stage.line = unfilled_line;
    unfilled->stage.tri = unfilled_tri;
    unfilled->stage.end = unfilled_end;
+   unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
 
    return &unfilled->stage;
 }
index ac721c589d43b87f159e2165a569f691d675bb06..ac126c5baa50f8f153a9910f956cd9549068126d 100644 (file)
@@ -151,12 +151,14 @@ static void draw_indexed_prim( struct draw_context *draw,
         prim.v[0] = get_vertex( draw, elts[i + 0] );
         prim.v[1] = get_vertex( draw, elts[i + 1] );
       
+         first->reset_stipple_counter( first );
         first->line( first, &prim );
       }
       break;
 
    case GL_LINE_LOOP:  
       if (count >= 2) {
+         first->reset_stipple_counter( first );
         for (i = 1; i < count; i++) {
            prim.v[0] = get_vertex( draw, elts[i-1] );
            prim.v[1] = get_vertex( draw, elts[i] );        
@@ -178,6 +180,7 @@ static void draw_indexed_prim( struct draw_context *draw,
        * require more complex code here.
        */
       if (count >= 2) {
+         first->reset_stipple_counter( first );
         prim.v[0] = 0;
         prim.v[1] = get_vertex( draw, elts[0] );
         
@@ -313,13 +316,15 @@ static void draw_prim( struct draw_context *draw,
       for (i = 0; i+1 < count; i += 2) {
         prim.v[0] = get_vertex( draw, start + i + 0 );
         prim.v[1] = get_vertex( draw, start + i + 1 );
-      
+
+         first->reset_stipple_counter( first );
         first->line( first, &prim );
       }
       break;
 
    case GL_LINE_LOOP:  
       if (count >= 2) {
+         first->reset_stipple_counter( first );
         for (i = 1; i < count; i++) {
            prim.v[0] = get_vertex( draw, start + i - 1 );
            prim.v[1] = get_vertex( draw, start + i );      
@@ -334,6 +339,7 @@ static void draw_prim( struct draw_context *draw,
 
    case GL_LINE_STRIP:
       if (count >= 2) {
+         first->reset_stipple_counter( first );
         prim.v[0] = 0;
         prim.v[1] = get_vertex( draw, start + 0 );
         
index ef1a06ccaf6ab63adf5f152470251928a46f2c36..8871b45d4fff6ace48deb77dcbb048575f7d34b7 100644 (file)
@@ -111,12 +111,16 @@ struct softpipe_context {
    GLboolean need_z;  /**< produce quad/fragment Z values? */
    GLboolean need_w;  /**< produce quad/fragment W values? */
 
+#if 0
    /* Stipple derived state:
     */
    GLubyte stipple_masks[16][16];
+#endif
 
    GLuint occlusion_counter;
 
+   GLuint line_stipple_counter;
+
    /** Software quad rendering pipeline */
    struct {
       struct quad_stage *polygon_stipple;
index 6420fc88094e7d626236d8bad5f7f58a5366a4b5..091a2343a9cb588862ecc59d982994607324592f 100644 (file)
@@ -706,6 +706,17 @@ plot(struct setup_stage *setup, GLint x, GLint y)
 }
 
 
+/**
+ * Determine whether or not to emit a line fragment by checking
+ * line stipple pattern.
+ */
+static INLINE GLuint
+stipple_test(GLint counter, GLushort pattern, GLint factor)
+{
+   GLint b = (counter / factor) & 0xf;
+   return (1 << b) & pattern;
+}
+
 
 /**
  * Do setup for line rasterization, then render the line.
@@ -718,6 +729,7 @@ setup_line(struct draw_stage *stage, struct prim_header *prim)
    const struct vertex_header *v0 = prim->v[0];
    const struct vertex_header *v1 = prim->v[1];
    struct setup_stage *setup = setup_stage( stage );
+   struct softpipe_context *sp = setup->softpipe;
 
    GLint x0 = (GLint) v0->data[0][0];
    GLint x1 = (GLint) v1->data[0][0];
@@ -763,7 +775,12 @@ setup_line(struct draw_stage *stage, struct prim_header *prim)
       const GLint errorDec = error - dx;
 
       for (i = 0; i < dx; i++) {
-         plot(setup, x0, y0);
+         if (!sp->setup.line_stipple_enable ||
+             stipple_test(sp->line_stipple_counter,
+                          sp->setup.line_stipple_pattern,
+                          sp->setup.line_stipple_factor + 1)) {
+             plot(setup, x0, y0);
+         }
 
          x0 += xstep;
          if (error < 0) {
@@ -773,6 +790,8 @@ setup_line(struct draw_stage *stage, struct prim_header *prim)
             error += errorDec;
             y0 += ystep;
          }
+
+         sp->line_stipple_counter++;
       }
    }
    else {
@@ -783,7 +802,12 @@ setup_line(struct draw_stage *stage, struct prim_header *prim)
       const GLint errorDec = error - dy;
 
       for (i = 0; i < dy; i++) {
-         plot(setup, x0, y0);
+         if (!sp->setup.line_stipple_enable ||
+             stipple_test(sp->line_stipple_counter,
+                          sp->setup.line_stipple_pattern,
+                          sp->setup.line_stipple_factor + 1)) {
+            plot(setup, x0, y0);
+         }
 
          y0 += ystep;
 
@@ -794,6 +818,8 @@ setup_line(struct draw_stage *stage, struct prim_header *prim)
             error += errorDec;
             x0 += xstep;
          }
+
+         sp->line_stipple_counter++;
       }
    }
 
@@ -984,6 +1010,13 @@ static void setup_end( struct draw_stage *stage )
 }
 
 
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+   struct setup_stage *setup = setup_stage(stage);
+   setup->softpipe->line_stipple_counter = 0;
+}
+
+
 /**
  * Create a new primitive setup/render stage.
  */
@@ -998,6 +1031,7 @@ struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
    setup->stage.line = setup_line;
    setup->stage.tri = setup_tri;
    setup->stage.end = setup_end;
+   setup->stage.reset_stipple_counter = reset_stipple_counter;
 
    setup->quad.coef = setup->coef;