llvmpipe: precalculate some offsets
[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
41 /* Render a 4x4 unmasked block:
42 */
43 static void block_full( struct lp_rasterizer *rast,
44 const struct lp_rast_triangle *tri,
45 int x, int y )
46 {
47 unsigned mask = ~0;
48
49 lp_rast_shade_quads(rast, &tri->inputs, x, y, mask);
50 }
51
52
53
54 /* Evaluate each pixel in a block, generate a mask and possibly render
55 * the quad:
56 */
57 static void
58 do_block( struct lp_rasterizer *rast,
59 const struct lp_rast_triangle *tri,
60 int x, int y,
61 int c1,
62 int c2,
63 int c3 )
64 {
65 int i;
66 unsigned mask = 0;
67
68 for (i = 0; i < 16; i++)
69 mask |= (~(((c1 + tri->step[0][i]) |
70 (c2 + tri->step[1][i]) |
71 (c3 + tri->step[2][i])) >> 31)) & (1 << i);
72
73
74 /* As we do trivial reject already, masks should rarely be all
75 * zero:
76 */
77 lp_rast_shade_quads(rast, &tri->inputs, x, y, mask );
78 }
79
80
81
82 /* Scan the tile in chunks and figure out which pixels to rasterize
83 * for this triangle:
84 */
85 void lp_rast_triangle( struct lp_rasterizer *rast,
86 const union lp_rast_cmd_arg arg )
87 {
88 const struct lp_rast_triangle *tri = arg.triangle;
89
90 const int step = BLOCKSIZE;
91
92 int ei1 = tri->ei1 * step;
93 int ei2 = tri->ei2 * step;
94 int ei3 = tri->ei3 * step;
95
96 int eo1 = tri->eo1 * step;
97 int eo2 = tri->eo2 * step;
98 int eo3 = tri->eo3 * step;
99
100 int xstep1 = -step * tri->dy12;
101 int xstep2 = -step * tri->dy23;
102 int xstep3 = -step * tri->dy31;
103
104 int ystep1 = step * tri->dx12;
105 int ystep2 = step * tri->dx23;
106 int ystep3 = step * tri->dx31;
107
108 /* Clamp to tile dimensions:
109 */
110 int minx = MAX2(tri->minx, rast->x);
111 int miny = MAX2(tri->miny, rast->y);
112 int maxx = MIN2(tri->maxx, rast->x + TILE_SIZE);
113 int maxy = MIN2(tri->maxy, rast->y + TILE_SIZE);
114
115 int x, y;
116 int c1, c2, c3;
117
118 debug_printf("%s\n", __FUNCTION__);
119
120 if (miny == maxy || minx == maxx) {
121 debug_printf("%s: non-intersecting triangle in bin\n", __FUNCTION__);
122 return;
123 }
124
125 minx &= ~(BLOCKSIZE-1);
126 miny &= ~(BLOCKSIZE-1);
127
128 c1 = tri->c1 + tri->dx12 * miny - tri->dy12 * minx;
129 c2 = tri->c2 + tri->dx23 * miny - tri->dy23 * minx;
130 c3 = tri->c3 + tri->dx31 * miny - tri->dy31 * minx;
131
132 for (y = miny; y < maxy; y += BLOCKSIZE)
133 {
134 int cx1 = c1;
135 int cx2 = c2;
136 int cx3 = c3;
137
138 for (x = minx; x < maxx; x += BLOCKSIZE)
139 {
140 if (cx1 + eo1 < 0 ||
141 cx2 + eo2 < 0 ||
142 cx3 + eo3 < 0)
143 {
144 }
145 else if (cx1 + ei1 > 0 &&
146 cx2 + ei2 > 0 &&
147 cx3 + ei3 > 0)
148 {
149 block_full(rast, tri, x, y); /* trivial accept */
150 }
151 else
152 {
153 do_block(rast, tri, x, y, cx1, cx2, cx3);
154 }
155
156 /* Iterate cx values across the region:
157 */
158 cx1 += xstep1;
159 cx2 += xstep2;
160 cx3 += xstep3;
161 }
162
163 /* Iterate c values down the region:
164 */
165 c1 += ystep1;
166 c2 += ystep2;
167 c3 += ystep3;
168 }
169 }
170