1/************************************************************************** 2 * 3 * Copyright 2019 Red Hat. 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 "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **************************************************************************/ 25 26#include "lp_context.h" 27#include "lp_state.h" 28#include "lp_texture.h" 29#include "lp_debug.h" 30 31#include "pipe/p_defines.h" 32#include "util/u_memory.h" 33#include "util/u_inlines.h" 34#include "draw/draw_context.h" 35#include "tgsi/tgsi_dump.h" 36#include "tgsi/tgsi_scan.h" 37#include "tgsi/tgsi_parse.h" 38 39 40static void * 41llvmpipe_create_tcs_state(struct pipe_context *pipe, 42 const struct pipe_shader_state *templ) 43{ 44 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 45 struct lp_tess_ctrl_shader *state; 46 47 state = CALLOC_STRUCT(lp_tess_ctrl_shader); 48 if (!state) 49 goto no_state; 50 51 /* debug */ 52 if (LP_DEBUG & DEBUG_TGSI && templ->type == PIPE_SHADER_IR_TGSI) { 53 debug_printf("llvmpipe: Create tess ctrl shader %p:\n", (void *)state); 54 tgsi_dump(templ->tokens, 0); 55 } 56 57 /* copy stream output info */ 58 state->no_tokens = !templ->tokens; 59 memcpy(&state->stream_output, &templ->stream_output, sizeof state->stream_output); 60 61 if (templ->tokens || templ->type == PIPE_SHADER_IR_NIR) { 62 state->dtcs = draw_create_tess_ctrl_shader(llvmpipe->draw, templ); 63 if (state->dtcs == NULL) { 64 goto no_dgs; 65 } 66 } 67 68 return state; 69 70no_dgs: 71 FREE( state ); 72no_state: 73 return NULL; 74} 75 76 77static void 78llvmpipe_bind_tcs_state(struct pipe_context *pipe, void *tcs) 79{ 80 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 81 82 llvmpipe->tcs = (struct lp_tess_ctrl_shader *)tcs; 83 84 draw_bind_tess_ctrl_shader(llvmpipe->draw, 85 (llvmpipe->tcs ? llvmpipe->tcs->dtcs : NULL)); 86 87 llvmpipe->dirty |= LP_NEW_TCS; 88} 89 90 91static void 92llvmpipe_delete_tcs_state(struct pipe_context *pipe, void *tcs) 93{ 94 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 95 96 struct lp_tess_ctrl_shader *state = 97 (struct lp_tess_ctrl_shader *)tcs; 98 99 if (!state) { 100 return; 101 } 102 103 draw_delete_tess_ctrl_shader(llvmpipe->draw, state->dtcs); 104 FREE(state); 105} 106 107 108static void * 109llvmpipe_create_tes_state(struct pipe_context *pipe, 110 const struct pipe_shader_state *templ) 111{ 112 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 113 struct lp_tess_eval_shader *state; 114 115 state = CALLOC_STRUCT(lp_tess_eval_shader); 116 if (!state) 117 goto no_state; 118 119 /* debug */ 120 if (LP_DEBUG & DEBUG_TGSI) { 121 debug_printf("llvmpipe: Create tess eval shader %p:\n", (void *)state); 122 tgsi_dump(templ->tokens, 0); 123 } 124 125 /* copy stream output info */ 126 state->no_tokens = !templ->tokens; 127 memcpy(&state->stream_output, &templ->stream_output, sizeof state->stream_output); 128 129 if (templ->tokens || templ->type == PIPE_SHADER_IR_NIR) { 130 state->dtes = draw_create_tess_eval_shader(llvmpipe->draw, templ); 131 if (state->dtes == NULL) { 132 goto no_dgs; 133 } 134 } 135 136 return state; 137 138no_dgs: 139 FREE( state ); 140no_state: 141 return NULL; 142} 143 144 145static void 146llvmpipe_bind_tes_state(struct pipe_context *pipe, void *tes) 147{ 148 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 149 150 llvmpipe->tes = (struct lp_tess_eval_shader *)tes; 151 152 draw_bind_tess_eval_shader(llvmpipe->draw, 153 (llvmpipe->tes ? llvmpipe->tes->dtes : NULL)); 154 155 llvmpipe->dirty |= LP_NEW_TES; 156} 157 158 159static void 160llvmpipe_delete_tes_state(struct pipe_context *pipe, void *tes) 161{ 162 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 163 164 struct lp_tess_eval_shader *state = 165 (struct lp_tess_eval_shader *)tes; 166 167 if (!state) { 168 return; 169 } 170 171 draw_delete_tess_eval_shader(llvmpipe->draw, state->dtes); 172 FREE(state); 173} 174 175static void 176llvmpipe_set_tess_state(struct pipe_context *pipe, 177 const float default_outer_level[4], 178 const float default_inner_level[2]) 179{ 180 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 181 draw_set_tess_state(llvmpipe->draw, default_outer_level, default_inner_level); 182} 183 184static void 185llvmpipe_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices) 186{ 187 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 188 189 llvmpipe->patch_vertices = patch_vertices; 190} 191 192void 193llvmpipe_init_tess_funcs(struct llvmpipe_context *llvmpipe) 194{ 195 llvmpipe->pipe.create_tcs_state = llvmpipe_create_tcs_state; 196 llvmpipe->pipe.bind_tcs_state = llvmpipe_bind_tcs_state; 197 llvmpipe->pipe.delete_tcs_state = llvmpipe_delete_tcs_state; 198 199 llvmpipe->pipe.create_tes_state = llvmpipe_create_tes_state; 200 llvmpipe->pipe.bind_tes_state = llvmpipe_bind_tes_state; 201 llvmpipe->pipe.delete_tes_state = llvmpipe_delete_tes_state; 202 203 llvmpipe->pipe.set_tess_state = llvmpipe_set_tess_state; 204 llvmpipe->pipe.set_patch_vertices = llvmpipe_set_patch_vertices; 205} 206