2
* Mesa 3-D graphics library
4
* Copyright 2008 VMware, Inc.
5
* Copyright (C) 2010 LunarG Inc.
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:
14
* The above copyright notice and this permission notice shall be included
15
* in all copies or substantial portions of the Software.
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.
26
* Keith Whitwell <keithw@vmware.com>
27
* Chia-I Wu <olv@lunarg.com>
30
/* these macros are optional */
35
#define FUNC_ENTER do {} while (0)
38
#define FUNC_EXIT do {} while (0)
41
#define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
44
#define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
56
/* prim, prim_flags, count, and last_vertex_last should have been defined */
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);
63
case PIPE_PRIM_POINTS:
64
for (i = 0; i < count; i++) {
71
flags = DRAW_PIPE_RESET_STIPPLE;
72
for (i = 0; i + 1 < count; i += 2) {
74
idx[1] = GET_ELT(i + 1);
75
LINE(flags, idx[0], idx[1]);
79
case PIPE_PRIM_LINE_LOOP:
80
case PIPE_PRIM_LINE_STRIP:
82
flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
86
for (i = 1; i < count; i++, flags = 0) {
89
LINE(flags, idx[0], idx[1]);
92
if (prim == PIPE_PRIM_LINE_LOOP && !prim_flags)
93
LINE(flags, idx[1], idx[2]);
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) {
101
idx[1] = GET_ELT(i + 1);
102
idx[2] = GET_ELT(i + 2);
103
TRIANGLE(flags, idx[0], idx[1], idx[2]);
107
case PIPE_PRIM_TRIANGLE_STRIP:
109
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
113
if (last_vertex_last) {
114
for (i = 0; i + 2 < count; i++) {
117
idx[2] = GET_ELT(i + 2);
118
/* always emit idx[2] last */
120
TRIANGLE(flags, idx[1], idx[0], idx[2]);
122
TRIANGLE(flags, idx[0], idx[1], idx[2]);
126
for (i = 0; i + 2 < count; i++) {
129
idx[2] = GET_ELT(i + 2);
130
/* always emit idx[0] first */
132
TRIANGLE(flags, idx[0], idx[2], idx[1]);
134
TRIANGLE(flags, idx[0], idx[1], idx[2]);
140
case PIPE_PRIM_TRIANGLE_FAN:
142
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
146
/* idx[0] is neither the first nor the last vertex */
147
if (last_vertex_last) {
148
for (i = 0; i + 2 < count; i++) {
150
idx[2] = GET_ELT(i + 2);
151
/* always emit idx[2] last */
152
TRIANGLE(flags, idx[0], idx[1], idx[2]);
156
for (i = 0; i + 2 < count; i++) {
158
idx[2] = GET_ELT(i + 2);
159
/* always emit idx[1] first */
160
TRIANGLE(flags, idx[1], idx[2], idx[0]);
166
case PIPE_PRIM_QUADS:
167
if (last_vertex_last) {
168
for (i = 0; i + 3 < count; i += 4) {
170
idx[1] = GET_ELT(i + 1);
171
idx[2] = GET_ELT(i + 2);
172
idx[3] = GET_ELT(i + 3);
174
QUAD(0, idx[0], idx[1],
177
flags = DRAW_PIPE_RESET_STIPPLE |
178
DRAW_PIPE_EDGE_FLAG_0 |
179
DRAW_PIPE_EDGE_FLAG_2;
180
/* always emit idx[3] last */
181
TRIANGLE(flags, idx[0], idx[1], idx[3]);
183
flags = DRAW_PIPE_EDGE_FLAG_0 |
184
DRAW_PIPE_EDGE_FLAG_1;
185
TRIANGLE(flags, idx[1], idx[2], idx[3]);
190
for (i = 0; i + 3 < count; i += 4) {
192
idx[1] = GET_ELT(i + 1);
193
idx[2] = GET_ELT(i + 2);
194
idx[3] = GET_ELT(i + 3);
196
QUAD(0, idx[0], idx[1],
199
flags = DRAW_PIPE_RESET_STIPPLE |
200
DRAW_PIPE_EDGE_FLAG_0 |
201
DRAW_PIPE_EDGE_FLAG_1;
202
/* always emit idx[3] / idx[0] first */
203
if (quads_flatshade_last)
204
TRIANGLE(flags, idx[3], idx[0], idx[1]);
206
TRIANGLE(flags, idx[0], idx[1], idx[2]);
208
flags = DRAW_PIPE_EDGE_FLAG_1 |
209
DRAW_PIPE_EDGE_FLAG_2;
210
if (quads_flatshade_last)
211
TRIANGLE(flags, idx[3], idx[1], idx[2]);
213
TRIANGLE(flags, idx[0], idx[2], idx[3]);
219
case PIPE_PRIM_QUAD_STRIP:
224
if (last_vertex_last) {
225
for (i = 0; i + 3 < count; i += 2) {
228
idx[2] = GET_ELT(i + 2);
229
idx[3] = GET_ELT(i + 3);
232
QUAD(0, idx[2], idx[0],
235
/* always emit idx[3] last */
236
flags = DRAW_PIPE_RESET_STIPPLE |
237
DRAW_PIPE_EDGE_FLAG_0 |
238
DRAW_PIPE_EDGE_FLAG_2;
239
TRIANGLE(flags, idx[2], idx[0], idx[3]);
241
flags = DRAW_PIPE_EDGE_FLAG_0 |
242
DRAW_PIPE_EDGE_FLAG_1;
243
TRIANGLE(flags, idx[0], idx[1], idx[3]);
248
for (i = 0; i + 3 < count; i += 2) {
251
idx[2] = GET_ELT(i + 2);
252
idx[3] = GET_ELT(i + 3);
255
QUAD(0, idx[3], idx[2],
258
flags = DRAW_PIPE_RESET_STIPPLE |
259
DRAW_PIPE_EDGE_FLAG_0 |
260
DRAW_PIPE_EDGE_FLAG_1;
261
/* always emit idx[3] / idx[0 first */
262
if (quads_flatshade_last)
263
TRIANGLE(flags, idx[3], idx[2], idx[0]);
265
TRIANGLE(flags, idx[0], idx[3], idx[2]);
267
flags = DRAW_PIPE_EDGE_FLAG_1 |
268
DRAW_PIPE_EDGE_FLAG_2;
269
if (quads_flatshade_last)
270
TRIANGLE(flags, idx[3], idx[0], idx[1]);
272
TRIANGLE(flags, idx[0], idx[1], idx[3]);
279
case PIPE_PRIM_POLYGON:
281
ushort edge_next, edge_finish;
283
if (last_vertex_last) {
284
flags = (DRAW_PIPE_RESET_STIPPLE |
285
DRAW_PIPE_EDGE_FLAG_0);
286
if (!(prim_flags & DRAW_SPLIT_BEFORE))
287
flags |= DRAW_PIPE_EDGE_FLAG_2;
289
edge_next = DRAW_PIPE_EDGE_FLAG_0;
291
(prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
294
flags = (DRAW_PIPE_RESET_STIPPLE |
295
DRAW_PIPE_EDGE_FLAG_1);
296
if (!(prim_flags & DRAW_SPLIT_BEFORE))
297
flags |= DRAW_PIPE_EDGE_FLAG_0;
299
edge_next = DRAW_PIPE_EDGE_FLAG_1;
301
(prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
307
for (i = 0; i + 2 < count; i++, flags = edge_next) {
309
idx[2] = GET_ELT(i + 2);
312
flags |= edge_finish;
314
/* idx[0] is both the first and the last vertex */
315
if (last_vertex_last)
316
TRIANGLE(flags, idx[1], idx[2], idx[0]);
318
TRIANGLE(flags, idx[0], idx[1], idx[2]);
323
case PIPE_PRIM_LINES_ADJACENCY:
324
flags = DRAW_PIPE_RESET_STIPPLE;
325
for (i = 0; i + 3 < count; i += 4) {
327
idx[1] = GET_ELT(i + 1);
328
idx[2] = GET_ELT(i + 2);
329
idx[3] = GET_ELT(i + 3);
330
LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
334
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
336
flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
341
for (i = 1; i + 2 < count; i++, flags = 0) {
345
idx[3] = GET_ELT(i + 2);
346
LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
351
case PIPE_PRIM_TRIANGLES_ADJACENCY:
352
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
353
for (i = 0; i + 5 < count; i += 6) {
355
idx[1] = GET_ELT(i + 1);
356
idx[2] = GET_ELT(i + 2);
357
idx[3] = GET_ELT(i + 3);
358
idx[4] = GET_ELT(i + 4);
359
idx[5] = GET_ELT(i + 5);
360
TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
364
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
366
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
373
* The vertices of the i-th triangle are stored in
374
* idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
376
* The adjacent vertices are stored in
377
* idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
379
* However, there are two exceptions:
381
* For the first triangle, idx[1] = 1;
382
* For the last triangle, idx[3] = 2*i+5.
384
if (last_vertex_last) {
385
for (i = 0; i + 5 < count; i += 2) {
392
idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
393
idx[5] = GET_ELT(i + 3);
396
* alternate the first two vertices (idx[0] and idx[2]) and the
397
* corresponding adjacent vertices (idx[3] and idx[5]) to have
398
* the correct orientation
402
idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
406
idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
411
for (i = 0; i + 5 < count; i += 2) {
418
idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
419
idx[5] = GET_ELT(i + 3);
422
* alternate the last two vertices (idx[2] and idx[4]) and the
423
* corresponding adjacent vertices (idx[1] and idx[5]) to have
424
* the correct orientation
428
idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
432
idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);