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
34 namespace 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 PIPE_ALIGN_VAR(32) uint32_t indices[3][MAX_INDEX_COUNT / 3];
47
48 public:
Init(enum pipe_prim_type tes_prim_mode,enum pipe_tess_spacing ts_spacing,bool tes_vertex_order_cw,bool tes_point_mode)49 void Init(enum pipe_prim_type tes_prim_mode,
50 enum pipe_tess_spacing ts_spacing,
51 bool tes_vertex_order_cw, bool tes_point_mode)
52 {
53 static D3D11_TESSELLATOR_PARTITIONING CVT_TS_D3D_PARTITIONING[] = {
54 D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD, // PIPE_TESS_SPACING_ODD
55 D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN, // PIPE_TESS_SPACING_EVEN
56 D3D11_TESSELLATOR_PARTITIONING_INTEGER, // PIPE_TESS_SPACING_EQUAL
57 };
58
59 D3D11_TESSELLATOR_OUTPUT_PRIMITIVE out_prim;
60 if (tes_point_mode)
61 out_prim = D3D11_TESSELLATOR_OUTPUT_POINT;
62 else if (tes_prim_mode == PIPE_PRIM_LINES)
63 out_prim = D3D11_TESSELLATOR_OUTPUT_LINE;
64 else if (tes_vertex_order_cw)
65 out_prim = D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW;
66 else
67 out_prim = D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW;
68
69 SUPER::Init(CVT_TS_D3D_PARTITIONING[ts_spacing],
70 out_prim);
71
72 prim_mode = tes_prim_mode;
73 num_domain_points = 0;
74 }
75
Tessellate(const struct pipe_tessellation_factors * tess_factors,struct pipe_tessellator_data * tess_data)76 void Tessellate(const struct pipe_tessellation_factors *tess_factors,
77 struct pipe_tessellator_data *tess_data)
78 {
79 switch (prim_mode)
80 {
81 case PIPE_PRIM_QUADS:
82 SUPER::TessellateQuadDomain(
83 tess_factors->outer_tf[0],
84 tess_factors->outer_tf[1],
85 tess_factors->outer_tf[2],
86 tess_factors->outer_tf[3],
87 tess_factors->inner_tf[0],
88 tess_factors->inner_tf[1]);
89 break;
90
91 case PIPE_PRIM_TRIANGLES:
92 SUPER::TessellateTriDomain(
93 tess_factors->outer_tf[0],
94 tess_factors->outer_tf[1],
95 tess_factors->outer_tf[2],
96 tess_factors->inner_tf[0]);
97 break;
98
99 case PIPE_PRIM_LINES:
100 SUPER::TessellateIsoLineDomain(
101 tess_factors->outer_tf[0],
102 tess_factors->outer_tf[1]);
103 break;
104
105 default:
106 assert(0);
107 return;
108 }
109
110 num_domain_points = (uint32_t)SUPER::GetPointCount();
111
112 DOMAIN_POINT *points = SUPER::GetPoints();
113 for (uint32_t i = 0; i < num_domain_points; i++) {
114 domain_points_u[i] = points[i].u;
115 domain_points_v[i] = points[i].v;
116 }
117 tess_data->num_domain_points = num_domain_points;
118 tess_data->domain_points_u = &domain_points_u[0];
119 tess_data->domain_points_v = &domain_points_v[0];
120
121 tess_data->num_indices = (uint32_t)SUPER::GetIndexCount();
122
123 tess_data->indices = (uint32_t*)SUPER::GetIndices();
124 }
125 };
126 } // namespace Tessellator
127
128 /* allocate tessellator */
129 struct pipe_tessellator *
p_tess_init(enum pipe_prim_type tes_prim_mode,enum pipe_tess_spacing spacing,bool tes_vertex_order_cw,bool tes_point_mode)130 p_tess_init(enum pipe_prim_type tes_prim_mode,
131 enum pipe_tess_spacing spacing,
132 bool tes_vertex_order_cw, bool tes_point_mode)
133 {
134 void *mem;
135 using pipe_tessellator_wrap::pipe_ts;
136
137 mem = align_malloc(sizeof(pipe_ts), 256);
138
139 pipe_ts* tessellator = new (mem) pipe_ts();
140
141 tessellator->Init(tes_prim_mode, spacing, tes_vertex_order_cw, tes_point_mode);
142
143 return (struct pipe_tessellator *)tessellator;
144 }
145
146 /* destroy tessellator */
p_tess_destroy(struct pipe_tessellator * pipe_tess)147 void p_tess_destroy(struct pipe_tessellator *pipe_tess)
148 {
149 using pipe_tessellator_wrap::pipe_ts;
150 pipe_ts *tessellator = (pipe_ts*)pipe_tess;
151
152 tessellator->~pipe_ts();
153 align_free(tessellator);
154 }
155
156 /* perform tessellation */
p_tessellate(struct pipe_tessellator * pipe_tess,const struct pipe_tessellation_factors * tess_factors,struct pipe_tessellator_data * tess_data)157 void p_tessellate(struct pipe_tessellator *pipe_tess,
158 const struct pipe_tessellation_factors *tess_factors,
159 struct pipe_tessellator_data *tess_data)
160 {
161 using pipe_tessellator_wrap::pipe_ts;
162 pipe_ts *tessellator = (pipe_ts*)pipe_tess;
163
164 tessellator->Tessellate(tess_factors, tess_data);
165 }
166
167