/************************************************************************** * * Copyright 2009-2021 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ #include #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_rect.h" #include "util/u_surface.h" #include "util/u_pack_color.h" #include "lp_scene_queue.h" #include "lp_debug.h" #include "lp_fence.h" #include "lp_perf.h" #include "lp_query.h" #include "lp_rast.h" #include "lp_rast_priv.h" #include "lp_scene.h" static void lp_rast_linear_clear(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; union util_color uc; LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); uc = arg.clear_rb->color_val; util_fill_rect(scene->cbufs[0].map, PIPE_FORMAT_B8G8R8A8_UNORM, scene->cbufs[0].stride, task->x, task->y, task->width, task->height, &uc); } /* Run the scanline version of the shader across the whole tile. */ static void lp_rast_linear_tile(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_rast_shader_inputs *inputs = arg.shade_tile; const struct lp_rast_state *state; struct lp_fragment_shader_variant *variant; const struct lp_scene *scene = task->scene; if (inputs->disable) return; state = task->state; assert(state); if (!state) { return; } variant = state->variant; if (variant->jit_linear_blit && inputs->is_blit) { if (variant->jit_linear_blit(state, task->x, task->y, task->width, task->height, (const float (*)[4])GET_A0(inputs), (const float (*)[4])GET_DADX(inputs), (const float (*)[4])GET_DADY(inputs), scene->cbufs[0].map, scene->cbufs[0].stride)) return; } if (variant->jit_linear) { if (variant->jit_linear(state, task->x, task->y, task->width, task->height, (const float (*)[4])GET_A0(inputs), (const float (*)[4])GET_DADX(inputs), (const float (*)[4])GET_DADY(inputs), scene->cbufs[0].map, scene->cbufs[0].stride)) return; } { struct u_rect box; box.x0 = task->x; box.x1 = task->x + task->width - 1; box.y0 = task->y; box.y1 = task->y + task->height - 1; lp_rast_linear_rect_fallback(task, inputs, &box); } } /* Run the scanline version of the shader on a rectangle within the * tile. */ static void lp_rast_linear_rect(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; const struct lp_rast_rectangle *rect = arg.rectangle; const struct lp_rast_shader_inputs *inputs = &rect->inputs; const struct lp_rast_state *state = task->state; struct lp_fragment_shader_variant *variant = state->variant; struct u_rect box; int width, height; if (inputs->disable) return; box.x0 = task->x; box.y0 = task->y; box.x1 = task->x + task->width - 1; box.y1 = task->y + task->height - 1; u_rect_find_intersection(&rect->box, &box); width = box.x1 - box.x0 + 1; height = box.y1 - box.y0 + 1; /* Note that blit primitives can end up in the non-full-tile path, * the binner currently doesn't try to classify sub-tile * primitives. Can detect them here though. */ if (variant->jit_linear_blit && inputs->is_blit) { if (variant->jit_linear_blit(state, box.x0, box.y0, width, height, (const float (*)[4])GET_A0(inputs), (const float (*)[4])GET_DADX(inputs), (const float (*)[4])GET_DADY(inputs), scene->cbufs[0].map, scene->cbufs[0].stride)) return; } if (variant->jit_linear) { if (variant->jit_linear(state, box.x0, box.y0, width, height, (const float (*)[4])GET_A0(inputs), (const float (*)[4])GET_DADX(inputs), (const float (*)[4])GET_DADY(inputs), scene->cbufs[0].map, scene->cbufs[0].stride)) return; } lp_rast_linear_rect_fallback(task, inputs, &box); } static const lp_rast_cmd_func dispatch_linear[] = { lp_rast_linear_clear, /* clear_color */ NULL, /* clear_zstencil */ NULL, /* triangle_1 */ NULL, /* triangle_2 */ NULL, /* triangle_3 */ NULL, /* triangle_4 */ NULL, /* triangle_5 */ NULL, /* triangle_6 */ NULL, /* triangle_7 */ NULL, /* triangle_8 */ NULL, /* triangle_3_4 */ NULL, /* triangle_3_16 */ NULL, /* triangle_4_16 */ lp_rast_linear_tile, /* shade_tile */ lp_rast_linear_tile, /* shade_tile_opaque */ NULL, /* begin_query */ NULL, /* end_query */ lp_rast_set_state, /* set_state */ NULL, /* lp_rast_triangle_32_1 */ NULL, /* lp_rast_triangle_32_2 */ NULL, /* lp_rast_triangle_32_3 */ NULL, /* lp_rast_triangle_32_4 */ NULL, /* lp_rast_triangle_32_5 */ NULL, /* lp_rast_triangle_32_6 */ NULL, /* lp_rast_triangle_32_7 */ NULL, /* lp_rast_triangle_32_8 */ NULL, /* lp_rast_triangle_32_3_4 */ NULL, /* lp_rast_triangle_32_3_16 */ NULL, /* lp_rast_triangle_32_4_16 */ NULL, /* lp_rast_triangle_ms_1 */ NULL, /* lp_rast_triangle_ms_2 */ NULL, /* lp_rast_triangle_ms_3 */ NULL, /* lp_rast_triangle_ms_4 */ NULL, /* lp_rast_triangle_ms_5 */ NULL, /* lp_rast_triangle_ms_6 */ NULL, /* lp_rast_triangle_ms_7 */ NULL, /* lp_rast_triangle_ms_8 */ NULL, /* lp_rast_triangle_ms_3_4 */ NULL, /* lp_rast_triangle_ms_3_16 */ NULL, /* lp_rast_triangle_ms_4_16 */ lp_rast_linear_rect, /* rect */ lp_rast_linear_tile, /* blit */ }; /* Assumptions for this path: * - Single color buffer, PIPE_FORMAT_B8G8R8A8_UNORM * - No depth buffer * - All primitives in bins are rect, tile, blit or clear. * - All shaders have a linear variant. */ void lp_linear_rasterize_bin(struct lp_rasterizer_task *task, const struct cmd_bin *bin) { const struct cmd_block *block; unsigned k; STATIC_ASSERT(ARRAY_SIZE(dispatch_linear) == LP_RAST_OP_MAX); if (0) debug_printf("%s\n", __FUNCTION__); for (block = bin->head; block; block = block->next) { for (k = 0; k < block->count; k++) { assert(dispatch_linear[block->cmd[k]]); dispatch_linear[block->cmd[k]]( task, block->arg[k] ); } } }