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