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
45 static void
lp_rast_linear_clear(struct lp_rasterizer_task * task,const union lp_rast_cmd_arg arg)46 lp_rast_linear_clear(struct lp_rasterizer_task *task,
47 const union lp_rast_cmd_arg arg)
48 {
49 LP_DBG(DEBUG_RAST, "%s\n", __func__);
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 */
67 static void
lp_rast_linear_tile(struct lp_rasterizer_task * task,const union lp_rast_cmd_arg arg)68 lp_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 */
126 static void
lp_rast_linear_rect(struct lp_rasterizer_task * task,const union lp_rast_cmd_arg arg)127 lp_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
184 static const lp_rast_cmd_func
185 dispatch_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 */
239 void
lp_linear_rasterize_bin(struct lp_rasterizer_task * task,const struct cmd_bin * bin)240 lp_linear_rasterize_bin(struct lp_rasterizer_task *task,
241 const struct cmd_bin *bin)
242 {
243 STATIC_ASSERT(ARRAY_SIZE(dispatch_linear) == LP_RAST_OP_MAX);
244
245 if (0) debug_printf("%s\n", __func__);
246
247 const struct cmd_block *block;
248 for (block = bin->head; block; block = block->next) {
249 for (unsigned k = 0; k < block->count; k++) {
250 assert(dispatch_linear[block->cmd[k]]);
251 dispatch_linear[block->cmd[k]](task, block->arg[k]);
252 }
253 }
254 }
255