2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * The Original Code is Copyright (C) 2013 Blender Foundation.
17 * All rights reserved.
20 #include "opensubdiv_capi.h"
30 #include <opensubdiv/osd/glMesh.h>
32 #ifdef OPENSUBDIV_HAS_CUDA
33 # include <opensubdiv/osd/cudaGLVertexBuffer.h>
34 #endif /* OPENSUBDIV_HAS_CUDA */
36 #include <opensubdiv/osd/cpuGLVertexBuffer.h>
37 #include <opensubdiv/osd/cpuEvaluator.h>
39 #include "MEM_guardedalloc.h"
41 #include "opensubdiv_capi.h"
42 #include "opensubdiv_topology_refiner.h"
44 using OpenSubdiv::Osd::GLMeshInterface;
46 extern "C" char datatoc_gpu_shader_opensubdiv_vertex_glsl[];
47 extern "C" char datatoc_gpu_shader_opensubdiv_geometry_glsl[];
48 extern "C" char datatoc_gpu_shader_opensubdiv_fragment_glsl[];
50 /* TODO(sergey): This is bit of bad level calls :S */
52 void copy_m3_m3(float m1[3][3], float m2[3][3]);
53 void copy_m3_m4(float m1[3][3], float m2[4][4]);
54 void adjoint_m3_m3(float m1[3][3], float m[3][3]);
55 float determinant_m3_array(float m[3][3]);
56 bool invert_m3_m3(float m1[3][3], float m2[3][3]);
57 bool invert_m3(float m[3][3]);
58 void transpose_m3(float mat[3][3]);
62 #define SUPPORT_COLOR_MATERIAL
64 typedef struct Light {
69 float spot_direction[4];
70 #ifdef SUPPORT_COLOR_MATERIAL
71 float constant_attenuation;
72 float linear_attenuation;
73 float quadratic_attenuation;
76 float spot_cos_cutoff;
81 typedef struct Lighting {
82 Light lights[MAX_LIGHTS];
86 typedef struct Transform {
87 float projection_matrix[16];
88 float model_view_matrix[16];
89 float normal_matrix[9];
92 static bool g_use_osd_glsl = false;
93 static int g_active_uv_index = 0;
95 static GLuint g_flat_fill_solid_program = 0;
96 static GLuint g_flat_fill_texture2d_program = 0;
97 static GLuint g_smooth_fill_solid_program = 0;
98 static GLuint g_smooth_fill_texture2d_program = 0;
100 static GLuint g_flat_fill_solid_shadeless_program = 0;
101 static GLuint g_flat_fill_texture2d_shadeless_program = 0;
102 static GLuint g_smooth_fill_solid_shadeless_program = 0;
103 static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
105 static GLuint g_wireframe_program = 0;
107 static GLuint g_lighting_ub = 0;
108 static Lighting g_lighting_data;
109 static Transform g_transform;
111 struct OpenSubdiv_GLMeshFVarData
113 OpenSubdiv_GLMeshFVarData() :
114 texture_buffer(0), offset_buffer(0) {
117 ~OpenSubdiv_GLMeshFVarData()
124 if (texture_buffer) {
125 glDeleteTextures(1, &texture_buffer);
128 glDeleteTextures(1, &offset_buffer);
133 channel_offsets.clear();
136 void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
137 const OpenSubdiv::Far::PatchTable *patch_table,
139 const float *fvar_src_data)
143 this->fvar_width = fvar_width;
145 /* Expand fvar data to per-patch array */
146 const int max_level = refiner->GetMaxLevel();
147 const int num_channels = patch_table->GetNumFVarChannels();
148 std::vector<float> data;
149 int fvar_data_offset = 0;
150 channel_offsets.resize(num_channels);
151 for (int channel = 0; channel < num_channels; ++channel) {
152 OpenSubdiv::Far::ConstIndexArray indices =
153 patch_table->GetFVarValues(channel);
155 channel_offsets[channel] = data.size();
156 data.reserve(data.size() + indices.size() * fvar_width);
158 for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
159 int index = indices[fvert] * fvar_width;
160 for (int i = 0; i < fvar_width; ++i) {
161 data.push_back(fvar_src_data[fvar_data_offset + index++]);
164 if (refiner->IsUniform()) {
165 const int num_values_max = refiner->GetLevel(max_level).GetNumFVarValues(channel);
166 fvar_data_offset += num_values_max * fvar_width;
168 const int num_values_total = refiner->GetNumFVarValuesTotal(channel);
169 fvar_data_offset += num_values_total * fvar_width;
174 glGenBuffers(1, &buffer);
175 glBindBuffer(GL_ARRAY_BUFFER, buffer);
176 glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
177 &data[0], GL_STATIC_DRAW);
179 glGenTextures(1, &texture_buffer);
180 glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
181 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
183 glDeleteBuffers(1, &buffer);
185 glGenBuffers(1, &buffer);
186 glBindBuffer(GL_ARRAY_BUFFER, buffer);
187 glBufferData(GL_ARRAY_BUFFER, channel_offsets.size()*sizeof(int),
188 &channel_offsets[0], GL_STATIC_DRAW);
190 glGenTextures(1, &offset_buffer);
191 glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
192 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
193 glBindTexture(GL_TEXTURE_BUFFER, 0);
194 glBindBuffer(GL_ARRAY_BUFFER, 0);
196 GLuint texture_buffer;
197 GLuint offset_buffer;
198 std::vector<int> channel_offsets;
204 GLuint compileShader(GLenum shaderType,
209 const char *sources[] = {
212 #ifdef SUPPORT_COLOR_MATERIAL
213 "#define SUPPORT_COLOR_MATERIAL\n",
220 GLuint shader = glCreateShader(shaderType);
221 glShaderSource(shader, 4, sources, NULL);
222 glCompileShader(shader);
225 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
226 if (status == GL_FALSE) {
228 glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
229 fprintf(stderr, "Error compiling GLSL: %s\n", emsg);
230 fprintf(stderr, "Version: %s\n", version);
231 fprintf(stderr, "Defines: %s\n", define);
232 fprintf(stderr, "Source: %s\n", source);
239 GLuint linkProgram(const char *version, const char *define)
241 GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
244 datatoc_gpu_shader_opensubdiv_vertex_glsl);
245 if (vertexShader == 0) {
248 GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
251 datatoc_gpu_shader_opensubdiv_geometry_glsl);
252 if (geometryShader == 0) {
255 GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
258 datatoc_gpu_shader_opensubdiv_fragment_glsl );
259 if (fragmentShader == 0) {
263 GLuint program = glCreateProgram();
265 glAttachShader(program, vertexShader);
266 glAttachShader(program, geometryShader);
267 glAttachShader(program, fragmentShader);
269 glBindAttribLocation(program, 0, "position");
270 glBindAttribLocation(program, 1, "normal");
273 if (!GLEW_VERSION_3_2) {
274 /* provide input/output layout info */
275 glProgramParameteriEXT(program,
276 GL_GEOMETRY_INPUT_TYPE_EXT,
277 GL_LINES_ADJACENCY_EXT);
279 bool wireframe = strstr(define, "WIREFRAME") != NULL;
281 glProgramParameteriEXT(program,
282 GL_GEOMETRY_OUTPUT_TYPE_EXT,
283 wireframe ? GL_LINE_STRIP : GL_TRIANGLE_STRIP);
285 glProgramParameteriEXT(program,
286 GL_GEOMETRY_VERTICES_OUT_EXT,
290 glLinkProgram(program);
292 glDeleteShader(vertexShader);
293 glDeleteShader(geometryShader);
294 glDeleteShader(fragmentShader);
297 glGetProgramiv(program, GL_LINK_STATUS, &status);
298 if (status == GL_FALSE) {
300 glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
301 fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
302 fprintf(stderr, "Defines: %s\n", define);
303 glDeleteProgram(program);
307 glUniformBlockBinding(program,
308 glGetUniformBlockIndex(program, "Lighting"),
311 glProgramUniform1i(program,
312 glGetUniformLocation(program, "texture_buffer"),
313 0); /* GL_TEXTURE0 */
315 glProgramUniform1i(program,
316 glGetUniformLocation(program, "FVarDataOffsetBuffer"),
317 30); /* GL_TEXTURE30 */
319 glProgramUniform1i(program,
320 glGetUniformLocation(program, "FVarDataBuffer"),
321 31); /* GL_TEXTURE31 */
326 void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
328 glUseProgram(program);
331 glUniformMatrix4fv(glGetUniformLocation(program, "modelViewMatrix"),
333 g_transform.model_view_matrix);
334 glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"),
336 g_transform.projection_matrix);
337 glUniformMatrix3fv(glGetUniformLocation(program, "normalMatrix"),
339 g_transform.normal_matrix);
342 glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
343 glBufferSubData(GL_UNIFORM_BUFFER,
344 0, sizeof(g_lighting_data), &g_lighting_data);
345 glBindBuffer(GL_UNIFORM_BUFFER, 0);
347 glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
350 GLboolean use_lighting;
351 glGetBooleanv(GL_LIGHTING, &use_lighting);
355 glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color);
356 glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
358 glGetMaterialfv(GL_FRONT, GL_SPECULAR, color);
359 glUniform4fv(glGetUniformLocation(program, "specular"), 1, color);
361 glGetMaterialfv(GL_FRONT, GL_SHININESS, color);
362 glUniform1f(glGetUniformLocation(program, "shininess"), color[0]);
366 glGetFloatv(GL_CURRENT_COLOR, color);
367 glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
370 /* Face-vertex data */
371 if (gl_mesh->fvar_data != NULL) {
372 if (gl_mesh->fvar_data->texture_buffer) {
373 glActiveTexture(GL_TEXTURE31);
374 glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
375 glActiveTexture(GL_TEXTURE0);
378 if (gl_mesh->fvar_data->offset_buffer) {
379 glActiveTexture(GL_TEXTURE30);
380 glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->offset_buffer);
381 glActiveTexture(GL_TEXTURE0);
384 glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
385 gl_mesh->fvar_data->fvar_width);
386 if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
387 g_active_uv_index >= 0)
389 glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
390 gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
392 glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
395 glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
396 glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
402 bool openSubdiv_osdGLDisplayInit(void)
404 static bool need_init = true;
405 static bool init_success = false;
408 if (!openSubdiv_supportGPUDisplay()) {
412 const char *version = "";
413 if (GLEW_VERSION_3_2) {
414 version = "#version 150 compatibility\n";
416 else if (GLEW_VERSION_3_1) {
417 version = "#version 140\n"
418 "#extension GL_ARB_compatibility: enable\n";
421 version = "#version 130\n";
422 /* minimum supported for OpenSubdiv */
425 g_flat_fill_solid_program = linkProgram(
427 "#define USE_COLOR_MATERIAL\n"
428 "#define USE_LIGHTING\n"
429 "#define FLAT_SHADING\n");
430 g_flat_fill_texture2d_program = linkProgram(
432 "#define USE_COLOR_MATERIAL\n"
433 "#define USE_LIGHTING\n"
434 "#define USE_TEXTURE_2D\n"
435 "#define FLAT_SHADING\n");
436 g_smooth_fill_solid_program = linkProgram(
438 "#define USE_COLOR_MATERIAL\n"
439 "#define USE_LIGHTING\n"
440 "#define SMOOTH_SHADING\n");
441 g_smooth_fill_texture2d_program = linkProgram(
443 "#define USE_COLOR_MATERIAL\n"
444 "#define USE_LIGHTING\n"
445 "#define USE_TEXTURE_2D\n"
446 "#define SMOOTH_SHADING\n");
448 g_flat_fill_solid_shadeless_program = linkProgram(
450 "#define USE_COLOR_MATERIAL\n"
451 "#define FLAT_SHADING\n");
452 g_flat_fill_texture2d_shadeless_program = linkProgram(
454 "#define USE_COLOR_MATERIAL\n"
455 "#define USE_TEXTURE_2D\n"
456 "#define FLAT_SHADING\n");
457 g_smooth_fill_solid_shadeless_program = linkProgram(
459 "#define USE_COLOR_MATERIAL\n"
460 "#define SMOOTH_SHADING\n");
461 g_smooth_fill_texture2d_shadeless_program = linkProgram(
463 "#define USE_COLOR_MATERIAL\n"
464 "#define USE_TEXTURE_2D\n"
465 "#define SMOOTH_SHADING\n");
467 g_wireframe_program = linkProgram(
469 "#define WIREFRAME\n");
471 glGenBuffers(1, &g_lighting_ub);
472 glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
473 glBufferData(GL_UNIFORM_BUFFER,
474 sizeof(g_lighting_data), NULL, GL_STATIC_DRAW);
477 init_success = g_flat_fill_solid_program != 0 &&
478 g_flat_fill_texture2d_program != 0 &&
479 g_smooth_fill_solid_program != 0 &&
480 g_smooth_fill_texture2d_program != 0 &&
486 void openSubdiv_osdGLDisplayDeinit(void)
488 if (g_lighting_ub != 0) {
489 glDeleteBuffers(1, &g_lighting_ub);
491 #define SAFE_DELETE_PROGRAM(program) \
494 glDeleteProgram(program); \
498 SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
499 SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
500 SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
501 SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
502 SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
503 SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
504 SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
505 SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
506 SAFE_DELETE_PROGRAM(g_wireframe_program);
508 #undef SAFE_DELETE_PROGRAM
511 void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
514 g_active_uv_index = active_uv_index;
515 g_use_osd_glsl = (use_osd_glsl != 0);
517 /* Update transformation matrices. */
518 glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
519 glGetFloatv(GL_MODELVIEW_MATRIX, g_transform.model_view_matrix);
521 copy_m3_m4((float (*)[3])g_transform.normal_matrix,
522 (float (*)[4])g_transform.model_view_matrix);
523 invert_m3((float (*)[3])g_transform.normal_matrix);
524 transpose_m3((float (*)[3])g_transform.normal_matrix);
526 /* Update OpenGL lights positions, colors etc. */
527 g_lighting_data.num_enabled = 0;
528 for (int i = 0; i < MAX_LIGHTS; ++i) {
530 glGetBooleanv(GL_LIGHT0 + i, &enabled);
532 g_lighting_data.num_enabled++;
535 glGetLightfv(GL_LIGHT0 + i,
537 g_lighting_data.lights[i].position);
538 glGetLightfv(GL_LIGHT0 + i,
540 g_lighting_data.lights[i].ambient);
541 glGetLightfv(GL_LIGHT0 + i,
543 g_lighting_data.lights[i].diffuse);
544 glGetLightfv(GL_LIGHT0 + i,
546 g_lighting_data.lights[i].specular);
547 glGetLightfv(GL_LIGHT0 + i,
549 g_lighting_data.lights[i].spot_direction);
550 #ifdef SUPPORT_COLOR_MATERIAL
551 glGetLightfv(GL_LIGHT0 + i,
552 GL_CONSTANT_ATTENUATION,
553 &g_lighting_data.lights[i].constant_attenuation);
554 glGetLightfv(GL_LIGHT0 + i,
555 GL_LINEAR_ATTENUATION,
556 &g_lighting_data.lights[i].linear_attenuation);
557 glGetLightfv(GL_LIGHT0 + i,
558 GL_QUADRATIC_ATTENUATION,
559 &g_lighting_data.lights[i].quadratic_attenuation);
560 glGetLightfv(GL_LIGHT0 + i,
562 &g_lighting_data.lights[i].spot_cutoff);
563 glGetLightfv(GL_LIGHT0 + i,
565 &g_lighting_data.lights[i].spot_exponent);
566 g_lighting_data.lights[i].spot_cos_cutoff =
567 cos(g_lighting_data.lights[i].spot_cutoff);
572 static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
576 if (!g_use_osd_glsl) {
577 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
580 glGetIntegerv(GL_SHADE_MODEL, &model);
582 GLint location = glGetUniformLocation(program, "osd_flat_shading");
583 if (location != -1) {
584 glUniform1i(location, model == GL_FLAT);
587 /* Face-vertex data */
588 if (gl_mesh->fvar_data != NULL) {
589 if (gl_mesh->fvar_data->texture_buffer) {
590 glActiveTexture(GL_TEXTURE31);
591 glBindTexture(GL_TEXTURE_BUFFER,
592 gl_mesh->fvar_data->texture_buffer);
593 glActiveTexture(GL_TEXTURE0);
596 if (gl_mesh->fvar_data->offset_buffer) {
597 glActiveTexture(GL_TEXTURE30);
598 glBindTexture(GL_TEXTURE_BUFFER,
599 gl_mesh->fvar_data->offset_buffer);
600 glActiveTexture(GL_TEXTURE0);
603 GLint location = glGetUniformLocation(program, "osd_fvar_count");
604 if (location != -1) {
605 glUniform1i(location, gl_mesh->fvar_data->fvar_width);
608 location = glGetUniformLocation(program, "osd_active_uv_offset");
609 if (location != -1) {
610 if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
611 g_active_uv_index >= 0)
613 glUniform1i(location,
614 gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
616 glUniform1i(location, 0);
620 glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
621 glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
629 GLboolean use_texture_2d, use_lighting;
630 glGetIntegerv(GL_SHADE_MODEL, &model);
631 glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
632 glGetBooleanv(GL_LIGHTING, &use_lighting);
633 if (model == GL_FLAT) {
634 if (use_texture_2d) {
635 program = use_lighting
636 ? g_flat_fill_texture2d_program
637 : g_flat_fill_texture2d_shadeless_program;
640 program = use_lighting
641 ? g_flat_fill_solid_program
642 : g_flat_fill_solid_shadeless_program;
646 if (use_texture_2d) {
647 program = use_lighting
648 ? g_smooth_fill_texture2d_program
649 : g_smooth_fill_texture2d_shadeless_program;
652 program = use_lighting
653 ? g_smooth_fill_solid_program
654 : g_smooth_fill_solid_shadeless_program;
659 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
660 program = g_wireframe_program;
663 bindProgram(gl_mesh, program);
668 static void perform_drawElements(GLuint program,
674 glUniform1i(glGetUniformLocation(program, "PrimitiveIdBase"),
677 glDrawElements(GL_LINES_ADJACENCY,
680 (void *)(start_element * sizeof(unsigned int)));
683 static void finish_patchDraw(bool fill_quads)
685 /* TODO(sergey): Some of the stuff could be done once after the whole
691 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
693 glBindVertexArray(0);
695 if (g_use_osd_glsl) {
696 /* TODO(sergey): Store previously used program and roll back to it? */
701 static void draw_partition_patches_range(GLMeshInterface *mesh,
706 int traversed_patches = 0, num_remained_patches = num_patches;
707 const OpenSubdiv::Osd::PatchArrayVector& patches =
708 mesh->GetPatchTable()->GetPatchArrays();
709 for (int i = 0; i < (int)patches.size(); ++i) {
710 const OpenSubdiv::Osd::PatchArray& patch = patches[i];
711 OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
712 OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
714 if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
715 const int num_block_patches = patch.GetNumPatches();
716 if (start_patch >= traversed_patches &&
717 start_patch < traversed_patches + num_block_patches)
719 const int num_control_verts = desc.GetNumControlVertices();
720 const int start_draw_patch = start_patch - traversed_patches;
721 const int num_draw_patches = std::min(num_remained_patches,
722 num_block_patches - start_draw_patch);
723 perform_drawElements(program,
724 i + start_draw_patch,
725 num_draw_patches * num_control_verts,
726 patch.GetIndexBase() + start_draw_patch * num_control_verts);
727 num_remained_patches -= num_draw_patches;
729 if (num_remained_patches == 0) {
732 traversed_patches += num_block_patches;
737 static void draw_all_patches(GLMeshInterface *mesh,
740 const OpenSubdiv::Osd::PatchArrayVector& patches =
741 mesh->GetPatchTable()->GetPatchArrays();
742 for (int i = 0; i < (int)patches.size(); ++i) {
743 const OpenSubdiv::Osd::PatchArray& patch = patches[i];
744 OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
745 OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
747 if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
748 perform_drawElements(program,
750 patch.GetNumPatches() * desc.GetNumControlVertices(),
751 patch.GetIndexBase());
756 void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
761 GLMeshInterface *mesh =
762 (GLMeshInterface *)(gl_mesh->descriptor);
764 /* Make sure all global invariants are initialized. */
765 if (!openSubdiv_osdGLDisplayInit()) {
769 /* Setup GLSL/OpenGL to draw patches in current context. */
770 GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
772 if (start_patch != -1) {
773 draw_partition_patches_range(mesh,
779 draw_all_patches(mesh, program);
782 /* Finish patch drawing by restoring all changes to the OpenGL context. */
783 finish_patchDraw(fill_quads != 0);
786 void openSubdiv_osdGLAllocFVar(OpenSubdiv_TopologyRefinerDescr *topology_refiner,
787 OpenSubdiv_GLMesh *gl_mesh,
788 const float *fvar_data)
790 GLMeshInterface *mesh =
791 (GLMeshInterface *)(gl_mesh->descriptor);
792 gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
793 gl_mesh->fvar_data->Create(topology_refiner->osd_refiner,
794 mesh->GetFarPatchTable(),
799 void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
801 if (gl_mesh->fvar_data != NULL) {
802 OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);