1
/**************************************************************************
3
* Copyright 2007-2021 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 rectangles within a tile
33
#include "util/u_math.h"
36
#include "lp_rast_priv.h"
38
/* Our 16-pixel stamps are layed out as:
45
* Define bitmasks for each row and column in this layout:
47
#define COLUMN0 ((1<<0)|(1<<4)|(1<<8) |(1<<12))
48
#define COLUMN1 ((1<<1)|(1<<5)|(1<<9) |(1<<13))
49
#define COLUMN2 ((1<<2)|(1<<6)|(1<<10)|(1<<14))
50
#define COLUMN3 ((1<<3)|(1<<7)|(1<<11)|(1<<15))
52
#define ROW0 ((1<<0) |(1<<1) |(1<<2) |(1<<3))
53
#define ROW1 ((1<<4) |(1<<5) |(1<<6) |(1<<7))
54
#define ROW2 ((1<<8) |(1<<9) |(1<<10)|(1<<11))
55
#define ROW3 ((1<<12)|(1<<13)|(1<<14)|(1<<15))
59
static unsigned left_mask_tab[STAMP_SIZE] = {
60
COLUMN0 | COLUMN1 | COLUMN2 | COLUMN3,
61
COLUMN1 | COLUMN2 | COLUMN3,
66
static unsigned right_mask_tab[STAMP_SIZE] = {
69
COLUMN0 | COLUMN1 | COLUMN2,
70
COLUMN0 | COLUMN1 | COLUMN2 | COLUMN3,
73
static unsigned top_mask_tab[STAMP_SIZE] = {
74
ROW0 | ROW1 | ROW2 | ROW3,
80
static unsigned bottom_mask_tab[STAMP_SIZE] = {
84
ROW0 | ROW1 | ROW2 | ROW3,
88
full(struct lp_rasterizer_task *task,
89
const struct lp_rast_rectangle *rect,
90
unsigned ix, unsigned iy)
92
LP_COUNT(nr_rect_fully_covered_4);
93
lp_rast_shade_quads_all(task,
95
task->x + ix * STAMP_SIZE,
96
task->y + iy * STAMP_SIZE);
100
partial(struct lp_rasterizer_task *task,
101
const struct lp_rast_rectangle *rect,
102
unsigned ix, unsigned iy,
105
/* Unfortunately we can end up generating full blocks on this path,
106
* need to catch them.
109
full(task, rect, ix, iy);
112
LP_COUNT(nr_rect_partially_covered_4);
113
lp_rast_shade_quads_mask(task,
115
task->x + ix * STAMP_SIZE,
116
task->y + iy * STAMP_SIZE,
123
intersect_rect_and_tile(struct lp_rasterizer_task *task,
124
const struct lp_rast_rectangle *rect,
129
box->x1 = task->x + TILE_SIZE - 1;
130
box->y1 = task->y + TILE_SIZE - 1;
132
assert(u_rect_test_intersection(&rect->box, box));
134
u_rect_find_intersection(&rect->box, box);
144
* Scan the tile in chunks and figure out which pixels to rasterize
145
* for this rectangle.
148
lp_rast_rectangle(struct lp_rasterizer_task *task,
149
const union lp_rast_cmd_arg arg)
151
const struct lp_rast_rectangle *rect = arg.rectangle;
154
unsigned ix0, ix1, iy0, iy1;
158
unsigned bottom_mask;
161
/* Check for "disabled" rectangles generated in out-of-memory
164
if (rect->inputs.disable) {
165
/* This command was partially binned and has been disabled */
169
/* Intersect the rectangle with this tile.
171
intersect_rect_and_tile(task, rect, &box);
173
/* The interior of the rectangle (if there is one) will be
174
* rasterized as full 4x4 stamps.
176
* At each edge of the rectangle, however, there will be a fringe
177
* of partial blocks where the edge lands somewhere in the middle
178
* of a 4-pixel stamp.
180
* For each edge, precalculate a mask of the pixels inside that
181
* edge for the first 4-pixel stamp.
183
* Note that at the corners, and for narrow rectangles, an
184
* individual stamp may have two or more edges active. We'll deal
185
* with that below by combining these masks as appropriate.
187
left_mask = left_mask_tab [box.x0 & (STAMP_SIZE - 1)];
188
right_mask = right_mask_tab [box.x1 & (STAMP_SIZE - 1)];
189
top_mask = top_mask_tab [box.y0 & (STAMP_SIZE - 1)];
190
bottom_mask = bottom_mask_tab [box.y1 & (STAMP_SIZE - 1)];
192
ix0 = box.x0 / STAMP_SIZE;
193
ix1 = box.x1 / STAMP_SIZE;
194
iy0 = box.y0 / STAMP_SIZE;
195
iy1 = box.y1 / STAMP_SIZE;
197
/* Various special cases.
199
if (ix0 == ix1 && iy0 == iy1) {
200
/* Rectangle is contained within a single 4x4 stamp:
202
partial(task, rect, ix0, iy0,
203
(left_mask & right_mask &
204
top_mask & bottom_mask));
206
else if (ix0 == ix1) {
207
/* Left and right edges fall on the same 4-pixel-wide column:
209
unsigned mask = left_mask & right_mask;
210
partial(task, rect, ix0, iy0, mask & top_mask);
211
for (i = iy0 + 1; i < iy1; i++)
212
partial(task, rect, ix0, i, mask);
213
partial(task, rect, ix0, iy1, mask & bottom_mask);
215
else if (iy0 == iy1) {
216
/* Top and bottom edges fall on the same 4-pixel-wide row:
218
unsigned mask = top_mask & bottom_mask;
219
partial(task, rect, ix0, iy0, mask & left_mask);
220
for (i = ix0 + 1; i < ix1; i++)
221
partial(task, rect, i, iy0, mask);
222
partial(task, rect, ix1, iy0, mask & right_mask);
225
/* Each pair of edges falls in a separate 4-pixel-wide
228
partial(task, rect, ix0, iy0, left_mask & top_mask);
229
partial(task, rect, ix0, iy1, left_mask & bottom_mask);
230
partial(task, rect, ix1, iy0, right_mask & top_mask);
231
partial(task, rect, ix1, iy1, right_mask & bottom_mask);
233
for (i = ix0 + 1; i < ix1; i++)
234
partial(task, rect, i, iy0, top_mask);
236
for (i = ix0 + 1; i < ix1; i++)
237
partial(task, rect, i, iy1, bottom_mask);
239
for (i = iy0 + 1; i < iy1; i++)
240
partial(task, rect, ix0, i, left_mask);
242
for (i = iy0 + 1; i < iy1; i++)
243
partial(task, rect, ix1, i, right_mask);
245
/* Full interior blocks
247
for (j = iy0 + 1; j < iy1; j++) {
248
for (i = ix0 + 1; i < ix1; i++) {
249
full(task, rect, i, j);