1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007-2021 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/*
29bf215546Sopenharmony_ci * Rasterization for binned rectangles within a tile
30bf215546Sopenharmony_ci */
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include <limits.h>
33bf215546Sopenharmony_ci#include "util/u_math.h"
34bf215546Sopenharmony_ci#include "lp_debug.h"
35bf215546Sopenharmony_ci#include "lp_perf.h"
36bf215546Sopenharmony_ci#include "lp_rast_priv.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci/* Our 16-pixel stamps are layed out as:
39bf215546Sopenharmony_ci *
40bf215546Sopenharmony_ci *    0  1  2  3
41bf215546Sopenharmony_ci *    4  5  6  7
42bf215546Sopenharmony_ci *    8  9  10 11
43bf215546Sopenharmony_ci *    12 13 14 15
44bf215546Sopenharmony_ci *
45bf215546Sopenharmony_ci * Define bitmasks for each row and column in this layout:
46bf215546Sopenharmony_ci */
47bf215546Sopenharmony_ci#define COLUMN0 ((1<<0)|(1<<4)|(1<<8) |(1<<12))
48bf215546Sopenharmony_ci#define COLUMN1 ((1<<1)|(1<<5)|(1<<9) |(1<<13))
49bf215546Sopenharmony_ci#define COLUMN2 ((1<<2)|(1<<6)|(1<<10)|(1<<14))
50bf215546Sopenharmony_ci#define COLUMN3 ((1<<3)|(1<<7)|(1<<11)|(1<<15))
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci#define ROW0 ((1<<0) |(1<<1) |(1<<2) |(1<<3))
53bf215546Sopenharmony_ci#define ROW1 ((1<<4) |(1<<5) |(1<<6) |(1<<7))
54bf215546Sopenharmony_ci#define ROW2 ((1<<8) |(1<<9) |(1<<10)|(1<<11))
55bf215546Sopenharmony_ci#define ROW3 ((1<<12)|(1<<13)|(1<<14)|(1<<15))
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci#define STAMP_SIZE 4
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_cistatic unsigned left_mask_tab[STAMP_SIZE] = {
60bf215546Sopenharmony_ci   COLUMN0 | COLUMN1 | COLUMN2 | COLUMN3,
61bf215546Sopenharmony_ci   COLUMN1 | COLUMN2 | COLUMN3,
62bf215546Sopenharmony_ci   COLUMN2 | COLUMN3,
63bf215546Sopenharmony_ci   COLUMN3,
64bf215546Sopenharmony_ci};
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistatic unsigned right_mask_tab[STAMP_SIZE] = {
67bf215546Sopenharmony_ci   COLUMN0,
68bf215546Sopenharmony_ci   COLUMN0 | COLUMN1,
69bf215546Sopenharmony_ci   COLUMN0 | COLUMN1 | COLUMN2,
70bf215546Sopenharmony_ci   COLUMN0 | COLUMN1 | COLUMN2 | COLUMN3,
71bf215546Sopenharmony_ci};
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_cistatic unsigned top_mask_tab[STAMP_SIZE] = {
74bf215546Sopenharmony_ci   ROW0 | ROW1 | ROW2 | ROW3,
75bf215546Sopenharmony_ci   ROW1 | ROW2 | ROW3,
76bf215546Sopenharmony_ci   ROW2 | ROW3,
77bf215546Sopenharmony_ci   ROW3,
78bf215546Sopenharmony_ci};
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_cistatic unsigned bottom_mask_tab[STAMP_SIZE] = {
81bf215546Sopenharmony_ci   ROW0,
82bf215546Sopenharmony_ci   ROW0 | ROW1,
83bf215546Sopenharmony_ci   ROW0 | ROW1 | ROW2,
84bf215546Sopenharmony_ci   ROW0 | ROW1 | ROW2 | ROW3,
85bf215546Sopenharmony_ci};
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_cistatic inline void
88bf215546Sopenharmony_cifull(struct lp_rasterizer_task *task,
89bf215546Sopenharmony_ci     const struct lp_rast_rectangle *rect,
90bf215546Sopenharmony_ci     unsigned ix, unsigned iy)
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   LP_COUNT(nr_rect_fully_covered_4);
93bf215546Sopenharmony_ci   lp_rast_shade_quads_all(task,
94bf215546Sopenharmony_ci                           &rect->inputs,
95bf215546Sopenharmony_ci                           task->x + ix * STAMP_SIZE,
96bf215546Sopenharmony_ci                           task->y + iy * STAMP_SIZE);
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_cistatic inline void
100bf215546Sopenharmony_cipartial(struct lp_rasterizer_task *task,
101bf215546Sopenharmony_ci        const struct lp_rast_rectangle *rect,
102bf215546Sopenharmony_ci        unsigned ix, unsigned iy,
103bf215546Sopenharmony_ci        unsigned mask)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci   /* Unfortunately we can end up generating full blocks on this path,
106bf215546Sopenharmony_ci    * need to catch them.
107bf215546Sopenharmony_ci    */
108bf215546Sopenharmony_ci   if (mask == 0xffff)
109bf215546Sopenharmony_ci      full(task, rect, ix, iy);
110bf215546Sopenharmony_ci   else {
111bf215546Sopenharmony_ci      assert(mask);
112bf215546Sopenharmony_ci      LP_COUNT(nr_rect_partially_covered_4);
113bf215546Sopenharmony_ci      lp_rast_shade_quads_mask(task,
114bf215546Sopenharmony_ci                               &rect->inputs,
115bf215546Sopenharmony_ci                               task->x + ix * STAMP_SIZE,
116bf215546Sopenharmony_ci                               task->y + iy * STAMP_SIZE,
117bf215546Sopenharmony_ci                               mask);
118bf215546Sopenharmony_ci   }
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_cistatic inline void
123bf215546Sopenharmony_ciintersect_rect_and_tile(struct lp_rasterizer_task *task,
124bf215546Sopenharmony_ci                        const struct lp_rast_rectangle *rect,
125bf215546Sopenharmony_ci                        struct u_rect *box)
126bf215546Sopenharmony_ci{
127bf215546Sopenharmony_ci   box->x0 = task->x;
128bf215546Sopenharmony_ci   box->y0 = task->y;
129bf215546Sopenharmony_ci   box->x1 = task->x + TILE_SIZE - 1;
130bf215546Sopenharmony_ci   box->y1 = task->y + TILE_SIZE - 1;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   assert(u_rect_test_intersection(&rect->box, box));
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   u_rect_find_intersection(&rect->box, box);
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   box->x0 -= task->x;
137bf215546Sopenharmony_ci   box->x1 -= task->x;
138bf215546Sopenharmony_ci   box->y0 -= task->y;
139bf215546Sopenharmony_ci   box->y1 -= task->y;
140bf215546Sopenharmony_ci}
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci/**
144bf215546Sopenharmony_ci * Scan the tile in chunks and figure out which pixels to rasterize
145bf215546Sopenharmony_ci * for this rectangle.
146bf215546Sopenharmony_ci */
147bf215546Sopenharmony_civoid
148bf215546Sopenharmony_cilp_rast_rectangle(struct lp_rasterizer_task *task,
149bf215546Sopenharmony_ci                  const union lp_rast_cmd_arg arg)
150bf215546Sopenharmony_ci{
151bf215546Sopenharmony_ci   const struct lp_rast_rectangle *rect = arg.rectangle;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   struct u_rect box;
154bf215546Sopenharmony_ci   unsigned ix0, ix1, iy0, iy1;
155bf215546Sopenharmony_ci   unsigned left_mask;
156bf215546Sopenharmony_ci   unsigned right_mask;
157bf215546Sopenharmony_ci   unsigned top_mask;
158bf215546Sopenharmony_ci   unsigned bottom_mask;
159bf215546Sopenharmony_ci   unsigned i,j;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   /* Check for "disabled" rectangles generated in out-of-memory
162bf215546Sopenharmony_ci    * conditions.
163bf215546Sopenharmony_ci    */
164bf215546Sopenharmony_ci   if (rect->inputs.disable) {
165bf215546Sopenharmony_ci      /* This command was partially binned and has been disabled */
166bf215546Sopenharmony_ci      return;
167bf215546Sopenharmony_ci   }
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   /* Intersect the rectangle with this tile.
170bf215546Sopenharmony_ci    */
171bf215546Sopenharmony_ci   intersect_rect_and_tile(task, rect, &box);
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   /* The interior of the rectangle (if there is one) will be
174bf215546Sopenharmony_ci    * rasterized as full 4x4 stamps.
175bf215546Sopenharmony_ci    *
176bf215546Sopenharmony_ci    * At each edge of the rectangle, however, there will be a fringe
177bf215546Sopenharmony_ci    * of partial blocks where the edge lands somewhere in the middle
178bf215546Sopenharmony_ci    * of a 4-pixel stamp.
179bf215546Sopenharmony_ci    *
180bf215546Sopenharmony_ci    * For each edge, precalculate a mask of the pixels inside that
181bf215546Sopenharmony_ci    * edge for the first 4-pixel stamp.
182bf215546Sopenharmony_ci    *
183bf215546Sopenharmony_ci    * Note that at the corners, and for narrow rectangles, an
184bf215546Sopenharmony_ci    * individual stamp may have two or more edges active.  We'll deal
185bf215546Sopenharmony_ci    * with that below by combining these masks as appropriate.
186bf215546Sopenharmony_ci    */
187bf215546Sopenharmony_ci   left_mask   = left_mask_tab   [box.x0 & (STAMP_SIZE - 1)];
188bf215546Sopenharmony_ci   right_mask  = right_mask_tab  [box.x1 & (STAMP_SIZE - 1)];
189bf215546Sopenharmony_ci   top_mask    = top_mask_tab    [box.y0 & (STAMP_SIZE - 1)];
190bf215546Sopenharmony_ci   bottom_mask = bottom_mask_tab [box.y1 & (STAMP_SIZE - 1)];
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   ix0 = box.x0 / STAMP_SIZE;
193bf215546Sopenharmony_ci   ix1 = box.x1 / STAMP_SIZE;
194bf215546Sopenharmony_ci   iy0 = box.y0 / STAMP_SIZE;
195bf215546Sopenharmony_ci   iy1 = box.y1 / STAMP_SIZE;
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   /* Various special cases.
198bf215546Sopenharmony_ci    */
199bf215546Sopenharmony_ci   if (ix0 == ix1 && iy0 == iy1) {
200bf215546Sopenharmony_ci      /* Rectangle is contained within a single 4x4 stamp:
201bf215546Sopenharmony_ci       */
202bf215546Sopenharmony_ci      partial(task, rect, ix0, iy0,
203bf215546Sopenharmony_ci              (left_mask & right_mask &
204bf215546Sopenharmony_ci               top_mask & bottom_mask));
205bf215546Sopenharmony_ci   }
206bf215546Sopenharmony_ci   else if (ix0 == ix1) {
207bf215546Sopenharmony_ci      /* Left and right edges fall on the same 4-pixel-wide column:
208bf215546Sopenharmony_ci       */
209bf215546Sopenharmony_ci      unsigned mask = left_mask & right_mask;
210bf215546Sopenharmony_ci      partial(task, rect, ix0, iy0, mask & top_mask);
211bf215546Sopenharmony_ci      for (i = iy0 + 1; i < iy1; i++)
212bf215546Sopenharmony_ci         partial(task, rect, ix0, i, mask);
213bf215546Sopenharmony_ci      partial(task, rect, ix0, iy1, mask & bottom_mask);
214bf215546Sopenharmony_ci   }
215bf215546Sopenharmony_ci   else if (iy0 == iy1) {
216bf215546Sopenharmony_ci      /* Top and bottom edges fall on the same 4-pixel-wide row:
217bf215546Sopenharmony_ci       */
218bf215546Sopenharmony_ci      unsigned mask = top_mask & bottom_mask;
219bf215546Sopenharmony_ci      partial(task, rect, ix0, iy0, mask & left_mask);
220bf215546Sopenharmony_ci      for (i = ix0 + 1; i < ix1; i++)
221bf215546Sopenharmony_ci         partial(task, rect, i, iy0, mask);
222bf215546Sopenharmony_ci      partial(task, rect, ix1, iy0, mask & right_mask);
223bf215546Sopenharmony_ci   }
224bf215546Sopenharmony_ci   else {
225bf215546Sopenharmony_ci      /* Each pair of edges falls in a separate 4-pixel-wide
226bf215546Sopenharmony_ci       * row/column.
227bf215546Sopenharmony_ci       */
228bf215546Sopenharmony_ci      partial(task, rect, ix0, iy0, left_mask  & top_mask);
229bf215546Sopenharmony_ci      partial(task, rect, ix0, iy1, left_mask  & bottom_mask);
230bf215546Sopenharmony_ci      partial(task, rect, ix1, iy0, right_mask & top_mask);
231bf215546Sopenharmony_ci      partial(task, rect, ix1, iy1, right_mask & bottom_mask);
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci      for (i = ix0 + 1; i < ix1; i++)
234bf215546Sopenharmony_ci         partial(task, rect, i, iy0, top_mask);
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci      for (i = ix0 + 1; i < ix1; i++)
237bf215546Sopenharmony_ci         partial(task, rect, i, iy1, bottom_mask);
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci      for (i = iy0 + 1; i < iy1; i++)
240bf215546Sopenharmony_ci         partial(task, rect, ix0, i, left_mask);
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci      for (i = iy0 + 1; i < iy1; i++)
243bf215546Sopenharmony_ci         partial(task, rect, ix1, i, right_mask);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci      /* Full interior blocks
246bf215546Sopenharmony_ci       */
247bf215546Sopenharmony_ci      for (j = iy0 + 1; j < iy1; j++) {
248bf215546Sopenharmony_ci         for (i = ix0 + 1; i < ix1; i++) {
249bf215546Sopenharmony_ci            full(task, rect, i, j);
250bf215546Sopenharmony_ci         }
251bf215546Sopenharmony_ci      }
252bf215546Sopenharmony_ci   }
253bf215546Sopenharmony_ci}
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci
256