Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3770 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
5
 * Copyright (C) 2010 LunarG Inc.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
 * DEALINGS IN THE SOFTWARE.
24
 *
25
 * Authors:
26
  *   Keith Whitwell 
27
 *    Chia-I Wu 
28
 */
29
 
30
/* these macros are optional */
31
#ifndef LOCAL_VARS
32
#define LOCAL_VARS
33
#endif
34
#ifndef FUNC_ENTER
35
#define FUNC_ENTER do {} while (0)
36
#endif
37
#ifndef FUNC_EXIT
38
#define FUNC_EXIT do {} while (0)
39
#endif
40
#ifndef LINE_ADJ
41
#define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
42
#endif
43
#ifndef TRIANGLE_ADJ
44
#define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
45
#endif
46
 
47
static void
48
FUNC(FUNC_VARS)
49
{
50
   unsigned idx[6], i;
51
   ushort flags;
52
   LOCAL_VARS
53
 
54
   FUNC_ENTER;
55
 
56
   /* prim, prim_flags, count, and last_vertex_last should have been defined */
57
   if (0) {
58
      debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
59
            __FUNCTION__, prim, prim_flags, count, last_vertex_last);
60
   }
61
 
62
   switch (prim) {
63
   case PIPE_PRIM_POINTS:
64
      for (i = 0; i < count; i++) {
65
         idx[0] = GET_ELT(i);
66
         POINT(idx[0]);
67
      }
68
      break;
69
 
70
   case PIPE_PRIM_LINES:
71
      flags = DRAW_PIPE_RESET_STIPPLE;
72
      for (i = 0; i + 1 < count; i += 2) {
73
         idx[0] = GET_ELT(i);
74
         idx[1] = GET_ELT(i + 1);
75
         LINE(flags, idx[0], idx[1]);
76
      }
77
      break;
78
 
79
   case PIPE_PRIM_LINE_LOOP:
80
   case PIPE_PRIM_LINE_STRIP:
81
      if (count >= 2) {
82
         flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
83
         idx[1] = GET_ELT(0);
84
         idx[2] = idx[1];
85
 
86
         for (i = 1; i < count; i++, flags = 0) {
87
            idx[0] = idx[1];
88
            idx[1] = GET_ELT(i);
89
            LINE(flags, idx[0], idx[1]);
90
         }
91
         /* close the loop */
92
         if (prim == PIPE_PRIM_LINE_LOOP && !prim_flags)
93
            LINE(flags, idx[1], idx[2]);
94
      }
95
      break;
96
 
97
   case PIPE_PRIM_TRIANGLES:
98
      flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
99
      for (i = 0; i + 2 < count; i += 3) {
100
         idx[0] = GET_ELT(i);
101
         idx[1] = GET_ELT(i + 1);
102
         idx[2] = GET_ELT(i + 2);
103
         TRIANGLE(flags, idx[0], idx[1], idx[2]);
104
      }
105
      break;
106
 
107
   case PIPE_PRIM_TRIANGLE_STRIP:
108
      if (count >= 3) {
109
         flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
110
         idx[1] = GET_ELT(0);
111
         idx[2] = GET_ELT(1);
112
 
113
         if (last_vertex_last) {
114
            for (i = 0; i + 2 < count; i++) {
115
               idx[0] = idx[1];
116
               idx[1] = idx[2];
117
               idx[2] = GET_ELT(i + 2);
118
               /* always emit idx[2] last */
119
               if (i & 1)
120
                  TRIANGLE(flags, idx[1], idx[0], idx[2]);
121
               else
122
                  TRIANGLE(flags, idx[0], idx[1], idx[2]);
123
            }
124
         }
125
         else {
126
            for (i = 0; i + 2 < count; i++) {
127
               idx[0] = idx[1];
128
               idx[1] = idx[2];
129
               idx[2] = GET_ELT(i + 2);
130
               /* always emit idx[0] first */
131
               if (i & 1)
132
                  TRIANGLE(flags, idx[0], idx[2], idx[1]);
133
               else
134
                  TRIANGLE(flags, idx[0], idx[1], idx[2]);
135
            }
136
         }
137
      }
138
      break;
139
 
140
   case PIPE_PRIM_TRIANGLE_FAN:
141
      if (count >= 3) {
142
         flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
143
         idx[0] = GET_ELT(0);
144
         idx[2] = GET_ELT(1);
145
 
146
         /* idx[0] is neither the first nor the last vertex */
147
         if (last_vertex_last) {
148
            for (i = 0; i + 2 < count; i++) {
149
               idx[1] = idx[2];
150
               idx[2] = GET_ELT(i + 2);
151
               /* always emit idx[2] last */
152
               TRIANGLE(flags, idx[0], idx[1], idx[2]);
153
            }
154
         }
155
         else {
156
            for (i = 0; i + 2 < count; i++) {
157
               idx[1] = idx[2];
158
               idx[2] = GET_ELT(i + 2);
159
               /* always emit idx[1] first */
160
               TRIANGLE(flags, idx[1], idx[2], idx[0]);
161
            }
162
         }
163
      }
164
      break;
165
 
166
   case PIPE_PRIM_QUADS:
167
      if (last_vertex_last) {
168
         for (i = 0; i + 3 < count; i += 4) {
169
            idx[0] = GET_ELT(i);
170
            idx[1] = GET_ELT(i + 1);
171
            idx[2] = GET_ELT(i + 2);
172
            idx[3] = GET_ELT(i + 3);
173
 
174
            flags = DRAW_PIPE_RESET_STIPPLE |
175
                    DRAW_PIPE_EDGE_FLAG_0 |
176
                    DRAW_PIPE_EDGE_FLAG_2;
177
            /* always emit idx[3] last */
178
            TRIANGLE(flags, idx[0], idx[1], idx[3]);
179
 
180
            flags = DRAW_PIPE_EDGE_FLAG_0 |
181
                    DRAW_PIPE_EDGE_FLAG_1;
182
            TRIANGLE(flags, idx[1], idx[2], idx[3]);
183
         }
184
      }
185
      else {
186
         for (i = 0; i + 3 < count; i += 4) {
187
            idx[0] = GET_ELT(i);
188
            idx[1] = GET_ELT(i + 1);
189
            idx[2] = GET_ELT(i + 2);
190
            idx[3] = GET_ELT(i + 3);
191
 
192
            flags = DRAW_PIPE_RESET_STIPPLE |
193
                    DRAW_PIPE_EDGE_FLAG_0 |
194
                    DRAW_PIPE_EDGE_FLAG_1;
195
            /* always emit idx[3] / idx[0] first */
196
            if (quads_flatshade_last)
197
               TRIANGLE(flags, idx[3], idx[0], idx[1]);
198
            else
199
               TRIANGLE(flags, idx[0], idx[1], idx[2]);
200
 
201
            flags = DRAW_PIPE_EDGE_FLAG_1 |
202
                    DRAW_PIPE_EDGE_FLAG_2;
203
            if (quads_flatshade_last)
204
               TRIANGLE(flags, idx[3], idx[1], idx[2]);
205
            else
206
               TRIANGLE(flags, idx[0], idx[2], idx[3]);
207
         }
208
      }
209
      break;
210
 
211
   case PIPE_PRIM_QUAD_STRIP:
212
      if (count >= 4) {
213
         idx[2] = GET_ELT(0);
214
         idx[3] = GET_ELT(1);
215
 
216
         if (last_vertex_last) {
217
            for (i = 0; i + 3 < count; i += 2) {
218
               idx[0] = idx[2];
219
               idx[1] = idx[3];
220
               idx[2] = GET_ELT(i + 2);
221
               idx[3] = GET_ELT(i + 3);
222
 
223
               /* always emit idx[3] last */
224
               flags = DRAW_PIPE_RESET_STIPPLE |
225
                       DRAW_PIPE_EDGE_FLAG_0 |
226
                       DRAW_PIPE_EDGE_FLAG_2;
227
               TRIANGLE(flags, idx[2], idx[0], idx[3]);
228
 
229
               flags = DRAW_PIPE_EDGE_FLAG_0 |
230
                       DRAW_PIPE_EDGE_FLAG_1;
231
               TRIANGLE(flags, idx[0], idx[1], idx[3]);
232
            }
233
         }
234
         else {
235
            for (i = 0; i + 3 < count; i += 2) {
236
               idx[0] = idx[2];
237
               idx[1] = idx[3];
238
               idx[2] = GET_ELT(i + 2);
239
               idx[3] = GET_ELT(i + 3);
240
 
241
               flags = DRAW_PIPE_RESET_STIPPLE |
242
                       DRAW_PIPE_EDGE_FLAG_0 |
243
                       DRAW_PIPE_EDGE_FLAG_1;
244
               /* always emit idx[3] / idx[0 first */
245
               if (quads_flatshade_last)
246
                  TRIANGLE(flags, idx[3], idx[2], idx[0]);
247
               else
248
                  TRIANGLE(flags, idx[0], idx[3], idx[2]);
249
 
250
               flags = DRAW_PIPE_EDGE_FLAG_1 |
251
                       DRAW_PIPE_EDGE_FLAG_2;
252
               if (quads_flatshade_last)
253
                  TRIANGLE(flags, idx[3], idx[0], idx[1]);
254
               else
255
                  TRIANGLE(flags, idx[0], idx[1], idx[3]);
256
            }
257
         }
258
      }
259
      break;
260
 
261
   case PIPE_PRIM_POLYGON:
262
      if (count >= 3) {
263
         ushort edge_next, edge_finish;
264
 
265
         if (last_vertex_last) {
266
            flags = (DRAW_PIPE_RESET_STIPPLE |
267
                     DRAW_PIPE_EDGE_FLAG_0);
268
            if (!(prim_flags & DRAW_SPLIT_BEFORE))
269
               flags |= DRAW_PIPE_EDGE_FLAG_2;
270
 
271
            edge_next = DRAW_PIPE_EDGE_FLAG_0;
272
            edge_finish =
273
               (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
274
         }
275
         else {
276
            flags = (DRAW_PIPE_RESET_STIPPLE |
277
                     DRAW_PIPE_EDGE_FLAG_1);
278
            if (!(prim_flags & DRAW_SPLIT_BEFORE))
279
               flags |= DRAW_PIPE_EDGE_FLAG_0;
280
 
281
            edge_next = DRAW_PIPE_EDGE_FLAG_1;
282
            edge_finish =
283
               (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
284
         }
285
 
286
         idx[0] = GET_ELT(0);
287
         idx[2] = GET_ELT(1);
288
 
289
         for (i = 0; i + 2 < count; i++, flags = edge_next) {
290
            idx[1] = idx[2];
291
            idx[2] = GET_ELT(i + 2);
292
 
293
            if (i + 3 == count)
294
               flags |= edge_finish;
295
 
296
            /* idx[0] is both the first and the last vertex */
297
            if (last_vertex_last)
298
               TRIANGLE(flags, idx[1], idx[2], idx[0]);
299
            else
300
               TRIANGLE(flags, idx[0], idx[1], idx[2]);
301
         }
302
      }
303
      break;
304
 
305
   case PIPE_PRIM_LINES_ADJACENCY:
306
      flags = DRAW_PIPE_RESET_STIPPLE;
307
      for (i = 0; i + 3 < count; i += 4) {
308
         idx[0] = GET_ELT(i);
309
         idx[1] = GET_ELT(i + 1);
310
         idx[2] = GET_ELT(i + 2);
311
         idx[3] = GET_ELT(i + 3);
312
         LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
313
      }
314
      break;
315
 
316
   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
317
      if (count >= 4) {
318
         flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
319
         idx[1] = GET_ELT(0);
320
         idx[2] = GET_ELT(1);
321
         idx[3] = GET_ELT(2);
322
 
323
         for (i = 1; i + 2 < count; i++, flags = 0) {
324
            idx[0] = idx[1];
325
            idx[1] = idx[2];
326
            idx[2] = idx[3];
327
            idx[3] = GET_ELT(i + 2);
328
            LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
329
         }
330
      }
331
      break;
332
 
333
   case PIPE_PRIM_TRIANGLES_ADJACENCY:
334
      flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
335
      for (i = 0; i + 5 < count; i += 6) {
336
         idx[0] = GET_ELT(i);
337
         idx[1] = GET_ELT(i + 1);
338
         idx[2] = GET_ELT(i + 2);
339
         idx[3] = GET_ELT(i + 3);
340
         idx[4] = GET_ELT(i + 4);
341
         idx[5] = GET_ELT(i + 5);
342
         TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
343
      }
344
      break;
345
 
346
   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
347
      if (count >= 6) {
348
         flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
349
         idx[0] = GET_ELT(1);
350
         idx[2] = GET_ELT(0);
351
         idx[4] = GET_ELT(2);
352
         idx[3] = GET_ELT(4);
353
 
354
         /*
355
          * The vertices of the i-th triangle are stored in
356
          * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
357
          *
358
          * The adjacent vertices are stored in
359
          * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
360
          *
361
          * However, there are two exceptions:
362
          *
363
          * For the first triangle, idx[1] = 1;
364
          * For the  last triangle, idx[3] = 2*i+5.
365
          */
366
         if (last_vertex_last) {
367
            for (i = 0; i + 5 < count; i += 2) {
368
               idx[1] = idx[0];
369
 
370
               idx[0] = idx[2];
371
               idx[2] = idx[4];
372
               idx[4] = idx[3];
373
 
374
               idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
375
               idx[5] = GET_ELT(i + 3);
376
 
377
               /*
378
                * alternate the first two vertices (idx[0] and idx[2]) and the
379
                * corresponding adjacent vertices (idx[3] and idx[5]) to have
380
                * the correct orientation
381
                */
382
               if (i & 2) {
383
                  TRIANGLE_ADJ(flags,
384
                        idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
385
               }
386
               else {
387
                  TRIANGLE_ADJ(flags,
388
                        idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
389
               }
390
            }
391
         }
392
         else {
393
            for (i = 0; i + 5 < count; i += 2) {
394
               idx[1] = idx[0];
395
 
396
               idx[0] = idx[2];
397
               idx[2] = idx[4];
398
               idx[4] = idx[3];
399
 
400
               idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
401
               idx[5] = GET_ELT(i + 3);
402
 
403
               /*
404
                * alternate the last two vertices (idx[2] and idx[4]) and the
405
                * corresponding adjacent vertices (idx[1] and idx[5]) to have
406
                * the correct orientation
407
                */
408
               if (i & 2) {
409
                  TRIANGLE_ADJ(flags,
410
                        idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
411
               }
412
               else {
413
                  TRIANGLE_ADJ(flags,
414
                        idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
415
               }
416
            }
417
         }
418
      }
419
      break;
420
 
421
   default:
422
      assert(0);
423
      break;
424
   }
425
 
426
   FUNC_EXIT;
427
}
428
 
429
#undef LOCAL_VARS
430
#undef FUNC_ENTER
431
#undef FUNC_EXIT
432
#undef LINE_ADJ
433
#undef TRIANGLE_ADJ
434
 
435
#undef FUNC
436
#undef FUNC_VARS
437
#undef GET_ELT
438
#undef POINT
439
#undef LINE
440
#undef TRIANGLE