1/************************************************************************** 2 * 3 * Copyright 2009-2021 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#include <limits.h> 29#include "util/u_memory.h" 30#include "util/u_math.h" 31#include "util/u_rect.h" 32#include "util/u_surface.h" 33#include "util/u_pack_color.h" 34 35#include "lp_scene_queue.h" 36#include "lp_debug.h" 37#include "lp_fence.h" 38#include "lp_perf.h" 39#include "lp_query.h" 40#include "lp_rast.h" 41#include "lp_rast_priv.h" 42#include "lp_scene.h" 43 44 45static void 46lp_rast_linear_clear(struct lp_rasterizer_task *task, 47 const union lp_rast_cmd_arg arg) 48{ 49 LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); 50 51 union util_color uc = arg.clear_rb->color_val; 52 53 const struct lp_scene *scene = task->scene; 54 util_fill_rect(scene->cbufs[0].map, 55 PIPE_FORMAT_B8G8R8A8_UNORM, 56 scene->cbufs[0].stride, 57 task->x, 58 task->y, 59 task->width, 60 task->height, 61 &uc); 62} 63 64 65/* Run the scanline version of the shader across the whole tile. 66 */ 67static void 68lp_rast_linear_tile(struct lp_rasterizer_task *task, 69 const union lp_rast_cmd_arg arg) 70{ 71 const struct lp_rast_shader_inputs *inputs = arg.shade_tile; 72 if (inputs->disable) 73 return; 74 75 const struct lp_rast_state *state = task->state; 76 assert(state); 77 if (!state) { 78 return; 79 } 80 81 const struct lp_fragment_shader_variant *variant = state->variant; 82 const struct lp_scene *scene = task->scene; 83 84 if (variant->jit_linear_blit && inputs->is_blit) { 85 if (variant->jit_linear_blit(state, 86 task->x, 87 task->y, 88 task->width, 89 task->height, 90 GET_A0(inputs), 91 GET_DADX(inputs), 92 GET_DADY(inputs), 93 scene->cbufs[0].map, 94 scene->cbufs[0].stride)) 95 return; 96 } 97 98 if (variant->jit_linear) { 99 if (variant->jit_linear(state, 100 task->x, 101 task->y, 102 task->width, 103 task->height, 104 GET_A0(inputs), 105 GET_DADX(inputs), 106 GET_DADY(inputs), 107 scene->cbufs[0].map, 108 scene->cbufs[0].stride)) 109 return; 110 } 111 112 { 113 struct u_rect box; 114 box.x0 = task->x; 115 box.x1 = task->x + task->width - 1; 116 box.y0 = task->y; 117 box.y1 = task->y + task->height - 1; 118 lp_rast_linear_rect_fallback(task, inputs, &box); 119 } 120} 121 122 123/* Run the scanline version of the shader on a rectangle within the 124 * tile. 125 */ 126static void 127lp_rast_linear_rect(struct lp_rasterizer_task *task, 128 const union lp_rast_cmd_arg arg) 129{ 130 const struct lp_scene *scene = task->scene; 131 const struct lp_rast_rectangle *rect = arg.rectangle; 132 const struct lp_rast_shader_inputs *inputs = &rect->inputs; 133 134 if (inputs->disable) 135 return; 136 137 struct u_rect box; 138 box.x0 = task->x; 139 box.y0 = task->y; 140 box.x1 = task->x + task->width - 1; 141 box.y1 = task->y + task->height - 1; 142 143 u_rect_find_intersection(&rect->box, &box); 144 145 const int width = box.x1 - box.x0 + 1; 146 const int height = box.y1 - box.y0 + 1; 147 148 /* Note that blit primitives can end up in the non-full-tile path, 149 * the binner currently doesn't try to classify sub-tile 150 * primitives. Can detect them here though. 151 */ 152 const struct lp_rast_state *state = task->state; 153 struct lp_fragment_shader_variant *variant = state->variant; 154 if (variant->jit_linear_blit && inputs->is_blit) { 155 if (variant->jit_linear_blit(state, 156 box.x0, box.y0, 157 width, height, 158 GET_A0(inputs), 159 GET_DADX(inputs), 160 GET_DADY(inputs), 161 scene->cbufs[0].map, 162 scene->cbufs[0].stride)) { 163 return; 164 } 165 } 166 167 if (variant->jit_linear) { 168 if (variant->jit_linear(state, 169 box.x0, box.y0, 170 width, height, 171 GET_A0(inputs), 172 GET_DADX(inputs), 173 GET_DADY(inputs), 174 scene->cbufs[0].map, 175 scene->cbufs[0].stride)) { 176 return; 177 } 178 } 179 180 lp_rast_linear_rect_fallback(task, inputs, &box); 181} 182 183 184static const lp_rast_cmd_func 185dispatch_linear[] = { 186 lp_rast_linear_clear, /* clear_color */ 187 NULL, /* clear_zstencil */ 188 NULL, /* triangle_1 */ 189 NULL, /* triangle_2 */ 190 NULL, /* triangle_3 */ 191 NULL, /* triangle_4 */ 192 NULL, /* triangle_5 */ 193 NULL, /* triangle_6 */ 194 NULL, /* triangle_7 */ 195 NULL, /* triangle_8 */ 196 NULL, /* triangle_3_4 */ 197 NULL, /* triangle_3_16 */ 198 NULL, /* triangle_4_16 */ 199 lp_rast_linear_tile, /* shade_tile */ 200 lp_rast_linear_tile, /* shade_tile_opaque */ 201 NULL, /* begin_query */ 202 NULL, /* end_query */ 203 lp_rast_set_state, /* set_state */ 204 NULL, /* lp_rast_triangle_32_1 */ 205 NULL, /* lp_rast_triangle_32_2 */ 206 NULL, /* lp_rast_triangle_32_3 */ 207 NULL, /* lp_rast_triangle_32_4 */ 208 NULL, /* lp_rast_triangle_32_5 */ 209 NULL, /* lp_rast_triangle_32_6 */ 210 NULL, /* lp_rast_triangle_32_7 */ 211 NULL, /* lp_rast_triangle_32_8 */ 212 NULL, /* lp_rast_triangle_32_3_4 */ 213 NULL, /* lp_rast_triangle_32_3_16 */ 214 NULL, /* lp_rast_triangle_32_4_16 */ 215 216 NULL, /* lp_rast_triangle_ms_1 */ 217 NULL, /* lp_rast_triangle_ms_2 */ 218 NULL, /* lp_rast_triangle_ms_3 */ 219 NULL, /* lp_rast_triangle_ms_4 */ 220 NULL, /* lp_rast_triangle_ms_5 */ 221 NULL, /* lp_rast_triangle_ms_6 */ 222 NULL, /* lp_rast_triangle_ms_7 */ 223 NULL, /* lp_rast_triangle_ms_8 */ 224 NULL, /* lp_rast_triangle_ms_3_4 */ 225 NULL, /* lp_rast_triangle_ms_3_16 */ 226 NULL, /* lp_rast_triangle_ms_4_16 */ 227 228 lp_rast_linear_rect, /* rect */ 229 lp_rast_linear_tile, /* blit */ 230}; 231 232 233/* Assumptions for this path: 234 * - Single color buffer, PIPE_FORMAT_B8G8R8A8_UNORM 235 * - No depth buffer 236 * - All primitives in bins are rect, tile, blit or clear. 237 * - All shaders have a linear variant. 238 */ 239void 240lp_linear_rasterize_bin(struct lp_rasterizer_task *task, 241 const struct cmd_bin *bin) 242{ 243 const struct cmd_block *block; 244 unsigned k; 245 246 STATIC_ASSERT(ARRAY_SIZE(dispatch_linear) == LP_RAST_OP_MAX); 247 248 if (0) debug_printf("%s\n", __FUNCTION__); 249 250 for (block = bin->head; block; block = block->next) { 251 for (k = 0; k < block->count; k++) { 252 assert(dispatch_linear[block->cmd[k]]); 253 dispatch_linear[block->cmd[k]]( task, block->arg[k] ); 254 } 255 } 256} 257