1/************************************************************************** 2 * 3 * Copyright 2020 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 "util/u_math.h" 27#include "util/u_memory.h" 28#include "pipe/p_defines.h" 29#include "p_tessellator.h" 30#include "tessellator.hpp" 31 32#include <new> 33 34namespace pipe_tessellator_wrap 35{ 36 /// Wrapper class for the CHWTessellator reference tessellator from MSFT 37 /// This class will store data not originally stored in CHWTessellator 38 class pipe_ts : private CHWTessellator 39 { 40 private: 41 typedef CHWTessellator SUPER; 42 enum pipe_prim_type prim_mode; 43 PIPE_ALIGN_VAR(32) float domain_points_u[MAX_POINT_COUNT]; 44 PIPE_ALIGN_VAR(32) float domain_points_v[MAX_POINT_COUNT]; 45 uint32_t num_domain_points; 46 47 public: 48 void Init(enum pipe_prim_type tes_prim_mode, 49 enum pipe_tess_spacing ts_spacing, 50 bool tes_vertex_order_cw, bool tes_point_mode) 51 { 52 static PIPE_TESSELLATOR_PARTITIONING CVT_TS_D3D_PARTITIONING[] = { 53 PIPE_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD, // PIPE_TESS_SPACING_ODD 54 PIPE_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN, // PIPE_TESS_SPACING_EVEN 55 PIPE_TESSELLATOR_PARTITIONING_INTEGER, // PIPE_TESS_SPACING_EQUAL 56 }; 57 58 PIPE_TESSELLATOR_OUTPUT_PRIMITIVE out_prim; 59 if (tes_point_mode) 60 out_prim = PIPE_TESSELLATOR_OUTPUT_POINT; 61 else if (tes_prim_mode == PIPE_PRIM_LINES) 62 out_prim = PIPE_TESSELLATOR_OUTPUT_LINE; 63 else if (tes_vertex_order_cw) 64 out_prim = PIPE_TESSELLATOR_OUTPUT_TRIANGLE_CW; 65 else 66 out_prim = PIPE_TESSELLATOR_OUTPUT_TRIANGLE_CCW; 67 68 SUPER::Init(CVT_TS_D3D_PARTITIONING[ts_spacing], 69 out_prim); 70 71 prim_mode = tes_prim_mode; 72 num_domain_points = 0; 73 } 74 75 void Tessellate(const struct pipe_tessellation_factors *tess_factors, 76 struct pipe_tessellator_data *tess_data) 77 { 78 switch (prim_mode) 79 { 80 case PIPE_PRIM_QUADS: 81 SUPER::TessellateQuadDomain( 82 tess_factors->outer_tf[0], 83 tess_factors->outer_tf[1], 84 tess_factors->outer_tf[2], 85 tess_factors->outer_tf[3], 86 tess_factors->inner_tf[0], 87 tess_factors->inner_tf[1]); 88 break; 89 90 case PIPE_PRIM_TRIANGLES: 91 SUPER::TessellateTriDomain( 92 tess_factors->outer_tf[0], 93 tess_factors->outer_tf[1], 94 tess_factors->outer_tf[2], 95 tess_factors->inner_tf[0]); 96 break; 97 98 case PIPE_PRIM_LINES: 99 SUPER::TessellateIsoLineDomain( 100 tess_factors->outer_tf[0], 101 tess_factors->outer_tf[1]); 102 break; 103 104 default: 105 assert(0); 106 return; 107 } 108 109 num_domain_points = (uint32_t)SUPER::GetPointCount(); 110 111 DOMAIN_POINT *points = SUPER::GetPoints(); 112 for (uint32_t i = 0; i < num_domain_points; i++) { 113 domain_points_u[i] = points[i].u; 114 domain_points_v[i] = points[i].v; 115 } 116 tess_data->num_domain_points = num_domain_points; 117 tess_data->domain_points_u = &domain_points_u[0]; 118 tess_data->domain_points_v = &domain_points_v[0]; 119 120 tess_data->num_indices = (uint32_t)SUPER::GetIndexCount(); 121 122 tess_data->indices = (uint32_t*)SUPER::GetIndices(); 123 } 124 }; 125} // namespace Tessellator 126 127/* allocate tessellator */ 128struct pipe_tessellator * 129p_tess_init(enum pipe_prim_type tes_prim_mode, 130 enum pipe_tess_spacing spacing, 131 bool tes_vertex_order_cw, bool tes_point_mode) 132{ 133 void *mem; 134 using pipe_tessellator_wrap::pipe_ts; 135 136 mem = align_malloc(sizeof(pipe_ts), 256); 137 138 pipe_ts* tessellator = new (mem) pipe_ts(); 139 140 tessellator->Init(tes_prim_mode, spacing, tes_vertex_order_cw, tes_point_mode); 141 142 return (struct pipe_tessellator *)tessellator; 143} 144 145/* destroy tessellator */ 146void p_tess_destroy(struct pipe_tessellator *pipe_tess) 147{ 148 using pipe_tessellator_wrap::pipe_ts; 149 pipe_ts *tessellator = (pipe_ts*)pipe_tess; 150 151 tessellator->~pipe_ts(); 152 align_free(tessellator); 153} 154 155/* perform tessellation */ 156void p_tessellate(struct pipe_tessellator *pipe_tess, 157 const struct pipe_tessellation_factors *tess_factors, 158 struct pipe_tessellator_data *tess_data) 159{ 160 using pipe_tessellator_wrap::pipe_ts; 161 pipe_ts *tessellator = (pipe_ts*)pipe_tess; 162 163 tessellator->Tessellate(tess_factors, tess_data); 164} 165 166