Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/opensubdiv/opensubdiv_gpu_capi.cc')
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc414
1 files changed, 269 insertions, 145 deletions
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 698fdfee00f..0cf6fcfef43 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -42,11 +42,29 @@
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
#include <opensubdiv/osd/cpuEvaluator.h>
+#include "MEM_guardedalloc.h"
+
+#include "opensubdiv_capi.h"
+#include "opensubdiv_topology_refiner.h"
+
using OpenSubdiv::Osd::GLMeshInterface;
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
+/* TODO(sergey): This is bit of bad level calls :S */
+extern "C" {
+void copy_m3_m3(float m1[3][3], float m2[3][3]);
+void copy_m3_m4(float m1[3][3], float m2[4][4]);
+void adjoint_m3_m3(float m1[3][3], float m[3][3]);
+float determinant_m3_array(float m[3][3]);
+bool invert_m3_m3(float m1[3][3], float m2[3][3]);
+bool invert_m3(float m[3][3]);
+void transpose_m3(float mat[3][3]);
+}
+
#define MAX_LIGHTS 8
+#define SUPPORT_COLOR_MATERIAL
+
typedef struct Light {
float position[4];
float ambient[4];
@@ -60,6 +78,7 @@ typedef struct Light {
float spot_cutoff;
float spot_exponent;
float spot_cos_cutoff;
+ float pad, pad2;
#endif
} Light;
@@ -75,114 +94,116 @@ typedef struct Transform {
} Transform;
static bool g_use_osd_glsl = false;
-static int g_active_uv_index = -1;
+static int g_active_uv_index = 0;
static GLuint g_flat_fill_solid_program = 0;
static GLuint g_flat_fill_texture2d_program = 0;
static GLuint g_smooth_fill_solid_program = 0;
static GLuint g_smooth_fill_texture2d_program = 0;
+
+static GLuint g_flat_fill_solid_shadeless_program = 0;
+static GLuint g_flat_fill_texture2d_shadeless_program = 0;
+static GLuint g_smooth_fill_solid_shadeless_program = 0;
+static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
+
static GLuint g_wireframe_program = 0;
static GLuint g_lighting_ub = 0;
static Lighting g_lighting_data;
static Transform g_transform;
-/* TODO(sergey): This is actually duplicated code from BLI. */
-namespace {
-void copy_m3_m3(float m1[3][3], float m2[3][3])
-{
- /* destination comes first: */
- memcpy(&m1[0], &m2[0], 9 * sizeof(float));
-}
-
-void copy_m3_m4(float m1[3][3], float m2[4][4])
-{
- m1[0][0] = m2[0][0];
- m1[0][1] = m2[0][1];
- m1[0][2] = m2[0][2];
-
- m1[1][0] = m2[1][0];
- m1[1][1] = m2[1][1];
- m1[1][2] = m2[1][2];
-
- m1[2][0] = m2[2][0];
- m1[2][1] = m2[2][1];
- m1[2][2] = m2[2][2];
-}
-
-void adjoint_m3_m3(float m1[3][3], float m[3][3])
-{
- m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
- m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
- m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
-
- m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
- m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
- m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
-
- m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
- m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
- m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
-}
-
-float determinant_m3_array(float m[3][3])
+struct OpenSubdiv_GLMeshFVarData
{
- return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
- m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
- m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
-}
-
-bool invert_m3_m3(float m1[3][3], float m2[3][3])
-{
- float det;
- int a, b;
- bool success;
-
- /* calc adjoint */
- adjoint_m3_m3(m1, m2);
+ OpenSubdiv_GLMeshFVarData() :
+ texture_buffer(0) {
+ }
- /* then determinant old matrix! */
- det = determinant_m3_array(m2);
+ ~OpenSubdiv_GLMeshFVarData()
+ {
+ Release();
+ }
- success = (det != 0.0f);
+ void Release()
+ {
+ if (texture_buffer) {
+ glDeleteTextures(1, &texture_buffer);
+ }
+ if (offset_buffer) {
+ glDeleteTextures(1, &offset_buffer);
+ }
+ texture_buffer = 0;
+ offset_buffer = 0;
+ fvar_width = 0;
+ channel_offsets.clear();
+ }
- if (det != 0.0f) {
- det = 1.0f / det;
- for (a = 0; a < 3; a++) {
- for (b = 0; b < 3; b++) {
- m1[a][b] *= det;
+ void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
+ const OpenSubdiv::Far::PatchTable *patch_table,
+ int fvar_width,
+ const float *fvar_src_data)
+ {
+ Release();
+
+ this->fvar_width = fvar_width;
+
+ /* Expand fvar data to per-patch array */
+ const int max_level = refiner->GetMaxLevel();
+ const int num_channels = patch_table->GetNumFVarChannels();
+ std::vector<float> data;
+ int fvar_data_offset = 0;
+ channel_offsets.resize(num_channels);
+ for (int channel = 0; channel < num_channels; ++channel) {
+ OpenSubdiv::Far::ConstIndexArray indices =
+ patch_table->GetFVarValues(channel);
+
+ channel_offsets[channel] = data.size();
+ data.reserve(data.size() + indices.size() * fvar_width);
+
+ for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
+ int index = indices[fvert] * fvar_width;
+ for (int i = 0; i < fvar_width; ++i) {
+ data.push_back(fvar_src_data[fvar_data_offset + index++]);
+ }
+ }
+ if (refiner->IsUniform()) {
+ const int num_values_max = refiner->GetLevel(max_level).GetNumFVarValues(channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ const int num_values_total = refiner->GetNumFVarValuesTotal(channel);
+ fvar_data_offset += num_values_total * fvar_width;
}
}
- }
- return success;
-}
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
+ &data[0], GL_STATIC_DRAW);
-bool invert_m3(float m[3][3])
-{
- float tmp[3][3];
- bool success;
+ glGenTextures(1, &texture_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
- success = invert_m3_m3(tmp, m);
- copy_m3_m3(m, tmp);
+ glDeleteBuffers(1, &buffer);
- return success;
-}
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, channel_offsets.size()*sizeof(int),
+ &channel_offsets[0], GL_STATIC_DRAW);
-void transpose_m3(float mat[3][3])
-{
- float t;
-
- t = mat[0][1];
- mat[0][1] = mat[1][0];
- mat[1][0] = t;
- t = mat[0][2];
- mat[0][2] = mat[2][0];
- mat[2][0] = t;
- t = mat[1][2];
- mat[1][2] = mat[2][1];
- mat[2][1] = t;
-}
+ glGenTextures(1, &offset_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ GLuint texture_buffer;
+ GLuint offset_buffer;
+ std::vector<int> channel_offsets;
+ int fvar_width;
+};
+
+namespace {
GLuint compileShader(GLenum shaderType,
const char *section,
@@ -196,11 +217,14 @@ GLuint compileShader(GLenum shaderType,
version,
define,
sdefine,
+#ifdef SUPPORT_COLOR_MATERIAL
+ "#define SUPPORT_COLOR_MATERIAL\n",
+#endif
datatoc_gpu_shader_opensubd_display_glsl
};
GLuint shader = glCreateShader(shaderType);
- glShaderSource(shader, 4, sources, NULL);
+ glShaderSource(shader, 5, sources, NULL);
glCompileShader(shader);
GLint status;
@@ -295,14 +319,17 @@ GLuint linkProgram(const char *version, const char *define)
0); /* GL_TEXTURE0 */
glProgramUniform1i(program,
+ glGetUniformLocation(program, "FVarDataOffsetBuffer"),
+ 30); /* GL_TEXTURE30 */
+
+ glProgramUniform1i(program,
glGetUniformLocation(program, "FVarDataBuffer"),
31); /* GL_TEXTURE31 */
return program;
}
-void bindProgram(GLMeshInterface * /*mesh*/,
- int program)
+void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
{
glUseProgram(program);
@@ -346,23 +373,34 @@ void bindProgram(GLMeshInterface * /*mesh*/,
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
}
- /* TODO(sergey): Bring face varying back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
- glActiveTexture(GL_TEXTURE0);
- }
-#endif
+ if (gl_mesh->fvar_data != NULL) {
+ if (gl_mesh->fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
- /* TODO(sergey): Bring face varying back. */
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
- 0/* * mesh->GetFVarCount()*/);
+ if (gl_mesh->fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
- g_active_uv_index * 2);
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
+ gl_mesh->fvar_data->fvar_width);
+ if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
+ g_active_uv_index >= 0)
+ {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
+ gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
}
} /* namespace */
@@ -390,11 +428,51 @@ bool openSubdiv_osdGLDisplayInit(void)
/* minimum supported for OpenSubdiv */
}
- g_flat_fill_solid_program = linkProgram(version, "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
- g_smooth_fill_solid_program = linkProgram(version, "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
- g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
+ g_flat_fill_solid_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+
+ g_flat_fill_solid_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+
+ g_wireframe_program = linkProgram(
+ version,
+ "#define WIREFRAME\n");
glGenBuffers(1, &g_lighting_ub);
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
@@ -416,28 +494,31 @@ void openSubdiv_osdGLDisplayDeinit(void)
if (g_lighting_ub != 0) {
glDeleteBuffers(1, &g_lighting_ub);
}
- if (g_flat_fill_solid_program) {
- glDeleteProgram(g_flat_fill_solid_program);
- }
- if (g_flat_fill_texture2d_program) {
- glDeleteProgram(g_flat_fill_texture2d_program);
- }
- if (g_smooth_fill_solid_program) {
- glDeleteProgram(g_flat_fill_solid_program);
- }
- if (g_smooth_fill_texture2d_program) {
- glDeleteProgram(g_smooth_fill_texture2d_program);
- }
- if (g_wireframe_program) {
- glDeleteProgram(g_wireframe_program);
- }
+#define SAFE_DELETE_PROGRAM(program) \
+ do { \
+ if (program) { \
+ glDeleteProgram(program); \
+ } \
+ } while (false)
+
+ SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_wireframe_program);
+
+#undef SAFE_DELETE_PROGRAM
}
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
int active_uv_index)
{
- g_use_osd_glsl = use_osd_glsl != 0;
g_active_uv_index = active_uv_index;
+ g_use_osd_glsl = (use_osd_glsl != 0);
/* Update transformation matrices. */
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
@@ -494,7 +575,7 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
}
}
-static GLuint prepare_patchDraw(GLMeshInterface *mesh,
+static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
bool fill_quads)
{
GLint program = 0;
@@ -509,51 +590,74 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
glUniform1i(location, model == GL_FLAT);
}
- /* TODO(sergey): Bring this back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
- glActiveTexture(GL_TEXTURE0);
+ if (gl_mesh->fvar_data != NULL) {
+ if (gl_mesh->fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ gl_mesh->fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ if (gl_mesh->fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ gl_mesh->fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
GLint location = glGetUniformLocation(program, "osd_fvar_count");
if (location != -1) {
- glUniform1i(location, mesh->GetFVarCount());
+ glUniform1i(location, gl_mesh->fvar_data->fvar_width);
}
location = glGetUniformLocation(program, "osd_active_uv_offset");
if (location != -1) {
- glUniform1i(location,
- g_active_uv_index * 2);
+ if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
+ g_active_uv_index >= 0)
+ {
+ glUniform1i(location,
+ gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(location, 0);
+ }
}
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
-#endif
-
}
return program;
}
if (fill_quads) {
int model;
- GLboolean use_texture_2d;
+ GLboolean use_texture_2d, use_lighting;
glGetIntegerv(GL_SHADE_MODEL, &model);
glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
+ glGetBooleanv(GL_LIGHTING, &use_lighting);
if (model == GL_FLAT) {
if (use_texture_2d) {
- program = g_flat_fill_texture2d_program;
+ program = use_lighting
+ ? g_flat_fill_texture2d_program
+ : g_flat_fill_texture2d_shadeless_program;
}
else {
- program = g_flat_fill_solid_program;
+ program = use_lighting
+ ? g_flat_fill_solid_program
+ : g_flat_fill_solid_shadeless_program;
}
}
else {
if (use_texture_2d) {
- program = g_smooth_fill_texture2d_program;
+ program = use_lighting
+ ? g_smooth_fill_texture2d_program
+ : g_smooth_fill_texture2d_shadeless_program;
}
else {
- program = g_smooth_fill_solid_program;
+ program = use_lighting
+ ? g_smooth_fill_solid_program
+ : g_smooth_fill_solid_shadeless_program;
}
}
}
@@ -562,7 +666,7 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
program = g_wireframe_program;
}
- bindProgram(mesh, program);
+ bindProgram(gl_mesh, program);
return program;
}
@@ -623,7 +727,7 @@ static void draw_partition_patches_range(GLMeshInterface *mesh,
const int num_draw_patches = std::min(num_remained_patches,
num_block_patches - start_draw_patch);
perform_drawElements(program,
- i,
+ i + start_draw_patch,
num_draw_patches * num_control_verts,
patch.GetIndexBase() + start_draw_patch * num_control_verts);
num_remained_patches -= num_draw_patches;
@@ -669,7 +773,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
}
/* Setup GLSL/OpenGL to draw patches in current context. */
- GLuint program = prepare_patchDraw(mesh, fill_quads != 0);
+ GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
if (start_patch != -1) {
draw_partition_patches_range(mesh,
@@ -684,3 +788,23 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
/* Finish patch drawing by restoring all changes to the OpenGL context. */
finish_patchDraw(fill_quads != 0);
}
+
+void openSubdiv_osdGLAllocFVar(OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data)
+{
+ GLMeshInterface *mesh =
+ (GLMeshInterface *)(gl_mesh->descriptor);
+ gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
+ gl_mesh->fvar_data->Create(topology_refiner->osd_refiner,
+ mesh->GetFarPatchTable(),
+ 2,
+ fvar_data);
+}
+
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
+{
+ if (gl_mesh->fvar_data != NULL) {
+ OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
+ }
+}