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:
-rw-r--r--SConstruct1
-rw-r--r--intern/opencolorio/CMakeLists.txt2
-rw-r--r--intern/opencolorio/SConscript7
-rw-r--r--intern/opencolorio/fallback_impl.cc3
-rw-r--r--intern/opencolorio/gpu_shader_display_transform.glsl123
-rw-r--r--intern/opencolorio/ocio_capi.cc5
-rw-r--r--intern/opencolorio/ocio_capi.h59
-rw-r--r--intern/opencolorio/ocio_impl.h9
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc164
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/screen/glutil.c9
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h9
-rw-r--r--source/blender/imbuf/intern/colormanagement.c119
-rw-r--r--source/blender/makesrna/intern/rna_render.c4
14 files changed, 428 insertions, 88 deletions
diff --git a/SConstruct b/SConstruct
index 539414d6fba..f9fa289a2b0 100644
--- a/SConstruct
+++ b/SConstruct
@@ -552,6 +552,7 @@ if B.targets != ['cudakernels']:
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
+ data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
# --- blender ---
data_to_c_simple("release/datafiles/bfont.pfb")
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
index 30a74baa646..3a139dc64cf 100644
--- a/intern/opencolorio/CMakeLists.txt
+++ b/intern/opencolorio/CMakeLists.txt
@@ -62,6 +62,8 @@ if(WITH_OPENCOLORIO)
${BOOST_INCLUDE_DIR}
)
endif()
+
+ data_to_c_simple(gpu_shader_display_transform.glsl SRC)
endif()
diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript
index 7f050f25cae..70aa9000719 100644
--- a/intern/opencolorio/SConscript
+++ b/intern/opencolorio/SConscript
@@ -39,6 +39,13 @@ if env['WITH_BF_OCIO']:
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ' + env['BF_BOOST_INC']
+
+ # generated data files
+ import os
+ sources.extend((
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_display_transform.glsl.c"),
+ ))
+
else:
sources.remove('ocio_impl.cc')
sources.remove('ocio_impl_glsl.cc')
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 36dac689287..ca999eab569 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -418,7 +418,8 @@ bool FallbackImpl::supportGLSLDraw(void)
return false;
}
-bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/, bool /*predivide*/)
+bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/,
+ OCIO_CurveMappingSettings * /*curve_mapping_settings*/, bool /*predivide*/)
{
return false;
}
diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
new file mode 100644
index 00000000000..6ba3fa55e8f
--- /dev/null
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -0,0 +1,123 @@
+uniform sampler2D image_texture;
+uniform sampler3D lut3d_texture;
+uniform bool predivide;
+
+#ifdef USE_CURVE_MAPPING
+/* Curve mapping parameters
+ *
+ * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
+ * (this ones pretyt much copies stuff from C structure.)
+ */
+uniform sampler1D curve_mapping_texture;
+uniform int curve_mapping_lut_size;
+uniform ivec4 use_curve_mapping_extend_extrapolate;
+uniform vec4 curve_mapping_mintable;
+uniform vec4 curve_mapping_range;
+uniform vec4 curve_mapping_ext_in_x;
+uniform vec4 curve_mapping_ext_in_y;
+uniform vec4 curve_mapping_ext_out_x;
+uniform vec4 curve_mapping_ext_out_y;
+uniform vec4 curve_mapping_first_x;
+uniform vec4 curve_mapping_first_y;
+uniform vec4 curve_mapping_last_x;
+uniform vec4 curve_mapping_last_y;
+uniform vec3 curve_mapping_black;
+uniform vec3 curve_mapping_bwmul;
+
+float read_curve_mapping(int table, int index)
+{
+ /* TODO(sergey): Without -1 here image is getting darken after applying unite curve.
+ * But is it actually correct to subtract 1 here?
+ */
+ float texture_index = float(index) / float(curve_mapping_lut_size - 1);
+ return texture1D(curve_mapping_texture, texture_index) [table];
+}
+
+float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
+{
+ if (x <= first[0]) {
+ if (use_curve_mapping_extend_extrapolate[table] == 0) {
+ /* no extrapolate */
+ return first[1];
+ }
+ else {
+ if (curve_mapping_ext_in_x[table] == 0.0)
+ return first[1] + curve_mapping_ext_in_y[table] * 10000.0;
+ else
+ return first[1] + curve_mapping_ext_in_y[table] * (x - first[0]) / curve_mapping_ext_in_x[table];
+ }
+ }
+ else if (x >= last[0]) {
+ if (use_curve_mapping_extend_extrapolate[table] == 0) {
+ /* no extrapolate */
+ return last[1];
+ }
+ else {
+ if (curve_mapping_ext_out_x[table] == 0.0)
+ return last[1] - curve_mapping_ext_out_y[table] * 10000.0;
+ else
+ return last[1] + curve_mapping_ext_out_y[table] * (x - last[0]) / curve_mapping_ext_out_x[table];
+ }
+ }
+ return 0.0;
+}
+
+float curvemap_evaluateF(int table, float value)
+{
+ float mintable_ = curve_mapping_mintable[table];
+ float range = curve_mapping_range[table];
+ float mintable = 0.0;
+ int CM_TABLE = curve_mapping_lut_size - 1;
+
+ float fi;
+ int i;
+
+ /* index in table */
+ fi = (value - mintable) * range;
+ i = int(fi);
+
+ /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */
+ if (fi < 0.0 || fi > float(CM_TABLE)) {
+ return curvemap_calc_extend(table, value,
+ vec2(curve_mapping_first_x[table], curve_mapping_first_y[table]),
+ vec2(curve_mapping_last_x[table], curve_mapping_last_y[table]));
+ }
+ else {
+ if (i < 0) return read_curve_mapping(table, 0);
+ if (i >= CM_TABLE) return read_curve_mapping(table, CM_TABLE);
+
+ fi = fi - float(i);
+ return (1.0 - fi) * read_curve_mapping(table, i) + fi * read_curve_mapping(table, i + 1);
+ }
+}
+
+vec4 curvemapping_evaluate_premulRGBF(vec4 col)
+{
+ vec4 result = col;
+ result[0] = curvemap_evaluateF(0, (col[0] - curve_mapping_black[0]) * curve_mapping_bwmul[0]);
+ result[1] = curvemap_evaluateF(1, (col[1] - curve_mapping_black[1]) * curve_mapping_bwmul[1]);
+ result[2] = curvemap_evaluateF(2, (col[2] - curve_mapping_black[2]) * curve_mapping_bwmul[2]);
+ result[3] = col[3];
+ return result;
+}
+#endif
+
+void main()
+{
+ vec4 col = texture2D(image_texture, gl_TexCoord[0].st);
+#ifdef USE_CURVE_MAPPING
+ col = curvemapping_evaluate_premulRGBF(col);
+#endif
+ if (predivide && col[3] > 0.0 && col[3] < 1.0) {
+ float inv_alpha = 1.0 / col[3];
+ col[0] *= inv_alpha;
+ col[1] *= inv_alpha;
+ col[2] *= inv_alpha;
+ }
+
+ /* NOTE: This is true we only do de-premul here and NO premul
+ * and the reason is simple -- opengl is always configured
+ * for straight alpha at this moment
+ */
+ gl_FragColor = OCIODisplay(col, lut3d_texture);
+}
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 1656ad9cbc0..30668dff245 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -323,9 +323,10 @@ int OCIO_supportGLSLDraw(void)
return (int) impl->supportGLSLDraw();
}
-int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide)
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
{
- return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide);
+ return (int) impl->setupGLSLDraw(state_r, processor, curve_mapping_settings, predivide);
}
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 0846b8ff7b3..5532ade1f3a 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -54,6 +54,62 @@ OCIO_DECLARE_HANDLE(OCIO_ExponentTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr);
+/* This structure is used to pass curve mapping settings from
+ * blender's DNA structure stored in view transform settings
+ * to a generic OpenColorIO C-API.
+ */
+typedef struct OCIO_CurveMappingSettings {
+ /* This is a LUT which contain values for all 4 curve mapping tables
+ * (combined, R, G and B).
+ *
+ * Element I for table T is stored at I * 4 + T element of this LUT.
+ *
+ * This array is usually returned by curvemapping_table_RGBA().
+ */
+ float *lut;
+
+ /* Size of single curve mapping table, 1/4 size of lut array. */
+ int lut_size;
+
+ /* Extend extrapolation flags for all the tables.
+ * if use_extend_extrapolate[T] != 0 means extrapolation for
+ * table T is needed.
+ */
+ int use_extend_extrapolate[4];
+
+ /* Minimal X value of the curve mapping tables. */
+ float mintable[4];
+
+ /* Per curve mapping table range. */
+ float range[4];
+
+ /* Lower extension value, stored as per-component arrays. */
+ float ext_in_x[4], ext_in_y[4];
+
+ /* Higher extension value, stored as per-component arrays. */
+ float ext_out_x[4], ext_out_y[4];
+
+ /* First points of the tables, both X and Y values.
+ * Needed for easier and faster access when extrapolating.
+ */
+ float first_x[4], first_y[4];
+
+ /* Last points of the tables, both X and Y values.
+ * Needed for easier and faster access when extrapolating.
+ */
+ float last_x[4], last_y[4];
+
+ /* Premultiplication settings: black level and scale to match
+ * with white level.
+ */
+ float black[3], bwmul[3];
+
+ /* Cache id of the original curve mapping, used to detect when
+ * upload of new settings to GPU is needed.
+ */
+ size_t cache_id;
+} OCIO_CurveMappingSettings;
+
void OCIO_init(void);
void OCIO_exit(void);
@@ -132,7 +188,8 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt);
void OCIO_matrixTransformScale(float *m44, float *offset4, const float *scale4);
int OCIO_supportGLSLDraw(void);
-int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide);
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 48d18fa78ea..8b666e8ae14 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -106,7 +106,8 @@ public:
virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0;
virtual bool supportGLSLDraw(void) = 0;
- virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) = 0;
+ virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide) = 0;
virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
};
@@ -189,7 +190,8 @@ public:
void matrixTransformScale(float *m44, float *offset4, const float *scale4);
bool supportGLSLDraw(void);
- bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide);
+ bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
};
@@ -273,7 +275,8 @@ public:
void matrixTransformScale(float * m44, float * offset4, const float * scale4);
bool supportGLSLDraw(void);
- bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide);
+ bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
};
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index 1a3132fa4b3..a10afcad200 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -48,6 +48,8 @@ using namespace OCIO_NAMESPACE;
static const int LUT3D_EDGE_SIZE = 64;
+extern char datatoc_gpu_shader_display_transform_glsl[];
+
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
typedef struct OCIO_GLSLDrawState {
@@ -60,42 +62,24 @@ typedef struct OCIO_GLSLDrawState {
float *lut3d; /* 3D LUT table */
+ bool curve_mapping_used;
+ bool curve_mapping_texture_allocated;
+ bool curve_mapping_texture_valid;
+ GLuint curve_mapping_texture;
+ size_t curve_mapping_cache_id;
+
/* Cache */
std::string lut3dcacheid;
std::string shadercacheid;
/* GLSL stuff */
- GLuint fragShader;
+ GLuint ocio_shader;
GLuint program;
/* Previous OpenGL state. */
GLint last_texture, last_texture_unit;
} OCIO_GLSLDrawState;
-/* Hardcoded to do alpha predivide before color space conversion */
-/* NOTE: This is true we only do de-premul here and NO premul
- * and the reason is simple -- opengl is always configured
- * for straight alpha at this moment
- */
-static const char *g_fragShaderText = ""
-"\n"
-"uniform sampler2D tex1;\n"
-"uniform sampler3D tex2;\n"
-"uniform bool predivide;\n"
-"\n"
-"void main()\n"
-"{\n"
-" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
-" if (predivide && col[3] > 0.0 && col[3] < 1.0) {\n"
-" float inv_alpha = 1.0 / col[3];\n"
-" col[0] *= inv_alpha;\n"
-" col[1] *= inv_alpha;\n"
-" col[2] *= inv_alpha;\n"
-" }\n"
-" gl_FragColor = OCIODisplay(col, tex2);\n"
-"\n"
-"}\n";
-
static GLuint compileShaderText(GLenum shaderType, const char *text)
{
GLuint shader;
@@ -117,15 +101,14 @@ static GLuint compileShaderText(GLenum shaderType, const char *text)
return shader;
}
-static GLuint linkShaders(GLuint fragShader)
+static GLuint linkShaders(GLuint ocio_shader)
{
- if (!fragShader)
+ if (!ocio_shader)
return 0;
GLuint program = glCreateProgram();
- if (fragShader)
- glAttachShader(program, fragShader);
+ glAttachShader(program, ocio_shader);
glLinkProgram(program);
@@ -197,6 +180,37 @@ static bool ensureLUT3DAllocated(OCIO_GLSLDrawState *state)
return state->lut3d_texture_valid;
}
+static bool ensureCurveMappingAllocated(OCIO_GLSLDrawState *state, OCIO_CurveMappingSettings *curve_mapping_settings)
+{
+ if (state->curve_mapping_texture_allocated)
+ return state->curve_mapping_texture_valid;
+
+ glGenTextures(1, &state->curve_mapping_texture);
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, state->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_ARB, curve_mapping_settings->lut_size,
+ 0, GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
+
+ state->curve_mapping_texture_allocated = true;
+
+ /* GL_RGB16F_ARB could be not supported at some drivers
+ * in this case we could not use GLSL display
+ */
+ state->curve_mapping_texture_valid = glGetError() == GL_NO_ERROR;
+
+ return state->curve_mapping_texture_valid;
+}
+
/* Detect if we can support GLSL drawing */
bool OCIOImpl::supportGLSLDraw()
{
@@ -214,9 +228,11 @@ 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 predivide)
+bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+ OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
{
ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
+ bool use_curve_mapping = curve_mapping_settings != NULL;
/* Create state if needed. */
OCIO_GLSLDrawState *state;
@@ -234,12 +250,36 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
return false;
}
+ if (use_curve_mapping) {
+ if (!ensureCurveMappingAllocated(state, curve_mapping_settings)) {
+ glActiveTexture(state->last_texture_unit);
+ glBindTexture(GL_TEXTURE_2D, state->last_texture);
+
+ return false;
+ }
+ }
+ else {
+ if (state->curve_mapping_texture_allocated) {
+ glDeleteTextures(1, &state->curve_mapping_texture);
+ state->curve_mapping_texture_allocated = false;
+ }
+ }
+
/* Step 1: Create a GPU Shader Description */
GpuShaderDesc shaderDesc;
shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0);
shaderDesc.setFunctionName("OCIODisplay");
shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
+ if (use_curve_mapping) {
+ if (state->curve_mapping_cache_id != curve_mapping_settings->cache_id) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
+ glTexSubImage1D(GL_TEXTURE_1D, 0, 0, curve_mapping_settings->lut_size,
+ GL_RGBA, GL_FLOAT, curve_mapping_settings->lut);
+ }
+ }
+
/* Step 2: Compute the 3D LUT */
std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc);
if (lut3dCacheID != state->lut3dcacheid) {
@@ -255,37 +295,73 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
/* Step 3: Compute the Shader */
std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
- if (state->program == 0 || shaderCacheID != state->shadercacheid) {
+ if (state->program == 0 ||
+ shaderCacheID != state->shadercacheid ||
+ use_curve_mapping != state->curve_mapping_used)
+ {
state->shadercacheid = shaderCacheID;
+ if (state->program) {
+ glDeleteProgram(state->program);
+ }
+
+ if (state->ocio_shader) {
+ glDeleteShader(state->ocio_shader);
+ }
+
std::ostringstream os;
- os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
- os << g_fragShaderText;
- if (state->fragShader)
- glDeleteShader(state->fragShader);
+ if (use_curve_mapping) {
+ os << "#define USE_CURVE_MAPPING\n";
+ }
- state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
+ os << ocio_processor->getGpuShaderText(shaderDesc) << "\n";
+ os << datatoc_gpu_shader_display_transform_glsl;
- if (state->fragShader) {
- if (state->program)
- glDeleteProgram(state->program);
+ state->ocio_shader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
- state->program = linkShaders(state->fragShader);
+ if (state->ocio_shader) {
+ state->program = linkShaders(state->ocio_shader);
}
+
+ state->curve_mapping_used = use_curve_mapping;
}
if (state->program) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, state->lut3d_texture);
+ if (use_curve_mapping) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_1D, state->curve_mapping_texture);
+ }
+
glActiveTexture(GL_TEXTURE0);
glUseProgram(state->program);
- glUniform1i(glGetUniformLocation(state->program, "tex1"), 0);
- glUniform1i(glGetUniformLocation(state->program, "tex2"), 1);
+
+ glUniform1i(glGetUniformLocation(state->program, "image_texture"), 0);
+ glUniform1i(glGetUniformLocation(state->program, "lut3d_texture"), 1);
glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide);
+ if (use_curve_mapping) {
+ glUniform1i(glGetUniformLocation(state->program, "curve_mapping_texture"), 2);
+ glUniform1i(glGetUniformLocation(state->program, "curve_mapping_lut_size"), curve_mapping_settings->lut_size);
+ glUniform4iv(glGetUniformLocation(state->program, "use_curve_mapping_extend_extrapolate"), 1, curve_mapping_settings->use_extend_extrapolate);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_mintable"), 1, curve_mapping_settings->mintable);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_range"), 1, curve_mapping_settings->range);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_in_x"), 1, curve_mapping_settings->ext_in_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_in_y"), 1, curve_mapping_settings->ext_in_y);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_out_x"), 1, curve_mapping_settings->ext_out_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_ext_out_y"), 1, curve_mapping_settings->ext_out_y);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_first_x"), 1, curve_mapping_settings->first_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_first_y"), 1, curve_mapping_settings->first_y);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_last_x"), 1, curve_mapping_settings->last_x);
+ glUniform4fv(glGetUniformLocation(state->program, "curve_mapping_last_y"), 1, curve_mapping_settings->last_y);
+ glUniform3fv(glGetUniformLocation(state->program, "curve_mapping_black"), 1, curve_mapping_settings->black);
+ glUniform3fv(glGetUniformLocation(state->program, "curve_mapping_bwmul"), 1, curve_mapping_settings->bwmul);
+ }
+
return true;
}
else {
@@ -316,8 +392,8 @@ void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state)
if (state->program)
glDeleteProgram(state->program);
- if (state->fragShader)
- glDeleteShader(state->fragShader);
+ if (state->ocio_shader)
+ glDeleteShader(state->ocio_shader);
state->lut3dcacheid.~string();
state->shadercacheid.~string();
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 39d6f836815..df8d5ec4e84 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1152,7 +1152,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
/* Try using GLSL display transform. */
if (force_fallback == false) {
- if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, true, false)) {
+ if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, true)) {
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 70e5aab6628..b70b06f2aa4 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1091,18 +1091,15 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
if (ibuf->rect_float) {
if (ibuf->float_colorspace) {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->float_colorspace,
- true, false);
+ ibuf->float_colorspace, true);
}
else {
- ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
- true, false);
+ ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, true);
}
}
else {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->rect_colorspace,
- false, false);
+ ibuf->rect_colorspace, false);
}
if (ok) {
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 64a2bbb72d9..8af86389db3 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -174,19 +174,16 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo
/* ** OpenGL drawing routines using GLSL for color space transform ** */
/* Test if GLSL drawing is supported for combination of graphics card and this configuration */
-bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings,
- bool skip_curves);
+bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings);
/* Configures GLSL shader for conversion from scene linear to display space */
bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
- bool predivide,
- bool skip_curves);
+ bool predivide);
/* Same as above, but display space conversion happens from a specified space */
bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
struct ColorSpace *colorspace,
- bool predivide,
- bool skip_curves);
+ bool predivide);
/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, bool predivide);
/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 61051464c7f..cf9cc0c2e6f 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -119,6 +119,11 @@ static struct global_glsl_state {
char input[MAX_COLORSPACE_NAME];
float exposure, gamma;
+ CurveMapping *curve_mapping, *orig_curve_mapping;
+ bool use_curve_mapping;
+ int curve_mapping_timestamp;
+ OCIO_CurveMappingSettings curve_mapping_settings;
+
/* Container for GLSL state needed for OCIO module. */
struct OCIO_GLSLDrawState *ocio_glsl_state;
struct OCIO_GLSLDrawState *transform_ocio_glsl_state;
@@ -663,6 +668,12 @@ void colormanagement_exit(void)
if (global_glsl_state.processor)
OCIO_processorRelease(global_glsl_state.processor);
+ if (global_glsl_state.curve_mapping)
+ curvemapping_free(global_glsl_state.curve_mapping);
+
+ if (global_glsl_state.curve_mapping_settings.lut)
+ MEM_freeN(global_glsl_state.curve_mapping_settings.lut);
+
if (global_glsl_state.ocio_glsl_state)
OCIO_freeOGLState(global_glsl_state.ocio_glsl_state);
@@ -2937,16 +2948,61 @@ static bool check_glsl_display_processor_changed(const ColorManagedViewSettings
STREQ(global_glsl_state.input, from_colorspace));
}
+static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping,
+ OCIO_CurveMappingSettings *curve_mapping_settings)
+{
+ int i;
+
+ curvemapping_initialize(curve_mapping);
+ curvemapping_premultiply(curve_mapping, false);
+ curvemapping_table_RGBA(curve_mapping,
+ &curve_mapping_settings->lut,
+ &curve_mapping_settings->lut_size);
+
+ for (i = 0; i < 4; i++) {
+ CurveMap *cuma = curve_mapping->cm + i;
+ curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != 0;
+ curve_mapping_settings->range[i] = cuma->range;
+ curve_mapping_settings->mintable[i] = cuma->mintable;
+ curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0];
+ curve_mapping_settings->ext_in_y[i] = cuma->ext_in[1];
+ curve_mapping_settings->ext_out_x[i] = cuma->ext_out[0];
+ curve_mapping_settings->ext_out_y[i] = cuma->ext_out[1];
+ curve_mapping_settings->first_x[i] = cuma->table[0].x;
+ curve_mapping_settings->first_y[i] = cuma->table[0].y;
+ curve_mapping_settings->last_x[i] = cuma->table[CM_TABLE].x;
+ curve_mapping_settings->last_y[i] = cuma->table[CM_TABLE].y;
+ }
+
+ copy_v3_v3(curve_mapping_settings->black, curve_mapping->black);
+ copy_v3_v3(curve_mapping_settings->bwmul, curve_mapping->bwmul);
+
+ curve_mapping_settings->cache_id = (size_t) curve_mapping;
+}
+
static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *from_colorspace)
{
+ bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0;
+ bool need_update = false;
+
+ need_update = global_glsl_state.processor == NULL ||
+ check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace) ||
+ use_curve_mapping != global_glsl_state.use_curve_mapping;
+
+ if (use_curve_mapping && need_update == false) {
+ need_update |= view_settings->curve_mapping->changed_timestamp != global_glsl_state.curve_mapping_timestamp ||
+ view_settings->curve_mapping != global_glsl_state.orig_curve_mapping;
+ }
+
/* Update state if there's no processor yet or
* processor settings has been changed.
*/
- if (global_glsl_state.processor == NULL ||
- check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace))
- {
+ if (need_update) {
+ OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings;
+ CurveMapping *new_curve_mapping = NULL;
+
/* Store settings of processor for further comparison. */
BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME);
@@ -2955,6 +3011,35 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
global_glsl_state.exposure = view_settings->exposure;
global_glsl_state.gamma = view_settings->gamma;
+ /* We're using curve mapping's address as a acache ID,
+ * so we need to make sure re-allocation gives new address here.
+ * We do this by allocating new curve mapping before freeing ol one.
+ */
+ if (use_curve_mapping) {
+ new_curve_mapping = curvemapping_copy(view_settings->curve_mapping);
+ }
+
+ if (global_glsl_state.curve_mapping) {
+ curvemapping_free(global_glsl_state.curve_mapping);
+ MEM_freeN(curve_mapping_settings->lut);
+ global_glsl_state.curve_mapping = NULL;
+ curve_mapping_settings->lut = NULL;
+ }
+
+ /* Fill in OCIO's curve mapping settings. */
+ if (use_curve_mapping) {
+ curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings);
+
+ global_glsl_state.curve_mapping = new_curve_mapping;
+ global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp;
+ global_glsl_state.orig_curve_mapping = view_settings->curve_mapping;
+ global_glsl_state.use_curve_mapping = true;
+ }
+ else {
+ global_glsl_state.orig_curve_mapping = NULL;
+ global_glsl_state.use_curve_mapping = false;
+ }
+
/* Free old processor, if any. */
if (global_glsl_state.processor)
OCIO_processorRelease(global_glsl_state.processor);
@@ -2970,14 +3055,8 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
}
}
-bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_settings,
- bool skip_curves)
+bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings))
{
- /* curves not supported yet */
- if (!skip_curves)
- if (view_settings && (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES))
- return 0;
-
return OCIO_supportGLSLDraw();
}
@@ -2996,8 +3075,7 @@ bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_
*/
bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
- struct ColorSpace *from_colorspace, bool predivide,
- bool skip_curves)
+ struct ColorSpace *from_colorspace, bool predivide)
{
ColorManagedViewSettings default_view_settings;
const ColorManagedViewSettings *applied_view_settings;
@@ -3014,25 +3092,22 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettin
applied_view_settings = &default_view_settings;
}
- /* RGB curves mapping is not supported on GPU yet. */
- if (!skip_curves)
- if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
- return false;
-
/* Make sure OCIO processor is up-to-date. */
update_glsl_display_processor(applied_view_settings, display_settings,
from_colorspace ? from_colorspace->name : global_role_scene_linear);
- return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, predivide);
+ return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor,
+ global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL,
+ predivide);
}
/* Configures GLSL shader for conversion from scene linear to display space */
bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
- bool predivide, bool skip_curves)
+ bool predivide)
{
return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- NULL, predivide, skip_curves);
+ NULL, predivide);
}
/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
@@ -3043,7 +3118,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
- return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide, false);
+ return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide);
}
/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
@@ -3082,7 +3157,7 @@ bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide
processor = colorspace_to_scene_linear_processor(colorspace);
- return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, predivide);
+ return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, NULL, predivide);
}
/* Finish GLSL-based color space conversion */
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 5b809a51705..7ebbcf7b39b 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -66,14 +66,14 @@ static void engine_tag_update(RenderEngine *engine)
static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
{
- return IMB_colormanagement_support_glsl_draw(&scene->view_settings, true);
+ return IMB_colormanagement_support_glsl_draw(&scene->view_settings);
}
static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
{
IMB_colormanagement_setup_glsl_draw(&scene->view_settings,
&scene->display_settings,
- false, true);
+ false);
}
static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine))