• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /**************************************************************************
2   *
3   * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4   * All Rights Reserved.
5   *
6   * Permission is hereby granted, free of charge, to any person obtaining a
7   * copy of this software and associated documentation files (the
8   * "Software"), to deal in the Software without restriction, including
9   * without limitation the rights to use, copy, modify, merge, publish,
10   * distribute, sub license, and/or sell copies of the Software, and to
11   * permit persons to whom the Software is furnished to do so, subject to
12   * the following conditions:
13   *
14   * The above copyright notice and this permission notice (including the
15   * next paragraph) shall be included in all copies or substantial portions
16   * of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19   * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21   * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22   * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25   *
26   **************************************************************************/
27  
28  /**
29   * \brief  Drawing stage for handling glPolygonMode(line/point).
30   * Convert triangles to points or lines as needed.
31   */
32  
33  /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
34   */
35  
36  #include "util/u_memory.h"
37  #include "pipe/p_defines.h"
38  #include "draw_private.h"
39  #include "draw_pipe.h"
40  
41  
42  struct unfilled_stage {
43     struct draw_stage stage;
44  
45     /** [0] = front face, [1] = back face.
46      * legal values:  PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE,
47      * and PIPE_POLYGON_MODE_POINT,
48      */
49     unsigned mode[2];
50  };
51  
52  
unfilled_stage(struct draw_stage * stage)53  static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage )
54  {
55     return (struct unfilled_stage *)stage;
56  }
57  
58  
59  
point(struct draw_stage * stage,struct vertex_header * v0)60  static void point( struct draw_stage *stage,
61  		   struct vertex_header *v0 )
62  {
63     struct prim_header tmp;
64     tmp.v[0] = v0;
65     stage->next->point( stage->next, &tmp );
66  }
67  
line(struct draw_stage * stage,struct vertex_header * v0,struct vertex_header * v1)68  static void line( struct draw_stage *stage,
69  		  struct vertex_header *v0,
70  		  struct vertex_header *v1 )
71  {
72     struct prim_header tmp;
73     tmp.v[0] = v0;
74     tmp.v[1] = v1;
75     stage->next->line( stage->next, &tmp );
76  }
77  
78  
points(struct draw_stage * stage,struct prim_header * header)79  static void points( struct draw_stage *stage,
80  		    struct prim_header *header )
81  {
82     struct vertex_header *v0 = header->v[0];
83     struct vertex_header *v1 = header->v[1];
84     struct vertex_header *v2 = header->v[2];
85  
86     if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) point( stage, v0 );
87     if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) point( stage, v1 );
88     if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) point( stage, v2 );
89  }
90  
91  
lines(struct draw_stage * stage,struct prim_header * header)92  static void lines( struct draw_stage *stage,
93  		   struct prim_header *header )
94  {
95     struct vertex_header *v0 = header->v[0];
96     struct vertex_header *v1 = header->v[1];
97     struct vertex_header *v2 = header->v[2];
98  
99     if (header->flags & DRAW_PIPE_RESET_STIPPLE)
100        stage->next->reset_stipple_counter( stage->next );
101  
102     if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) line( stage, v2, v0 );
103     if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) line( stage, v0, v1 );
104     if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) line( stage, v1, v2 );
105  }
106  
107  
108  /** For debugging */
109  static void
print_header_flags(unsigned flags)110  print_header_flags(unsigned flags)
111  {
112     debug_printf("header->flags = ");
113     if (flags & DRAW_PIPE_RESET_STIPPLE)
114        debug_printf("RESET_STIPPLE ");
115     if (flags & DRAW_PIPE_EDGE_FLAG_0)
116        debug_printf("EDGE_FLAG_0 ");
117     if (flags & DRAW_PIPE_EDGE_FLAG_1)
118        debug_printf("EDGE_FLAG_1 ");
119     if (flags & DRAW_PIPE_EDGE_FLAG_2)
120        debug_printf("EDGE_FLAG_2 ");
121     debug_printf("\n");
122  }
123  
124  
125  /* Unfilled tri:
126   *
127   * Note edgeflags in the vertex struct is not sufficient as we will
128   * need to manipulate them when decomposing primitives.
129   *
130   * We currently keep the vertex edgeflag and primitive edgeflag mask
131   * separate until the last possible moment.
132   */
unfilled_tri(struct draw_stage * stage,struct prim_header * header)133  static void unfilled_tri( struct draw_stage *stage,
134  			  struct prim_header *header )
135  {
136     struct unfilled_stage *unfilled = unfilled_stage(stage);
137     unsigned cw = header->det >= 0.0;
138     unsigned mode = unfilled->mode[cw];
139  
140     if (0)
141        print_header_flags(header->flags);
142  
143     switch (mode) {
144     case PIPE_POLYGON_MODE_FILL:
145        stage->next->tri( stage->next, header );
146        break;
147     case PIPE_POLYGON_MODE_LINE:
148        lines( stage, header );
149        break;
150     case PIPE_POLYGON_MODE_POINT:
151        points( stage, header );
152        break;
153     default:
154        assert(0);
155     }
156  }
157  
158  
unfilled_first_tri(struct draw_stage * stage,struct prim_header * header)159  static void unfilled_first_tri( struct draw_stage *stage,
160  				struct prim_header *header )
161  {
162     struct unfilled_stage *unfilled = unfilled_stage(stage);
163     const struct pipe_rasterizer_state *rast = stage->draw->rasterizer;
164  
165     unfilled->mode[0] = rast->front_ccw ? rast->fill_front : rast->fill_back;
166     unfilled->mode[1] = rast->front_ccw ? rast->fill_back : rast->fill_front;
167  
168     stage->tri = unfilled_tri;
169     stage->tri( stage, header );
170  }
171  
172  
173  
unfilled_flush(struct draw_stage * stage,unsigned flags)174  static void unfilled_flush( struct draw_stage *stage,
175  			    unsigned flags )
176  {
177     stage->next->flush( stage->next, flags );
178  
179     stage->tri = unfilled_first_tri;
180  }
181  
182  
unfilled_reset_stipple_counter(struct draw_stage * stage)183  static void unfilled_reset_stipple_counter( struct draw_stage *stage )
184  {
185     stage->next->reset_stipple_counter( stage->next );
186  }
187  
188  
unfilled_destroy(struct draw_stage * stage)189  static void unfilled_destroy( struct draw_stage *stage )
190  {
191     draw_free_temp_verts( stage );
192     FREE( stage );
193  }
194  
195  
196  /**
197   * Create unfilled triangle stage.
198   */
draw_unfilled_stage(struct draw_context * draw)199  struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
200  {
201     struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage);
202     if (unfilled == NULL)
203        goto fail;
204  
205     unfilled->stage.draw = draw;
206     unfilled->stage.name = "unfilled";
207     unfilled->stage.next = NULL;
208     unfilled->stage.tmp = NULL;
209     unfilled->stage.point = draw_pipe_passthrough_point;
210     unfilled->stage.line = draw_pipe_passthrough_line;
211     unfilled->stage.tri = unfilled_first_tri;
212     unfilled->stage.flush = unfilled_flush;
213     unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
214     unfilled->stage.destroy = unfilled_destroy;
215  
216     if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))
217        goto fail;
218  
219     return &unfilled->stage;
220  
221   fail:
222     if (unfilled)
223        unfilled->stage.destroy( &unfilled->stage );
224  
225     return NULL;
226  }
227