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
47 public:
Init(enum pipe_prim_type tes_prim_mode,enum pipe_tess_spacing ts_spacing,bool tes_vertex_order_cw,bool tes_point_mode)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
Tessellate(const struct pipe_tessellation_factors * tess_factors,struct pipe_tessellator_data * tess_data)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 */
128 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)129 p_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 */
p_tess_destroy(struct pipe_tessellator * pipe_tess)146 void 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 */
p_tessellate(struct pipe_tessellator * pipe_tess,const struct pipe_tessellation_factors * tess_factors,struct pipe_tessellator_data * tess_data)156 void 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