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