Cleanup: space after template bracket
[blender.git] / intern / opensubdiv / internal / opensubdiv_evaluator_internal.cc
1 // Copyright 2018 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 // Author: Sergey Sharybin
18
19 #include "internal/opensubdiv_evaluator_internal.h"
20
21 #include <cassert>
22 #include <cstdio>
23
24 #ifdef _MSC_VER
25 #  include <iso646.h>
26 #endif
27
28 #include <opensubdiv/far/patchMap.h>
29 #include <opensubdiv/far/patchTable.h>
30 #include <opensubdiv/far/patchTableFactory.h>
31 #include <opensubdiv/osd/cpuEvaluator.h>
32 #include <opensubdiv/osd/cpuPatchTable.h>
33 #include <opensubdiv/osd/cpuVertexBuffer.h>
34 #include <opensubdiv/osd/mesh.h>
35 #include <opensubdiv/osd/types.h>
36 #include <opensubdiv/version.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "internal/opensubdiv_topology_refiner_internal.h"
41 #include "internal/opensubdiv_util.h"
42 #include "internal/opensubdiv_util.h"
43 #include "opensubdiv_topology_refiner_capi.h"
44
45 using OpenSubdiv::Osd::BufferDescriptor;
46 using OpenSubdiv::Osd::CpuEvaluator;
47 using OpenSubdiv::Osd::CpuPatchTable;
48 using OpenSubdiv::Osd::CpuVertexBuffer;
49 using OpenSubdiv::Osd::PatchCoord;
50 using OpenSubdiv::Far::PatchMap;
51 using OpenSubdiv::Far::PatchTable;
52 using OpenSubdiv::Far::PatchTableFactory;
53 using OpenSubdiv::Far::StencilTable;
54 using OpenSubdiv::Far::StencilTableFactory;
55 using OpenSubdiv::Far::TopologyRefiner;
56
57 // TODO(sergey): Remove after official requirement bump for OSD version.
58 #if OPENSUBDIV_VERSION_NUMBER >= 30200
59 #  define OPENSUBDIV_HAS_FVAR_EVALUATION
60 #else
61 #  undef OPENSUBDIV_HAS_FVAR_EVALUATION
62 #endif
63
64 namespace opensubdiv_capi {
65
66 namespace {
67
68 // Helper class to wrap numerous of patch coordinates into a buffer.
69 // Used to pass coordinates to the CPU evaluator. Other evaluators are not
70 // supported.
71 class PatchCoordBuffer : public vector<PatchCoord> {
72  public:
73   static PatchCoordBuffer* Create(int size) {
74     PatchCoordBuffer* buffer = new PatchCoordBuffer();
75     buffer->resize(size);
76     return buffer;
77   }
78
79   PatchCoord* BindCpuBuffer() {
80     return reinterpret_cast<PatchCoord*>(&(*this)[0]);
81   }
82
83   int GetNumVertices() {
84     return size();
85   }
86
87   void UpdateData(const PatchCoord* patch_coords, int num_patch_coords) {
88     memcpy(&(*this)[0],
89            reinterpret_cast<const void*>(patch_coords),
90            sizeof(PatchCoord) * num_patch_coords);
91   }
92 };
93
94 // Helper class to wrap single of patch coord into a buffer. Used to pass
95 // coordinates to the CPU evaluator. Other evaluators are not supported.
96 class SinglePatchCoordBuffer {
97  public:
98   static SinglePatchCoordBuffer* Create() {
99     return new SinglePatchCoordBuffer();
100   }
101
102   SinglePatchCoordBuffer() {
103   }
104
105   explicit SinglePatchCoordBuffer(const PatchCoord &patch_coord)
106       : patch_coord_(patch_coord) {
107   }
108
109   PatchCoord* BindCpuBuffer() {
110     return &patch_coord_;
111   }
112
113   int GetNumVertices() {
114     return 1;
115   }
116
117   void UpdateData(const PatchCoord &patch_coord) {
118     patch_coord_ = patch_coord;
119   }
120
121  protected:
122   PatchCoord patch_coord_;
123 };
124
125 // Helper class which is aimed to be used in cases when buffer is small enough
126 // and better to be allocated in stack rather than in heap.
127 //
128 // TODO(sergey): Check if bare arrays could be used by CPU evaluator.
129 template <int element_size, int num_vertices>
130 class StackAllocatedBuffer {
131  public:
132   static PatchCoordBuffer* Create(int /*size*/) {
133     // TODO(sergey): Validate that requested dize is smaller than static
134     // stack memory size.
135     return new StackAllocatedBuffer<element_size, num_vertices>();
136   }
137
138   float* BindCpuBuffer() {
139     return &data_[0];
140   }
141
142   int GetNumVertices() {
143     return num_vertices;
144   }
145
146   // TODO(sergey): Support UpdateData().
147  protected:
148   float data_[element_size * num_vertices];
149 };
150
151 template <typename EVAL_VERTEX_BUFFER,
152           typename STENCIL_TABLE,
153           typename PATCH_TABLE,
154           typename EVALUATOR,
155           typename DEVICE_CONTEXT = void>
156 class FaceVaryingVolatileEval {
157  public:
158   typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
159
160   FaceVaryingVolatileEval(int face_varying_channel,
161                           const StencilTable* face_varying_stencils,
162                           int face_varying_width,
163                           PATCH_TABLE* patch_table,
164                           EvaluatorCache* evaluator_cache = NULL,
165                           DEVICE_CONTEXT* device_context = NULL)
166       : face_varying_channel_(face_varying_channel),
167         src_face_varying_desc_(0, face_varying_width, face_varying_width),
168         patch_table_(patch_table),
169         evaluator_cache_(evaluator_cache),
170         device_context_(device_context) {
171     using OpenSubdiv::Osd::convertToCompatibleStencilTable;
172     num_coarse_face_varying_vertices_ =
173         face_varying_stencils->GetNumControlVertices();
174     const int num_total_face_varying_vertices =
175         face_varying_stencils->GetNumControlVertices() +
176         face_varying_stencils->GetNumStencils();
177     src_face_varying_data_ =
178         EVAL_VERTEX_BUFFER::Create(2,
179                                    num_total_face_varying_vertices,
180                                    device_context);
181     face_varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
182         face_varying_stencils, device_context_);
183   }
184
185   ~FaceVaryingVolatileEval() {
186     delete src_face_varying_data_;
187     delete face_varying_stencils_;
188   }
189
190   void updateData(const float* src, int start_vertex, int num_vertices) {
191     src_face_varying_data_->UpdateData(src,
192                                        start_vertex,
193                                        num_vertices,
194                                        device_context_);
195   }
196
197   void refine() {
198     BufferDescriptor dst_face_varying_desc = src_face_varying_desc_;
199     dst_face_varying_desc.offset += num_coarse_face_varying_vertices_ *
200                                     src_face_varying_desc_.stride;
201     const EVALUATOR* eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
202         evaluator_cache_,
203         src_face_varying_desc_,
204         dst_face_varying_desc,
205         device_context_);
206     EVALUATOR::EvalStencils(src_face_varying_data_, src_face_varying_desc_,
207                             src_face_varying_data_, dst_face_varying_desc,
208                             face_varying_stencils_,
209                             eval_instance,
210                             device_context_);
211   }
212
213   void evalPatch(const PatchCoord& patch_coord, float face_varying[2]) {
214     StackAllocatedBuffer<2, 1> face_varying_data;
215     BufferDescriptor face_varying_desc(0, 2, 2);
216     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
217     const EVALUATOR* eval_instance =
218         OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
219                                                  src_face_varying_desc_,
220                                                  face_varying_desc,
221                                                  device_context_);
222     EVALUATOR::EvalPatchesFaceVarying(
223         src_face_varying_data_, src_face_varying_desc_,
224         &face_varying_data, face_varying_desc,
225         patch_coord_buffer.GetNumVertices(),
226         &patch_coord_buffer,
227         patch_table_,
228         face_varying_channel_,
229         eval_instance,
230         device_context_);
231     const float* refined_face_varying = face_varying_data.BindCpuBuffer();
232     memcpy(face_varying, refined_face_varying, sizeof(float) * 2);
233   }
234
235  protected:
236   int face_varying_channel_;
237
238   BufferDescriptor src_face_varying_desc_;
239
240   int num_coarse_face_varying_vertices_;
241   EVAL_VERTEX_BUFFER* src_face_varying_data_;
242   const STENCIL_TABLE* face_varying_stencils_;
243
244   // NOTE: We reference this, do not own it.
245   PATCH_TABLE* patch_table_;
246
247   EvaluatorCache* evaluator_cache_;
248   DEVICE_CONTEXT* device_context_;
249 };
250
251 // Volatile evaluator which can be used from threads.
252 //
253 // TODO(sergey): Make it possible to evaluate coordinates in chunks.
254 // TODO(sergey): Make it possible to evaluate multiple face varying layers.
255 //               (or maybe, it's cheap to create new evaluator for existing
256 //               topology to evaluate all needed face varying layers?)
257 template <typename SRC_VERTEX_BUFFER,
258           typename EVAL_VERTEX_BUFFER,
259           typename STENCIL_TABLE,
260           typename PATCH_TABLE,
261           typename EVALUATOR,
262           typename DEVICE_CONTEXT = void>
263 class VolatileEvalOutput {
264  public:
265   typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
266   typedef FaceVaryingVolatileEval<EVAL_VERTEX_BUFFER,
267                                   STENCIL_TABLE,
268                                   PATCH_TABLE,
269                                   EVALUATOR,
270                                   DEVICE_CONTEXT> FaceVaryingEval;
271
272   VolatileEvalOutput(
273       const StencilTable* vertex_stencils,
274       const StencilTable* varying_stencils,
275       const vector<const StencilTable*>& all_face_varying_stencils,
276       const int face_varying_width,
277       const PatchTable* patch_table,
278       EvaluatorCache* evaluator_cache = NULL,
279       DEVICE_CONTEXT* device_context = NULL)
280       : src_desc_(0, 3, 3),
281         src_varying_desc_(0, 3, 3),
282         face_varying_width_(face_varying_width),
283         evaluator_cache_(evaluator_cache),
284         device_context_(device_context) {
285     // Total number of vertices = coarse points + refined points + local points.
286     int num_total_vertices = vertex_stencils->GetNumControlVertices() +
287                              vertex_stencils->GetNumStencils();
288     num_coarse_vertices_ = vertex_stencils->GetNumControlVertices();
289     using OpenSubdiv::Osd::convertToCompatibleStencilTable;
290     src_data_ =
291         SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
292     src_varying_data_ =
293         SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
294     patch_table_ = PATCH_TABLE::Create(patch_table, device_context_);
295     patch_coords_ = NULL;
296     vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
297         vertex_stencils, device_context_);
298     varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
299         varying_stencils, device_context_);
300     // Create evaluators for every face varying channel.
301     face_varying_evaluators.reserve(all_face_varying_stencils.size());
302     int face_varying_channel = 0;
303     foreach (const StencilTable* face_varying_stencils,
304              all_face_varying_stencils) {
305       face_varying_evaluators.push_back(
306           new FaceVaryingEval(face_varying_channel,
307                               face_varying_stencils,
308                               face_varying_width,
309                               patch_table_,
310                               evaluator_cache_,
311                               device_context_));
312       ++face_varying_channel;
313     }
314   }
315
316   ~VolatileEvalOutput() {
317     delete src_data_;
318     delete src_varying_data_;
319     delete patch_table_;
320     delete vertex_stencils_;
321     delete varying_stencils_;
322     foreach (FaceVaryingEval* face_varying_evaluator, face_varying_evaluators) {
323       delete face_varying_evaluator;
324     }
325   }
326
327   // TODO(sergey): Implement binding API.
328
329   void updateData(const float* src, int start_vertex, int num_vertices) {
330     src_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
331   }
332
333   void updateVaryingData(const float* src, int start_vertex, int num_vertices) {
334     src_varying_data_->UpdateData(src,
335                                   start_vertex,
336                                   num_vertices,
337                                   device_context_);
338   }
339
340   void updateFaceVaryingData(const int face_varying_channel,
341                              const float* src,
342                              int start_vertex,
343                              int num_vertices) {
344     assert(face_varying_channel >= 0);
345     assert(face_varying_channel < face_varying_evaluators.size());
346     face_varying_evaluators[face_varying_channel]->updateData(
347         src, start_vertex, num_vertices);
348   }
349
350   bool hasVaryingData() const {
351     // return varying_stencils_ != NULL;
352     // TODO(sergey): Check this based on actual topology.
353     return false;
354   }
355
356   bool hasFaceVaryingData() const {
357     return face_varying_evaluators.size() != 0;
358   }
359
360   void refine() {
361     // Evaluate vertex positions.
362     BufferDescriptor dst_desc = src_desc_;
363     dst_desc.offset += num_coarse_vertices_ * src_desc_.stride;
364     const EVALUATOR* eval_instance =
365         OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
366                                                  src_desc_,
367                                                  dst_desc,
368                                                  device_context_);
369     EVALUATOR::EvalStencils(src_data_, src_desc_,
370                             src_data_, dst_desc,
371                             vertex_stencils_,
372                             eval_instance,
373                             device_context_);
374     // Evaluate varying data.
375     if (hasVaryingData()) {
376       BufferDescriptor dst_varying_desc = src_varying_desc_;
377       dst_varying_desc.offset +=
378           num_coarse_vertices_ * src_varying_desc_.stride;
379       eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
380           evaluator_cache_,
381           src_varying_desc_,
382           dst_varying_desc,
383           device_context_);
384       EVALUATOR::EvalStencils(src_varying_data_, src_varying_desc_,
385                               src_varying_data_, dst_varying_desc,
386                               varying_stencils_,
387                               eval_instance, device_context_);
388     }
389     // Evaluate face-varying data.
390     if (hasFaceVaryingData()) {
391       foreach (FaceVaryingEval* face_varying_evaluator,
392                face_varying_evaluators) {
393         face_varying_evaluator->refine();
394       }
395     }
396   }
397
398   void evalPatchCoord(const PatchCoord& patch_coord, float P[3]) {
399     StackAllocatedBuffer<6, 1> vertex_data;
400     // TODO(sergey): Varying data is interleaved in vertex array, so need to
401     // adjust stride if there is a varying data.
402     // BufferDescriptor vertex_desc(0, 3, 6);
403     BufferDescriptor vertex_desc(0, 3, 3);
404     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
405     const EVALUATOR* eval_instance =
406         OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
407                                                  src_desc_,
408                                                  vertex_desc,
409                                                  device_context_);
410     EVALUATOR::EvalPatches(src_data_,
411                            src_desc_,
412                            &vertex_data,
413                            vertex_desc,
414                            patch_coord_buffer.GetNumVertices(),
415                            &patch_coord_buffer,
416                            patch_table_,
417                            eval_instance,
418                            device_context_);
419     const float* refined_vertices = vertex_data.BindCpuBuffer();
420     memcpy(P, refined_vertices, sizeof(float) * 3);
421   }
422
423   void evalPatchesWithDerivatives(const PatchCoord& patch_coord,
424                                   float P[3],
425                                   float dPdu[3], float dPdv[3]) {
426     StackAllocatedBuffer<6, 1> vertex_data, derivatives;
427     // TODO(sergey): Varying data is interleaved in vertex array, so need to
428     // adjust stride if there is a varying data.
429     // BufferDescriptor vertex_desc(0, 3, 6);
430     BufferDescriptor vertex_desc(0, 3, 3);
431     BufferDescriptor du_desc(0, 3, 6), dv_desc(3, 3, 6);
432     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
433     const EVALUATOR* eval_instance =
434         OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
435                                                  src_desc_,
436                                                  vertex_desc,
437                                                  du_desc, dv_desc,
438                                                  device_context_);
439     EVALUATOR::EvalPatches(src_data_, src_desc_,
440                            &vertex_data, vertex_desc,
441                            &derivatives, du_desc,
442                            &derivatives, dv_desc,
443                            patch_coord_buffer.GetNumVertices(),
444                            &patch_coord_buffer,
445                            patch_table_,
446                            eval_instance,
447                            device_context_);
448     const float* refined_vertices = vertex_data.BindCpuBuffer();
449     memcpy(P, refined_vertices, sizeof(float) * 3);
450     if (dPdu != NULL || dPdv != NULL) {
451       const float* refined_derivatives = derivatives.BindCpuBuffer();
452       if (dPdu != NULL) {
453         memcpy(dPdu, refined_derivatives, sizeof(float) * 3);
454       }
455       if (dPdv != NULL) {
456         memcpy(dPdv, refined_derivatives + 3, sizeof(float) * 3);
457       }
458     }
459   }
460
461   void evalPatchVarying(const PatchCoord& patch_coord, float varying[3]) {
462     StackAllocatedBuffer<6, 1> varying_data;
463     BufferDescriptor varying_desc(3, 3, 6);
464     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
465     const EVALUATOR* eval_instance =
466         OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
467                                                  src_varying_desc_,
468                                                  varying_desc,
469                                                  device_context_);
470     EVALUATOR::EvalPatchesVarying(src_varying_data_, src_varying_desc_,
471                                   &varying_data, varying_desc,
472                                   patch_coord_buffer.GetNumVertices(),
473                                   &patch_coord_buffer,
474                                   patch_table_,
475                                   eval_instance,
476                                   device_context_);
477     const float* refined_varying = varying_data.BindCpuBuffer();
478     memcpy(varying, refined_varying, sizeof(float) * 3);
479   }
480
481   void evalPatchFaceVarying(const int face_varying_channel,
482                             const PatchCoord& patch_coord,
483                             float face_varying[2]) {
484     assert(face_varying_channel >= 0);
485     assert(face_varying_channel < face_varying_evaluators.size());
486     face_varying_evaluators[face_varying_channel]->evalPatch(
487         patch_coord, face_varying);
488   }
489
490  private:
491   SRC_VERTEX_BUFFER* src_data_;
492   SRC_VERTEX_BUFFER* src_varying_data_;
493   PatchCoordBuffer* patch_coords_;
494   PATCH_TABLE* patch_table_;
495   BufferDescriptor src_desc_;
496   BufferDescriptor src_varying_desc_;
497
498   int num_coarse_vertices_;
499
500   const STENCIL_TABLE* vertex_stencils_;
501   const STENCIL_TABLE* varying_stencils_;
502
503   int face_varying_width_;
504   vector<FaceVaryingEval*> face_varying_evaluators;
505
506   EvaluatorCache* evaluator_cache_;
507   DEVICE_CONTEXT* device_context_;
508 };
509
510 }  // namespace
511
512 // Note: Define as a class instead of typedcef to make it possible
513 // to have anonymous class in opensubdiv_evaluator_internal.h
514 class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
515                                                 CpuVertexBuffer,
516                                                 StencilTable,
517                                                 CpuPatchTable,
518                                                 CpuEvaluator> {
519  public:
520   CpuEvalOutput(const StencilTable* vertex_stencils,
521                 const StencilTable* varying_stencils,
522                 const vector<const StencilTable*>& all_face_varying_stencils,
523                 const int face_varying_width,
524                 const PatchTable* patch_table,
525                 EvaluatorCache* evaluator_cache = NULL)
526       : VolatileEvalOutput<CpuVertexBuffer,
527                            CpuVertexBuffer,
528                            StencilTable,
529                            CpuPatchTable,
530                            CpuEvaluator>(vertex_stencils,
531                                          varying_stencils,
532                                          all_face_varying_stencils,
533                                          face_varying_width,
534                                          patch_table,
535                                          evaluator_cache) {
536   }
537 };
538
539 ////////////////////////////////////////////////////////////////////////////////
540 // Evaluator wrapper for anonymous API.
541
542 CpuEvalOutputAPI::CpuEvalOutputAPI(CpuEvalOutput* implementation,
543                                    OpenSubdiv::Far::PatchMap* patch_map)
544     : implementation_(implementation),
545       patch_map_(patch_map) {
546 }
547
548 CpuEvalOutputAPI::~CpuEvalOutputAPI() {
549   delete implementation_;
550 }
551
552 void CpuEvalOutputAPI::setCoarsePositions(const float* positions,
553                                           const int start_vertex_index,
554                                           const int num_vertices) {
555   // TODO(sergey): Add sanity check on indices.
556   implementation_->updateData(positions, start_vertex_index, num_vertices);
557 }
558
559 void CpuEvalOutputAPI::setVaryingData(const float* varying_data,
560                                       const int start_vertex_index,
561                                       const int num_vertices) {
562   // TODO(sergey): Add sanity check on indices.
563   implementation_->updateVaryingData(varying_data,
564                                      start_vertex_index,
565                                      num_vertices);
566 }
567
568 void CpuEvalOutputAPI::setFaceVaryingData(const int face_varying_channel,
569                                           const float* face_varying_data,
570                                           const int start_vertex_index,
571                                           const int num_vertices) {
572   // TODO(sergey): Add sanity check on indices.
573   implementation_->updateFaceVaryingData(face_varying_channel,
574                                          face_varying_data,
575                                          start_vertex_index,
576                                          num_vertices);
577 }
578
579 void CpuEvalOutputAPI::setCoarsePositionsFromBuffer(
580     const void* buffer,
581     const int start_offset,
582     const int stride,
583     const int start_vertex_index,
584     const int num_vertices) {
585   // TODO(sergey): Add sanity check on indices.
586   const unsigned char* current_buffer = (unsigned char *)buffer;
587   current_buffer += start_offset;
588   for (int i = 0; i < num_vertices; ++i) {
589     const int current_vertex_index = start_vertex_index + i;
590     implementation_->updateData(reinterpret_cast<const float*>(current_buffer),
591                                 current_vertex_index, 1);
592     current_buffer += stride;
593   }
594 }
595
596 void CpuEvalOutputAPI::setVaryingDataFromBuffer(
597     const void* buffer,
598     const int start_offset,
599     const int stride,
600     const int start_vertex_index,
601     const int num_vertices) {
602   // TODO(sergey): Add sanity check on indices.
603   const unsigned char* current_buffer = (unsigned char *)buffer;
604   current_buffer += start_offset;
605   for (int i = 0; i < num_vertices; ++i) {
606     const int current_vertex_index = start_vertex_index + i;
607     implementation_->updateVaryingData(
608         reinterpret_cast<const float*>(current_buffer),
609         current_vertex_index, 1);
610     current_buffer += stride;
611   }
612 }
613
614 void CpuEvalOutputAPI::setFaceVaryingDataFromBuffer(
615     const int face_varying_channel,
616     const void* buffer,
617     const int start_offset,
618     const int stride,
619     const int start_vertex_index,
620     const int num_vertices) {
621   // TODO(sergey): Add sanity check on indices.
622   const unsigned char* current_buffer = (unsigned char *)buffer;
623   current_buffer += start_offset;
624   for (int i = 0; i < num_vertices; ++i) {
625     const int current_vertex_index = start_vertex_index + i;
626     implementation_->updateFaceVaryingData(
627         face_varying_channel,
628         reinterpret_cast<const float*>(current_buffer),
629         current_vertex_index, 1);
630     current_buffer += stride;
631   }
632 }
633
634 void CpuEvalOutputAPI::refine() {
635   implementation_->refine();
636 }
637
638 void CpuEvalOutputAPI::evaluateLimit(const int ptex_face_index,
639                                      float face_u, float face_v,
640                                      float P[3], float dPdu[3], float dPdv[3]) {
641   assert(face_u >= 0.0f);
642   assert(face_u <= 1.0f);
643   assert(face_v >= 0.0f);
644   assert(face_v <= 1.0f);
645   const PatchTable::PatchHandle* handle =
646       patch_map_->FindPatch(ptex_face_index, face_u, face_v);
647   PatchCoord patch_coord(*handle, face_u, face_v);
648   if (dPdu != NULL || dPdv != NULL) {
649     implementation_->evalPatchesWithDerivatives(patch_coord, P, dPdu, dPdv);
650   } else {
651     implementation_->evalPatchCoord(patch_coord, P);
652   }}
653
654 void CpuEvalOutputAPI::evaluateVarying(const int ptex_face_index,
655                                        float face_u, float face_v,
656                                        float varying[3]) {
657   assert(face_u >= 0.0f);
658   assert(face_u <= 1.0f);
659   assert(face_v >= 0.0f);
660   assert(face_v <= 1.0f);
661   const PatchTable::PatchHandle* handle =
662       patch_map_->FindPatch(ptex_face_index, face_u, face_v);
663   PatchCoord patch_coord(*handle, face_u, face_v);
664   implementation_->evalPatchVarying(patch_coord, varying);
665 }
666
667 void CpuEvalOutputAPI::evaluateFaceVarying(const int face_varying_channel,
668                                            const int ptex_face_index,
669                                            float face_u, float face_v,
670                                            float face_varying[2]) {
671   assert(face_u >= 0.0f);
672   assert(face_u <= 1.0f);
673   assert(face_v >= 0.0f);
674   assert(face_v <= 1.0f);
675   const PatchTable::PatchHandle* handle =
676       patch_map_->FindPatch(ptex_face_index, face_u, face_v);
677   PatchCoord patch_coord(*handle, face_u, face_v);
678   implementation_->evalPatchFaceVarying(
679       face_varying_channel, patch_coord, face_varying);
680 }
681
682 }  // namespace opensubdiv_capi
683
684 OpenSubdiv_EvaluatorInternal::OpenSubdiv_EvaluatorInternal()
685     : eval_output(NULL),
686       patch_map(NULL),
687       patch_table(NULL) {
688 }
689
690 OpenSubdiv_EvaluatorInternal::~OpenSubdiv_EvaluatorInternal() {
691   delete eval_output;
692   delete patch_map;
693   delete patch_table;
694 }
695
696 OpenSubdiv_EvaluatorInternal* openSubdiv_createEvaluatorInternal(
697     OpenSubdiv_TopologyRefiner* topology_refiner) {
698   using opensubdiv_capi::vector;
699   TopologyRefiner* refiner = topology_refiner->internal->osd_topology_refiner;
700   if (refiner == NULL) {
701     // Happens on bad topology.
702     return NULL;
703   }
704   // TODO(sergey): Base this on actual topology.
705   const bool has_varying_data = false;
706   const int num_face_varying_channels = refiner->GetNumFVarChannels();
707   const bool has_face_varying_data = (num_face_varying_channels != 0);
708   const int level = topology_refiner->getSubdivisionLevel(topology_refiner);
709   const bool is_adaptive = topology_refiner->getIsAdaptive(topology_refiner);
710   // Common settings for stencils and patches.
711   const bool stencil_generate_intermediate_levels = is_adaptive;
712   const bool stencil_generate_offsets = true;
713   const bool use_inf_sharp_patch = true;
714   // Refine the topology with given settings.
715   // TODO(sergey): What if topology is already refined?
716   if (is_adaptive) {
717     TopologyRefiner::AdaptiveOptions options(level);
718     options.considerFVarChannels = has_face_varying_data;
719     options.useInfSharpPatch = use_inf_sharp_patch;
720     refiner->RefineAdaptive(options);
721   } else {
722     TopologyRefiner::UniformOptions options(level);
723     refiner->RefineUniform(options);
724   }
725   // Generate stencil table to update the bi-cubic patches control vertices
726   // after they have been re-posed (both for vertex & varying interpolation).
727   //
728   // Vertex stencils.
729   StencilTableFactory::Options vertex_stencil_options;
730   vertex_stencil_options.generateOffsets = stencil_generate_offsets;
731   vertex_stencil_options.generateIntermediateLevels =
732       stencil_generate_intermediate_levels;
733   const StencilTable* vertex_stencils =
734       StencilTableFactory::Create(*refiner, vertex_stencil_options);
735   // Varying stencils.
736   //
737   // TODO(sergey): Seems currently varying stencils are always required in
738   // OpenSubdiv itself.
739   const StencilTable* varying_stencils = NULL;
740   if (has_varying_data) {
741     StencilTableFactory::Options varying_stencil_options;
742     varying_stencil_options.generateOffsets = stencil_generate_offsets;
743     varying_stencil_options.generateIntermediateLevels =
744         stencil_generate_intermediate_levels;
745     varying_stencil_options.interpolationMode =
746         StencilTableFactory::INTERPOLATE_VARYING;
747     varying_stencils =
748         StencilTableFactory::Create(*refiner, varying_stencil_options);
749   }
750   // Face warying stencil.
751 vector<const StencilTable*> all_face_varying_stencils;
752 #ifdef OPENSUBDIV_HAS_FVAR_EVALUATION
753   all_face_varying_stencils.reserve(num_face_varying_channels);
754   for (int face_varying_channel = 0;
755        face_varying_channel < num_face_varying_channels;
756        ++face_varying_channel) {
757     StencilTableFactory::Options face_varying_stencil_options;
758     face_varying_stencil_options.generateOffsets = stencil_generate_offsets;
759     face_varying_stencil_options.generateIntermediateLevels =
760         stencil_generate_intermediate_levels;
761     face_varying_stencil_options.interpolationMode =
762         StencilTableFactory::INTERPOLATE_FACE_VARYING;
763     face_varying_stencil_options.fvarChannel = face_varying_channel;
764     all_face_varying_stencils.push_back(
765         StencilTableFactory::Create(*refiner, face_varying_stencil_options));
766   }
767 #endif
768   // Generate bi-cubic patch table for the limit surface.
769   // TODO(sergey): Ideally we would want to expose end-cap settings via
770   // C-API to make it more generic. Currently it matches old Blender's
771   // subsurf code.
772   PatchTableFactory::Options patch_options(level);
773   patch_options.SetEndCapType(PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
774   patch_options.useInfSharpPatch = use_inf_sharp_patch;
775   patch_options.generateFVarTables = has_face_varying_data;
776   patch_options.generateFVarLegacyLinearPatches = false;
777   const PatchTable* patch_table = PatchTableFactory::Create(
778       *refiner, patch_options);
779   // Append local points stencils.
780   // Point stencils.
781   const StencilTable* local_point_stencil_table =
782       patch_table->GetLocalPointStencilTable();
783   if (local_point_stencil_table != NULL) {
784     const StencilTable* table =
785         StencilTableFactory::AppendLocalPointStencilTable(
786             *refiner, vertex_stencils, local_point_stencil_table);
787     delete vertex_stencils;
788     vertex_stencils = table;
789   }
790   // Varying stencils.
791   if (has_varying_data) {
792     const StencilTable* local_point_varying_stencil_table =
793         patch_table->GetLocalPointVaryingStencilTable();
794     if (local_point_varying_stencil_table != NULL) {
795       const StencilTable* table =
796           StencilTableFactory::AppendLocalPointStencilTable(
797               *refiner, varying_stencils, local_point_varying_stencil_table);
798       delete varying_stencils;
799       varying_stencils = table;
800     }
801   }
802 #ifdef OPENSUBDIV_HAS_FVAR_EVALUATION
803   for (int face_varying_channel = 0;
804        face_varying_channel < num_face_varying_channels;
805        ++face_varying_channel) {
806     const StencilTable* table =
807         StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
808               *refiner,
809               all_face_varying_stencils[face_varying_channel],
810               patch_table->GetLocalPointFaceVaryingStencilTable(
811                   face_varying_channel),
812               face_varying_channel);
813     if (table != NULL) {
814       delete all_face_varying_stencils[face_varying_channel];
815       all_face_varying_stencils[face_varying_channel] = table;
816     }
817   }
818 #endif
819   // Create OpenSubdiv's CPU side evaluator.
820   // TODO(sergey): Make it possible to use different evaluators.
821   opensubdiv_capi::CpuEvalOutput* eval_output =
822       new opensubdiv_capi::CpuEvalOutput(vertex_stencils,
823                                          varying_stencils,
824                                          all_face_varying_stencils,
825                                          2,
826                                          patch_table);
827   OpenSubdiv::Far::PatchMap* patch_map = new PatchMap(*patch_table);
828   // Wrap everything we need into an object which we control from our side.
829   OpenSubdiv_EvaluatorInternal* evaluator_descr;
830   evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorInternal);
831   evaluator_descr->eval_output =
832       new opensubdiv_capi::CpuEvalOutputAPI(eval_output, patch_map);
833   evaluator_descr->patch_map = patch_map;
834   evaluator_descr->patch_table = patch_table;
835   // TOOD(sergey): Look into whether we've got duplicated stencils arrays.
836   delete vertex_stencils;
837   delete varying_stencils;
838   foreach (const StencilTable* table, all_face_varying_stencils) {
839     delete table;
840   }
841   return evaluator_descr;
842 }
843
844 void openSubdiv_deleteEvaluatorInternal(
845     OpenSubdiv_EvaluatorInternal* evaluator) {
846   OBJECT_GUARDED_DELETE(evaluator, OpenSubdiv_EvaluatorInternal);
847 }