diff options
Diffstat (limited to 'intern/opencolorio')
-rw-r--r-- | intern/opencolorio/fallback_impl.cc | 366 | ||||
-rw-r--r-- | intern/opencolorio/gpu_shader_display_transform.glsl | 42 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.cc | 205 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.h | 90 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.cc | 361 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.h | 247 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl_glsl.cc | 787 |
7 files changed, 881 insertions, 1217 deletions
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index a6b93ac4959..9bbc9843e9d 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -34,7 +34,7 @@ using std::max; enum TransformType { TRANSFORM_LINEAR_TO_SRGB, TRANSFORM_SRGB_TO_LINEAR, - TRANSFORM_MATRIX, + TRANSFORM_SCALE, TRANSFORM_EXPONENT, TRANSFORM_UNKNOWN, }; @@ -53,147 +53,72 @@ typedef struct OCIO_PackedImageDescription { } OCIO_PackedImageDescription; struct FallbackTransform { - FallbackTransform() : type(TRANSFORM_UNKNOWN), linear_transform(NULL), display_transform(NULL) + FallbackTransform() : type(TRANSFORM_UNKNOWN), scale(1.0f), exponent(1.0f) { } virtual ~FallbackTransform() { - delete linear_transform; - delete display_transform; } void applyRGB(float *pixel) { if (type == TRANSFORM_LINEAR_TO_SRGB) { - applyLinearRGB(pixel); + pixel[0] *= scale; + pixel[1] *= scale; + pixel[2] *= scale; + linearrgb_to_srgb_v3_v3(pixel, pixel); - applyDisplayRGB(pixel); + + pixel[0] = powf(max(0.0f, pixel[0]), exponent); + pixel[1] = powf(max(0.0f, pixel[1]), exponent); + pixel[2] = powf(max(0.0f, pixel[2]), exponent); } else if (type == TRANSFORM_SRGB_TO_LINEAR) { srgb_to_linearrgb_v3_v3(pixel, pixel); } else if (type == TRANSFORM_EXPONENT) { - pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]); - pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]); - pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]); + pixel[0] = powf(max(0.0f, pixel[0]), exponent); + pixel[1] = powf(max(0.0f, pixel[1]), exponent); + pixel[2] = powf(max(0.0f, pixel[2]), exponent); } - else if (type == TRANSFORM_MATRIX) { - float r = pixel[0]; - float g = pixel[1]; - float b = pixel[2]; - pixel[0] = r * matrix[0] + g * matrix[1] + b * matrix[2]; - pixel[1] = r * matrix[4] + g * matrix[5] + b * matrix[6]; - pixel[2] = r * matrix[8] + g * matrix[9] + b * matrix[10]; - pixel[0] += offset[0]; - pixel[1] += offset[1]; - pixel[2] += offset[2]; + else if (type == TRANSFORM_SCALE) { + pixel[0] *= scale; + pixel[1] *= scale; + pixel[2] *= scale; } } void applyRGBA(float *pixel) { - if (type == TRANSFORM_LINEAR_TO_SRGB) { - applyLinearRGBA(pixel); - linearrgb_to_srgb_v4(pixel, pixel); - applyDisplayRGBA(pixel); - } - else if (type == TRANSFORM_SRGB_TO_LINEAR) { - srgb_to_linearrgb_v4(pixel, pixel); - } - else if (type == TRANSFORM_EXPONENT) { - pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]); - pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]); - pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]); - pixel[3] = powf(max(0.0f, pixel[3]), exponent[3]); - } - else if (type == TRANSFORM_MATRIX) { - float r = pixel[0]; - float g = pixel[1]; - float b = pixel[2]; - float a = pixel[3]; - pixel[0] = r * matrix[0] + g * matrix[1] + b * matrix[2] + a * matrix[3]; - pixel[1] = r * matrix[4] + g * matrix[5] + b * matrix[6] + a * matrix[7]; - pixel[2] = r * matrix[8] + g * matrix[9] + b * matrix[10] + a * matrix[11]; - pixel[3] = r * matrix[12] + g * matrix[13] + b * matrix[14] + a * matrix[15]; - pixel[0] += offset[0]; - pixel[1] += offset[1]; - pixel[2] += offset[2]; - pixel[3] += offset[3]; - } - } - - void applyLinearRGB(float *pixel) - { - if (linear_transform != NULL) { - linear_transform->applyRGB(pixel); - } - } - - void applyLinearRGBA(float *pixel) - { - if (linear_transform != NULL) { - linear_transform->applyRGBA(pixel); - } - } - - void applyDisplayRGB(float *pixel) - { - if (display_transform != NULL) { - display_transform->applyRGB(pixel); - } - } - - void applyDisplayRGBA(float *pixel) - { - if (display_transform != NULL) { - display_transform->applyRGBA(pixel); - } + applyRGB(pixel); } TransformType type; - FallbackTransform *linear_transform; - FallbackTransform *display_transform; + /* Scale transform. */ + float scale; /* Exponent transform. */ - float exponent[4]; - /* Matrix transform. */ - float matrix[16]; - float offset[4]; + float exponent; MEM_CXX_CLASS_ALLOC_FUNCS("FallbackTransform"); }; -struct FallbackGroupTransform : FallbackTransform { - ~FallbackGroupTransform() - { - for (auto transform : list) { - delete transform; - } - } - std::vector<FallbackTransform *> list; -}; - struct FallbackProcessor { - FallbackProcessor() : transform(NULL) + FallbackProcessor(const FallbackTransform &transform) : transform(transform) { } - ~FallbackProcessor() - { - delete transform; - } - void applyRGB(float *pixel) { - transform->applyRGB(pixel); + transform.applyRGB(pixel); } void applyRGBA(float *pixel) { - transform->applyRGBA(pixel); + transform.applyRGBA(pixel); } - FallbackTransform *transform; + FallbackTransform transform; MEM_CXX_CLASS_ALLOC_FUNCS("FallbackProcessor"); }; @@ -403,30 +328,35 @@ OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstCo { OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName); OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName); - FallbackTransform *transform = new FallbackTransform(); + FallbackTransform transform; if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) { - transform->type = TRANSFORM_LINEAR_TO_SRGB; + transform.type = TRANSFORM_LINEAR_TO_SRGB; } else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) { - transform->type = TRANSFORM_SRGB_TO_LINEAR; + transform.type = TRANSFORM_SRGB_TO_LINEAR; } else { - transform->type = TRANSFORM_UNKNOWN; + transform.type = TRANSFORM_UNKNOWN; } - FallbackProcessor *processor = new FallbackProcessor(); - processor->transform = transform; - return (OCIO_ConstProcessorRcPtr *)processor; + return (OCIO_ConstProcessorRcPtr *)new FallbackProcessor(transform); +} + +OCIO_ConstCPUProcessorRcPtr *FallbackImpl::processorGetCPUProcessor( + OCIO_ConstProcessorRcPtr *processor) +{ + /* Just make a copy of the processor so that we are compatible with OCIO + * which does need it as a separate object. */ + FallbackProcessor *fallback_processor = (FallbackProcessor *)processor; + return (OCIO_ConstCPUProcessorRcPtr *)new FallbackProcessor(*fallback_processor); } -OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/, - OCIO_ConstTransformRcPtr *transform) +void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor) { - FallbackProcessor *processor = new FallbackProcessor(); - processor->transform = (FallbackTransform *)transform; - return (OCIO_ConstProcessorRcPtr *)processor; + delete (FallbackProcessor *)(processor); } -void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +void FallbackImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img) { /* OCIO_TODO stride not respected, channels must be 3 or 4 */ OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img; @@ -441,15 +371,15 @@ void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_Pack float *pixel = pixels + channels * (y * width + x); if (channels == 4) - processorApplyRGBA(processor, pixel); + cpuProcessorApplyRGBA(cpu_processor, pixel); else if (channels == 3) - processorApplyRGB(processor, pixel); + cpuProcessorApplyRGB(cpu_processor, pixel); } } } -void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, - OCIO_PackedImageDesc *img) +void FallbackImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img) { /* OCIO_TODO stride not respected, channels must be 3 or 4 */ OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img; @@ -464,27 +394,28 @@ void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel = pixels + channels * (y * width + x); if (channels == 4) - processorApplyRGBA_predivide(processor, pixel); + cpuProcessorApplyRGBA_predivide(cpu_processor, pixel); else if (channels == 3) - processorApplyRGB(processor, pixel); + cpuProcessorApplyRGB(cpu_processor, pixel); } } } -void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void FallbackImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) { - ((FallbackProcessor *)processor)->applyRGB(pixel); + ((FallbackProcessor *)cpu_processor)->applyRGB(pixel); } -void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void FallbackImpl::cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) { - ((FallbackProcessor *)processor)->applyRGBA(pixel); + ((FallbackProcessor *)cpu_processor)->applyRGBA(pixel); } -void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void FallbackImpl::cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + float *pixel) { if (pixel[3] == 1.0f || pixel[3] == 0.0f) { - processorApplyRGBA(processor, pixel); + cpuProcessorApplyRGBA(cpu_processor, pixel); } else { float alpha, inv_alpha; @@ -496,7 +427,7 @@ void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *proces pixel[1] *= inv_alpha; pixel[2] *= inv_alpha; - processorApplyRGBA(processor, pixel); + cpuProcessorApplyRGBA(cpu_processor, pixel); pixel[0] *= alpha; pixel[1] *= alpha; @@ -504,9 +435,9 @@ void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *proces } } -void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor) +void FallbackImpl::cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor) { - delete (FallbackProcessor *)(processor); + delete (FallbackProcessor *)(cpu_processor); } const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) @@ -530,54 +461,20 @@ const char *FallbackImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr * /*cs*/ return ""; } -OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void) -{ - FallbackTransform *transform = new FallbackTransform(); - transform->type = TRANSFORM_LINEAR_TO_SRGB; - return (OCIO_DisplayTransformRcPtr *)transform; -} - -void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/, - const char * /*name*/) -{ -} - -void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr * /*dt*/, - const char * /*name*/) -{ -} - -void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr * /*dt*/, - const char * /*name*/) -{ -} - -void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *et) -{ - FallbackTransform *transform = (FallbackTransform *)dt; - transform->display_transform = (FallbackTransform *)et; -} - -void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *et) -{ - FallbackTransform *transform = (FallbackTransform *)dt; - transform->linear_transform = (FallbackTransform *)et; -} - -void FallbackImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr * /*dt*/, - const char * /*looks*/) -{ -} - -void FallbackImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr * /*dt*/, - bool /*enabled*/) +OCIO_ConstProcessorRcPtr *FallbackImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr * /*config*/, + const char * /*input*/, + const char * /*view*/, + const char * /*display*/, + const char * /*look*/, + const float scale, + const float exponent) { -} + FallbackTransform transform; + transform.type = TRANSFORM_LINEAR_TO_SRGB; + transform.scale = scale; + transform.exponent = exponent; -void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr * /*dt*/) -{ + return (OCIO_ConstProcessorRcPtr *)new FallbackProcessor(transform); } OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, @@ -605,127 +502,6 @@ void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id) MEM_freeN(id); } -OCIO_GroupTransformRcPtr *FallbackImpl::createGroupTransform(void) -{ - FallbackTransform *transform = new FallbackGroupTransform(); - transform->type = TRANSFORM_UNKNOWN; - return (OCIO_GroupTransformRcPtr *)transform; -} - -void FallbackImpl::groupTransformSetDirection(OCIO_GroupTransformRcPtr * /*gt*/, - const bool /*forward */) -{ -} - -void FallbackImpl::groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, - OCIO_ConstTransformRcPtr *transform) -{ - FallbackGroupTransform *group = (FallbackGroupTransform *)gt; - group->list.push_back((FallbackTransform *)transform); -} - -void FallbackImpl::groupTransformRelease(OCIO_GroupTransformRcPtr * /*gt*/) -{ -} - -OCIO_ColorSpaceTransformRcPtr *FallbackImpl::createColorSpaceTransform(void) -{ - FallbackTransform *transform = new FallbackTransform(); - transform->type = TRANSFORM_UNKNOWN; - return (OCIO_ColorSpaceTransformRcPtr *)transform; -} - -void FallbackImpl::colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr * /*ct*/, - const char * /*name*/) -{ -} - -void FallbackImpl::colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr * /*ct*/) -{ -} - -OCIO_ExponentTransformRcPtr *FallbackImpl::createExponentTransform(void) -{ - FallbackTransform *transform = new FallbackTransform(); - transform->type = TRANSFORM_EXPONENT; - return (OCIO_ExponentTransformRcPtr *)transform; -} - -void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, - const float *exponent) -{ - FallbackTransform *transform = (FallbackTransform *)et; - copy_v4_v4(transform->exponent, exponent); -} - -void FallbackImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr * /*et*/) -{ -} - -OCIO_MatrixTransformRcPtr *FallbackImpl::createMatrixTransform(void) -{ - FallbackTransform *transform = new FallbackTransform(); - transform->type = TRANSFORM_MATRIX; - return (OCIO_MatrixTransformRcPtr *)transform; -} - -void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4) -{ - FallbackTransform *transform = (FallbackTransform *)mt; - copy_m4_m4((float(*)[4])transform->matrix, (float(*)[4])m44); - copy_v4_v4(transform->offset, offset4); -} - -void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr * /*mt*/) -{ -} - -void FallbackImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4) -{ - if (scale4 == NULL) { - return; - } - if (m44 != NULL) { - memset(m44, 0, 16 * sizeof(float)); - m44[0] = scale4[0]; - m44[5] = scale4[1]; - m44[10] = scale4[2]; - m44[15] = scale4[3]; - } - if (offset4 != NULL) { - offset4[0] = 0.0f; - offset4[1] = 0.0f; - offset4[2] = 0.0f; - offset4[3] = 0.0f; - } -} - -bool FallbackImpl::supportGLSLDraw(void) -{ - return false; -} - -bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, - OCIO_ConstProcessorRcPtr * /*ocio_processor_scene_to_ui*/, - OCIO_ConstProcessorRcPtr * /*ocio_processor_ui_to_display*/, - OCIO_CurveMappingSettings * /*curve_mapping_settings*/, - float /*dither*/, - bool /*predivide*/, - bool /*overlay*/) -{ - return false; -} - -void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/) -{ -} - -void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState * /*state_r*/) -{ -} - const char *FallbackImpl::getVersionString(void) { return "fallback"; diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl index 61da755f02f..ca0d2566ed1 100644 --- a/intern/opencolorio/gpu_shader_display_transform.glsl +++ b/intern/opencolorio/gpu_shader_display_transform.glsl @@ -1,17 +1,18 @@ /* Blender OpenColorIO implementation */ -uniform sampler1D curve_mapping_texture; uniform sampler2D image_texture; uniform sampler2D overlay_texture; -uniform sampler3D lut3d_texture; -uniform sampler3D lut3d_display_texture; uniform float dither; +uniform float scale; +uniform float exponent; uniform bool predivide; -uniform bool curve_mapping; uniform bool overlay; -layout(std140) uniform OCIO_GLSLCurveMappingParameters +#ifdef USE_CURVE_MAPPING +uniform sampler1D curve_mapping_texture; + +layout(std140) uniform OCIO_GPUCurveMappingParameters { /* Curve mapping parameters * @@ -114,6 +115,7 @@ vec4 curvemapping_evaluate_premulRGBF(vec4 col) result.a = col.a; return result; } +#endif /* USE_CURVE_MAPPING */ /* Using a triangle distribution which gives a more final uniform noise. * See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */ @@ -145,9 +147,9 @@ vec4 apply_dither(vec4 col, vec2 uv) vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv) { - if (curve_mapping) { - col = curvemapping_evaluate_premulRGBF(col); - } +#ifdef USE_CURVE_MAPPING + col = curvemapping_evaluate_premulRGBF(col); +#endif if (predivide) { if (col.a > 0.0 && col.a < 1.0) { @@ -160,15 +162,31 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv) * for straight alpha at this moment */ - col = OCIO_to_display_linear_with_look(col, lut3d_texture); + /* Convert to scene linear (usually a no-op). */ + col = OCIO_to_scene_linear(col); + + /* Apply exposure in scene linear. */ + col.rgb *= scale; + + /* Convert to display space. */ + col = OCIO_to_display(col); + /* Blend with overlay in UI colorspace. + * + * UI colorspace here refers to the display linear color space, + * i.e: The linear color space w.r.t. display chromaticity and radiometry. + * We separate the colormanagement process into two steps to be able to + * merge UI using alpha blending in the correct color space. */ if (overlay) { + col.rgb = pow(col.rgb, vec3(exponent * 2.2)); col = clamp(col, 0.0, 1.0); col *= 1.0 - col_overlay.a; col += col_overlay; /* Assumed unassociated alpha. */ + col.rgb = pow(col.rgb, vec3(1.0 / 2.2)); + } + else { + col.rgb = pow(col.rgb, vec3(exponent)); } - - col = OCIO_to_display_encoded(col, lut3d_display_texture); if (dither > 0.0) { col = apply_dither(col, noise_uv); @@ -189,4 +207,4 @@ void main() vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st); fragColor = OCIO_ProcessColor(col, col_overlay, noise_uv); -}
\ No newline at end of file +} diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index 84c36de364c..a7416f82b91 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -194,40 +194,45 @@ OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr return impl->configGetProcessorWithNames(config, srcName, dstName); } -OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config, - OCIO_ConstTransformRcPtr *transform) +void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *processor) { - return impl->configGetProcessor(config, transform); + impl->processorRelease(processor); } -void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor) { - impl->processorApply(processor, img); + return impl->processorGetCPUProcessor(processor); } -void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img) { - impl->processorApply_predivide(processor, img); + impl->cpuProcessorApply(cpu_processor, img); } -void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void OCIO_cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img) { - impl->processorApplyRGB(processor, pixel); + impl->cpuProcessorApply_predivide(cpu_processor, img); } -void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void OCIO_cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) { - impl->processorApplyRGBA(processor, pixel); + impl->cpuProcessorApplyRGB(cpu_processor, pixel); } -void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void OCIO_cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) { - impl->processorApplyRGBA_predivide(processor, pixel); + impl->cpuProcessorApplyRGBA(cpu_processor, pixel); } -void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p) +void OCIO_cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *processor, float *pixel) { - impl->processorRelease(p); + impl->cpuProcessorApplyRGBA_predivide(processor, pixel); +} + +void OCIO_cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor) +{ + impl->cpuProcessorRelease(cpu_processor); } const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) @@ -245,49 +250,15 @@ const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) return impl->colorSpaceGetFamily(cs); } -OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void) -{ - return impl->createDisplayTransform(); -} - -void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name) -{ - impl->displayTransformSetInputColorSpaceName(dt, name); -} - -void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) -{ - impl->displayTransformSetDisplay(dt, name); -} - -void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) -{ - impl->displayTransformSetView(dt, name); -} - -void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t) -{ - impl->displayTransformSetDisplayCC(dt, t); -} - -void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t) +OCIO_ConstProcessorRcPtr *OCIO_createDisplayProcessor(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + const float scale, + const float exponent) { - impl->displayTransformSetLinearCC(dt, t); -} - -void OCIO_displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks) -{ - impl->displayTransformSetLooksOverride(dt, looks); -} - -void OCIO_displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled) -{ - impl->displayTransformSetLooksOverrideEnabled(dt, enabled); -} - -void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) -{ - impl->displayTransformRelease(dt); + return impl->createDisplayProcessor(config, input, view, display, look, scale, exponent); } OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, @@ -307,108 +278,44 @@ void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id) impl->OCIO_PackedImageDescRelease(id); } -OCIO_GroupTransformRcPtr *OCIO_createGroupTransform(void) -{ - return impl->createGroupTransform(); -} - -void OCIO_groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward) -{ - impl->groupTransformSetDirection(gt, forward); -} - -void OCIO_groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr) -{ - impl->groupTransformPushBack(gt, tr); -} - -void OCIO_groupTransformRelease(OCIO_GroupTransformRcPtr *gt) -{ - impl->groupTransformRelease(gt); -} - -OCIO_ColorSpaceTransformRcPtr *OCIO_createColorSpaceTransform(void) -{ - return impl->createColorSpaceTransform(); -} - -void OCIO_colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name) -{ - impl->colorSpaceTransformSetSrc(ct, name); -} - -void OCIO_colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct) -{ - impl->colorSpaceTransformRelease(ct); -} - -OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void) -{ - return impl->createExponentTransform(); -} - -void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent) -{ - impl->exponentTransformSetValue(et, exponent); -} - -void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) -{ - impl->exponentTransformRelease(et); -} - -OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void) -{ - return impl->createMatrixTransform(); -} - -void OCIO_matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4) -{ - impl->matrixTransformSetValue(mt, m44, offset4); -} - -void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) -{ - impl->matrixTransformRelease(mt); -} - -void OCIO_matrixTransformScale(float *m44, float *offset4, const float *scale4f) -{ - impl->matrixTransformScale(m44, offset4, scale4f); -} - -int OCIO_supportGLSLDraw(void) +bool OCIO_supportGPUShader() { - return (int)impl->supportGLSLDraw(); + return impl->supportGPUShader(); } -int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, - OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui, - OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, - OCIO_CurveMappingSettings *curve_mapping_settings, - float dither, - bool predivide, - bool overlay) +bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + OCIO_CurveMappingSettings *curve_mapping_settings, + const float scale, + const float exponent, + const float dither, + const bool use_predivide, + const bool use_overlay) { - return (int)impl->setupGLSLDraw(state_r, - ocio_processor_scene_to_ui, - ocio_processor_ui_to_display, - curve_mapping_settings, - dither, - predivide, - overlay); + return impl->gpuDisplayShaderBind(config, + input, + view, + display, + look, + curve_mapping_settings, + scale, + exponent, + dither, + use_predivide, + use_overlay); } -void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state) +void OCIO_gpuDisplayShaderUnbind(void) { - impl->finishGLSLDraw(state); + impl->gpuDisplayShaderUnbind(); } -void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state) +void OCIO_gpuCacheFree(void) { - impl->freeGLState(state); + impl->gpuCacheFree(); } const char *OCIO_getVersionString(void) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 57799222788..8b319d4ed68 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -24,7 +24,7 @@ extern "C" { #endif -struct OCIO_GLSLDrawState; +typedef struct OCIO_GPUShader OCIO_GPUShader; #define OCIO_DECLARE_HANDLE(name) \ typedef struct name##__ { \ @@ -42,14 +42,9 @@ struct OCIO_GLSLDrawState; OCIO_DECLARE_HANDLE(OCIO_ConstConfigRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstColorSpaceRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstProcessorRcPtr); +OCIO_DECLARE_HANDLE(OCIO_ConstCPUProcessorRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstContextRcPtr); OCIO_DECLARE_HANDLE(OCIO_PackedImageDesc); -OCIO_DECLARE_HANDLE(OCIO_DisplayTransformRcPtr); -OCIO_DECLARE_HANDLE(OCIO_ConstTransformRcPtr); -OCIO_DECLARE_HANDLE(OCIO_ColorSpaceTransformRcPtr); -OCIO_DECLARE_HANDLE(OCIO_ExponentTransformRcPtr); -OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr); -OCIO_DECLARE_HANDLE(OCIO_GroupTransformRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr); /* Standard XYZ to linear sRGB transform, for fallback. */ @@ -163,32 +158,28 @@ void OCIO_lookRelease(OCIO_ConstLookRcPtr *look); OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName); -OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config, - OCIO_ConstTransformRcPtr *transform); +void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *cpu_processor); -void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); -void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); -void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); -void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); -void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); - -void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p); +OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor); +void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img); +void OCIO_cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img); +void OCIO_cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); +void OCIO_cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); +void OCIO_cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); +void OCIO_cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *processor); const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); const char *OCIO_colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); -OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void); -void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); -void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); -void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); -void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *et); -void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *et); -void OCIO_displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks); -void OCIO_displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled); -void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); +OCIO_ConstProcessorRcPtr *OCIO_createDisplayProcessor(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + const float scale, + const float exponent); OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, @@ -200,37 +191,20 @@ OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); -OCIO_GroupTransformRcPtr *OCIO_createGroupTransform(void); -void OCIO_groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward); -void OCIO_groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr); -void OCIO_groupTransformRelease(OCIO_GroupTransformRcPtr *gt); - -OCIO_ColorSpaceTransformRcPtr *OCIO_createColorSpaceTransform(void); -void OCIO_colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name); -void OCIO_colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct); - -OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void); -void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); -void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); - -OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void); -void OCIO_matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4); -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 *ocio_processor_scene_to_ui, - OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, - OCIO_CurveMappingSettings *curve_mapping_settings, - float dither, - bool predivide, - bool overlay); -void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state); -void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state); +bool OCIO_supportGPUShader(void); +bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + OCIO_CurveMappingSettings *curve_mapping_settings, + const float scale, + const float exponent, + const float dither, + const bool use_predivide, + const bool use_overlay); +void OCIO_gpuDisplayShaderUnbind(void); +void OCIO_gpuCacheFree(void); const char *OCIO_getVersionString(void); int OCIO_getVersionHex(void); diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index cf3571b4662..69a8d8b17af 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -17,6 +17,7 @@ * All rights reserved. */ +#include <cassert> #include <iostream> #include <math.h> #include <sstream> @@ -35,7 +36,9 @@ using namespace OCIO_NAMESPACE; #include "MEM_guardedalloc.h" +#include "BLI_math.h" #include "BLI_math_color.h" +#include "BLI_math_matrix.h" #include "ocio_impl.h" @@ -267,7 +270,7 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf const char *view) { try { - return (*(ConstConfigRcPtr *)config)->getDisplayColorSpaceName(display, view); + return (*(ConstConfigRcPtr *)config)->getDisplayViewColorSpaceName(display, view); } catch (Exception &exception) { OCIO_reportException(exception); @@ -279,13 +282,46 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) { try { - (*(ConstConfigRcPtr *)config)->getDefaultLumaCoefs(rgb); + double rgb_double[3]; + (*(ConstConfigRcPtr *)config)->getDefaultLumaCoefs(rgb_double); + rgb[0] = rgb_double[0]; + rgb[1] = rgb_double[1]; + rgb[2] = rgb_double[2]; } catch (Exception &exception) { OCIO_reportException(exception); } } +static bool to_scene_linear_matrix(ConstConfigRcPtr &config, + const char *colorspace, + float to_scene_linear[3][3]) +{ + ConstProcessorRcPtr processor; + try { + processor = config->getProcessor(colorspace, ROLE_SCENE_LINEAR); + } + catch (Exception &exception) { + OCIO_reportException(exception); + return false; + } + + if (!processor) { + return false; + } + + ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor(); + if (!cpu_processor) { + return false; + } + + unit_m3(to_scene_linear); + cpu_processor->applyRGB(to_scene_linear[0]); + cpu_processor->applyRGB(to_scene_linear[1]); + cpu_processor->applyRGB(to_scene_linear[2]); + return true; +} + void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rgb[3][3]) { ConstConfigRcPtr config = (*(ConstConfigRcPtr *)config_); @@ -293,24 +329,25 @@ void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rg /* Default to ITU-BT.709 in case no appropriate transform found. */ memcpy(xyz_to_rgb, OCIO_XYZ_TO_LINEAR_SRGB, sizeof(OCIO_XYZ_TO_LINEAR_SRGB)); - /* Auto estimate from XYZ and scene_linear roles, assumed to be a linear transform. */ - if (config->hasRole("XYZ") && config->hasRole("scene_linear")) { - ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear"); - if (to_rgb_processor) { - xyz_to_rgb[0][0] = 1.0f; - xyz_to_rgb[0][1] = 0.0f; - xyz_to_rgb[0][2] = 0.0f; - xyz_to_rgb[1][0] = 0.0f; - xyz_to_rgb[1][1] = 1.0f; - xyz_to_rgb[1][2] = 0.0f; - xyz_to_rgb[2][0] = 0.0f; - xyz_to_rgb[2][1] = 0.0f; - xyz_to_rgb[2][2] = 1.0f; - to_rgb_processor->applyRGB(xyz_to_rgb[0]); - to_rgb_processor->applyRGB(xyz_to_rgb[1]); - to_rgb_processor->applyRGB(xyz_to_rgb[2]); + /* Get from OpenColorO config if it has the required roles. */ + if (!config->hasRole(ROLE_SCENE_LINEAR)) { + return; + } + + if (config->hasRole("aces_interchange")) { + /* Standard OpenColorIO role, defined as ACES2065-1. */ + const float xyz_to_aces[3][3] = {{1.0498110175f, -0.4959030231f, 0.0f}, + {0.0f, 1.3733130458f, 0.0f}, + {-0.0000974845f, 0.0982400361f, 0.9912520182f}}; + float aces_to_rgb[3][3]; + if (to_scene_linear_matrix(config, "aces_interchange", aces_to_rgb)) { + mul_m3_m3m3(xyz_to_rgb, aces_to_rgb, xyz_to_aces); } } + else if (config->hasRole("XYZ")) { + /* Custom role used before the standard existed. */ + to_scene_linear_matrix(config, "XYZ", xyz_to_rgb); + } } int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config) @@ -431,6 +468,8 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_, return; } + ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor(); + is_scene_linear = true; is_srgb = true; for (int i = 0; i < 256; i++) { @@ -440,10 +479,10 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_, float cG[3] = {0, v, 0}; float cB[3] = {0, 0, v}; float cW[3] = {v, v, v}; - processor->applyRGB(cR); - processor->applyRGB(cG); - processor->applyRGB(cB); - processor->applyRGB(cW); + cpu_processor->applyRGB(cR); + cpu_processor->applyRGB(cG); + cpu_processor->applyRGB(cB); + cpu_processor->applyRGB(cW); /* Make sure that there is no channel crosstalk. */ if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f || @@ -485,62 +524,57 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfig const char *srcName, const char *dstName) { - ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr); + ConstProcessorRcPtr *processor = OBJECT_GUARDED_NEW(ConstProcessorRcPtr); try { - *p = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName); + *processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName); - if (*p) - return (OCIO_ConstProcessorRcPtr *)p; + if (*processor) + return (OCIO_ConstProcessorRcPtr *)processor; } catch (Exception &exception) { OCIO_reportException(exception); } - OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr); + OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr); return 0; } -OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, - OCIO_ConstTransformRcPtr *transform) +void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor) { - ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr); - - try { - *p = (*(ConstConfigRcPtr *)config)->getProcessor(*(ConstTransformRcPtr *)transform); - - if (*p) - return (OCIO_ConstProcessorRcPtr *)p; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr); + OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr); +} - return NULL; +OCIO_ConstCPUProcessorRcPtr *OCIOImpl::processorGetCPUProcessor( + OCIO_ConstProcessorRcPtr *processor) +{ + ConstCPUProcessorRcPtr *cpu_processor = OBJECT_GUARDED_NEW(ConstCPUProcessorRcPtr); + *cpu_processor = (*(ConstProcessorRcPtr *)processor)->getDefaultCPUProcessor(); + return (OCIO_ConstCPUProcessorRcPtr *)cpu_processor; } -void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +void OCIOImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img) { try { - (*(ConstProcessorRcPtr *)processor)->apply(*(PackedImageDesc *)img); + (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*(PackedImageDesc *)img); } catch (Exception &exception) { OCIO_reportException(exception); } } -void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, - OCIO_PackedImageDesc *img_) +void OCIOImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img_) { try { PackedImageDesc *img = (PackedImageDesc *)img_; int channels = img->getNumChannels(); if (channels == 4) { - float *pixels = img->getData(); + assert(img->isFloat()); + float *pixels = (float *)img->getData(); int width = img->getWidth(); int height = img->getHeight(); @@ -549,12 +583,12 @@ void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, for (int x = 0; x < width; x++) { float *pixel = pixels + 4 * (y * width + x); - processorApplyRGBA_predivide(processor, pixel); + cpuProcessorApplyRGBA_predivide(cpu_processor, pixel); } } } else { - (*(ConstProcessorRcPtr *)processor)->apply(*img); + (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*img); } } catch (Exception &exception) { @@ -562,20 +596,21 @@ void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, } } -void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void OCIOImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) { - (*(ConstProcessorRcPtr *)processor)->applyRGB(pixel); + (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGB(pixel); } -void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void OCIOImpl::cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) { - (*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel); + (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel); } -void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) +void OCIOImpl::cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + float *pixel) { if (pixel[3] == 1.0f || pixel[3] == 0.0f) { - (*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel); + (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel); } else { float alpha, inv_alpha; @@ -587,7 +622,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, pixel[1] *= inv_alpha; pixel[2] *= inv_alpha; - (*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel); + (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel); pixel[0] *= alpha; pixel[1] *= alpha; @@ -595,9 +630,9 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, } } -void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p) +void OCIOImpl::cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor) { - OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr); + OBJECT_GUARDED_DELETE(cpu_processor, ConstCPUProcessorRcPtr); } const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) @@ -615,57 +650,85 @@ const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) return (*(ConstColorSpaceRcPtr *)cs)->getFamily(); } -OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void) +OCIO_ConstProcessorRcPtr *OCIOImpl::createDisplayProcessor(OCIO_ConstConfigRcPtr *config_, + const char *input, + const char *view, + const char *display, + const char *look, + const float scale, + const float exponent) + { - DisplayTransformRcPtr *dt = OBJECT_GUARDED_NEW(DisplayTransformRcPtr); + ConstConfigRcPtr config = *(ConstConfigRcPtr *)config_; + GroupTransformRcPtr group = GroupTransform::Create(); - *dt = DisplayTransform::Create(); + /* Exposure. */ + if (scale != 1.0f) { + /* Always apply exposure in scene linear. */ + ColorSpaceTransformRcPtr ct = ColorSpaceTransform::Create(); + ct->setSrc(input); + ct->setDst(ROLE_SCENE_LINEAR); + group->appendTransform(ct); - return (OCIO_DisplayTransformRcPtr *)dt; -} + /* Make further transforms aware of the color space change. */ + input = ROLE_SCENE_LINEAR; -void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, - const char *name) -{ - (*(DisplayTransformRcPtr *)dt)->setInputColorSpaceName(name); -} + /* Apply scale. */ + MatrixTransformRcPtr mt = MatrixTransform::Create(); + const double matrix[16] = { + scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, 1.0}; + mt->setMatrix(matrix); + group->appendTransform(mt); + } -void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) -{ - (*(DisplayTransformRcPtr *)dt)->setDisplay(name); -} + /* Add look transform. */ + const bool use_look = (strlen(look) != 0); + if (use_look) { + const char *look_output = LookTransform::GetLooksResultColorSpace( + config, config->getCurrentContext(), look); -void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) -{ - (*(DisplayTransformRcPtr *)dt)->setView(name); -} + LookTransformRcPtr lt = LookTransform::Create(); + lt->setSrc(input); + lt->setDst(look_output); + lt->setLooks(look); + group->appendTransform(lt); -void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *t) -{ - (*(DisplayTransformRcPtr *)dt)->setDisplayCC(*(ConstTransformRcPtr *)t); -} + /* Make further transforms aware of the color space change. */ + input = look_output; + } -void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *t) -{ - (*(DisplayTransformRcPtr *)dt)->setLinearCC(*(ConstTransformRcPtr *)t); -} + /* Add view and display transform. */ + DisplayViewTransformRcPtr dvt = DisplayViewTransform::Create(); + dvt->setSrc(input); + dvt->setLooksBypass(use_look); + dvt->setView(view); + dvt->setDisplay(display); + group->appendTransform(dvt); -void OCIOImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks) -{ - (*(DisplayTransformRcPtr *)dt)->setLooksOverride(looks); -} + /* Gamma. */ + if (exponent != 1.0f) { + ExponentTransformRcPtr et = ExponentTransform::Create(); + const double value[4] = {exponent, exponent, exponent, 1.0}; + et->setValue(value); + group->appendTransform(et); + } -void OCIOImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, - bool enabled) -{ - (*(DisplayTransformRcPtr *)dt)->setLooksOverrideEnabled(enabled); -} + /* Create processor from transform. This is the moment were OCIO validates + * the entire transform, no need to check for the validity of inputs above. */ + ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr); -void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) -{ - OBJECT_GUARDED_DELETE((DisplayTransformRcPtr *)dt, DisplayTransformRcPtr); + try { + *p = config->getProcessor(group); + + if (*p) + return (OCIO_ConstProcessorRcPtr *)p; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr); + return NULL; } OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, @@ -678,8 +741,14 @@ OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, { try { void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__); - PackedImageDesc *id = new (mem) PackedImageDesc( - data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); + PackedImageDesc *id = new (mem) PackedImageDesc(data, + width, + height, + numChannels, + BIT_DEPTH_F32, + chanStrideBytes, + xStrideBytes, + yStrideBytes); return (OCIO_PackedImageDesc *)id; } @@ -695,96 +764,6 @@ void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id) OBJECT_GUARDED_DELETE((PackedImageDesc *)id, PackedImageDesc); } -OCIO_GroupTransformRcPtr *OCIOImpl::createGroupTransform(void) -{ - GroupTransformRcPtr *gt = OBJECT_GUARDED_NEW(GroupTransformRcPtr); - - *gt = GroupTransform::Create(); - - return (OCIO_GroupTransformRcPtr *)gt; -} - -void OCIOImpl::groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward) -{ - TransformDirection dir = forward ? TRANSFORM_DIR_FORWARD : TRANSFORM_DIR_INVERSE; - (*(GroupTransformRcPtr *)gt)->setDirection(dir); -} - -void OCIOImpl::groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr) -{ - (*(GroupTransformRcPtr *)gt)->push_back(*(ConstTransformRcPtr *)tr); -} - -void OCIOImpl::groupTransformRelease(OCIO_GroupTransformRcPtr *gt) -{ - OBJECT_GUARDED_DELETE((GroupTransformRcPtr *)gt, GroupTransformRcPtr); -} - -OCIO_ColorSpaceTransformRcPtr *OCIOImpl::createColorSpaceTransform(void) -{ - ColorSpaceTransformRcPtr *ct = OBJECT_GUARDED_NEW(ColorSpaceTransformRcPtr); - - *ct = ColorSpaceTransform::Create(); - (*ct)->setDirection(TRANSFORM_DIR_FORWARD); - - return (OCIO_ColorSpaceTransformRcPtr *)ct; -} - -void OCIOImpl::colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name) -{ - (*(ColorSpaceTransformRcPtr *)ct)->setSrc(name); -} - -void OCIOImpl::colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct) -{ - OBJECT_GUARDED_DELETE((ColorSpaceTransformRcPtr *)ct, ColorSpaceTransformRcPtr); -} - -OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void) -{ - ExponentTransformRcPtr *et = OBJECT_GUARDED_NEW(ExponentTransformRcPtr); - - *et = ExponentTransform::Create(); - - return (OCIO_ExponentTransformRcPtr *)et; -} - -void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent) -{ - (*(ExponentTransformRcPtr *)et)->setValue(exponent); -} - -void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) -{ - OBJECT_GUARDED_DELETE((ExponentTransformRcPtr *)et, ExponentTransformRcPtr); -} - -OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void) -{ - MatrixTransformRcPtr *mt = OBJECT_GUARDED_NEW(MatrixTransformRcPtr); - - *mt = MatrixTransform::Create(); - - return (OCIO_MatrixTransformRcPtr *)mt; -} - -void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4) -{ - (*(MatrixTransformRcPtr *)mt)->setValue(m44, offset4); -} - -void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) -{ - OBJECT_GUARDED_DELETE((MatrixTransformRcPtr *)mt, MatrixTransformRcPtr); -} - -void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *scale4f) -{ - MatrixTransform::Scale(m44, offset4, scale4f); -} - const char *OCIOImpl::getVersionString(void) { return GetVersion(); diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index 3ffc0a4a475..0c759a35e15 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -76,36 +76,30 @@ class IOCIOImpl { virtual OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName) = 0; - virtual OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, - OCIO_ConstTransformRcPtr *transform) = 0; - - virtual void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) = 0; - virtual void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, - OCIO_PackedImageDesc *img) = 0; - virtual void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; - virtual void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; - virtual void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; - - virtual void processorRelease(OCIO_ConstProcessorRcPtr *p) = 0; + virtual void processorRelease(OCIO_ConstProcessorRcPtr *processor) = 0; + + virtual OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *p) = 0; + virtual void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img) = 0; + virtual void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img) = 0; + virtual void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) = 0; + virtual void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) = 0; + virtual void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + float *pixel) = 0; + virtual void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor) = 0; virtual const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) = 0; virtual const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) = 0; virtual const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) = 0; - virtual OCIO_DisplayTransformRcPtr *createDisplayTransform(void) = 0; - virtual void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, - const char *name) = 0; - virtual void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; - virtual void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; - virtual void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *et) = 0; - virtual void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, - OCIO_ConstTransformRcPtr *et) = 0; - virtual void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, - const char *looks) = 0; - virtual void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, - bool enabled) = 0; - virtual void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) = 0; + virtual OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + const float scale, + const float exponent) = 0; virtual OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, long width, @@ -117,39 +111,31 @@ class IOCIOImpl { virtual void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p) = 0; - virtual OCIO_GroupTransformRcPtr *createGroupTransform(void) = 0; - virtual void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward) = 0; - virtual void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, - OCIO_ConstTransformRcPtr *transform) = 0; - virtual void groupTransformRelease(OCIO_GroupTransformRcPtr *gt) = 0; - - virtual OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void) = 0; - virtual void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name) = 0; - virtual void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct) = 0; - - virtual OCIO_ExponentTransformRcPtr *createExponentTransform(void) = 0; - virtual void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, - const float *exponent) = 0; - virtual void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) = 0; - - virtual OCIO_MatrixTransformRcPtr *createMatrixTransform(void) = 0; - virtual void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4) = 0; - virtual void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) = 0; - - 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 *ocio_processor_scene_to_ui, - OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, - OCIO_CurveMappingSettings *curve_mapping_settings, - float dither, - bool predivide, - bool overlay) = 0; - virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0; - virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0; + /* Optional GPU support. */ + virtual bool supportGPUShader() + { + return false; + } + virtual bool gpuDisplayShaderBind(OCIO_ConstConfigRcPtr * /*config*/, + const char * /*input*/, + const char * /*view*/, + const char * /*display*/, + const char * /*look*/, + OCIO_CurveMappingSettings * /*curve_mapping_settings*/, + const float /*scale*/, + const float /*exponent*/, + const float /*dither*/, + const bool /*use_predivide*/, + const bool /*use_overlay*/) + { + return false; + } + virtual void gpuDisplayShaderUnbind(void) + { + } + virtual void gpuCacheFree(void) + { + } virtual const char *getVersionString(void) = 0; virtual int getVersionHex(void) = 0; @@ -206,30 +192,28 @@ class FallbackImpl : public IOCIOImpl { OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName); - OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, - OCIO_ConstTransformRcPtr *transform); + void processorRelease(OCIO_ConstProcessorRcPtr *processor); - void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); - void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); - void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); - void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); - void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); - - void processorRelease(OCIO_ConstProcessorRcPtr *p); + OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor); + void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img); + void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img); + void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); + void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); + void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); + void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor); const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); - OCIO_DisplayTransformRcPtr *createDisplayTransform(void); - void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); - void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); - void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); - void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); - void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); - void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks); - void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled); - void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); + OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + const float scale, + const float exponent); OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, long width, @@ -241,38 +225,6 @@ class FallbackImpl : public IOCIOImpl { void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); - OCIO_GroupTransformRcPtr *createGroupTransform(void); - void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward); - void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *transform); - void groupTransformRelease(OCIO_GroupTransformRcPtr *gt); - - OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void); - void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name); - void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct); - - OCIO_ExponentTransformRcPtr *createExponentTransform(void); - void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); - void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); - - OCIO_MatrixTransformRcPtr *createMatrixTransform(void); - void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4); - void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); - - void matrixTransformScale(float *m44, float *offset4, const float *scale4); - - bool supportGLSLDraw(void); - bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, - OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui, - OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, - OCIO_CurveMappingSettings *curve_mapping_settings, - float dither, - bool predivide, - bool overlay); - void finishGLSLDraw(struct OCIO_GLSLDrawState *state); - void freeGLState(struct OCIO_GLSLDrawState *state_r); - const char *getVersionString(void); int getVersionHex(void); }; @@ -327,30 +279,28 @@ class OCIOImpl : public IOCIOImpl { OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName); - OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, - OCIO_ConstTransformRcPtr *transform); - - void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); - void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); - void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); - void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); - void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); + void processorRelease(OCIO_ConstProcessorRcPtr *processor); - void processorRelease(OCIO_ConstProcessorRcPtr *p); + OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor); + void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img); + void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, + OCIO_PackedImageDesc *img); + void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); + void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); + void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel); + void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor); const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); - OCIO_DisplayTransformRcPtr *createDisplayTransform(void); - void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); - void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); - void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); - void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); - void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); - void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks); - void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled); - void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); + OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + const float scale, + const float exponent); OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, long width, @@ -362,37 +312,20 @@ class OCIOImpl : public IOCIOImpl { void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); - OCIO_GroupTransformRcPtr *createGroupTransform(void); - void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward); - void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *transform); - void groupTransformRelease(OCIO_GroupTransformRcPtr *gt); - - OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void); - void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name); - void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct); - - OCIO_ExponentTransformRcPtr *createExponentTransform(void); - void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); - void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); - - OCIO_MatrixTransformRcPtr *createMatrixTransform(void); - void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, - const float *m44, - const float *offset4); - void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); - - void matrixTransformScale(float *m44, float *offset4, const float *scale4); - - bool supportGLSLDraw(void); - bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, - OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui, - OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, - OCIO_CurveMappingSettings *curve_mapping_settings, - float dither, - bool predivide, - bool overlay); - void finishGLSLDraw(struct OCIO_GLSLDrawState *state); - void freeGLState(struct OCIO_GLSLDrawState *state_r); + bool supportGPUShader(); + bool gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + OCIO_CurveMappingSettings *curve_mapping_settings, + const float scale, + const float exponent, + const float dither, + const bool use_predivide, + const bool use_overlay); + void gpuDisplayShaderUnbind(void); + void gpuCacheFree(void); const char *getVersionString(void); int getVersionHex(void); diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 0213646345c..841f1386af1 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -31,8 +31,10 @@ */ #include <limits> +#include <list> #include <sstream> #include <string.h> +#include <vector> #ifdef _MSC_VER # pragma warning(push) @@ -53,24 +55,24 @@ using namespace OCIO_NAMESPACE; #include "ocio_impl.h" -static const int LUT3D_EDGE_SIZE = 64; -static const int LUT3D_TEXTURE_SIZE = sizeof(float) * 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * - LUT3D_EDGE_SIZE; -static const int SHADER_CACHE_SIZE = 4; - -#define UBO_BIND_LOC 0 - extern "C" char datatoc_gpu_shader_display_transform_glsl[]; extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[]; /* **** OpenGL drawing routines using GLSL for color space transform ***** */ +enum OCIO_GPUTextureSlots { + TEXTURE_SLOT_IMAGE = 0, + TEXTURE_SLOT_OVERLAY = 1, + TEXTURE_SLOT_CURVE_MAPPING = 2, + TEXTURE_SLOT_LUTS_OFFSET = 3, +}; + /* Curve mapping parameters * * See documentation for OCIO_CurveMappingSettings to get fields descriptions. * (this ones pretty much copies stuff from C structure.) */ -struct OCIO_GLSLCurveMappingParameters { +struct OCIO_GPUCurveMappingParameters { float curve_mapping_mintable[4]; float curve_mapping_range[4]; float curve_mapping_ext_in_x[4]; @@ -89,79 +91,108 @@ struct OCIO_GLSLCurveMappingParameters { /** WARNING: Needs to be 16byte aligned. Used as UBO data. */ }; -struct OCIO_GLSLShader { - /** Cache IDs */ - std::string cacheId; +struct OCIO_GPUShader { + /* GPU shader. */ + struct GPUShader *shader = nullptr; - struct GPUShader *shader; /** Uniform locations. */ - int dither_loc; - int overlay_loc; - int predivide_loc; - int curve_mapping_loc; - int ubo_bind; - /** Error checking. */ - bool valid; + int scale_loc = 0; + int exponent_loc = 0; + int dither_loc = 0; + int overlay_loc = 0; + int predivide_loc = 0; + int ubo_bind = 0; + + /* Destructor. */ + ~OCIO_GPUShader() + { + if (shader) { + GPU_shader_free(shader); + } + } }; -struct OCIO_GLSLLut3d { - /** Cache IDs */ - std::string cacheId; - /** OpenGL Texture handles. NULL if not allocated. */ - GPUTexture *texture; - GPUTexture *texture_display; - GPUTexture *texture_dummy; - /** Error checking. */ - bool valid; +struct OCIO_GPULutTexture { + GPUTexture *texture = nullptr; + std::string sampler_name; +}; + +struct OCIO_GPUUniform { + GpuShaderDesc::UniformData data; + std::string name; +}; + +struct OCIO_GPUTextures { + /** LUT Textures */ + std::vector<OCIO_GPULutTexture> luts; + + /* Dummy in case of no overlay. */ + GPUTexture *dummy = nullptr; + + /* Uniforms */ + std::vector<OCIO_GPUUniform> uniforms; + + /* Destructor. */ + ~OCIO_GPUTextures() + { + for (OCIO_GPULutTexture &lut : luts) { + GPU_texture_free(lut.texture); + } + if (dummy) { + GPU_texture_free(dummy); + } + } }; -struct OCIO_GLSLCurveMappping { - /** Cache IDs */ - size_t cacheId; +struct OCIO_GPUCurveMappping { /** GPU Uniform Buffer handle. 0 if not allocated. */ - GPUUniformBuf *buffer; + GPUUniformBuf *buffer = nullptr; /** OpenGL Texture handles. 0 if not allocated. */ - GPUTexture *texture; - /** Error checking. */ - bool valid; -}; + GPUTexture *texture = nullptr; + /* To detect when to update the uniforms and textures. */ + size_t cache_id = 0; -struct OCIO_GLSLCacheHandle { - size_t cache_id; - void *data; + /* Destructor. */ + ~OCIO_GPUCurveMappping() + { + if (texture) { + GPU_texture_free(texture); + } + if (buffer) { + GPU_uniformbuf_free(buffer); + } + } }; -struct OCIO_GLSLDrawState { - /* Shader Cache */ - OCIO_GLSLCacheHandle shader_cache[SHADER_CACHE_SIZE]; - OCIO_GLSLCacheHandle lut3d_cache[SHADER_CACHE_SIZE]; - OCIO_GLSLCacheHandle curvemap_cache[SHADER_CACHE_SIZE]; +struct OCIO_GPUDisplayShader { + OCIO_GPUShader shader; + OCIO_GPUTextures textures; + OCIO_GPUCurveMappping curvemap; + + /* Cache variables. */ + std::string input; + std::string view; + std::string display; + std::string look; + bool use_curve_mapping = false; + + /** Error checking. */ + bool valid = false; }; -static OCIO_GLSLDrawState *allocateOpenGLState(void) -{ - return (OCIO_GLSLDrawState *)MEM_callocN(sizeof(OCIO_GLSLDrawState), "OCIO OpenGL State struct"); -} +static const int SHADER_CACHE_MAX_SIZE = 4; +std::list<OCIO_GPUDisplayShader> SHADER_CACHE; /* -------------------------------------------------------------------- */ /** \name Shader * \{ */ -static void updateGLSLShader(OCIO_GLSLShader *shader, - ConstProcessorRcPtr *processor_scene_to_ui, - ConstProcessorRcPtr *processpr_ui_to_display, - GpuShaderDesc *shader_desc, - const std::string &cache_id) +static bool createGPUShader(OCIO_GPUShader &shader, + OCIO_GPUTextures &textures, + const GpuShaderDescRcPtr &shaderdesc_to_scene_linear, + const GpuShaderDescRcPtr &shaderdesc_to_display, + const bool use_curve_mapping) { - if (shader->cacheId == cache_id) { - return; - } - - /* Delete any previous shader. */ - if (shader->shader) { - GPU_shader_free(shader->shader); - } - std::ostringstream os; { /* Fragment shader */ @@ -170,146 +201,222 @@ static void updateGLSLShader(OCIO_GLSLShader *shader, os << "#define texture2D texture\n"; os << "#define texture3D texture\n"; - shader_desc->setFunctionName("OCIO_to_display_linear_with_look"); - os << (*processor_scene_to_ui)->getGpuShaderText(*shader_desc) << "\n"; + if (use_curve_mapping) { + os << "#define USE_CURVE_MAPPING\n"; + } - shader_desc->setFunctionName("OCIO_to_display_encoded"); - os << (*processpr_ui_to_display)->getGpuShaderText(*shader_desc) << "\n"; + os << shaderdesc_to_scene_linear->getShaderText() << "\n"; + os << shaderdesc_to_display->getShaderText() << "\n"; os << datatoc_gpu_shader_display_transform_glsl; } - shader->shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl, - os.str().c_str(), - NULL, - NULL, - NULL, - "OCIOShader"); + shader.shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl, + os.str().c_str(), + nullptr, + nullptr, + nullptr, + "OCIOShader"); - if (shader->shader) { - shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither"); - shader->overlay_loc = GPU_shader_get_uniform(shader->shader, "overlay"); - shader->predivide_loc = GPU_shader_get_uniform(shader->shader, "predivide"); - shader->curve_mapping_loc = GPU_shader_get_uniform(shader->shader, "curve_mapping"); - shader->ubo_bind = GPU_shader_get_uniform_block_binding(shader->shader, - "OCIO_GLSLCurveMappingParameters"); + if (shader.shader == nullptr) { + return false; + } - GPU_shader_bind(shader->shader); + shader.scale_loc = GPU_shader_get_uniform(shader.shader, "scale"); + shader.exponent_loc = GPU_shader_get_uniform(shader.shader, "exponent"); + shader.dither_loc = GPU_shader_get_uniform(shader.shader, "dither"); + shader.overlay_loc = GPU_shader_get_uniform(shader.shader, "overlay"); + shader.predivide_loc = GPU_shader_get_uniform(shader.shader, "predivide"); + shader.ubo_bind = GPU_shader_get_uniform_block_binding(shader.shader, + "OCIO_GPUCurveMappingParameters"); - /* Set texture bind point uniform once. This is saved by the shader. */ - GPUShader *sh = shader->shader; - GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), 0); - GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), 1); - GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_texture"), 2); - GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_display_texture"), 3); - GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), 4); - } + GPU_shader_bind(shader.shader); - shader->cacheId = cache_id; - shader->valid = (shader->shader != NULL); -} + /* Set texture bind point uniform once. This is saved by the shader. */ + GPUShader *sh = shader.shader; + GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), TEXTURE_SLOT_IMAGE); + GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), TEXTURE_SLOT_OVERLAY); -static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr, - ConstProcessorRcPtr *processor_scene_to_ui, - ConstProcessorRcPtr *processpr_ui_to_display, - GpuShaderDesc *shader_desc, - const std::string &cache_id) -{ - if (*shader_ptr != NULL) { - return; + if (use_curve_mapping) { + GPU_shader_uniform_int( + sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), TEXTURE_SLOT_CURVE_MAPPING); } - OCIO_GLSLShader *shader = OBJECT_GUARDED_NEW(OCIO_GLSLShader); - - updateGLSLShader(shader, processor_scene_to_ui, processpr_ui_to_display, shader_desc, cache_id); + /* Set LUT textures. */ + for (int i = 0; i < textures.luts.size(); i++) { + GPU_shader_uniform_int(sh, + GPU_shader_get_uniform(sh, textures.luts[i].sampler_name.c_str()), + TEXTURE_SLOT_LUTS_OFFSET + i); + } - *shader_ptr = shader; -} + /* Set uniforms. */ + for (OCIO_GPUUniform &uniform : textures.uniforms) { + const GpuShaderDesc::UniformData &data = uniform.data; + const char *name = name; -static void freeGLSLShader(OCIO_GLSLShader *shader) -{ - if (shader->shader) { - GPU_shader_free(shader->shader); + if (data.m_getDouble) { + GPU_shader_uniform_1f(sh, name, (float)data.m_getDouble()); + } + else if (data.m_getBool) { + GPU_shader_uniform_1f(sh, name, (float)(data.m_getBool() ? 1.0f : 0.0f)); + } + else if (data.m_getFloat3) { + GPU_shader_uniform_3f(sh, + name, + (float)data.m_getFloat3()[0], + (float)data.m_getFloat3()[1], + (float)data.m_getFloat3()[2]); + } + else if (data.m_vectorFloat.m_getSize && data.m_vectorFloat.m_getVector) { + GPU_shader_uniform_vector(sh, + GPU_shader_get_uniform(sh, name), + (int)data.m_vectorFloat.m_getSize(), + 1, + (float *)data.m_vectorFloat.m_getVector()); + } + else if (data.m_vectorInt.m_getSize && data.m_vectorInt.m_getVector) { + GPU_shader_uniform_vector_int(sh, + GPU_shader_get_uniform(sh, name), + (int)data.m_vectorInt.m_getSize(), + 1, + (int *)data.m_vectorInt.m_getVector()); + } } - OBJECT_GUARDED_DELETE(shader, OCIO_GLSLShader); + return true; } /** \} */ /* -------------------------------------------------------------------- */ -/** \name Lut3D +/** \name Textures * \{ */ -static void updateGLSLLut3d(OCIO_GLSLLut3d *lut3d, - ConstProcessorRcPtr *processor_scene_to_ui, - ConstProcessorRcPtr *processpr_ui_to_display, - GpuShaderDesc *shader_desc, - const std::string &cache_id) +static bool addGPUUniform(OCIO_GPUTextures &textures, + const GpuShaderDescRcPtr &shader_desc, + int index) { - if (lut3d->cacheId == cache_id) - return; - - float *lut_data = (float *)MEM_mallocN(LUT3D_TEXTURE_SIZE, __func__); + OCIO_GPUUniform uniform; + uniform.name = shader_desc->getUniform(index, uniform.data); + if (uniform.data.m_type == UNIFORM_UNKNOWN) { + return false; + } - ConstProcessorRcPtr *ocio_processors[2] = {processor_scene_to_ui, processpr_ui_to_display}; + textures.uniforms.push_back(uniform); + return true; +} - for (int i = 0; i < 2; i++) { - ConstProcessorRcPtr *processor = ocio_processors[i]; - GPUTexture *texture = (&lut3d->texture)[i]; +static bool addGPULut2D(OCIO_GPUTextures &textures, + const GpuShaderDescRcPtr &shader_desc, + int index) +{ + const char *texture_name = nullptr; + const char *sampler_name = nullptr; + unsigned int width = 0; + unsigned int height = 0; + GpuShaderCreator::TextureType channel = GpuShaderCreator::TEXTURE_RGB_CHANNEL; + Interpolation interpolation = INTERP_LINEAR; + shader_desc->getTexture( + index, texture_name, sampler_name, width, height, channel, interpolation); + + const float *values; + shader_desc->getTextureValues(index, values); + if (texture_name == nullptr || sampler_name == nullptr || width == 0 || height == 0 || + values == nullptr) { + return false; + } - (*processor)->getGpuLut3D(lut_data, *shader_desc); + eGPUTextureFormat format = (channel == GpuShaderCreator::TEXTURE_RGB_CHANNEL) ? GPU_RGB16F : + GPU_R16F; - int offset[3] = {0, 0, 0}; - int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE}; - GPU_texture_update_sub(texture, GPU_DATA_FLOAT, lut_data, UNPACK3(offset), UNPACK3(extent)); + OCIO_GPULutTexture lut; + lut.texture = GPU_texture_create_2d(texture_name, width, height, 0, format, values); + if (lut.texture == nullptr) { + return false; } - MEM_freeN(lut_data); + GPU_texture_filter_mode(lut.texture, interpolation != INTERP_NEAREST); + GPU_texture_wrap_mode(lut.texture, false, true); + + lut.sampler_name = sampler_name; - lut3d->cacheId = cache_id; + textures.luts.push_back(lut); + return true; } -static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr, - ConstProcessorRcPtr *processor_scene_to_ui, - ConstProcessorRcPtr *processpr_ui_to_display, - GpuShaderDesc *shaderDesc, - const std::string &cache_id) +static bool addGPULut3D(OCIO_GPUTextures &textures, + const GpuShaderDescRcPtr &shader_desc, + int index) { - if (*lut3d_ptr != NULL) { - return; + const char *texture_name = nullptr; + const char *sampler_name = nullptr; + unsigned int edgelen = 0; + Interpolation interpolation = INTERP_LINEAR; + shader_desc->get3DTexture(index, texture_name, sampler_name, edgelen, interpolation); + + const float *values; + shader_desc->get3DTextureValues(index, values); + if (texture_name == nullptr || sampler_name == nullptr || edgelen == 0 || values == nullptr) { + return false; } - OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d); - - int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE}; - - lut3d->texture = GPU_texture_create_3d( - "OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL); - GPU_texture_filter_mode(lut3d->texture, true); - GPU_texture_wrap_mode(lut3d->texture, false, true); - - lut3d->texture_display = GPU_texture_create_3d( - "OCIOLutDisplay", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL); - GPU_texture_filter_mode(lut3d->texture_display, true); - GPU_texture_wrap_mode(lut3d->texture_display, false, true); - - lut3d->texture_dummy = GPU_texture_create_error(2, false); + OCIO_GPULutTexture lut; + lut.texture = GPU_texture_create_3d( + texture_name, edgelen, edgelen, edgelen, 0, GPU_RGB16F, GPU_DATA_FLOAT, values); + if (lut.texture == nullptr) { + return false; + } - updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id); + GPU_texture_filter_mode(lut.texture, interpolation != INTERP_NEAREST); + GPU_texture_wrap_mode(lut.texture, false, true); - lut3d->valid = (lut3d->texture && lut3d->texture_display); + lut.sampler_name = sampler_name; - *lut3d_ptr = lut3d; + textures.luts.push_back(lut); + return true; } -static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d) +static bool createGPUTextures(OCIO_GPUTextures &textures, + const GpuShaderDescRcPtr &shaderdesc_to_scene_linear, + const GpuShaderDescRcPtr &shaderdesc_to_display) { - GPU_texture_free(lut3d->texture); - GPU_texture_free(lut3d->texture_display); - GPU_texture_free(lut3d->texture_dummy); + textures.dummy = GPU_texture_create_error(2, false); + + textures.luts.clear(); + textures.uniforms.clear(); + + for (int index = 0; index < shaderdesc_to_scene_linear->getNumUniforms(); index++) { + if (!addGPUUniform(textures, shaderdesc_to_scene_linear, index)) { + return false; + } + } + for (int index = 0; index < shaderdesc_to_scene_linear->getNumTextures(); index++) { + if (!addGPULut2D(textures, shaderdesc_to_scene_linear, index)) { + return false; + } + } + for (int index = 0; index < shaderdesc_to_scene_linear->getNum3DTextures(); index++) { + if (!addGPULut3D(textures, shaderdesc_to_scene_linear, index)) { + return false; + } + } + for (int index = 0; index < shaderdesc_to_display->getNumUniforms(); index++) { + if (!addGPUUniform(textures, shaderdesc_to_display, index)) { + return false; + } + } + for (int index = 0; index < shaderdesc_to_display->getNumTextures(); index++) { + if (!addGPULut2D(textures, shaderdesc_to_display, index)) { + return false; + } + } + for (int index = 0; index < shaderdesc_to_display->getNum3DTextures(); index++) { + if (!addGPULut3D(textures, shaderdesc_to_display, index)) { + return false; + } + } - OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d); + return true; } /** \} */ @@ -317,72 +424,47 @@ static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d) /* -------------------------------------------------------------------- */ /** \name Curve Mapping * \{ */ -static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap, - OCIO_CurveMappingSettings *curve_mapping_settings) -{ - int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1; - /* Do not initialize. Only if used. */ - curvemap->texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, NULL); - GPU_texture_filter_mode(curvemap->texture, false); - GPU_texture_wrap_mode(curvemap->texture, false, true); -} -/* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */ -static void ensureGLSLCurveMapping(OCIO_GLSLCurveMappping **curvemap_ptr, - OCIO_CurveMappingSettings *curve_mapping_settings) +static bool createGPUCurveMapping(OCIO_GPUCurveMappping &curvemap, + OCIO_CurveMappingSettings *curve_mapping_settings) { - if (*curvemap_ptr != NULL) { - return; - } - - OCIO_GLSLCurveMappping *curvemap = OBJECT_GUARDED_NEW(OCIO_GLSLCurveMappping); + if (curve_mapping_settings) { + int lut_size = curve_mapping_settings->lut_size; - /* Texture. */ - allocateCurveMappingTexture(curvemap, curve_mapping_settings); + curvemap.texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, nullptr); + GPU_texture_filter_mode(curvemap.texture, false); + GPU_texture_wrap_mode(curvemap.texture, false, true); - /* Uniform buffer object. */ - curvemap->buffer = GPU_uniformbuf_create(sizeof(OCIO_GLSLCurveMappingParameters)); + curvemap.buffer = GPU_uniformbuf_create(sizeof(OCIO_GPUCurveMappingParameters)); - curvemap->valid = (curvemap->texture != 0); - curvemap->cacheId = 0; - - *curvemap_ptr = curvemap; -} - -static void freeGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap) -{ - GPU_texture_free(curvemap->texture); - GPU_uniformbuf_free(curvemap->buffer); + if (curvemap.texture == nullptr || curvemap.buffer == nullptr) { + return false; + } + } - OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping); + return true; } -static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap, - OCIO_CurveMappingSettings *curve_mapping_settings, - size_t cacheId) +static void updateGPUCurveMapping(OCIO_GPUCurveMappping &curvemap, + OCIO_CurveMappingSettings *curve_mapping_settings) { - /* No need to continue if curvemapping is not used. Just use whatever is in this cache. */ - if (curve_mapping_settings == NULL) + /* Test if we need to update. The caller ensures the curve_mapping_settings + * changes when its contents changes. */ + if (curve_mapping_settings == nullptr || curvemap.cache_id == curve_mapping_settings->cache_id) { return; - - if (curvemap->cacheId == cacheId) - return; - - if (curvemap->cacheId == 0) { - /* This cache was previously used as dummy. Recreate the texture. */ - GPU_texture_free(curvemap->texture); - allocateCurveMappingTexture(curvemap, curve_mapping_settings); } + curvemap.cache_id = curve_mapping_settings->cache_id; + /* Update texture. */ int offset[3] = {0, 0, 0}; int extent[3] = {curve_mapping_settings->lut_size, 0, 0}; const float *pixels = curve_mapping_settings->lut; GPU_texture_update_sub( - curvemap->texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent)); + curvemap.texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent)); /* Update uniforms. */ - OCIO_GLSLCurveMappingParameters data; + OCIO_GPUCurveMappingParameters data; for (int i = 0; i < 4; i++) { data.curve_mapping_range[i] = curve_mapping_settings->range[i]; data.curve_mapping_mintable[i] = curve_mapping_settings->mintable[i]; @@ -402,198 +484,193 @@ static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap, data.curve_mapping_lut_size = curve_mapping_settings->lut_size; data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate; - GPU_uniformbuf_update(curvemap->buffer, &data); - - curvemap->cacheId = cacheId; + GPU_uniformbuf_update(curvemap.buffer, &data); } /** \} */ /* -------------------------------------------------------------------- */ -/** \name LRU cache +/** \name OCIO GPU Shader Implementation * \{ */ -static size_t hash_string(const char *str) +bool OCIOImpl::supportGPUShader() { - size_t i = 0, c; - while ((c = *str++)) { - i = i * 37 + c; - } - return i; + /* Minimum supported version 3.3 does meet all requirements. */ + return true; } -static OCIO_GLSLCacheHandle *cacheSearch(OCIO_GLSLCacheHandle cache[SHADER_CACHE_SIZE], - size_t cache_id) +static OCIO_GPUDisplayShader &getGPUDisplayShader( + OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + OCIO_CurveMappingSettings *curve_mapping_settings) { - OCIO_GLSLCacheHandle *cached_item = &cache[0]; - for (int i = 0; i < SHADER_CACHE_SIZE; i++, cached_item++) { - if (cached_item->data == NULL) { - continue; - } - else if (cached_item->cache_id == cache_id) { - /* LRU cache, so move to front. */ - OCIO_GLSLCacheHandle found_item = *cached_item; - for (int j = i; j > 0; j--) { - cache[j] = cache[j - 1]; + /* Find existing shader in cache. */ + const bool use_curve_mapping = (curve_mapping_settings != nullptr); + for (std::list<OCIO_GPUDisplayShader>::iterator it = SHADER_CACHE.begin(); + it != SHADER_CACHE.end(); + it++) { + if (it->input == input && it->view == view && it->display == display && it->look == look && + it->use_curve_mapping == use_curve_mapping) { + /* Move to front of the cache to mark as most recently used. */ + if (it != SHADER_CACHE.begin()) { + SHADER_CACHE.splice(SHADER_CACHE.begin(), SHADER_CACHE, it); } - cache[0] = found_item; - return &cache[0]; + + return *it; } } - /* LRU cache, shift other items back so we can insert at the front. */ - OCIO_GLSLCacheHandle last_item = cache[SHADER_CACHE_SIZE - 1]; - for (int j = SHADER_CACHE_SIZE - 1; j > 0; j--) { - cache[j] = cache[j - 1]; + + /* Remove least recently used element from cache. */ + if (SHADER_CACHE.size() >= SHADER_CACHE_MAX_SIZE) { + SHADER_CACHE.pop_back(); } - /* Copy last to front and let the caller initialize it. */ - cache[0] = last_item; - return &cache[0]; -} -/** \} */ + /* Create GPU shader. */ + SHADER_CACHE.emplace_front(); + OCIO_GPUDisplayShader &display_shader = SHADER_CACHE.front(); + + display_shader.input = input; + display_shader.view = view; + display_shader.display = display; + display_shader.look = look; + display_shader.use_curve_mapping = use_curve_mapping; + display_shader.valid = false; + + /* Create Processors. + * + * Scale and exponent are handled outside of OCIO shader so we can handle them + * as uniforms at the binding stage. OCIO would otherwise bake them into the + * shader code, requiring slow recompiles when interactively adjusting them. + * + * Note that OCIO does have the concept of dynamic properties, however there + * is no dynamic gamma and exposure is part of more expensive operations only. + * + * Since exposure must happen in scene linear, we use two processors. The input + * is usually scene linear already and so that conversion is often a no-op. + */ + OCIO_ConstProcessorRcPtr *processor_to_scene_linear = OCIO_configGetProcessorWithNames( + config, input, ROLE_SCENE_LINEAR); + OCIO_ConstProcessorRcPtr *processor_to_display = OCIO_createDisplayProcessor( + config, ROLE_SCENE_LINEAR, view, display, look, 1.0f, 1.0f); + + /* Create shader descriptions. */ + if (processor_to_scene_linear && processor_to_display) { + GpuShaderDescRcPtr shaderdesc_to_scene_linear = GpuShaderDesc::CreateShaderDesc(); + shaderdesc_to_scene_linear->setLanguage(GPU_LANGUAGE_GLSL_1_3); + shaderdesc_to_scene_linear->setFunctionName("OCIO_to_scene_linear"); + (*(ConstProcessorRcPtr *)processor_to_scene_linear) + ->getDefaultGPUProcessor() + ->extractGpuShaderInfo(shaderdesc_to_scene_linear); + shaderdesc_to_scene_linear->finalize(); + + GpuShaderDescRcPtr shaderdesc_to_display = GpuShaderDesc::CreateShaderDesc(); + shaderdesc_to_display->setLanguage(GPU_LANGUAGE_GLSL_1_3); + shaderdesc_to_display->setFunctionName("OCIO_to_display"); + (*(ConstProcessorRcPtr *)processor_to_display) + ->getDefaultGPUProcessor() + ->extractGpuShaderInfo(shaderdesc_to_display); + shaderdesc_to_display->finalize(); + + /* Create GPU shader and textures. */ + if (createGPUTextures( + display_shader.textures, shaderdesc_to_scene_linear, shaderdesc_to_display) && + createGPUCurveMapping(display_shader.curvemap, curve_mapping_settings) && + createGPUShader(display_shader.shader, + display_shader.textures, + shaderdesc_to_scene_linear, + shaderdesc_to_display, + use_curve_mapping)) { + display_shader.valid = true; + } + } -/* -------------------------------------------------------------------- */ -/** \name OCIO GLSL Implementation - * \{ */ + /* Free processors. */ + if (processor_to_scene_linear) { + OCIO_processorRelease(processor_to_scene_linear); + } + if (processor_to_display) { + OCIO_processorRelease(processor_to_display); + } -/* Detect if we can support GLSL drawing */ -bool OCIOImpl::supportGLSLDraw() -{ - /* Minimum supported version 3.3 does meet all requirements. */ - return true; + return display_shader; } /** - * Setup OpenGL contexts for a transform defined by processor using GLSL + * Setup GPU contexts for a transform defined by processor using GLSL. * All LUT allocating baking and shader compilation happens here. * * Once this function is called, callee could start drawing images * using regular 2D texture. * - * When all drawing is finished, finishGLSLDraw shall be called to - * restore OpenGL context to its pre-GLSL draw state. + * When all drawing is finished, gpuDisplayShaderUnbind must be called to + * restore GPU context to its previous state. */ -bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, - OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui, - OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, - OCIO_CurveMappingSettings *curve_mapping_settings, - float dither, - bool use_predivide, - bool use_overlay) +bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config, + const char *input, + const char *view, + const char *display, + const char *look, + OCIO_CurveMappingSettings *curve_mapping_settings, + const float scale, + const float exponent, + const float dither, + const bool use_predivide, + const bool use_overlay) { - ConstProcessorRcPtr processor_scene_to_ui = *(ConstProcessorRcPtr *)ocio_processor_scene_to_ui; - ConstProcessorRcPtr processpr_ui_to_display = *( - ConstProcessorRcPtr *)ocio_processor_ui_to_display; - bool use_curve_mapping = curve_mapping_settings != NULL; - - if (!processor_scene_to_ui || !processor_scene_to_ui) { + /* Get GPU shader from cache or create new one. */ + OCIO_GPUDisplayShader &display_shader = getGPUDisplayShader( + config, input, view, display, look, curve_mapping_settings); + if (!display_shader.valid) { return false; } - /* Create state if needed. */ - OCIO_GLSLDrawState *state; - if (!*state_r) - *state_r = allocateOpenGLState(); - state = *state_r; - - /* Compute cache IDs. */ - GpuShaderDesc shaderDesc; - shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3); - shaderDesc.setFunctionName("OCIODisplay"); - shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE); - - const char *shader_cache_str = processor_scene_to_ui->getGpuShaderTextCacheID(shaderDesc); - const char *lut3d_cache_str = processor_scene_to_ui->getGpuLut3DCacheID(shaderDesc); - /* Used for comparison. */ - std::string shaderCacheID = shader_cache_str; - std::string lut3dCacheID = lut3d_cache_str; - - size_t shader_cache_id = hash_string(shader_cache_str); - size_t lut3d_cache_id = hash_string(lut3d_cache_str); - size_t curvemap_cache_id = curve_mapping_settings ? curve_mapping_settings->cache_id : 0; - - OCIO_GLSLCacheHandle *shader_handle = cacheSearch(state->shader_cache, shader_cache_id); - OCIO_GLSLCacheHandle *lut3d_handle = cacheSearch(state->lut3d_cache, lut3d_cache_id); - /* We cannot keep more than one cache for curvemap because their cache id is a pointer. - * The pointer cannot be the same for one update but can be the same after a second update. */ - OCIO_GLSLCacheHandle *curvemap_handle = &state->curvemap_cache[0]; - - OCIO_GLSLShader **shader_ptr = (OCIO_GLSLShader **)&shader_handle->data; - OCIO_GLSLLut3d **lut3d_ptr = (OCIO_GLSLLut3d **)&lut3d_handle->data; - OCIO_GLSLCurveMappping **curvemap_ptr = (OCIO_GLSLCurveMappping **)&curvemap_handle->data; - - ensureGLSLShader( - shader_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID); - ensureGLSLLut3d( - lut3d_ptr, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID); - ensureGLSLCurveMapping(curvemap_ptr, curve_mapping_settings); - - OCIO_GLSLShader *shader = (OCIO_GLSLShader *)shader_handle->data; - OCIO_GLSLLut3d *shader_lut = (OCIO_GLSLLut3d *)lut3d_handle->data; - OCIO_GLSLCurveMappping *shader_curvemap = (OCIO_GLSLCurveMappping *)curvemap_handle->data; - - updateGLSLShader( - shader, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, shaderCacheID); - updateGLSLLut3d( - shader_lut, &processor_scene_to_ui, &processpr_ui_to_display, &shaderDesc, lut3dCacheID); - updateGLSLCurveMapping(shader_curvemap, curve_mapping_settings, curvemap_cache_id); - - /* Update handles cache keys. */ - shader_handle->cache_id = shader_cache_id; - lut3d_handle->cache_id = lut3d_cache_id; - curvemap_handle->cache_id = curvemap_cache_id; - - if (shader->valid && shader_lut->valid && shader_curvemap->valid) { - /* Bind textures to sampler units. Texture 0 is set by caller. - * Uniforms have already been set for texture bind points.*/ - - if (!use_overlay) { - /* Avoid missing binds. */ - GPU_texture_bind(shader_lut->texture_dummy, 1); - } - GPU_texture_bind(shader_lut->texture, 2); - GPU_texture_bind(shader_lut->texture_display, 3); - GPU_texture_bind(shader_curvemap->texture, 4); + /* Verify the shader is valid. */ + OCIO_GPUTextures &textures = display_shader.textures; + OCIO_GPUShader &shader = display_shader.shader; + OCIO_GPUCurveMappping &curvemap = display_shader.curvemap; - /* Bind UBO. */ - GPU_uniformbuf_bind(shader_curvemap->buffer, shader->ubo_bind); + /* Update and bind curve mapping data. */ + if (curve_mapping_settings) { + updateGPUCurveMapping(curvemap, curve_mapping_settings); + GPU_uniformbuf_bind(curvemap.buffer, shader.ubo_bind); + GPU_texture_bind(curvemap.texture, TEXTURE_SLOT_CURVE_MAPPING); + } - /* TODO(fclem): remove remains of IMM. */ - immBindShader(shader->shader); + /* Bind textures to sampler units. Texture 0 is set by caller. + * Uniforms have already been set for texture bind points.*/ + if (!use_overlay) { + /* Avoid missing binds. */ + GPU_texture_bind(textures.dummy, TEXTURE_SLOT_OVERLAY); + } + for (int i = 0; i < textures.luts.size(); i++) { + GPU_texture_bind(textures.luts[i].texture, TEXTURE_SLOT_LUTS_OFFSET + i); + } - /* Bind Shader and set uniforms. */ - // GPU_shader_bind(shader->shader); - GPU_shader_uniform_float(shader->shader, shader->dither_loc, dither); - GPU_shader_uniform_int(shader->shader, shader->overlay_loc, use_overlay); - GPU_shader_uniform_int(shader->shader, shader->predivide_loc, use_predivide); - GPU_shader_uniform_int(shader->shader, shader->curve_mapping_loc, use_curve_mapping); + /* TODO(fclem): remove remains of IMM. */ + immBindShader(shader.shader); - return true; - } + /* Bind Shader and set uniforms. */ + // GPU_shader_bind(shader.shader); + GPU_shader_uniform_float(shader.shader, shader.scale_loc, scale); + GPU_shader_uniform_float(shader.shader, shader.exponent_loc, exponent); + GPU_shader_uniform_float(shader.shader, shader.dither_loc, dither); + GPU_shader_uniform_int(shader.shader, shader.overlay_loc, use_overlay); + GPU_shader_uniform_int(shader.shader, shader.predivide_loc, use_predivide); - return false; + return true; } -void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/) +void OCIOImpl::gpuDisplayShaderUnbind() { immUnbindProgram(); } -void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state) +void OCIOImpl::gpuCacheFree() { - for (int i = 0; i < SHADER_CACHE_SIZE; i++) { - if (state->shader_cache[i].data) { - freeGLSLShader((OCIO_GLSLShader *)state->shader_cache[i].data); - } - if (state->lut3d_cache[i].data) { - freeGLSLLut3d((OCIO_GLSLLut3d *)state->lut3d_cache[i].data); - } - if (state->curvemap_cache[i].data) { - freeGLSLCurveMapping((OCIO_GLSLCurveMappping *)state->curvemap_cache[i].data); - } - } - - MEM_freeN(state); + SHADER_CACHE.clear(); } /** \} */ |