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