1 /**************************************************************************
3 * Copyright 2007-2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 * Rasterization for binned triangles within a tile
32 #include "lp_context.h"
34 #include "lp_quad_pipe.h"
37 #include "draw/draw_context.h"
38 #include "draw/draw_private.h"
39 #include "draw/draw_vertex.h"
40 #include "pipe/p_shader_tokens.h"
41 #include "pipe/p_thread.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
48 /* Convert 8x8 block into four runs of quads and render each in turn.
51 static void block_full( struct triangle
*tri
, int x
, int y
)
53 struct quad_header
*ptrs
[4];
56 tri
->quad
[0].input
.x0
= x
+ 0;
57 tri
->quad
[1].input
.x0
= x
+ 2;
58 tri
->quad
[2].input
.x0
= x
+ 4;
59 tri
->quad
[3].input
.x0
= x
+ 6;
61 for (i
= 0; i
< 4; i
++, y
+= 2) {
62 tri
->quad
[0].inout
.mask
= 0xf;
63 tri
->quad
[1].inout
.mask
= 0xf;
64 tri
->quad
[2].inout
.mask
= 0xf;
65 tri
->quad
[3].inout
.mask
= 0xf;
67 tri
->quad
[0].input
.y0
= y
;
68 tri
->quad
[1].input
.y0
= y
;
69 tri
->quad
[2].input
.y0
= y
;
70 tri
->quad
[3].input
.y0
= y
;
72 /* XXX: don't bother with this ptrs business */
73 ptrs
[0] = &tri
->quad
[0];
74 ptrs
[1] = &tri
->quad
[1];
75 ptrs
[2] = &tri
->quad
[2];
76 ptrs
[3] = &tri
->quad
[3];
78 tri
->llvmpipe
->quad
.first
->run( tri
->llvmpipe
->quad
.first
, ptrs
, 4 );
82 static void block_full( struct triangle
*tri
, int x
, int y
)
84 struct quad_header
*ptrs
[4];
87 tri
->quad
[0].input
.x0
= x
+ 0;
88 tri
->quad
[1].input
.x0
= x
+ 2;
90 for (iy
= 0; iy
< 4; iy
+= 2) {
91 tri
->quad
[0].inout
.mask
= 0xf;
92 tri
->quad
[1].inout
.mask
= 0xf;
94 tri
->quad
[0].input
.y0
= y
+ iy
;
95 tri
->quad
[1].input
.y0
= y
+ iy
;
97 /* XXX: don't bother with this ptrs business */
98 ptrs
[0] = &tri
->quad
[0];
99 ptrs
[1] = &tri
->quad
[1];
101 tri
->llvmpipe
->quad
.first
->run( tri
->llvmpipe
->quad
.first
, ptrs
, 2 );
107 do_quad( struct lp_rasterizer
*rast
,
109 float c1
, float c2
, float c3
)
111 struct triangle
*tri
= rast
->tri
;
112 struct quad_header
*quad
= &rast
->quad
[0];
114 float xstep1
= -tri
->dy12
;
115 float xstep2
= -tri
->dy23
;
116 float xstep3
= -tri
->dy31
;
118 float ystep1
= tri
->dx12
;
119 float ystep2
= tri
->dx23
;
120 float ystep3
= tri
->dx31
;
124 quad
->inout
.mask
= 0;
129 quad
->inout
.mask
|= 1;
131 if (c1
+ xstep1
> 0 &&
134 quad
->inout
.mask
|= 2;
136 if (c1
+ ystep1
> 0 &&
139 quad
->inout
.mask
|= 4;
141 if (c1
+ ystep1
+ xstep1
> 0 &&
142 c2
+ ystep2
+ xstep2
> 0 &&
143 c3
+ ystep3
+ xstep3
> 0)
144 quad
->inout
.mask
|= 8;
146 if (quad
->inout
.mask
)
147 rast
->state
->run( rast
->state
->state
, &quad
, 1 );
150 /* Evaluate each pixel in a block, generate a mask and possibly render
154 do_block( struct triangle
*tri
,
162 float xstep1
= -step
* tri
->dy12
;
163 float xstep2
= -step
* tri
->dy23
;
164 float xstep3
= -step
* tri
->dy31
;
166 float ystep1
= step
* tri
->dx12
;
167 float ystep2
= step
* tri
->dx23
;
168 float ystep3
= step
* tri
->dx31
;
172 for (iy
= 0; iy
< BLOCKSIZE
; iy
+= 2) {
177 for (ix
= 0; ix
< BLOCKSIZE
; ix
+= 2) {
179 do_quad(tri
, x
+ix
, y
+iy
, cx1
, cx2
, cx3
);
194 /* Scan the tile in chunks and figure out which pixels to rasterize
197 void lp_rast_triangle( struct lp_rasterizer
*rast
,
198 const struct lp_rast_triangle
*tri
)
200 int minx
, maxx
, miny
, maxy
;
202 /* Clamp to tile dimensions:
204 minx
= MAX2(tri
->maxx
, rast
->x
);
205 miny
= MAX2(tri
->miny
, rast
->y
);
206 maxx
= MIN2(tri
->maxx
, rast
->x
+ TILE_SIZE
);
207 maxy
= MIN2(tri
->maxy
, rast
->y
+ TILE_SIZE
);
211 debug_printf("%s: non-intersecting triangle in bin\n", __FUNCTION__
);
216 /* Bind parameter interpolants:
218 for (i
= 0; i
< Elements(rast
->quad
); i
++) {
219 rast
->quad
[i
].coef
= tri
->coef
;
220 rast
->quad
[i
].posCoef
= &tri
->position_coef
;
225 if (miny
+ 16 > maxy
&&
230 float xstep1
= -step
* tri
->dy12
;
231 float xstep2
= -step
* tri
->dy23
;
232 float xstep3
= -step
* tri
->dy31
;
234 float ystep1
= step
* tri
->dx12
;
235 float ystep2
= step
* tri
->dx23
;
236 float ystep3
= step
* tri
->dx31
;
238 float eo1
= tri
->eo1
* step
;
239 float eo2
= tri
->eo2
* step
;
240 float eo3
= tri
->eo3
* step
;
247 /* Subdivide space into NxM blocks, where each block is square and
248 * power-of-four in dimension.
250 * Trivially accept or reject blocks, else jump to per-pixel
253 for (y
= miny
; y
< maxy
; y
+= step
)
259 for (x
= minx
; x
< maxx
; x
+= step
)
268 do_quad(&tri
, x
, y
, cx1
, cx2
, cx3
);
271 /* Iterate cx values across the region:
278 /* Iterate c values down the region:
287 const int step
= BLOCKSIZE
;
289 float ei1
= tri
->ei1
* step
;
290 float ei2
= tri
->ei2
* step
;
291 float ei3
= tri
->ei3
* step
;
293 float eo1
= tri
->eo1
* step
;
294 float eo2
= tri
->eo2
* step
;
295 float eo3
= tri
->eo3
* step
;
297 float xstep1
= -step
* tri
->dy12
;
298 float xstep2
= -step
* tri
->dy23
;
299 float xstep3
= -step
* tri
->dy31
;
301 float ystep1
= step
* tri
->dx12
;
302 float ystep2
= step
* tri
->dx23
;
303 float ystep3
= step
* tri
->dx31
;
309 for (y
= miny
; y
< maxy
; y
+= step
)
315 for (x
= minx
; x
< maxx
; x
+= step
)
322 else if (cx1
+ ei1
> 0 &&
326 block_full(&tri
, x
, y
); /* trivial accept */
330 do_block(&tri
, x
, y
, cx1
, cx2
, cx3
);
333 /* Iterate cx values across the region:
340 /* Iterate c values down the region: