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/opencolorio/ocio_impl_glsl.cc')
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc801
1 files changed, 414 insertions, 387 deletions
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index cf41d0a4983..4d0908eafd5 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -64,211 +64,224 @@ extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
typedef struct OCIO_GLSLShader {
- /* Cache ID */
- std::string lut3dCacheID;
- std::string shaderCacheID;
-
- /* LUT */
- bool lut3d_texture_allocated; /* boolean flag indicating whether
- * lut texture is allocated
- */
- bool lut3d_texture_valid;
-
- GLuint lut3d_texture; /* OGL texture ID for 3D LUT */
-
- float *lut3d; /* 3D LUT table */
-
- /* Dither */
- bool use_dither;
-
- /* Curve Mapping */
- bool use_curve_mapping;
- bool curve_mapping_texture_allocated;
- bool curve_mapping_texture_valid;
- GLuint curve_mapping_texture;
- size_t curve_mapping_cache_id;
-
- /* Alpha Predivide */
- bool use_predivide;
-
- /* GLSL stuff */
- GLuint ocio_shader;
- GLuint vert_shader;
- GLuint program;
- GPUShaderInterface *shader_interface;
+ /* Cache ID */
+ std::string lut3dCacheID;
+ std::string shaderCacheID;
+
+ /* LUT */
+ bool lut3d_texture_allocated; /* boolean flag indicating whether
+ * lut texture is allocated
+ */
+ bool lut3d_texture_valid;
+
+ GLuint lut3d_texture; /* OGL texture ID for 3D LUT */
+
+ float *lut3d; /* 3D LUT table */
+
+ /* Dither */
+ bool use_dither;
+
+ /* Curve Mapping */
+ bool use_curve_mapping;
+ bool curve_mapping_texture_allocated;
+ bool curve_mapping_texture_valid;
+ GLuint curve_mapping_texture;
+ size_t curve_mapping_cache_id;
+
+ /* Alpha Predivide */
+ bool use_predivide;
+
+ /* GLSL stuff */
+ GLuint ocio_shader;
+ GLuint vert_shader;
+ GLuint program;
+ GPUShaderInterface *shader_interface;
} GLSLDrawState;
typedef struct OCIO_GLSLDrawState {
- /* Shader Cache */
- OCIO_GLSLShader *shader_cache[SHADER_CACHE_SIZE];
+ /* Shader Cache */
+ OCIO_GLSLShader *shader_cache[SHADER_CACHE_SIZE];
- /* Previous OpenGL state. */
- GLint last_texture, last_texture_unit;
+ /* Previous OpenGL state. */
+ GLint last_texture, last_texture_unit;
} OCIO_GLSLDrawState;
static GLuint compileShaderText(GLenum shaderType, const char *text)
{
- GLuint shader;
- GLint stat;
-
- shader = glCreateShader(shaderType);
- glShaderSource(shader, 1, (const GLchar **) &text, NULL);
- glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
-
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- glGetShaderInfoLog(shader, 1000, &len, log);
- fprintf(stderr, "Shader compile error:\n%s\n", log);
- return 0;
- }
-
- return shader;
+ GLuint shader;
+ GLint stat;
+
+ shader = glCreateShader(shaderType);
+ glShaderSource(shader, 1, (const GLchar **)&text, NULL);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
+
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetShaderInfoLog(shader, 1000, &len, log);
+ fprintf(stderr, "Shader compile error:\n%s\n", log);
+ return 0;
+ }
+
+ return shader;
}
static GLuint linkShaders(GLuint ocio_shader, GLuint vert_shader)
{
- if (!ocio_shader || !vert_shader)
- return 0;
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, ocio_shader);
- glAttachShader(program, vert_shader);
-
- glLinkProgram(program);
-
- /* check link */
- {
- GLint stat;
- glGetProgramiv(program, GL_LINK_STATUS, &stat);
- if (!stat) {
- GLchar log[1000];
- GLsizei len;
- glGetProgramInfoLog(program, 1000, &len, log);
- fprintf(stderr, "Shader link error:\n%s\n", log);
- return 0;
- }
- }
-
- return program;
+ if (!ocio_shader || !vert_shader)
+ return 0;
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, ocio_shader);
+ glAttachShader(program, vert_shader);
+
+ glLinkProgram(program);
+
+ /* check link */
+ {
+ GLint stat;
+ glGetProgramiv(program, GL_LINK_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetProgramInfoLog(program, 1000, &len, log);
+ fprintf(stderr, "Shader link error:\n%s\n", log);
+ return 0;
+ }
+ }
+
+ return program;
}
static OCIO_GLSLDrawState *allocateOpenGLState(void)
{
- return (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState),
- "OCIO OpenGL State struct");
+ return (OCIO_GLSLDrawState *)MEM_callocN(sizeof(OCIO_GLSLDrawState), "OCIO OpenGL State struct");
}
/* Ensure LUT texture and array are allocated */
static bool ensureLUT3DAllocated(OCIO_GLSLShader *shader)
{
- int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
-
- if (shader->lut3d_texture_allocated)
- return shader->lut3d_texture_valid;
-
- glGenTextures(1, &shader->lut3d_texture);
-
- shader->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- /* clean glError buffer */
- while (glGetError() != GL_NO_ERROR) {}
-
- glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
- LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
- 0, GL_RGB, GL_FLOAT, shader->lut3d);
-
- shader->lut3d_texture_allocated = true;
-
- /* GL_RGB16F_ARB could be not supported at some drivers
- * in this case we could not use GLSL display
- */
- shader->lut3d_texture_valid = glGetError() == GL_NO_ERROR;
-
- return shader->lut3d_texture_valid;
+ int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE;
+
+ if (shader->lut3d_texture_allocated)
+ return shader->lut3d_texture_valid;
+
+ glGenTextures(1, &shader->lut3d_texture);
+
+ shader->lut3d = (float *)MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT");
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ /* clean glError buffer */
+ while (glGetError() != GL_NO_ERROR) {
+ }
+
+ glTexImage3D(GL_TEXTURE_3D,
+ 0,
+ GL_RGB16F_ARB,
+ LUT3D_EDGE_SIZE,
+ LUT3D_EDGE_SIZE,
+ LUT3D_EDGE_SIZE,
+ 0,
+ GL_RGB,
+ GL_FLOAT,
+ shader->lut3d);
+
+ shader->lut3d_texture_allocated = true;
+
+ /* GL_RGB16F_ARB could be not supported at some drivers
+ * in this case we could not use GLSL display
+ */
+ shader->lut3d_texture_valid = glGetError() == GL_NO_ERROR;
+
+ return shader->lut3d_texture_valid;
}
-static bool ensureCurveMappingAllocated(OCIO_GLSLShader *shader, OCIO_CurveMappingSettings *curve_mapping_settings)
+static bool ensureCurveMappingAllocated(OCIO_GLSLShader *shader,
+ OCIO_CurveMappingSettings *curve_mapping_settings)
{
- if (shader->curve_mapping_texture_allocated)
- return shader->curve_mapping_texture_valid;
-
- glGenTextures(1, &shader->curve_mapping_texture);
-
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- /* clean glError buffer */
- while (glGetError() != GL_NO_ERROR) {}
-
- glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, curve_mapping_settings->lut_size,
- 0, GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
-
- shader->curve_mapping_texture_allocated = true;
-
- /* GL_RGB16F_ARB could be not supported at some drivers
- * in this case we could not use GLSL display
- */
- shader->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
-
- return shader->curve_mapping_texture_valid;
+ if (shader->curve_mapping_texture_allocated)
+ return shader->curve_mapping_texture_valid;
+
+ glGenTextures(1, &shader->curve_mapping_texture);
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ /* clean glError buffer */
+ while (glGetError() != GL_NO_ERROR) {
+ }
+
+ glTexImage1D(GL_TEXTURE_1D,
+ 0,
+ GL_RGBA16F,
+ curve_mapping_settings->lut_size,
+ 0,
+ GL_RGBA,
+ GL_FLOAT,
+ curve_mapping_settings->lut);
+
+ shader->curve_mapping_texture_allocated = true;
+
+ /* GL_RGB16F_ARB could be not supported at some drivers
+ * in this case we could not use GLSL display
+ */
+ shader->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
+
+ return shader->curve_mapping_texture_valid;
}
static void freeGLSLShader(OCIO_GLSLShader *shader)
{
- if (shader->curve_mapping_texture_allocated) {
- glDeleteTextures(1, &shader->curve_mapping_texture);
- }
+ if (shader->curve_mapping_texture_allocated) {
+ glDeleteTextures(1, &shader->curve_mapping_texture);
+ }
- if (shader->lut3d_texture_allocated) {
- glDeleteTextures(1, &shader->lut3d_texture);
- }
+ if (shader->lut3d_texture_allocated) {
+ glDeleteTextures(1, &shader->lut3d_texture);
+ }
- if (shader->lut3d) {
- MEM_freeN(shader->lut3d);
- }
+ if (shader->lut3d) {
+ MEM_freeN(shader->lut3d);
+ }
- if (shader->program) {
- glDeleteProgram(shader->program);
- }
+ if (shader->program) {
+ glDeleteProgram(shader->program);
+ }
- if (shader->shader_interface) {
- GPU_shaderinterface_discard(shader->shader_interface);
- }
+ if (shader->shader_interface) {
+ GPU_shaderinterface_discard(shader->shader_interface);
+ }
- if (shader->ocio_shader) {
- glDeleteShader(shader->ocio_shader);
- }
+ if (shader->ocio_shader) {
+ glDeleteShader(shader->ocio_shader);
+ }
- using std::string;
- shader->lut3dCacheID.~string();
- shader->shaderCacheID.~string();
+ using std::string;
+ shader->lut3dCacheID.~string();
+ shader->shaderCacheID.~string();
- MEM_freeN(shader);
+ MEM_freeN(shader);
}
-
-
/* Detect if we can support GLSL drawing */
bool OCIOImpl::supportGLSLDraw()
{
- /* uses GL_RGB16F_ARB */
- return GLEW_VERSION_3_0 || GLEW_ARB_texture_float;
+ /* uses GL_RGB16F_ARB */
+ return GLEW_VERSION_3_0 || GLEW_ARB_texture_float;
}
/**
@@ -281,237 +294,251 @@ bool OCIOImpl::supportGLSLDraw()
* When all drawing is finished, finishGLSLDraw shall be called to
* restore OpenGL context to it's pre-GLSL draw state.
*/
-bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r,
+ OCIO_ConstProcessorRcPtr *processor,
OCIO_CurveMappingSettings *curve_mapping_settings,
- float dither, bool use_predivide)
+ float dither,
+ bool use_predivide)
{
- ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
- bool use_curve_mapping = curve_mapping_settings != NULL;
- bool use_dither = dither > std::numeric_limits<float>::epsilon();
-
- /* Create state if needed. */
- OCIO_GLSLDrawState *state;
- if (!*state_r)
- *state_r = allocateOpenGLState();
- state = *state_r;
-
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &state->last_texture);
- glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
-
- /* Compute cache IDs. */
- GpuShaderDesc shaderDesc;
- shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
- shaderDesc.setFunctionName("OCIODisplay");
- shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
-
- std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
- std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
-
- /* Find matching cached shader. */
- OCIO_GLSLShader *shader = NULL;
- for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
- OCIO_GLSLShader *cached_shader = state->shader_cache[i];
- if (cached_shader == NULL) {
- continue;
- }
-
- if (cached_shader->lut3dCacheID == lut3dCacheID &&
- cached_shader->shaderCacheID == shaderCacheID &&
- cached_shader->use_predivide == use_predivide &&
- cached_shader->use_curve_mapping == use_curve_mapping &&
- cached_shader->use_dither == use_dither)
- {
- /* LRU cache, so move to front. */
- for (int j = i; j > 0; j--) {
- state->shader_cache[j] = state->shader_cache[j - 1];
- }
- state->shader_cache[0] = cached_shader;
-
- shader = cached_shader;
- break;
- }
- }
-
- if (shader == NULL) {
- /* LRU cache, shift other items back so we can insert at the front. */
- OCIO_GLSLShader *last_shader = state->shader_cache[SHADER_CACHE_SIZE - 1];
- if (last_shader) {
- freeGLSLShader(last_shader);
- }
- for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) {
- state->shader_cache[j] = state->shader_cache[j - 1];
- }
-
- /* Allocate memory for shader. */
- shader = (OCIO_GLSLShader *) MEM_callocN(sizeof(OCIO_GLSLShader),
- "OCIO GLSL Shader");
- state->shader_cache[0] = shader;
-
- new (&shader->lut3dCacheID) std::string();
- new (&shader->shaderCacheID) std::string();
-
- shader->lut3dCacheID = lut3dCacheID;
- shader->shaderCacheID = shaderCacheID;
- shader->use_curve_mapping = use_curve_mapping;
- shader->use_dither = use_dither;
- shader->use_predivide = use_predivide;
-
- bool valid = true;
-
- /* Compute 3D LUT. */
- if (valid && ensureLUT3DAllocated(shader)) {
- ocio_processor->getGpuLut3D(shader->lut3d, shaderDesc);
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
- glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
- LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE,
- GL_RGB, GL_FLOAT, shader->lut3d);
- }
- else {
- valid = false;
- }
-
- /* Allocate curve mapping texture. */
- if (valid && use_curve_mapping) {
- if (!ensureCurveMappingAllocated(shader, curve_mapping_settings)) {
- valid = false;
- }
- }
-
- if (valid) {
- /* Vertex shader */
- std::ostringstream osv;
-
- osv << "#version 330\n";
- osv << datatoc_gpu_shader_display_transform_vertex_glsl;
-
- shader->vert_shader = compileShaderText(GL_VERTEX_SHADER, osv.str().c_str());
-
- /* Fragment shader */
- std::ostringstream os;
-
- os << "#version 330\n";
-
- /* Work around OpenColorIO not supporting latest GLSL yet. */
- os << "#define texture2D texture\n";
- os << "#define texture3D texture\n";
-
- if (use_predivide) {
- os << "#define USE_PREDIVIDE\n";
- }
-
- if (use_dither) {
- os << "#define USE_DITHER\n";
- }
-
- if (use_curve_mapping) {
- os << "#define USE_CURVE_MAPPING\n";
- }
-
- os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
- os << datatoc_gpu_shader_display_transform_glsl;
-
- shader->ocio_shader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
-
- /* Program */
- if (shader->ocio_shader && shader->vert_shader) {
- shader->program = linkShaders(shader->ocio_shader, shader->vert_shader);
- }
-
- if (shader->program) {
- if (shader->shader_interface) {
- GPU_shaderinterface_discard(shader->shader_interface);
- }
- shader->shader_interface = GPU_shaderinterface_create(shader->program);
- }
- }
- }
-
- /* Update curve mapping texture. */
- if (use_curve_mapping && shader->curve_mapping_texture_allocated) {
- if (shader->curve_mapping_cache_id != curve_mapping_settings->cache_id) {
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
- glTexSubImage1D(GL_TEXTURE_1D, 0, 0, curve_mapping_settings->lut_size,
- GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
- }
- }
-
- /* Bind Shader. */
- if (shader->program) {
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
-
- if (use_curve_mapping) {
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
- }
-
- glActiveTexture(GL_TEXTURE0);
-
- /* IMM needs vertex format even if we don't draw with it.
- *
- * NOTE: The only reason why it's here is because of Cycles viewport.
- * All other areas are managing their own vertex formats.
- * Doing it here is probably harmless, but kind of stupid.
- *
- * TODO(sergey): Look into some nicer solution.
- */
- GPUVertFormat *format = immVertexFormat();
- GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindProgram(shader->program, shader->shader_interface);
-
- immUniform1i("image_texture", 0);
- immUniform1i("lut3d_texture", 1);
-
- if (use_dither) {
- immUniform1f("dither", dither);
- }
-
- if (use_curve_mapping) {
- immUniform1i("curve_mapping_texture", 2);
- immUniform1i("curve_mapping_lut_size", curve_mapping_settings->lut_size);
- immUniform4iv("use_curve_mapping_extend_extrapolate", curve_mapping_settings->use_extend_extrapolate);
- immUniform4fv("curve_mapping_mintable", curve_mapping_settings->mintable);
- immUniform4fv("curve_mapping_range", curve_mapping_settings->range);
- immUniform4fv("curve_mapping_ext_in_x", curve_mapping_settings->ext_in_x);
- immUniform4fv("curve_mapping_ext_in_y", curve_mapping_settings->ext_in_y);
- immUniform4fv("curve_mapping_ext_out_x", curve_mapping_settings->ext_out_x);
- immUniform4fv("curve_mapping_ext_out_y", curve_mapping_settings->ext_out_y);
- immUniform4fv("curve_mapping_first_x", curve_mapping_settings->first_x);
- immUniform4fv("curve_mapping_first_y", curve_mapping_settings->first_y);
- immUniform4fv("curve_mapping_last_x", curve_mapping_settings->last_x);
- immUniform4fv("curve_mapping_last_y", curve_mapping_settings->last_y);
- immUniform3fv("curve_mapping_black", curve_mapping_settings->black);
- immUniform3fv("curve_mapping_bwmul", curve_mapping_settings->bwmul);
- }
-
- return true;
- }
- else {
- glActiveTexture(state->last_texture_unit);
- glBindTexture(GL_TEXTURE_2D, state->last_texture);
-
- return false;
- }
+ ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *)processor;
+ bool use_curve_mapping = curve_mapping_settings != NULL;
+ bool use_dither = dither > std::numeric_limits<float>::epsilon();
+
+ /* Create state if needed. */
+ OCIO_GLSLDrawState *state;
+ if (!*state_r)
+ *state_r = allocateOpenGLState();
+ state = *state_r;
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &state->last_texture);
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit);
+
+ /* Compute cache IDs. */
+ GpuShaderDesc shaderDesc;
+ shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
+ shaderDesc.setFunctionName("OCIODisplay");
+ shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+
+ std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
+ std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
+
+ /* Find matching cached shader. */
+ OCIO_GLSLShader *shader = NULL;
+ for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
+ OCIO_GLSLShader *cached_shader = state->shader_cache[i];
+ if (cached_shader == NULL) {
+ continue;
+ }
+
+ if (cached_shader->lut3dCacheID == lut3dCacheID &&
+ cached_shader->shaderCacheID == shaderCacheID &&
+ cached_shader->use_predivide == use_predivide &&
+ cached_shader->use_curve_mapping == use_curve_mapping &&
+ cached_shader->use_dither == use_dither) {
+ /* LRU cache, so move to front. */
+ for (int j = i; j > 0; j--) {
+ state->shader_cache[j] = state->shader_cache[j - 1];
+ }
+ state->shader_cache[0] = cached_shader;
+
+ shader = cached_shader;
+ break;
+ }
+ }
+
+ if (shader == NULL) {
+ /* LRU cache, shift other items back so we can insert at the front. */
+ OCIO_GLSLShader *last_shader = state->shader_cache[SHADER_CACHE_SIZE - 1];
+ if (last_shader) {
+ freeGLSLShader(last_shader);
+ }
+ for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) {
+ state->shader_cache[j] = state->shader_cache[j - 1];
+ }
+
+ /* Allocate memory for shader. */
+ shader = (OCIO_GLSLShader *)MEM_callocN(sizeof(OCIO_GLSLShader), "OCIO GLSL Shader");
+ state->shader_cache[0] = shader;
+
+ new (&shader->lut3dCacheID) std::string();
+ new (&shader->shaderCacheID) std::string();
+
+ shader->lut3dCacheID = lut3dCacheID;
+ shader->shaderCacheID = shaderCacheID;
+ shader->use_curve_mapping = use_curve_mapping;
+ shader->use_dither = use_dither;
+ shader->use_predivide = use_predivide;
+
+ bool valid = true;
+
+ /* Compute 3D LUT. */
+ if (valid && ensureLUT3DAllocated(shader)) {
+ ocio_processor->getGpuLut3D(shader->lut3d, shaderDesc);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
+ glTexSubImage3D(GL_TEXTURE_3D,
+ 0,
+ 0,
+ 0,
+ 0,
+ LUT3D_EDGE_SIZE,
+ LUT3D_EDGE_SIZE,
+ LUT3D_EDGE_SIZE,
+ GL_RGB,
+ GL_FLOAT,
+ shader->lut3d);
+ }
+ else {
+ valid = false;
+ }
+
+ /* Allocate curve mapping texture. */
+ if (valid && use_curve_mapping) {
+ if (!ensureCurveMappingAllocated(shader, curve_mapping_settings)) {
+ valid = false;
+ }
+ }
+
+ if (valid) {
+ /* Vertex shader */
+ std::ostringstream osv;
+
+ osv << "#version 330\n";
+ osv << datatoc_gpu_shader_display_transform_vertex_glsl;
+
+ shader->vert_shader = compileShaderText(GL_VERTEX_SHADER, osv.str().c_str());
+
+ /* Fragment shader */
+ std::ostringstream os;
+
+ os << "#version 330\n";
+
+ /* Work around OpenColorIO not supporting latest GLSL yet. */
+ os << "#define texture2D texture\n";
+ os << "#define texture3D texture\n";
+
+ if (use_predivide) {
+ os << "#define USE_PREDIVIDE\n";
+ }
+
+ if (use_dither) {
+ os << "#define USE_DITHER\n";
+ }
+
+ if (use_curve_mapping) {
+ os << "#define USE_CURVE_MAPPING\n";
+ }
+
+ os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
+ os << datatoc_gpu_shader_display_transform_glsl;
+
+ shader->ocio_shader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+
+ /* Program */
+ if (shader->ocio_shader && shader->vert_shader) {
+ shader->program = linkShaders(shader->ocio_shader, shader->vert_shader);
+ }
+
+ if (shader->program) {
+ if (shader->shader_interface) {
+ GPU_shaderinterface_discard(shader->shader_interface);
+ }
+ shader->shader_interface = GPU_shaderinterface_create(shader->program);
+ }
+ }
+ }
+
+ /* Update curve mapping texture. */
+ if (use_curve_mapping && shader->curve_mapping_texture_allocated) {
+ if (shader->curve_mapping_cache_id != curve_mapping_settings->cache_id) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
+ glTexSubImage1D(GL_TEXTURE_1D,
+ 0,
+ 0,
+ curve_mapping_settings->lut_size,
+ GL_RGBA,
+ GL_FLOAT,
+ curve_mapping_settings->lut);
+ }
+ }
+
+ /* Bind Shader. */
+ if (shader->program) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_3D, shader->lut3d_texture);
+
+ if (use_curve_mapping) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, shader->curve_mapping_texture);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+
+ /* IMM needs vertex format even if we don't draw with it.
+ *
+ * NOTE: The only reason why it's here is because of Cycles viewport.
+ * All other areas are managing their own vertex formats.
+ * Doing it here is probably harmless, but kind of stupid.
+ *
+ * TODO(sergey): Look into some nicer solution.
+ */
+ GPUVertFormat *format = immVertexFormat();
+ GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindProgram(shader->program, shader->shader_interface);
+
+ immUniform1i("image_texture", 0);
+ immUniform1i("lut3d_texture", 1);
+
+ if (use_dither) {
+ immUniform1f("dither", dither);
+ }
+
+ if (use_curve_mapping) {
+ immUniform1i("curve_mapping_texture", 2);
+ immUniform1i("curve_mapping_lut_size", curve_mapping_settings->lut_size);
+ immUniform4iv("use_curve_mapping_extend_extrapolate",
+ curve_mapping_settings->use_extend_extrapolate);
+ immUniform4fv("curve_mapping_mintable", curve_mapping_settings->mintable);
+ immUniform4fv("curve_mapping_range", curve_mapping_settings->range);
+ immUniform4fv("curve_mapping_ext_in_x", curve_mapping_settings->ext_in_x);
+ immUniform4fv("curve_mapping_ext_in_y", curve_mapping_settings->ext_in_y);
+ immUniform4fv("curve_mapping_ext_out_x", curve_mapping_settings->ext_out_x);
+ immUniform4fv("curve_mapping_ext_out_y", curve_mapping_settings->ext_out_y);
+ immUniform4fv("curve_mapping_first_x", curve_mapping_settings->first_x);
+ immUniform4fv("curve_mapping_first_y", curve_mapping_settings->first_y);
+ immUniform4fv("curve_mapping_last_x", curve_mapping_settings->last_x);
+ immUniform4fv("curve_mapping_last_y", curve_mapping_settings->last_y);
+ immUniform3fv("curve_mapping_black", curve_mapping_settings->black);
+ immUniform3fv("curve_mapping_bwmul", curve_mapping_settings->bwmul);
+ }
+
+ return true;
+ }
+ else {
+ glActiveTexture(state->last_texture_unit);
+ glBindTexture(GL_TEXTURE_2D, state->last_texture);
+
+ return false;
+ }
}
void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state)
{
- glActiveTexture(state->last_texture_unit);
- glBindTexture(GL_TEXTURE_2D, state->last_texture);
- immUnbindProgram();
+ glActiveTexture(state->last_texture_unit);
+ glBindTexture(GL_TEXTURE_2D, state->last_texture);
+ immUnbindProgram();
}
void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state)
{
- for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
- if (state->shader_cache[i]) {
- freeGLSLShader(state->shader_cache[i]);
- }
- }
+ for (int i = 0; i < SHADER_CACHE_SIZE; i++) {
+ if (state->shader_cache[i]) {
+ freeGLSLShader(state->shader_cache[i]);
+ }
+ }
- MEM_freeN(state);
+ MEM_freeN(state);
}