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