2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2013 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Sergey Sharybin.
24 * ***** END GPL LICENSE BLOCK *****
27 #include "opensubdiv_capi.h"
36 #include <opensubdiv/osd/glMesh.h>
39 #include <opensubdiv/osd/cpuGLVertexBuffer.h>
40 #include <opensubdiv/osd/cpuEvaluator.h>
42 #ifdef OPENSUBDIV_HAS_OPENMP
43 # include <opensubdiv/osd/ompEvaluator.h>
44 #endif /* OPENSUBDIV_HAS_OPENMP */
46 #ifdef OPENSUBDIV_HAS_OPENCL
47 # include <opensubdiv/osd/clGLVertexBuffer.h>
48 # include <opensubdiv/osd/clEvaluator.h>
49 # include "opensubdiv_device_context_opencl.h"
50 #endif /* OPENSUBDIV_HAS_OPENCL */
52 #ifdef OPENSUBDIV_HAS_CUDA
53 # include <opensubdiv/osd/cudaGLVertexBuffer.h>
54 # include <opensubdiv/osd/cudaEvaluator.h>
55 # include "opensubdiv_device_context_cuda.h"
56 #endif /* OPENSUBDIV_HAS_CUDA */
58 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
59 # include <opensubdiv/osd/glXFBEvaluator.h>
60 # include <opensubdiv/osd/glVertexBuffer.h>
61 #endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
63 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
64 # include <opensubdiv/osd/glComputeEvaluator.h>
65 # include <opensubdiv/osd/glVertexBuffer.h>
66 #endif /* OPENSUBDIV_HAS_GLSL_COMPUTE */
68 #include <opensubdiv/osd/glPatchTable.h>
69 #include <opensubdiv/far/stencilTable.h>
71 #include "opensubdiv_intern.h"
73 #include "MEM_guardedalloc.h"
75 /* **************** Types declaration **************** */
77 using OpenSubdiv::Osd::GLMeshInterface;
78 using OpenSubdiv::Osd::Mesh;
79 using OpenSubdiv::Osd::MeshBitset;
80 using OpenSubdiv::Far::StencilTable;
81 using OpenSubdiv::Osd::GLPatchTable;
83 using OpenSubdiv::Osd::Mesh;
86 using OpenSubdiv::Osd::CpuGLVertexBuffer;
87 using OpenSubdiv::Osd::CpuEvaluator;
88 typedef Mesh<CpuGLVertexBuffer,
91 GLPatchTable> OsdCpuMesh;
93 #ifdef OPENSUBDIV_HAS_OPENMP
94 using OpenSubdiv::Osd::OmpEvaluator;
95 typedef Mesh<CpuGLVertexBuffer,
98 GLPatchTable> OsdOmpMesh;
99 #endif /* OPENSUBDIV_HAS_OPENMP */
101 #ifdef OPENSUBDIV_HAS_OPENCL
102 using OpenSubdiv::Osd::CLEvaluator;
103 using OpenSubdiv::Osd::CLGLVertexBuffer;
104 using OpenSubdiv::Osd::CLStencilTable;
105 /* TODO(sergey): Use CLDeviceCOntext similar to OSD examples? */
106 typedef Mesh<CLGLVertexBuffer,
110 CLDeviceContext> OsdCLMesh;
111 static CLDeviceContext g_clDeviceContext;
112 #endif /* OPENSUBDIV_HAS_OPENCL */
114 #ifdef OPENSUBDIV_HAS_CUDA
115 using OpenSubdiv::Osd::CudaEvaluator;
116 using OpenSubdiv::Osd::CudaGLVertexBuffer;
117 using OpenSubdiv::Osd::CudaStencilTable;
118 typedef Mesh<CudaGLVertexBuffer,
121 GLPatchTable> OsdCudaMesh;
122 static CudaDeviceContext g_cudaDeviceContext;
123 #endif /* OPENSUBDIV_HAS_CUDA */
125 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
126 using OpenSubdiv::Osd::GLXFBEvaluator;
127 using OpenSubdiv::Osd::GLStencilTableTBO;
128 using OpenSubdiv::Osd::GLVertexBuffer;
129 typedef Mesh<GLVertexBuffer,
132 GLPatchTable> OsdGLSLTransformFeedbackMesh;
133 #endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
135 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
136 using OpenSubdiv::Osd::GLComputeEvaluator;
137 using OpenSubdiv::Osd::GLStencilTableSSBO;
138 using OpenSubdiv::Osd::GLVertexBuffer;
139 typedef Mesh<GLVertexBuffer,
142 GLPatchTable> OsdGLSLComputeMesh;
145 struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
146 OpenSubdiv_TopologyRefinerDescr *topology_refiner,
149 int /*subdivide_uvs*/)
151 using OpenSubdiv::Far::TopologyRefiner;
154 /* TODO(sergey): Adaptive subdivisions are not currently
155 * possible because of the lack of tessellation shader.
157 bits.set(OpenSubdiv::Osd::MeshAdaptive, 0);
158 bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
159 bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
160 bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
161 bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
163 const int num_vertex_elements = 3;
164 const int num_varying_elements = 3;
166 GLMeshInterface *mesh = NULL;
167 TopologyRefiner *refiner = (TopologyRefiner*)topology_refiner;
169 switch(evaluator_type) {
170 #define CHECK_EVALUATOR_TYPE(type, class) \
171 case OPENSUBDIV_EVALUATOR_ ## type: \
172 mesh = new class(refiner, \
173 num_vertex_elements, \
174 num_varying_elements, \
179 CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
181 #ifdef OPENSUBDIV_HAS_OPENMP
182 CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
185 #ifdef OPENSUBDIV_HAS_OPENCL
186 CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
189 #ifdef OPENSUBDIV_HAS_CUDA
190 CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
193 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
194 CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK,
195 OsdGLSLTransformFeedbackMesh)
198 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
199 CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
202 #undef CHECK_EVALUATOR_TYPE
209 OpenSubdiv_GLMesh *gl_mesh =
210 (OpenSubdiv_GLMesh *) OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
211 gl_mesh->evaluator_type = evaluator_type;
212 gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
213 gl_mesh->topology_refiner = (OpenSubdiv_TopologyRefinerDescr*)refiner;
218 void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
220 switch (gl_mesh->evaluator_type) {
221 #define CHECK_EVALUATOR_TYPE(type, class) \
222 case OPENSUBDIV_EVALUATOR_ ## type: \
223 delete (class *) gl_mesh->descriptor; \
226 CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
228 #ifdef OPENSUBDIV_HAS_OPENMP
229 CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
232 #ifdef OPENSUBDIV_HAS_OPENCL
233 CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
236 #ifdef OPENSUBDIV_HAS_CUDA
237 CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
240 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
241 CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK,
242 OsdGLSLTransformFeedbackMesh)
245 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
246 CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
249 #undef CHECK_EVALUATOR_TYPE
252 OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
255 unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(struct OpenSubdiv_GLMesh *gl_mesh)
257 return ((GLMeshInterface *)gl_mesh->descriptor)->GetPatchTable()->GetPatchIndexBuffer();
260 unsigned int openSubdiv_getOsdGLMeshVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh)
262 return ((GLMeshInterface *)gl_mesh->descriptor)->BindVertexBuffer();
265 void openSubdiv_osdGLMeshUpdateVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh,
266 const float *vertex_data,
270 ((GLMeshInterface *)gl_mesh->descriptor)->UpdateVertexBuffer(vertex_data,
275 void openSubdiv_osdGLMeshRefine(struct OpenSubdiv_GLMesh *gl_mesh)
277 ((GLMeshInterface *)gl_mesh->descriptor)->Refine();
280 void openSubdiv_osdGLMeshSynchronize(struct OpenSubdiv_GLMesh *gl_mesh)
282 ((GLMeshInterface *)gl_mesh->descriptor)->Synchronize();
285 void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
287 ((GLMeshInterface *)gl_mesh->descriptor)->BindVertexBuffer();
290 const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefiner(
291 OpenSubdiv_GLMesh *gl_mesh)
293 return gl_mesh->topology_refiner;
296 int openSubdiv_supportGPUDisplay(void)
299 /* Currently Intel GPUs has hard time working on Windows.
301 * For until we've got access to a hardware which demonstrates
302 * the issue we disable OpenSubdiv on Intel GPUs.
304 static bool vendor_checked = false;
305 static bool is_intel = false;
306 if (!vendor_checked) {
307 const char *vendor = (const char *)glGetString(GL_VENDOR);
308 if (strstr(vendor, "Intel")) {
309 if(getenv("OPENSUBDIV_ALLOW_INTEL") == NULL) {
319 return GLEW_EXT_geometry_shader4 &&
320 GLEW_ARB_gpu_shader5 &&
321 GLEW_ARB_uniform_buffer_object;