5f22aca668a32f2c3cae74ee4b4ecbb2c1761ed9
[mesa.git] / src / gallium / drivers / llvmpipe / lp_rast_tri.c
1 /**************************************************************************
2 *
3 * Copyright 2007-2009 VMware, Inc.
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 VMWARE 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 * Rasterization for binned triangles within a tile
30 */
31
32 #include "util/u_math.h"
33 #include "lp_rast_priv.h"
34 #include "lp_tile_soa.h"
35
36
37 #define BLOCKSIZE 4
38
39
40 /* Render a 4x4 unmasked block:
41 */
42 static void block_full( struct lp_rasterizer *rast,
43 const struct lp_rast_triangle *tri,
44 int x, int y )
45 {
46 static const uint32_t ALIGN16_ATTRIB masks[4][4] =
47 { {~0, ~0, ~0, ~0},
48 {~0, ~0, ~0, ~0},
49 {~0, ~0, ~0, ~0},
50 {~0, ~0, ~0, ~0} };
51
52 lp_rast_shade_quads(rast, &tri->inputs, x, y, &masks[0][0]);
53 }
54
55
56 static INLINE void
57 do_quad( const struct lp_rast_triangle *tri,
58 int c1, int c2, int c3,
59 int32_t *mask )
60 {
61 const int xstep1 = -tri->dy12 ;
62 const int xstep2 = -tri->dy23 ;
63 const int xstep3 = -tri->dy31 ;
64
65 const int ystep1 = tri->dx12 ;
66 const int ystep2 = tri->dx23 ;
67 const int ystep3 = tri->dx31 ;
68
69 mask[0] = ~(((c1) |
70 (c2) |
71 (c3)) >> 31);
72
73 mask[1] = ~(((c1 + xstep1) |
74 (c2 + xstep2) |
75 (c3 + xstep3)) >> 31);
76
77 mask[2] = ~(((c1 + ystep1) |
78 (c2 + ystep2) |
79 (c3 + ystep3)) >> 31);
80
81 mask[3] = ~(((c1 + ystep1 + xstep1) |
82 (c2 + ystep2 + xstep2) |
83 (c3 + ystep3 + xstep3)) >> 31);
84 }
85
86 /* Evaluate each pixel in a block, generate a mask and possibly render
87 * the quad:
88 */
89 static void
90 do_block( struct lp_rasterizer *rast,
91 const struct lp_rast_triangle *tri,
92 int x, int y,
93 int c1,
94 int c2,
95 int c3 )
96 {
97 const int step = 2 ;
98
99 const int xstep1 = -step * tri->dy12;
100 const int xstep2 = -step * tri->dy23;
101 const int xstep3 = -step * tri->dy31;
102
103 const int ystep1 = step * tri->dx12;
104 const int ystep2 = step * tri->dx23;
105 const int ystep3 = step * tri->dx31;
106
107 int ix, iy;
108 uint32_t ALIGN16_ATTRIB mask[4][4];
109
110
111 for (iy = 0; iy < 4; iy += 2) {
112 int cx1 = c1;
113 int cx2 = c2;
114 int cx3 = c3;
115
116 for (ix = 0; ix < 2; ix ++) {
117
118 do_quad(tri, cx1, cx2, cx3, (int32_t *)mask[iy+ix]);
119
120 cx1 += xstep1;
121 cx2 += xstep2;
122 cx3 += xstep3;
123 }
124
125 c1 += ystep1;
126 c2 += ystep2;
127 c3 += ystep3;
128 }
129
130 /* As we do trivial reject already, masks should rarely be all
131 * zero:
132 */
133 lp_rast_shade_quads(rast, &tri->inputs, x, y, &mask[0][0] );
134 }
135
136
137
138 /* Scan the tile in chunks and figure out which pixels to rasterize
139 * for this triangle:
140 */
141 void lp_rast_triangle( struct lp_rasterizer *rast,
142 const union lp_rast_cmd_arg arg )
143 {
144 const struct lp_rast_triangle *tri = arg.triangle;
145
146 const int step = BLOCKSIZE;
147
148 int ei1 = tri->ei1 * step;
149 int ei2 = tri->ei2 * step;
150 int ei3 = tri->ei3 * step;
151
152 int eo1 = tri->eo1 * step;
153 int eo2 = tri->eo2 * step;
154 int eo3 = tri->eo3 * step;
155
156 int xstep1 = -step * tri->dy12;
157 int xstep2 = -step * tri->dy23;
158 int xstep3 = -step * tri->dy31;
159
160 int ystep1 = step * tri->dx12;
161 int ystep2 = step * tri->dx23;
162 int ystep3 = step * tri->dx31;
163
164 /* Clamp to tile dimensions:
165 */
166 int minx = MAX2(tri->minx, rast->x);
167 int miny = MAX2(tri->miny, rast->y);
168 int maxx = MIN2(tri->maxx, rast->x + TILE_SIZE);
169 int maxy = MIN2(tri->maxy, rast->y + TILE_SIZE);
170
171 int x, y;
172 int c1, c2, c3;
173
174 debug_printf("%s\n", __FUNCTION__);
175
176 if (miny == maxy || minx == maxx) {
177 debug_printf("%s: non-intersecting triangle in bin\n", __FUNCTION__);
178 return;
179 }
180
181 minx &= ~(BLOCKSIZE-1);
182 miny &= ~(BLOCKSIZE-1);
183
184 c1 = tri->c1 + tri->dx12 * miny - tri->dy12 * minx;
185 c2 = tri->c2 + tri->dx23 * miny - tri->dy23 * minx;
186 c3 = tri->c3 + tri->dx31 * miny - tri->dy31 * minx;
187
188 for (y = miny; y < maxy; y += BLOCKSIZE)
189 {
190 int cx1 = c1;
191 int cx2 = c2;
192 int cx3 = c3;
193
194 for (x = minx; x < maxx; x += BLOCKSIZE)
195 {
196 if (cx1 + eo1 < 0 ||
197 cx2 + eo2 < 0 ||
198 cx3 + eo3 < 0)
199 {
200 }
201 else if (cx1 + ei1 > 0 &&
202 cx2 + ei2 > 0 &&
203 cx3 + ei3 > 0)
204 {
205 block_full(rast, tri, x, y); /* trivial accept */
206 }
207 else
208 {
209 do_block(rast, tri, x, y, cx1, cx2, cx3);
210 }
211
212 /* Iterate cx values across the region:
213 */
214 cx1 += xstep1;
215 cx2 += xstep2;
216 cx3 += xstep3;
217 }
218
219 /* Iterate c values down the region:
220 */
221 c1 += ystep1;
222 c2 += ystep2;
223 c3 += ystep3;
224 }
225 }
226