00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "pipe/p_defines.h"
00040 #include "pipe/p_shader_tokens.h"
00041 #include "util/u_math.h"
00042 #include "util/u_memory.h"
00043
00044 #include "draw/draw_pipe.h"
00045
00046
00048 struct stipple_stage {
00049 struct draw_stage stage;
00050 float counter;
00051 uint pattern;
00052 uint factor;
00053 };
00054
00055
00056 static INLINE struct stipple_stage *
00057 stipple_stage(struct draw_stage *stage)
00058 {
00059 return (struct stipple_stage *) stage;
00060 }
00061
00062
00068 static void
00069 screen_interp( struct draw_context *draw,
00070 struct vertex_header *dst,
00071 float t,
00072 const struct vertex_header *v0,
00073 const struct vertex_header *v1 )
00074 {
00075 uint attr;
00076 for (attr = 0; attr < draw->vs.num_vs_outputs; attr++) {
00077 const float *val0 = v0->data[attr];
00078 const float *val1 = v1->data[attr];
00079 float *newv = dst->data[attr];
00080 uint i;
00081 for (i = 0; i < 4; i++) {
00082 newv[i] = val0[i] + t * (val1[i] - val0[i]);
00083 }
00084 }
00085 }
00086
00087
00088 static void
00089 emit_segment(struct draw_stage *stage, struct prim_header *header,
00090 float t0, float t1)
00091 {
00092 struct vertex_header *v0new = dup_vert(stage, header->v[0], 0);
00093 struct vertex_header *v1new = dup_vert(stage, header->v[1], 1);
00094 struct prim_header newprim = *header;
00095
00096 if (t0 > 0.0) {
00097 screen_interp( stage->draw, v0new, t0, header->v[0], header->v[1] );
00098 newprim.v[0] = v0new;
00099 }
00100
00101 if (t1 < 1.0) {
00102 screen_interp( stage->draw, v1new, t1, header->v[0], header->v[1] );
00103 newprim.v[1] = v1new;
00104 }
00105
00106 stage->next->line( stage->next, &newprim );
00107 }
00108
00109
00110 static INLINE unsigned
00111 stipple_test(int counter, ushort pattern, int factor)
00112 {
00113 int b = (counter / factor) & 0xf;
00114 return (1 << b) & pattern;
00115 }
00116
00117
00118 static void
00119 stipple_line(struct draw_stage *stage, struct prim_header *header)
00120 {
00121 struct stipple_stage *stipple = stipple_stage(stage);
00122 struct vertex_header *v0 = header->v[0];
00123 struct vertex_header *v1 = header->v[1];
00124 const unsigned pos = stage->draw->vs.position_output;
00125 const float *pos0 = v0->data[pos];
00126 const float *pos1 = v1->data[pos];
00127 float start = 0;
00128 int state = 0;
00129
00130 float x0 = pos0[0];
00131 float x1 = pos1[0];
00132 float y0 = pos0[1];
00133 float y1 = pos1[1];
00134
00135 float dx = x0 > x1 ? x0 - x1 : x1 - x0;
00136 float dy = y0 > y1 ? y0 - y1 : y1 - y0;
00137
00138 float length = MAX2(dx, dy);
00139 int i;
00140
00141 if (header->flags & DRAW_PIPE_RESET_STIPPLE)
00142 stipple->counter = 0;
00143
00144
00145
00146
00147 for (i = 0; i < length; i++) {
00148 int result = stipple_test( (int) stipple->counter+i,
00149 (ushort) stipple->pattern, stipple->factor );
00150 if (result != state) {
00151
00152 if (state) {
00153 if (start != i) {
00154
00155 emit_segment( stage, header, start / length, i / length );
00156 }
00157 }
00158 else {
00159
00160 start = (float) i;
00161 }
00162 state = result;
00163 }
00164 }
00165
00166 if (state && start < length)
00167 emit_segment( stage, header, start / length, 1.0 );
00168
00169 stipple->counter += length;
00170 }
00171
00172
00173 static void
00174 reset_stipple_counter(struct draw_stage *stage)
00175 {
00176 struct stipple_stage *stipple = stipple_stage(stage);
00177 stipple->counter = 0;
00178 stage->next->reset_stipple_counter( stage->next );
00179 }
00180
00181 static void
00182 stipple_reset_point(struct draw_stage *stage, struct prim_header *header)
00183 {
00184 struct stipple_stage *stipple = stipple_stage(stage);
00185 stipple->counter = 0;
00186 stage->next->point(stage->next, header);
00187 }
00188
00189 static void
00190 stipple_reset_tri(struct draw_stage *stage, struct prim_header *header)
00191 {
00192 struct stipple_stage *stipple = stipple_stage(stage);
00193 stipple->counter = 0;
00194 stage->next->tri(stage->next, header);
00195 }
00196
00197
00198 static void
00199 stipple_first_line(struct draw_stage *stage,
00200 struct prim_header *header)
00201 {
00202 struct stipple_stage *stipple = stipple_stage(stage);
00203 struct draw_context *draw = stage->draw;
00204
00205 stipple->pattern = draw->rasterizer->line_stipple_pattern;
00206 stipple->factor = draw->rasterizer->line_stipple_factor + 1;
00207
00208 stage->line = stipple_line;
00209 stage->line( stage, header );
00210 }
00211
00212
00213 static void
00214 stipple_flush(struct draw_stage *stage, unsigned flags)
00215 {
00216 stage->line = stipple_first_line;
00217 stage->next->flush( stage->next, flags );
00218 }
00219
00220
00221
00222
00223 static void
00224 stipple_destroy( struct draw_stage *stage )
00225 {
00226 draw_free_temp_verts( stage );
00227 FREE( stage );
00228 }
00229
00230
00234 struct draw_stage *draw_stipple_stage( struct draw_context *draw )
00235 {
00236 struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage);
00237
00238 draw_alloc_temp_verts( &stipple->stage, 2 );
00239
00240 stipple->stage.draw = draw;
00241 stipple->stage.next = NULL;
00242 stipple->stage.point = stipple_reset_point;
00243 stipple->stage.line = stipple_first_line;
00244 stipple->stage.tri = stipple_reset_tri;
00245 stipple->stage.reset_stipple_counter = reset_stipple_counter;
00246 stipple->stage.flush = stipple_flush;
00247 stipple->stage.destroy = stipple_destroy;
00248
00249 return &stipple->stage;
00250 }