Cleanup: manually remove header text not handled by automation
[blender.git] / intern / opensubdiv / internal / opensubdiv_gl_mesh.cc
1 // Copyright 2013 Blender Foundation. All rights reserved.
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software Foundation,
15 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
17 #include "opensubdiv_gl_mesh_capi.h"
18
19 #ifdef _MSC_VER
20 #  include <iso646.h>
21 #endif
22
23 #include <opensubdiv/far/stencilTable.h>
24 #include <opensubdiv/osd/glMesh.h>
25 #include <opensubdiv/osd/glPatchTable.h>
26
27 using OpenSubdiv::Far::StencilTable;
28 using OpenSubdiv::Osd::GLMeshInterface;
29 using OpenSubdiv::Osd::GLPatchTable;
30 using OpenSubdiv::Osd::Mesh;
31 using OpenSubdiv::Osd::MeshBitset;
32
33 // CPU backend.
34 #include <opensubdiv/osd/cpuEvaluator.h>
35 #include <opensubdiv/osd/cpuGLVertexBuffer.h>
36 using OpenSubdiv::Osd::CpuGLVertexBuffer;
37 using OpenSubdiv::Osd::CpuEvaluator;
38 typedef Mesh<CpuGLVertexBuffer,
39              StencilTable,
40              CpuEvaluator,
41              GLPatchTable> OsdCpuMesh;
42 // OpenMP backend.
43 #ifdef OPENSUBDIV_HAS_OPENMP
44 #  include <opensubdiv/osd/ompEvaluator.h>
45 using OpenSubdiv::Osd::OmpEvaluator;
46 typedef Mesh<CpuGLVertexBuffer,
47              StencilTable,
48              OmpEvaluator,
49              GLPatchTable> OsdOmpMesh;
50 #endif
51 // OpenCL backend.
52 #ifdef OPENSUBDIV_HAS_OPENCL
53 #  include <opensubdiv/osd/clEvaluator.h>
54 #  include <opensubdiv/osd/clGLVertexBuffer.h>
55 #  include "opensubdiv_device_context_opencl.h"
56 using OpenSubdiv::Osd::CLEvaluator;
57 using OpenSubdiv::Osd::CLGLVertexBuffer;
58 using OpenSubdiv::Osd::CLStencilTable;
59 /* TODO(sergey): Use CLDeviceContext similar to OSD examples? */
60 typedef Mesh<CLGLVertexBuffer,
61              CLStencilTable,
62              CLEvaluator,
63              GLPatchTable,
64              CLDeviceContext> OsdCLMesh;
65 static CLDeviceContext g_cl_device_context;
66 #endif
67 // CUDA backend.
68 #ifdef OPENSUBDIV_HAS_CUDA
69 #  include <opensubdiv/osd/cudaEvaluator.h>
70 #  include <opensubdiv/osd/cudaGLVertexBuffer.h>
71 #  include "opensubdiv_device_context_cuda.h"
72 using OpenSubdiv::Osd::CudaEvaluator;
73 using OpenSubdiv::Osd::CudaGLVertexBuffer;
74 using OpenSubdiv::Osd::CudaStencilTable;
75 typedef Mesh<CudaGLVertexBuffer,
76              CudaStencilTable,
77              CudaEvaluator,
78              GLPatchTable> OsdCudaMesh;
79 static CudaDeviceContext g_cuda_device_context;
80 #endif
81 // Transform feedback backend.
82 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
83 #  include <opensubdiv/osd/glVertexBuffer.h>
84 #  include <opensubdiv/osd/glXFBEvaluator.h>
85 using OpenSubdiv::Osd::GLXFBEvaluator;
86 using OpenSubdiv::Osd::GLStencilTableTBO;
87 using OpenSubdiv::Osd::GLVertexBuffer;
88 typedef Mesh<GLVertexBuffer,
89              GLStencilTableTBO,
90              GLXFBEvaluator,
91              GLPatchTable> OsdGLSLTransformFeedbackMesh;
92 #endif
93 // GLSL compute backend.
94 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
95 #  include <opensubdiv/osd/glComputeEvaluator.h>
96 #  include <opensubdiv/osd/glVertexBuffer.h>
97 using OpenSubdiv::Osd::GLComputeEvaluator;
98 using OpenSubdiv::Osd::GLStencilTableSSBO;
99 using OpenSubdiv::Osd::GLVertexBuffer;
100 typedef Mesh<GLVertexBuffer,
101              GLStencilTableSSBO,
102              GLComputeEvaluator,
103              GLPatchTable> OsdGLSLComputeMesh;
104 #endif
105
106 #include "MEM_guardedalloc.h"
107
108 #include "opensubdiv_topology_refiner_capi.h"
109 #include "internal/opensubdiv_gl_mesh_draw.h"
110 #include "internal/opensubdiv_gl_mesh_fvar.h"
111 #include "internal/opensubdiv_gl_mesh_internal.h"
112 #include "internal/opensubdiv_topology_refiner_internal.h"
113 #include "internal/opensubdiv_util.h"
114
115 using opensubdiv_capi::vector;
116
117 namespace {
118
119 GLMeshInterface* createGLMeshInterface(
120     OpenSubdiv::Far::TopologyRefiner* topology_refiner,
121     const MeshBitset& bits,
122     const int num_vertex_elements,
123     const int num_varying_elements,
124     const int level,
125     eOpenSubdivEvaluator evaluator_type) {
126   GLMeshInterface* mesh = NULL;
127   switch (evaluator_type) {
128 #define CHECK_EVALUATOR_TYPE(type, class)                                \
129   case OPENSUBDIV_EVALUATOR_##type:                                      \
130     mesh = new class(topology_refiner,                                   \
131                      num_vertex_elements,                                \
132                      num_varying_elements,                               \
133                      level,                                              \
134                      bits);                                              \
135     break;
136
137 #define CHECK_EVALUATOR_TYPE_STUB(type)                                  \
138   case OPENSUBDIV_EVALUATOR_##type:                                      \
139     mesh = NULL;                                                         \
140     break;
141
142     CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
143 #ifdef OPENSUBDIV_HAS_OPENMP
144     CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
145 #else
146     CHECK_EVALUATOR_TYPE_STUB(OPENMP)
147 #endif
148 #ifdef OPENSUBDIV_HAS_OPENCL
149     CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
150 #else
151     CHECK_EVALUATOR_TYPE_STUB(OPENCL)
152 #endif
153 #ifdef OPENSUBDIV_HAS_CUDA
154     CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
155 #else
156     CHECK_EVALUATOR_TYPE_STUB(CUDA)
157 #endif
158 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
159     CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK, OsdGLSLTransformFeedbackMesh)
160 #else
161     CHECK_EVALUATOR_TYPE_STUB(GLSL_TRANSFORM_FEEDBACK)
162 #endif
163 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
164     CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
165 #else
166     CHECK_EVALUATOR_TYPE_STUB(GLSL_COMPUTE)
167 #endif
168
169 #undef CHECK_EVALUATOR_TYPE
170 #undef CHECK_EVALUATOR_TYPE_STUB
171   }
172   return mesh;
173 }
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // GLMesh structure "methods".
177
178 opensubdiv_capi::GLMeshFVarData* createFVarData(
179     OpenSubdiv::Far::TopologyRefiner* topology_refiner,
180     GLMeshInterface* mesh,
181     const float *fvar_src_buffer) {
182   using opensubdiv_capi::GLMeshFVarData;
183   GLMeshFVarData* fvar_data = new GLMeshFVarData();
184   fvar_data->create(topology_refiner,
185                     mesh->GetFarPatchTable(),
186                     2,
187                     fvar_src_buffer);
188   return fvar_data;
189 }
190
191 unsigned int getPatchIndexBuffer(OpenSubdiv_GLMesh* gl_mesh) {
192   return gl_mesh->internal->mesh_interface
193              ->GetPatchTable()
194              ->GetPatchIndexBuffer();
195 }
196
197 void bindVertexBuffer(OpenSubdiv_GLMesh* gl_mesh) {
198   gl_mesh->internal->mesh_interface->BindVertexBuffer();
199 }
200
201 void setCoarsePositions(OpenSubdiv_GLMesh* gl_mesh,
202                         const float* positions,
203                         const int start_vertex,
204                         const int num_vertices) {
205   gl_mesh->internal->mesh_interface->UpdateVertexBuffer(positions,
206                                                         start_vertex,
207                                                         num_vertices);
208 }
209
210 void refine(OpenSubdiv_GLMesh* gl_mesh) {
211   gl_mesh->internal->mesh_interface->Refine();
212 }
213
214 void synchronize(struct OpenSubdiv_GLMesh* gl_mesh) {
215   gl_mesh->internal->mesh_interface->Synchronize();
216 }
217
218 void assignFunctionPointers(OpenSubdiv_GLMesh* gl_mesh) {
219   gl_mesh->getPatchIndexBuffer = getPatchIndexBuffer;
220   gl_mesh->bindVertexBuffer = bindVertexBuffer;
221   gl_mesh->setCoarsePositions = setCoarsePositions;
222   gl_mesh->refine = refine;
223   gl_mesh->synchronize = synchronize;
224
225   gl_mesh->prepareDraw = opensubdiv_capi::GLMeshDisplayPrepare;
226   gl_mesh->drawPatches = opensubdiv_capi::GLMeshDisplayDrawPatches;
227 }
228
229 }  // namespace
230
231 struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
232     OpenSubdiv_TopologyRefiner* topology_refiner,
233     eOpenSubdivEvaluator evaluator_type) {
234   using OpenSubdiv::Far::TopologyRefiner;
235   TopologyRefiner* osd_topology_refiner =
236       topology_refiner->internal->osd_topology_refiner;
237   // TODO(sergey): Query this from refiner.
238   const bool is_adaptive = false;
239   MeshBitset bits;
240   bits.set(OpenSubdiv::Osd::MeshAdaptive, is_adaptive);
241   bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
242   bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
243   bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
244   bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
245   const int num_vertex_elements = 3;
246   const int num_varying_elements = 3;
247   GLMeshInterface* mesh = createGLMeshInterface(
248       osd_topology_refiner,
249       bits,
250       num_vertex_elements,
251       num_varying_elements,
252       osd_topology_refiner->GetMaxLevel(),
253       evaluator_type);
254   if (mesh == NULL) {
255     return NULL;
256   }
257   OpenSubdiv_GLMesh* gl_mesh = OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
258   assignFunctionPointers(gl_mesh);
259   gl_mesh->internal = new OpenSubdiv_GLMeshInternal();
260   gl_mesh->internal->evaluator_type = evaluator_type;
261   gl_mesh->internal->mesh_interface = mesh;
262   // Face-varying support.
263   // TODO(sergey): This part needs to be re-done.
264   if (osd_topology_refiner->GetNumFVarChannels() > 0) {
265     // TODO(sergey): This is a temporary stub to get things compiled. Need
266     // to store base level UVs somewhere else.
267     vector<float> uvs;
268     vector<float> fvar_data_buffer;
269     opensubdiv_capi::interpolateFVarData(*osd_topology_refiner,
270                                          uvs,
271                                          &fvar_data_buffer);
272     gl_mesh->internal->fvar_data = createFVarData(osd_topology_refiner,
273                                                   mesh,
274                                                   &fvar_data_buffer[0]);
275   } else {
276     gl_mesh->internal->fvar_data = NULL;
277   }
278   return gl_mesh;
279 }
280
281 void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh* gl_mesh) {
282   delete gl_mesh->internal;
283   OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
284 }