Compare commits

...

8 Commits

Author SHA1 Message Date
28f799df92 OpenColorIO: address review comments 2021-02-03 15:12:28 +01:00
6adb1fd37c Windows: OCIO2 build fixes
Nothing too interesting here, the static imports define
changed as did some of the library names/locations
2021-02-01 10:47:44 -07:00
1b01957bb5 OpenColorIO: remove default display workaround
A fix for this is in 2.0 (and recent 1.1.x versions), no need for this anymore.
2021-02-01 15:42:46 +01:00
7c8cbc67ab OpenColorIO: use aces_interchange role to detect CIE XYZ values
We need standard CIE XYZ values for rendering effects like blackbody emission.
The relation to the scene linear role is based on OpenColorIO configuration.

In OpenColorIO 2.0 configs roles can no longer have the same name as color
spaces, which means our XYZ role and colorspace in the configuration give an
error.

Instead use the new standard aces_interchange role, which relates scene linear
to a known scene referred color space. Compatibility with the old XYZ role is
preserved, if the configuration file has no conflicting names.

Also includes a non-functional change to the configuraton file to use an
XYZ-to-ACES matrix instead of REC709-to-ACES, makes debugging a little easier
since the matrix is the same one we have in the code now and that is also
found easily in the ACES specs.

There is a new cie_xyz_d65_interchange role that we should add support for,
for interchange of display referred colorspace (as opposed to scene referred).
I couldn't immediately understand how that is supposed to be defined, will
probably leave that for another patch unless someone knows how.
2021-02-01 15:42:46 +01:00
4e352851e4 OpenColorIO: update GPU display shader for version 2.0
To avoid baking exposure and gamma into the GLSL shader and requiring slow
recompiles when tweaking, we manually apply them in the shader. This leads
to some logic duplicaton between the CPU and GPU display processor, but it
seems unavoidable.

Caching was also changed. Previously this was done both on the imbuf and
opencolorio module levels. Now it's all done in the opencolorio module by
simply matching color space names. We no longer use cacheIDs from OpenColorIO
since computing them is expensive, and they are unlikely to match now that
more is baked into the shader code.

Shaders can now use multiple 2D textures, 3D textures and uniforms, rather
than a single 3D texture. So allocating and binding those adds some code.

Color space conversions for blending with overlays is now hardcoded in the
shader. This was using harcoded numbers anyway, if this every becomes a
general OpenColorIO transform it can be changed, but for now there is no
point to add code complexity.
2021-02-01 15:42:46 +01:00
a5139ce82c OpenColorIO: update display transforms for version 2.0
Needs a bit more manual work constructing the transform. LegacyViewingPipeline
could also have been used, but isn't really any simpler and since it's legacy
we better not rely on it.

This moves more logic into the opencolorio module, to simplify the API. There is
no need to wrap a dozen functions just to be able to do this in C rather than C++.
It's also tightly coupled to the GPU shader logic, and so should be in the same
module.
2021-02-01 15:42:46 +01:00
0eb26e349d OpenColorIO: update processors and transforms for version 2.0
CPU processors now need to be created to do CPU processing. These are cached
internally, but the cache lookup is not fast enough to execute per pixel or
texture sample, so for performance these are now also exposed in the C API.

The C API for transform will no longer be needed afer all changes, so remove
it to simplify the API and fallback implementation.
2021-02-01 14:46:15 +01:00
84f4e9b431 Build: OpenColorIO 2.0.0 support for make deps and install_deps.sh
* Tinyxml was replaced with Expat, adding a new dependency.
* Yaml-cpp is now built as a dependency on Unix, as was already done on Windows.
* Removed currently unused LCMS code, couldn't be bothered to update and test it.
* Pystring remains built as part of OCIO itself, since it has no good build system.

We currently require OpenColorIO 2.0.0 and the upcoming code changes have no
compatibility with 1.x. Compatibility could be added, but it's rather complicated
and I only want to do the work if it's really needed.

The install_deps.sh support was implemented by Jeroen, I have no tested it myself.

The Windows code was updated, but I have not tested if it actually works, it
almost certainly will not.
2021-02-01 14:46:14 +01:00
30 changed files with 1356 additions and 1868 deletions

View File

@@ -727,8 +727,9 @@ set_and_warn_dependency(WITH_TBB WITH_MOD_FLUID OFF)
# NanoVDB requires OpenVDB to convert the data structure # NanoVDB requires OpenVDB to convert the data structure
set_and_warn_dependency(WITH_OPENVDB WITH_NANOVDB OFF) set_and_warn_dependency(WITH_OPENVDB WITH_NANOVDB OFF)
# OpenVDB uses 'half' type from OpenEXR & fails to link without OpenEXR enabled. # OpenVDB and OpenColorIO uses 'half' type from OpenEXR
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF) set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENCOLORIO OFF)
# auto enable openimageio for cycles # auto enable openimageio for cycles
if(WITH_CYCLES) if(WITH_CYCLES)

View File

@@ -70,7 +70,6 @@ include(cmake/cuew.cmake)
include(cmake/opensubdiv.cmake) include(cmake/opensubdiv.cmake)
include(cmake/sdl.cmake) include(cmake/sdl.cmake)
include(cmake/opencollada.cmake) include(cmake/opencollada.cmake)
include(cmake/opencolorio.cmake)
include(cmake/llvm.cmake) include(cmake/llvm.cmake)
include(cmake/clang.cmake) include(cmake/clang.cmake)
if(APPLE) if(APPLE)
@@ -104,18 +103,15 @@ if(NOT APPLE)
include(cmake/xr_openxr.cmake) include(cmake/xr_openxr.cmake)
endif() endif()
# OpenColorIO and dependencies.
include(cmake/expat.cmake)
include(cmake/yamlcpp.cmake)
include(cmake/opencolorio.cmake)
if(WITH_WEBP) if(WITH_WEBP)
include(cmake/webp.cmake) include(cmake/webp.cmake)
endif() endif()
if(WIN32)
# OCIO deps
include(cmake/tinyxml.cmake)
include(cmake/yamlcpp.cmake)
# LCMS is an OCIO dep, but only if you build the apps, leaving it here for convenience
# include(cmake/lcms.cmake)
endif()
if(NOT WIN32 OR ENABLE_MINGW64) if(NOT WIN32 OR ENABLE_MINGW64)
include(cmake/gmp.cmake) include(cmake/gmp.cmake)
include(cmake/openjpeg.cmake) include(cmake/openjpeg.cmake)

View File

@@ -16,16 +16,20 @@
# #
# ***** END GPL LICENSE BLOCK ***** # ***** END GPL LICENSE BLOCK *****
set(LCMS_EXTRA_ARGS set(EXPAT_EXTRA_ARGS
-DEXPAT_BUILD_DOCS=OFF
-DEXPAT_BUILD_EXAMPLES=OFF
-DEXPAT_BUILD_TESTS=OFF
-DEXPAT_BUILD_TOOLS=OFF
-DEXPAT_SHARED_LIBS=OFF
) )
ExternalProject_Add(external_lcms ExternalProject_Add(external_expat
URL ${LCMS_URI} URL ${EXPAT_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR} DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${LCMS_HASH} URL_HASH MD5=${EXPAT_HASH}
PREFIX ${BUILD_DIR}/lcms PREFIX ${BUILD_DIR}/expat
# Patch taken from ocio. CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/expat ${DEFAULT_CMAKE_FLAGS} ${EXPAT_EXTRA_ARGS}
PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/cmakelists_lcms.txt ${BUILD_DIR}/lcms/src/external_lcms/CMakeLists.txt INSTALL_DIR ${LIBDIR}/expat
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/lcms ${DEFAULT_CMAKE_FLAGS} ${LCMS_EXTRA_ARGS} SOURCE_SUBDIR expat
INSTALL_DIR ${LIBDIR}/lcms
) )

View File

@@ -22,8 +22,8 @@ ExternalProject_Add(external_nasm
URL_HASH SHA256=${NASM_HASH} URL_HASH SHA256=${NASM_HASH}
PREFIX ${BUILD_DIR}/nasm PREFIX ${BUILD_DIR}/nasm
PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/nasm/src/external_nasm < ${PATCH_DIR}/nasm.diff PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/nasm/src/external_nasm < ${PATCH_DIR}/nasm.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/nasm CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && ./autogen.sh && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/nasm
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make -j${MAKE_THREADS} BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make -j${MAKE_THREADS} && make manpages
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make install INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/nasm/src/external_nasm/ && make install
INSTALL_DIR ${LIBDIR}/nasm INSTALL_DIR ${LIBDIR}/nasm
) )

View File

@@ -18,16 +18,22 @@
set(OPENCOLORIO_EXTRA_ARGS set(OPENCOLORIO_EXTRA_ARGS
-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_APPS=OFF
-DOCIO_BUILD_PYGLUE=OFF -DOCIO_BUILD_PYTHON=OFF
-DOCIO_BUILD_NUKE=OFF -DOCIO_BUILD_NUKE=OFF
-DOCIO_USE_BOOST_PTR=OFF -DOCIO_BUILD_JAVA=OFF
-DOCIO_BUILD_STATIC=ON -DBUILD_SHARED_LIBS=OFF
-DOCIO_BUILD_SHARED=OFF
-DOCIO_BUILD_TRUELIGHT=OFF
-DOCIO_BUILD_DOCS=OFF -DOCIO_BUILD_DOCS=OFF
-DOCIO_BUILD_PYGLUE=OFF -DOCIO_BUILD_TESTS=OFF
-DOCIO_BUILD_JNIGLUE=OFF -DOCIO_BUILD_GPU_TESTS=OFF
-DOCIO_STATIC_JNIGLUE=OFF -DOCIO_USE_SSE=ON
# Manually build ext packages except for pystring, which does not have
# a CMake or autotools build system that we can easily use.
-DOCIO_INSTALL_EXT_PACKAGES=MISSING
-DHalf_ROOT=${LIBDIR}/openexr
-DHalf_STATIC_LIBRARY=ON
-Dexpat_ROOT=${LIBDIR}/expat
-Dyaml-cpp_ROOT=${LIBDIR}/yamlcpp
) )
if(APPLE AND NOT("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")) if(APPLE AND NOT("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64"))
@@ -41,24 +47,7 @@ if(WIN32)
set(OCIO_PATCH opencolorio_win.diff) set(OCIO_PATCH opencolorio_win.diff)
set(OPENCOLORIO_EXTRA_ARGS set(OPENCOLORIO_EXTRA_ARGS
${OPENCOLORIO_EXTRA_ARGS} ${OPENCOLORIO_EXTRA_ARGS}
-DOCIO_BUILD_TESTS=OFF
-DOCIO_USE_SSE=ON
-DOCIO_INLINES_HIDDEN=OFF -DOCIO_INLINES_HIDDEN=OFF
-DOCIO_PYGLUE_LINK=OFF
-DOCIO_PYGLUE_RESPECT_ABI=OFF
-DOCIO_PYGLUE_SONAME=OFF
-DOCIO_PYGLUE_LIB_PREFIX=OFF
-DUSE_EXTERNAL_TINYXML=ON
-DTINYXML_INCLUDE_DIR=${LIBDIR}/tinyxml/include
-DTINYXML_LIBRARY=${LIBDIR}/tinyxml/lib/tinyxml${libext}
-DUSE_EXTERNAL_YAML=ON
-DYAML_CPP_FOUND=ON
-DYAML_CPP_VERSION=${YAMLCPP_VERSION}
-DUSE_EXTERNAL_LCMS=ON
-DINC_1=${LIBDIR}/tinyxml/include
-DINC_2=${LIBDIR}/yamlcpp/include
# Lie because ocio cmake is demanding boost even though it is not needed.
-DYAML_CPP_VERSION=0.5.0
) )
else() else()
set(OCIO_PATCH opencolorio.diff) set(OCIO_PATCH opencolorio.diff)
@@ -72,48 +61,42 @@ ExternalProject_Add(external_opencolorio
DOWNLOAD_DIR ${DOWNLOAD_DIR} DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${OPENCOLORIO_HASH} URL_HASH MD5=${OPENCOLORIO_HASH}
PREFIX ${BUILD_DIR}/opencolorio PREFIX ${BUILD_DIR}/opencolorio
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/opencolorio/src/external_opencolorio < ${PATCH_DIR}/${OCIO_PATCH}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencolorio ${DEFAULT_CMAKE_FLAGS} ${OPENCOLORIO_EXTRA_ARGS} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opencolorio ${DEFAULT_CMAKE_FLAGS} ${OPENCOLORIO_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/opencolorio INSTALL_DIR ${LIBDIR}/opencolorio
) )
if(NOT WIN32)
add_custom_command(
OUTPUT ${LIBDIR}/opencolorio/lib/libtinyxml.a
COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libtinyxml.a ${LIBDIR}/opencolorio/lib/libtinyxml.a
COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/libyaml-cpp.a
)
add_custom_target(external_opencolorio_extra ALL DEPENDS external_opencolorio ${LIBDIR}/opencolorio/lib/libtinyxml.a)
endif()
add_dependencies( add_dependencies(
external_opencolorio external_opencolorio
external_boost external_yamlcpp
external_expat
external_openexr
) )
if(WIN32) if(WIN32)
add_dependencies(
external_opencolorio
external_tinyxml
external_yamlcpp
)
if(BUILD_MODE STREQUAL Release) if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_opencolorio after_install ExternalProject_Add_Step(external_opencolorio after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/include ${HARVEST_TARGET}/opencolorio/include COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/include ${HARVEST_TARGET}/opencolorio/include
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/lib/static ${HARVEST_TARGET}/opencolorio/lib COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencolorio/lib ${HARVEST_TARGET}/opencolorio/lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/yamlcpp/lib/libyaml-cppmd.lib ${HARVEST_TARGET}/opencolorio/lib/libyaml-cpp.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/yamlcpp/lib/libyaml-cppmd.lib ${HARVEST_TARGET}/opencolorio/lib/libyaml-cpp.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tinyxml/lib/tinyxml.lib ${HARVEST_TARGET}/opencolorio/lib/tinyxml.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/expat/lib/libexpatMD.lib ${HARVEST_TARGET}/opencolorio/lib/libexpatMD.lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/pystring.lib ${HARVEST_TARGET}/opencolorio/lib/pystring.lib
DEPENDEES install DEPENDEES install
) )
endif() endif()
if(BUILD_MODE STREQUAL Debug) if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_opencolorio after_install ExternalProject_Add_Step(external_opencolorio after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencolorio/lib/static/Opencolorio.lib ${HARVEST_TARGET}/opencolorio/lib/OpencolorIO_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencolorio/lib/Opencolorio.lib ${HARVEST_TARGET}/opencolorio/lib/OpencolorIO_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/yamlcpp/lib/libyaml-cppmdd.lib ${HARVEST_TARGET}/opencolorio/lib/libyaml-cpp_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/yamlcpp/lib/libyaml-cppmdd.lib ${HARVEST_TARGET}/opencolorio/lib/libyaml-cpp_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tinyxml/lib/tinyxml.lib ${HARVEST_TARGET}/opencolorio/lib/tinyxml_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/expat/lib/libexpatdMD.lib ${HARVEST_TARGET}/opencolorio/lib/libexpatdMD.lib
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/pystring.lib ${HARVEST_TARGET}/opencolorio/lib/pystring_d.lib
DEPENDEES install DEPENDEES install
) )
endif() endif()
else()
ExternalProject_Add_Step(external_opencolorio after_install
COMMAND cp ${LIBDIR}/yamlcpp/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${LIBDIR}/expat/lib/libexpat.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${BUILD_DIR}/opencolorio/src/external_opencolorio-build/ext/dist/lib/libpystring.a ${LIBDIR}/opencolorio/lib/
DEPENDEES install
)
endif() endif()

View File

@@ -1,31 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
set(TINYXML_EXTRA_ARGS
)
ExternalProject_Add(external_tinyxml
URL ${TINYXML_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${TINYXML_HASH}
PREFIX ${BUILD_DIR}/tinyxml
# patch taken from ocio
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/tinyxml/src/external_tinyxml < ${PATCH_DIR}/tinyxml.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/tinyxml ${DEFAULT_CMAKE_FLAGS} ${TINYXML_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/tinyxml
)

View File

@@ -109,9 +109,9 @@ set(OPENCOLLADA_VERSION v1.6.68)
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz) set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
set(OPENCOLLADA_HASH ee7dae874019fea7be11613d07567493) set(OPENCOLLADA_HASH ee7dae874019fea7be11613d07567493)
set(OPENCOLORIO_VERSION 1.1.1) set(OPENCOLORIO_VERSION 2.0.0)
set(OPENCOLORIO_URI https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz) set(OPENCOLORIO_URI https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz)
set(OPENCOLORIO_HASH 23d8b9ac81599305539a5a8674b94a3d) set(OPENCOLORIO_HASH 1a2e3478b6cd9a1549f24e1b2205e3f0)
set(LLVM_VERSION 9.0.1) set(LLVM_VERSION 9.0.1)
set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz) set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz)
@@ -256,9 +256,9 @@ set(YAMLCPP_VERSION 0.6.3)
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION}) set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2) set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
set(LCMS_VERSION 2.9) set(EXPAT_VERSION 2_2_10)
set(LCMS_URI https://nchc.dl.sourceforge.net/project/lcms/lcms/${LCMS_VERSION}/lcms2-${LCMS_VERSION}.tar.gz) set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
set(LCMS_HASH 8de1b7724f578d2995c8fdfa35c3ad0e) set(EXPAT_HASH 7ca5f09959fcb9a57618368deb627b9f)
set(PUGIXML_VERSION 1.10) set(PUGIXML_VERSION 1.10)
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz) set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
@@ -313,8 +313,8 @@ set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa//mesa-${MESA_VERSION}.tar.xz)
set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be) set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be)
set(NASM_VERSION 2.15.02) set(NASM_VERSION 2.15.02)
set(NASM_URI https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.xz) set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
set(NASM_HASH f4fd1329b1713e1ccd34b2fc121c4bcd278c9f91cc4cb205ae8fcd2e4728dd14) set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
set(XR_OPENXR_SDK_VERSION 1.0.8) set(XR_OPENXR_SDK_VERSION 1.0.8)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz) set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)

View File

@@ -17,13 +17,18 @@
# ***** END GPL LICENSE BLOCK ***** # ***** END GPL LICENSE BLOCK *****
set(YAMLCPP_EXTRA_ARGS set(YAMLCPP_EXTRA_ARGS
-DBUILD_GMOCK=OFF
-DYAML_CPP_BUILD_TESTS=OFF -DYAML_CPP_BUILD_TESTS=OFF
-DYAML_CPP_BUILD_TOOLS=OFF -DYAML_CPP_BUILD_TOOLS=OFF
-DYAML_CPP_BUILD_CONTRIB=OFF -DYAML_CPP_BUILD_CONTRIB=OFF
-DYAML_MSVC_SHARED_RT=ON
) )
if(WIN32)
set(YAMLCPP_EXTRA_ARGS
${YAMLCPP_EXTRA_ARGS}
-DBUILD_GMOCK=OFF
-DYAML_MSVC_SHARED_RT=ON)
endif()
ExternalProject_Add(external_yamlcpp ExternalProject_Add(external_yamlcpp
URL ${YAMLCPP_URI} URL ${YAMLCPP_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR} DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@@ -419,10 +419,10 @@ TBB_FORCE_BUILD=false
TBB_FORCE_REBUILD=false TBB_FORCE_REBUILD=false
TBB_SKIP=false TBB_SKIP=false
OCIO_VERSION="1.1.1" OCIO_VERSION="2.0.0"
OCIO_VERSION_SHORT="1.1" OCIO_VERSION_SHORT="2.0"
OCIO_VERSION_MIN="1.0" OCIO_VERSION_MIN="2.0"
OCIO_VERSION_MAX="1.2" OCIO_VERSION_MAX="2.0"
OCIO_FORCE_BUILD=false OCIO_FORCE_BUILD=false
OCIO_FORCE_REBUILD=false OCIO_FORCE_REBUILD=false
OCIO_SKIP=false OCIO_SKIP=false
@@ -1808,8 +1808,8 @@ compile_OCIO() {
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D OCIO_BUILD_APPS=OFF" cmake_d="$cmake_d -D OCIO_BUILD_APPS=OFF"
cmake_d="$cmake_d -D OCIO_BUILD_PYGLUE=OFF" cmake_d="$cmake_d -D OCIO_BUILD_PYTHON=OFF"
cmake_d="$cmake_d -D STOP_ON_WARNING=OFF" cmake_d="$cmake_d -D OCIO_BUILD_GPU_TESTS=OFF"
if file /bin/cp | grep -q '32-bit'; then if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686" cflags="-fPIC -m32 -march=i686"

View File

@@ -26,7 +26,8 @@ ENDIF()
SET(_opencolorio_FIND_COMPONENTS SET(_opencolorio_FIND_COMPONENTS
OpenColorIO OpenColorIO
yaml-cpp yaml-cpp
tinyxml expat
pystring
) )
SET(_opencolorio_SEARCH_DIRS SET(_opencolorio_SEARCH_DIRS
@@ -60,12 +61,23 @@ FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS})
ENDIF() ENDIF()
ENDFOREACH() ENDFOREACH()
IF(EXISTS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h")
# Search twice, because this symbol changed between OCIO 1.x and 2.x
FILE(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" _opencolorio_version
REGEX "^#define OCIO_VERSION_STR[ \t].*$")
IF(NOT _opencolorio_version)
file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" _opencolorio_version
REGEX "^#define OCIO_VERSION[ \t].*$")
ENDIF()
STRING(REGEX MATCHALL "[0-9]+[.0-9]+" OPENCOLORIO_VERSION ${_opencolorio_version})
ENDIF()
# handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if # handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if
# all listed variables are TRUE # all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs) INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO DEFAULT_MSG FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO
_opencolorio_LIBRARIES OPENCOLORIO_INCLUDE_DIR) REQUIRED_VARS _opencolorio_LIBRARIES OPENCOLORIO_INCLUDE_DIR
VERSION_VAR OPENCOLORIO_VERSION)
IF(OPENCOLORIO_FOUND) IF(OPENCOLORIO_FOUND)
SET(OPENCOLORIO_LIBRARIES ${_opencolorio_LIBRARIES}) SET(OPENCOLORIO_LIBRARIES ${_opencolorio_LIBRARIES})
@@ -78,6 +90,7 @@ MARK_AS_ADVANCED(
OPENCOLORIO_OPENCOLORIO_LIBRARY OPENCOLORIO_OPENCOLORIO_LIBRARY
OPENCOLORIO_TINYXML_LIBRARY OPENCOLORIO_TINYXML_LIBRARY
OPENCOLORIO_YAML-CPP_LIBRARY OPENCOLORIO_YAML-CPP_LIBRARY
OPENCOLORIO_VERSION
) )
UNSET(COMPONENT) UNSET(COMPONENT)

View File

@@ -293,7 +293,12 @@ if(WITH_OPENIMAGEIO)
endif() endif()
if(WITH_OPENCOLORIO) if(WITH_OPENCOLORIO)
find_package(OpenColorIO) find_package(OpenColorIO 2.0.0)
if(NOT OPENCOLORIO_FOUND)
set(WITH_OPENCOLORIO OFF)
message(STATUS "OpenColorIO not found")
endif()
endif() endif()
if(WITH_OPENVDB) if(WITH_OPENVDB)

View File

@@ -385,7 +385,7 @@ if(WITH_OPENIMAGEIO)
endif() endif()
if(WITH_OPENCOLORIO) if(WITH_OPENCOLORIO)
find_package_wrapper(OpenColorIO) find_package_wrapper(OpenColorIO 2.0.0)
set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES}) set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES})
set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere

View File

@@ -500,7 +500,7 @@ if(WITH_OPENIMAGEIO)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG}) set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0") set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD") set(OPENCOLORIO_DEFINITIONS "-DDOpenColorIO_SKIP_IMPORTS")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe") set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
add_definitions(-DOIIO_STATIC_DEFINE) add_definitions(-DOIIO_STATIC_DEFINE)
add_definitions(-DOIIO_NO_SSE=1) add_definitions(-DOIIO_NO_SSE=1)
@@ -538,11 +538,13 @@ if(WITH_OPENCOLORIO)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib) set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
set(OPENCOLORIO_LIBRARIES set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib
optimized ${OPENCOLORIO_LIBPATH}/tinyxml.lib
optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib
optimized ${OPENCOLORIO_LIBPATH}/libexpatMD.lib
optimized ${OPENCOLORIO_LIBPATH}/pystring.lib
debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib
debug ${OPENCOLORIO_LIBPATH}/tinyxml_d.lib
debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
) )
set(OPENCOLORIO_DEFINITIONS) set(OPENCOLORIO_DEFINITIONS)
endif() endif()

View File

@@ -134,7 +134,7 @@ if(WITH_OPENCOLORIO)
${OPENCOLORIO_INCLUDE_DIRS} ${OPENCOLORIO_INCLUDE_DIRS}
) )
if(WIN32) if(WIN32)
add_definitions(-DOpenColorIO_STATIC) add_definitions(-DOpenColorIO_SKIP_IMPORTS)
endif() endif()
endif() endif()

View File

@@ -192,6 +192,7 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace,
return; return;
} }
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
is_scene_linear = true; is_scene_linear = true;
is_srgb = true; is_srgb = true;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
@@ -201,10 +202,10 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace,
float cG[3] = {0, v, 0}; float cG[3] = {0, v, 0};
float cB[3] = {0, 0, v}; float cB[3] = {0, 0, v};
float cW[3] = {v, v, v}; float cW[3] = {v, v, v};
processor->applyRGB(cR); device_processor->applyRGB(cR);
processor->applyRGB(cG); device_processor->applyRGB(cG);
processor->applyRGB(cB); device_processor->applyRGB(cB);
processor->applyRGB(cW); device_processor->applyRGB(cW);
/* Make sure that there is no channel crosstalk. */ /* Make sure that there is no channel crosstalk. */
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f || if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
@@ -267,6 +268,7 @@ inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels,
/* TODO: implement faster version for when we know the conversion /* TODO: implement faster version for when we know the conversion
* is a simple matrix transform between linear spaces. In that case * is a simple matrix transform between linear spaces. In that case
* un-premultiply is not needed. */ * un-premultiply is not needed. */
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
/* Process large images in chunks to keep temporary memory requirement down. */ /* Process large images in chunks to keep temporary memory requirement down. */
const size_t chunk_size = std::min((size_t)(16 * 1024 * 1024), num_pixels); const size_t chunk_size = std::min((size_t)(16 * 1024 * 1024), num_pixels);
@@ -289,7 +291,7 @@ inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels,
} }
OCIO::PackedImageDesc desc((float *)float_pixels.data(), width, 1, 4); OCIO::PackedImageDesc desc((float *)float_pixels.data(), width, 1, 4);
processor->apply(desc); device_processor->apply(desc);
for (size_t i = 0; i < width; i++) { for (size_t i = 0; i < width; i++) {
float4 value = float_pixels[i]; float4 value = float_pixels[i];
@@ -345,13 +347,14 @@ void ColorSpaceManager::to_scene_linear(ColorSpaceProcessor *processor_,
const OCIO::Processor *processor = (const OCIO::Processor *)processor_; const OCIO::Processor *processor = (const OCIO::Processor *)processor_;
if (processor) { if (processor) {
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
if (channels == 3) { if (channels == 3) {
processor->applyRGB(pixel); device_processor->applyRGB(pixel);
} }
else if (channels == 4) { else if (channels == 4) {
if (pixel[3] == 1.0f || pixel[3] == 0.0f) { if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
/* Fast path for RGBA. */ /* Fast path for RGBA. */
processor->applyRGB(pixel); device_processor->applyRGB(pixel);
} }
else { else {
/* Un-associate and associate alpha since color management should not /* Un-associate and associate alpha since color management should not
@@ -363,7 +366,7 @@ void ColorSpaceManager::to_scene_linear(ColorSpaceProcessor *processor_,
pixel[1] *= inv_alpha; pixel[1] *= inv_alpha;
pixel[2] *= inv_alpha; pixel[2] *= inv_alpha;
processor->applyRGB(pixel); device_processor->applyRGB(pixel);
pixel[0] *= alpha; pixel[0] *= alpha;
pixel[1] *= alpha; pixel[1] *= alpha;

View File

@@ -35,6 +35,7 @@
#include "util/util_foreach.h" #include "util/util_foreach.h"
#include "util/util_murmurhash.h" #include "util/util_murmurhash.h"
#include "util/util_task.h" #include "util/util_task.h"
#include "util/util_transform.h"
#ifdef WITH_OCIO #ifdef WITH_OCIO
# include <OpenColorIO/OpenColorIO.h> # include <OpenColorIO/OpenColorIO.h>
@@ -399,39 +400,7 @@ ShaderManager::ShaderManager()
update_flags = UPDATE_ALL; update_flags = UPDATE_ALL;
beckmann_table_offset = TABLE_OFFSET_INVALID; beckmann_table_offset = TABLE_OFFSET_INVALID;
xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f); init_xyz_transforms();
xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
if (config) {
if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
if (to_rgb_processor && to_xyz_processor) {
float r[] = {1.0f, 0.0f, 0.0f};
float g[] = {0.0f, 1.0f, 0.0f};
float b[] = {0.0f, 0.0f, 1.0f};
to_xyz_processor->applyRGB(r);
to_xyz_processor->applyRGB(g);
to_xyz_processor->applyRGB(b);
rgb_to_y = make_float3(r[1], g[1], b[1]);
float x[] = {1.0f, 0.0f, 0.0f};
float y[] = {0.0f, 1.0f, 0.0f};
float z[] = {0.0f, 0.0f, 1.0f};
to_rgb_processor->applyRGB(x);
to_rgb_processor->applyRGB(y);
to_rgb_processor->applyRGB(z);
xyz_to_r = make_float3(x[0], y[0], z[0]);
xyz_to_g = make_float3(x[1], y[1], z[1]);
xyz_to_b = make_float3(x[2], y[2], z[2]);
}
}
}
#endif
} }
ShaderManager::~ShaderManager() ShaderManager::~ShaderManager()
@@ -829,4 +798,89 @@ bool ShaderManager::need_update() const
return update_flags != UPDATE_NONE; return update_flags != UPDATE_NONE;
} }
#ifdef WITH_OCIO
static bool to_scene_linear_transform(OCIO::ConstConfigRcPtr &config,
const char *colorspace,
Transform &to_scene_linear)
{
OCIO::ConstProcessorRcPtr processor;
try {
processor = config->getProcessor(OCIO::ROLE_SCENE_LINEAR, colorspace);
}
catch (OCIO::Exception &exception) {
return false;
}
if (!processor) {
return false;
}
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
if (!device_processor) {
return false;
}
to_scene_linear = transform_identity();
device_processor->applyRGB(&to_scene_linear.x.x);
device_processor->applyRGB(&to_scene_linear.y.x);
device_processor->applyRGB(&to_scene_linear.z.x);
to_scene_linear = transform_transposed_inverse(to_scene_linear);
return true;
}
#endif
void ShaderManager::init_xyz_transforms()
{
/* Default to ITU-BT.709 in case no appropriate transform found. */
xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
/* Get from OpenColorO config if it has the required roles. */
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
if (!config && config->hasRole(OCIO::ROLE_SCENE_LINEAR)) {
return;
}
Transform xyz_to_rgb;
if (config->hasRole("aces_interchange")) {
/* Standard OpenColorIO role, defined as ACES2065-1. */
const Transform xyz_to_aces = make_transform(1.0498110175f,
0.0f,
-0.0000974845f,
0.0f,
-0.4959030231f,
1.3733130458f,
0.0982400361f,
0.0f,
0.0f,
0.0f,
0.9912520182f,
0.0f);
Transform aces_to_rgb;
if (!to_scene_linear_transform(config, "aces_interchange", aces_to_rgb)) {
return;
}
xyz_to_rgb = aces_to_rgb * xyz_to_aces;
}
else if (config->hasRole("XYZ")) {
/* Custom role used before the standard existed. */
if (!to_scene_linear_transform(config, "XYZ", xyz_to_rgb)) {
return;
}
}
xyz_to_r = float4_to_float3(xyz_to_rgb.x);
xyz_to_g = float4_to_float3(xyz_to_rgb.y);
xyz_to_b = float4_to_float3(xyz_to_rgb.z);
const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb);
rgb_to_y = float4_to_float3(rgb_to_xyz.y);
#endif
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -221,6 +221,8 @@ class ShaderManager {
bool need_update() const; bool need_update() const;
void init_xyz_transforms();
protected: protected:
ShaderManager(); ShaderManager();

View File

@@ -34,7 +34,7 @@ using std::max;
enum TransformType { enum TransformType {
TRANSFORM_LINEAR_TO_SRGB, TRANSFORM_LINEAR_TO_SRGB,
TRANSFORM_SRGB_TO_LINEAR, TRANSFORM_SRGB_TO_LINEAR,
TRANSFORM_MATRIX, TRANSFORM_SCALE,
TRANSFORM_EXPONENT, TRANSFORM_EXPONENT,
TRANSFORM_UNKNOWN, TRANSFORM_UNKNOWN,
}; };
@@ -53,147 +53,72 @@ typedef struct OCIO_PackedImageDescription {
} OCIO_PackedImageDescription; } OCIO_PackedImageDescription;
struct FallbackTransform { struct FallbackTransform {
FallbackTransform() : type(TRANSFORM_UNKNOWN), linear_transform(NULL), display_transform(NULL) FallbackTransform() : type(TRANSFORM_UNKNOWN), scale(1.0f), exponent(1.0f)
{ {
} }
virtual ~FallbackTransform() virtual ~FallbackTransform()
{ {
delete linear_transform;
delete display_transform;
} }
void applyRGB(float *pixel) void applyRGB(float *pixel)
{ {
if (type == TRANSFORM_LINEAR_TO_SRGB) { if (type == TRANSFORM_LINEAR_TO_SRGB) {
applyLinearRGB(pixel); pixel[0] *= scale;
pixel[1] *= scale;
pixel[2] *= scale;
linearrgb_to_srgb_v3_v3(pixel, pixel); 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) { else if (type == TRANSFORM_SRGB_TO_LINEAR) {
srgb_to_linearrgb_v3_v3(pixel, pixel); srgb_to_linearrgb_v3_v3(pixel, pixel);
} }
else if (type == TRANSFORM_EXPONENT) { else if (type == TRANSFORM_EXPONENT) {
pixel[0] = powf(max(0.0f, pixel[0]), exponent[0]); pixel[0] = powf(max(0.0f, pixel[0]), exponent);
pixel[1] = powf(max(0.0f, pixel[1]), exponent[1]); pixel[1] = powf(max(0.0f, pixel[1]), exponent);
pixel[2] = powf(max(0.0f, pixel[2]), exponent[2]); pixel[2] = powf(max(0.0f, pixel[2]), exponent);
} }
else if (type == TRANSFORM_MATRIX) { else if (type == TRANSFORM_SCALE) {
float r = pixel[0]; pixel[0] *= scale;
float g = pixel[1]; pixel[1] *= scale;
float b = pixel[2]; pixel[2] *= scale;
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];
} }
} }
void applyRGBA(float *pixel) void applyRGBA(float *pixel)
{ {
if (type == TRANSFORM_LINEAR_TO_SRGB) { applyRGB(pixel);
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);
}
} }
TransformType type; TransformType type;
FallbackTransform *linear_transform; /* Scale transform. */
FallbackTransform *display_transform; float scale;
/* Exponent transform. */ /* Exponent transform. */
float exponent[4]; float exponent;
/* Matrix transform. */
float matrix[16];
float offset[4];
MEM_CXX_CLASS_ALLOC_FUNCS("FallbackTransform"); MEM_CXX_CLASS_ALLOC_FUNCS("FallbackTransform");
}; };
struct FallbackGroupTransform : FallbackTransform {
~FallbackGroupTransform()
{
for (auto transform : list) {
delete transform;
}
}
std::vector<FallbackTransform *> list;
};
struct FallbackProcessor { struct FallbackProcessor {
FallbackProcessor() : transform(NULL) FallbackProcessor(const FallbackTransform &transform) : transform(transform)
{ {
} }
~FallbackProcessor()
{
delete transform;
}
void applyRGB(float *pixel) void applyRGB(float *pixel)
{ {
transform->applyRGB(pixel); transform.applyRGB(pixel);
} }
void applyRGBA(float *pixel) void applyRGBA(float *pixel)
{ {
transform->applyRGBA(pixel); transform.applyRGBA(pixel);
} }
FallbackTransform *transform; FallbackTransform transform;
MEM_CXX_CLASS_ALLOC_FUNCS("FallbackProcessor"); 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_src = configGetColorSpace(config, srcName);
OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName); OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName);
FallbackTransform *transform = new FallbackTransform(); FallbackTransform transform;
if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) { 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) { else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) {
transform->type = TRANSFORM_SRGB_TO_LINEAR; transform.type = TRANSFORM_SRGB_TO_LINEAR;
} }
else { else {
transform->type = TRANSFORM_UNKNOWN; transform.type = TRANSFORM_UNKNOWN;
} }
FallbackProcessor *processor = new FallbackProcessor(); return (OCIO_ConstProcessorRcPtr *)new FallbackProcessor(transform);
processor->transform = transform;
return (OCIO_ConstProcessorRcPtr *)processor;
} }
OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/, OCIO_ConstCPUProcessorRcPtr *FallbackImpl::processorGetCPUProcessor(
OCIO_ConstTransformRcPtr *transform) OCIO_ConstProcessorRcPtr *processor)
{ {
FallbackProcessor *processor = new FallbackProcessor(); /* Just make a copy of the processor so that we are compatible with OCIO
processor->transform = (FallbackTransform *)transform; * which does need it as a separate object. */
return (OCIO_ConstProcessorRcPtr *)processor; FallbackProcessor *fallback_processor = (FallbackProcessor *)processor;
return (OCIO_ConstCPUProcessorRcPtr *)new FallbackProcessor(*fallback_processor);
} }
void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
{
delete (FallbackProcessor *)(processor);
}
void FallbackImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{ {
/* OCIO_TODO stride not respected, channels must be 3 or 4 */ /* OCIO_TODO stride not respected, channels must be 3 or 4 */
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img; 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); float *pixel = pixels + channels * (y * width + x);
if (channels == 4) if (channels == 4)
processorApplyRGBA(processor, pixel); cpuProcessorApplyRGBA(cpu_processor, pixel);
else if (channels == 3) else if (channels == 3)
processorApplyRGB(processor, pixel); cpuProcessorApplyRGB(cpu_processor, pixel);
} }
} }
} }
void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, void FallbackImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img) OCIO_PackedImageDesc *img)
{ {
/* OCIO_TODO stride not respected, channels must be 3 or 4 */ /* OCIO_TODO stride not respected, channels must be 3 or 4 */
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img; OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription *)img;
@@ -464,27 +394,28 @@ void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
float *pixel = pixels + channels * (y * width + x); float *pixel = pixels + channels * (y * width + x);
if (channels == 4) if (channels == 4)
processorApplyRGBA_predivide(processor, pixel); cpuProcessorApplyRGBA_predivide(cpu_processor, pixel);
else if (channels == 3) 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) { if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
processorApplyRGBA(processor, pixel); cpuProcessorApplyRGBA(cpu_processor, pixel);
} }
else { else {
float alpha, inv_alpha; float alpha, inv_alpha;
@@ -496,7 +427,7 @@ void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *proces
pixel[1] *= inv_alpha; pixel[1] *= inv_alpha;
pixel[2] *= inv_alpha; pixel[2] *= inv_alpha;
processorApplyRGBA(processor, pixel); cpuProcessorApplyRGBA(cpu_processor, pixel);
pixel[0] *= alpha; pixel[0] *= alpha;
pixel[1] *= 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) const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@@ -530,54 +461,20 @@ const char *FallbackImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr * /*cs*/
return ""; return "";
} }
OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void) 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 = new FallbackTransform(); FallbackTransform transform;
transform->type = TRANSFORM_LINEAR_TO_SRGB; transform.type = TRANSFORM_LINEAR_TO_SRGB;
return (OCIO_DisplayTransformRcPtr *)transform; transform.scale = scale;
} transform.exponent = exponent;
void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/, return (OCIO_ConstProcessorRcPtr *)new FallbackProcessor(transform);
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*/)
{
}
void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr * /*dt*/)
{
} }
OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data,
@@ -605,127 +502,6 @@ void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
MEM_freeN(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) const char *FallbackImpl::getVersionString(void)
{ {
return "fallback"; return "fallback";

View File

@@ -1,17 +1,20 @@
/* Blender OpenColorIO implementation */ /* Blender OpenColorIO implementation */
#ifdef USE_CURVE_MAPPING
uniform sampler1D curve_mapping_texture; uniform sampler1D curve_mapping_texture;
#endif
uniform sampler2D image_texture; uniform sampler2D image_texture;
uniform sampler2D overlay_texture; uniform sampler2D overlay_texture;
uniform sampler3D lut3d_texture;
uniform sampler3D lut3d_display_texture;
uniform float dither; uniform float dither;
uniform float scale;
uniform float exponent;
uniform bool predivide; uniform bool predivide;
uniform bool curve_mapping;
uniform bool overlay; uniform bool overlay;
layout(std140) uniform OCIO_GLSLCurveMappingParameters #ifdef USE_CURVE_MAPPING
layout(std140) uniform OCIO_GPUCurveMappingParameters
{ {
/* Curve mapping parameters /* Curve mapping parameters
* *
@@ -114,6 +117,7 @@ vec4 curvemapping_evaluate_premulRGBF(vec4 col)
result.a = col.a; result.a = col.a;
return result; return result;
} }
#endif /* USE_CURVE_MAPPING */
/* Using a triangle distribution which gives a more final uniform noise. /* 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) */ * See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */
@@ -145,9 +149,9 @@ vec4 apply_dither(vec4 col, vec2 uv)
vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv) vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
{ {
if (curve_mapping) { #ifdef USE_CURVE_MAPPING
col = curvemapping_evaluate_premulRGBF(col); col = curvemapping_evaluate_premulRGBF(col);
} #endif
if (predivide) { if (predivide) {
if (col.a > 0.0 && col.a < 1.0) { if (col.a > 0.0 && col.a < 1.0) {
@@ -160,15 +164,31 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
* for straight alpha at this moment * 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) { if (overlay) {
col.rgb = pow(col.rgb, vec3(exponent * 2.2));
col = clamp(col, 0.0, 1.0); col = clamp(col, 0.0, 1.0);
col *= 1.0 - col_overlay.a; col *= 1.0 - col_overlay.a;
col += col_overlay; /* Assumed unassociated alpha. */ 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) { if (dither > 0.0) {
col = apply_dither(col, noise_uv); col = apply_dither(col, noise_uv);
@@ -189,4 +209,4 @@ void main()
vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st); vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st);
fragColor = OCIO_ProcessColor(col, col_overlay, noise_uv); fragColor = OCIO_ProcessColor(col, col_overlay, noise_uv);
} }

View File

@@ -194,40 +194,45 @@ OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr
return impl->configGetProcessorWithNames(config, srcName, dstName); return impl->configGetProcessorWithNames(config, srcName, dstName);
} }
OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config, void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *processor)
OCIO_ConstTransformRcPtr *transform)
{ {
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) const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@@ -245,49 +250,15 @@ const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
return impl->colorSpaceGetFamily(cs); return impl->colorSpaceGetFamily(cs);
} }
OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void) 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)
{ {
return impl->createDisplayTransform(); return impl->createDisplayProcessor(config, input, view, display, look, scale, exponent);
}
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)
{
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);
} }
OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data,
@@ -307,108 +278,44 @@ void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
impl->OCIO_PackedImageDescRelease(id); impl->OCIO_PackedImageDescRelease(id);
} }
OCIO_GroupTransformRcPtr *OCIO_createGroupTransform(void) bool OCIO_supportGPUShader()
{ {
return impl->createGroupTransform(); return impl->supportGPUShader();
} }
void OCIO_groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward) 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)
{ {
impl->groupTransformSetDirection(gt, forward); return impl->gpuDisplayShaderBind(config,
input,
view,
display,
look,
curve_mapping_settings,
scale,
exponent,
dither,
use_predivide,
use_overlay);
} }
void OCIO_groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr) void OCIO_gpuDisplayShaderUnbind(void)
{ {
impl->groupTransformPushBack(gt, tr); impl->gpuDisplayShaderUnbind();
} }
void OCIO_groupTransformRelease(OCIO_GroupTransformRcPtr *gt) void OCIO_gpuCacheFree(void)
{ {
impl->groupTransformRelease(gt); impl->gpuCacheFree();
}
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)
{
return (int)impl->supportGLSLDraw();
}
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)
{
return (int)impl->setupGLSLDraw(state_r,
ocio_processor_scene_to_ui,
ocio_processor_ui_to_display,
curve_mapping_settings,
dither,
predivide,
overlay);
}
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
{
impl->finishGLSLDraw(state);
}
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state)
{
impl->freeGLState(state);
} }
const char *OCIO_getVersionString(void) const char *OCIO_getVersionString(void)

View File

@@ -24,7 +24,7 @@
extern "C" { extern "C" {
#endif #endif
struct OCIO_GLSLDrawState; typedef struct OCIO_GPUShader OCIO_GPUShader;
#define OCIO_DECLARE_HANDLE(name) \ #define OCIO_DECLARE_HANDLE(name) \
typedef struct name##__ { \ typedef struct name##__ { \
@@ -42,14 +42,9 @@ struct OCIO_GLSLDrawState;
OCIO_DECLARE_HANDLE(OCIO_ConstConfigRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstConfigRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstColorSpaceRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstColorSpaceRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstProcessorRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstProcessorRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstCPUProcessorRcPtr);
OCIO_DECLARE_HANDLE(OCIO_ConstContextRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstContextRcPtr);
OCIO_DECLARE_HANDLE(OCIO_PackedImageDesc); 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); OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr);
/* Standard XYZ to linear sRGB transform, for fallback. */ /* 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, OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName, const char *srcName,
const char *dstName); const char *dstName);
OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config, void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *cpu_processor);
OCIO_ConstTransformRcPtr *transform);
void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); void OCIO_cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); OCIO_PackedImageDesc *img);
void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); void OCIO_cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void OCIO_cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p); 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_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs);
const char *OCIO_colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); const char *OCIO_colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs);
const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs);
OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void); OCIO_ConstProcessorRcPtr *OCIO_createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *input,
void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *view,
void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *display,
void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, const char *look,
OCIO_ConstTransformRcPtr *et); const float scale,
void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, const float exponent);
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_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data,
long width, long width,
@@ -200,37 +191,20 @@ OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data,
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
OCIO_GroupTransformRcPtr *OCIO_createGroupTransform(void); bool OCIO_supportGPUShader(void);
void OCIO_groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward); bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
void OCIO_groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *tr); const char *input,
void OCIO_groupTransformRelease(OCIO_GroupTransformRcPtr *gt); const char *view,
const char *display,
OCIO_ColorSpaceTransformRcPtr *OCIO_createColorSpaceTransform(void); const char *look,
void OCIO_colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name); OCIO_CurveMappingSettings *curve_mapping_settings,
void OCIO_colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct); const float scale,
const float exponent,
OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void); const float dither,
void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); const bool use_predivide,
void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); const bool use_overlay);
void OCIO_gpuDisplayShaderUnbind(void);
OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void); void OCIO_gpuCacheFree(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);
const char *OCIO_getVersionString(void); const char *OCIO_getVersionString(void);
int OCIO_getVersionHex(void); int OCIO_getVersionHex(void);

View File

@@ -17,6 +17,7 @@
* All rights reserved. * All rights reserved.
*/ */
#include <cassert>
#include <iostream> #include <iostream>
#include <math.h> #include <math.h>
#include <sstream> #include <sstream>
@@ -35,7 +36,9 @@ using namespace OCIO_NAMESPACE;
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_math_color.h" #include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "ocio_impl.h" #include "ocio_impl.h"
@@ -50,27 +53,6 @@ using namespace OCIO_NAMESPACE;
# define __func__ __FUNCTION__ # define __func__ __FUNCTION__
#endif #endif
/* NOTE: This is because OCIO 1.1.0 has a bug which makes default
* display to be the one which is first alphabetically.
*
* Fix has been submitted as a patch
* https://github.com/imageworks/OpenColorIO/pull/638
*
* For until then we use first usable display instead. */
#define DEFAULT_DISPLAY_WORKAROUND
#ifdef DEFAULT_DISPLAY_WORKAROUND
# include <algorithm>
# include <map>
# include <mutex>
# include <set>
# include <string>
# include <vector>
using std::map;
using std::set;
using std::string;
using std::vector;
#endif
static void OCIO_reportError(const char *err) static void OCIO_reportError(const char *err)
{ {
std::cerr << "OpenColorIO Error: " << err << std::endl; std::cerr << "OpenColorIO Error: " << err << std::endl;
@@ -213,30 +195,6 @@ int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const c
const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config) const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config)
{ {
#ifdef DEFAULT_DISPLAY_WORKAROUND
if (getenv("OCIO_ACTIVE_DISPLAYS") == NULL) {
const char *active_displays = (*(ConstConfigRcPtr *)config)->getActiveDisplays();
if (active_displays[0] != '\0') {
const char *separator_pos = strchr(active_displays, ',');
if (separator_pos == NULL) {
return active_displays;
}
static std::string active_display;
/* NOTE: Configuration is shared and is never changed during
* runtime, so we only guarantee two threads don't initialize at the
* same. */
static std::mutex mutex;
mutex.lock();
if (active_display.empty()) {
active_display = active_displays;
active_display[separator_pos - active_displays] = '\0';
}
mutex.unlock();
return active_display.c_str();
}
}
#endif
try { try {
return (*(ConstConfigRcPtr *)config)->getDefaultDisplay(); return (*(ConstConfigRcPtr *)config)->getDefaultDisplay();
} }
@@ -271,90 +229,8 @@ const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index)
return NULL; return NULL;
} }
#ifdef DEFAULT_DISPLAY_WORKAROUND
namespace {
void splitStringEnvStyle(vector<string> *tokens, const string &str)
{
tokens->clear();
const int len = str.length();
int token_start = 0, token_length = 0;
for (int i = 0; i < len; ++i) {
const char ch = str[i];
if (ch != ',' && ch != ':') {
/* Append non-separator char to a token. */
++token_length;
}
else {
/* Append current token to the list (if any). */
if (token_length > 0) {
string token = str.substr(token_start, token_length);
tokens->push_back(token);
}
/* Re-set token pointers. */
token_start = i + 1;
token_length = 0;
}
}
/* Append token which might be at the end of the string. */
if (token_length != 0) {
string token = str.substr(token_start, token_length);
tokens->push_back(token);
}
}
string stringToLower(const string &str)
{
string lower = str;
std::transform(lower.begin(), lower.end(), lower.begin(), tolower);
return lower;
}
} // namespace
#endif
const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display) const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display)
{ {
#ifdef DEFAULT_DISPLAY_WORKAROUND
/* NOTE: We assume that first active view always exists for a default
* display. */
if (getenv("OCIO_ACTIVE_VIEWS") == NULL) {
ConstConfigRcPtr config_ptr = *((ConstConfigRcPtr *)config);
const char *active_views_encoded = config_ptr->getActiveViews();
if (active_views_encoded[0] != '\0') {
const string display_lower = stringToLower(display);
static map<string, string> default_display_views;
static std::mutex mutex;
mutex.lock();
/* Check if the view is already known. */
map<string, string>::const_iterator it = default_display_views.find(display_lower);
if (it != default_display_views.end()) {
mutex.unlock();
return it->second.c_str();
}
/* Active views. */
vector<string> active_views;
splitStringEnvStyle(&active_views, active_views_encoded);
/* Get all views supported by tge display. */
set<string> display_views;
const int num_display_views = config_ptr->getNumViews(display);
for (int view_index = 0; view_index < num_display_views; ++view_index) {
const char *view = config_ptr->getView(display, view_index);
display_views.insert(stringToLower(view));
}
/* Get first view which is supported by tge display. */
for (const string &view : active_views) {
const string view_lower = stringToLower(view);
if (display_views.find(view_lower) != display_views.end()) {
default_display_views[display_lower] = view;
mutex.unlock();
return default_display_views[display_lower].c_str();
}
}
mutex.unlock();
}
}
#endif
try { try {
return (*(ConstConfigRcPtr *)config)->getDefaultView(display); return (*(ConstConfigRcPtr *)config)->getDefaultView(display);
} }
@@ -394,7 +270,7 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf
const char *view) const char *view)
{ {
try { try {
return (*(ConstConfigRcPtr *)config)->getDisplayColorSpaceName(display, view); return (*(ConstConfigRcPtr *)config)->getDisplayViewColorSpaceName(display, view);
} }
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
@@ -406,13 +282,46 @@ const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *conf
void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb)
{ {
try { 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) { catch (Exception &exception) {
OCIO_reportException(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]) void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rgb[3][3])
{ {
ConstConfigRcPtr config = (*(ConstConfigRcPtr *)config_); ConstConfigRcPtr config = (*(ConstConfigRcPtr *)config_);
@@ -420,24 +329,25 @@ void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rg
/* Default to ITU-BT.709 in case no appropriate transform found. */ /* 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)); 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. */ /* Get from OpenColorO config if it has the required roles. */
if (config->hasRole("XYZ") && config->hasRole("scene_linear")) { if (!config->hasRole(ROLE_SCENE_LINEAR)) {
ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear"); return;
if (to_rgb_processor) { }
xyz_to_rgb[0][0] = 1.0f;
xyz_to_rgb[0][1] = 0.0f; if (config->hasRole("aces_interchange")) {
xyz_to_rgb[0][2] = 0.0f; /* Standard OpenColorIO role, defined as ACES2065-1. */
xyz_to_rgb[1][0] = 0.0f; const float xyz_to_aces[3][3] = {{1.0498110175f, -0.4959030231f, 0.0f},
xyz_to_rgb[1][1] = 1.0f; {0.0f, 1.3733130458f, 0.0f},
xyz_to_rgb[1][2] = 0.0f; {-0.0000974845f, 0.0982400361f, 0.9912520182f}};
xyz_to_rgb[2][0] = 0.0f; float aces_to_rgb[3][3];
xyz_to_rgb[2][1] = 0.0f; if (to_scene_linear_matrix(config, "aces_interchange", aces_to_rgb)) {
xyz_to_rgb[2][2] = 1.0f; mul_m3_m3m3(xyz_to_rgb, aces_to_rgb, xyz_to_aces);
to_rgb_processor->applyRGB(xyz_to_rgb[0]);
to_rgb_processor->applyRGB(xyz_to_rgb[1]);
to_rgb_processor->applyRGB(xyz_to_rgb[2]);
} }
} }
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) int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config)
@@ -558,6 +468,8 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
return; return;
} }
ConstCPUProcessorRcPtr cpu_processor = processor->getDefaultCPUProcessor();
is_scene_linear = true; is_scene_linear = true;
is_srgb = true; is_srgb = true;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
@@ -567,10 +479,10 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
float cG[3] = {0, v, 0}; float cG[3] = {0, v, 0};
float cB[3] = {0, 0, v}; float cB[3] = {0, 0, v};
float cW[3] = {v, v, v}; float cW[3] = {v, v, v};
processor->applyRGB(cR); cpu_processor->applyRGB(cR);
processor->applyRGB(cG); cpu_processor->applyRGB(cG);
processor->applyRGB(cB); cpu_processor->applyRGB(cB);
processor->applyRGB(cW); cpu_processor->applyRGB(cW);
/* Make sure that there is no channel crosstalk. */ /* Make sure that there is no channel crosstalk. */
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f || if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
@@ -612,62 +524,57 @@ OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfig
const char *srcName, const char *srcName,
const char *dstName) const char *dstName)
{ {
ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr); ConstProcessorRcPtr *processor = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
try { try {
*p = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName); *processor = (*(ConstConfigRcPtr *)config)->getProcessor(srcName, dstName);
if (*p) if (*processor)
return (OCIO_ConstProcessorRcPtr *)p; return (OCIO_ConstProcessorRcPtr *)processor;
} }
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
OBJECT_GUARDED_DELETE(p, ConstProcessorRcPtr); OBJECT_GUARDED_DELETE(processor, ConstProcessorRcPtr);
return 0; return 0;
} }
OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
OCIO_ConstTransformRcPtr *transform)
{ {
ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr); OBJECT_GUARDED_DELETE(processor, 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);
return NULL;
} }
void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) 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::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{ {
try { try {
(*(ConstProcessorRcPtr *)processor)->apply(*(PackedImageDesc *)img); (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*(PackedImageDesc *)img);
} }
catch (Exception &exception) { catch (Exception &exception) {
OCIO_reportException(exception); OCIO_reportException(exception);
} }
} }
void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, void OCIOImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img_) OCIO_PackedImageDesc *img_)
{ {
try { try {
PackedImageDesc *img = (PackedImageDesc *)img_; PackedImageDesc *img = (PackedImageDesc *)img_;
int channels = img->getNumChannels(); int channels = img->getNumChannels();
if (channels == 4) { if (channels == 4) {
float *pixels = img->getData(); assert(img->isFloat());
float *pixels = (float *)img->getData();
int width = img->getWidth(); int width = img->getWidth();
int height = img->getHeight(); int height = img->getHeight();
@@ -676,12 +583,12 @@ void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
float *pixel = pixels + 4 * (y * width + x); float *pixel = pixels + 4 * (y * width + x);
processorApplyRGBA_predivide(processor, pixel); cpuProcessorApplyRGBA_predivide(cpu_processor, pixel);
} }
} }
} }
else { else {
(*(ConstProcessorRcPtr *)processor)->apply(*img); (*(ConstCPUProcessorRcPtr *)cpu_processor)->apply(*img);
} }
} }
catch (Exception &exception) { catch (Exception &exception) {
@@ -689,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) { if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
(*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel); (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
} }
else { else {
float alpha, inv_alpha; float alpha, inv_alpha;
@@ -714,7 +622,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor,
pixel[1] *= inv_alpha; pixel[1] *= inv_alpha;
pixel[2] *= inv_alpha; pixel[2] *= inv_alpha;
(*(ConstProcessorRcPtr *)processor)->applyRGBA(pixel); (*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGBA(pixel);
pixel[0] *= alpha; pixel[0] *= alpha;
pixel[1] *= alpha; pixel[1] *= alpha;
@@ -722,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) const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
@@ -742,57 +650,85 @@ const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs)
return (*(ConstColorSpaceRcPtr *)cs)->getFamily(); 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, /* Apply scale. */
const char *name) MatrixTransformRcPtr mt = MatrixTransform::Create();
{ const double matrix[16] = {
(*(DisplayTransformRcPtr *)dt)->setInputColorSpaceName(name); 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) /* Add look transform. */
{ const bool use_look = (strlen(look) != 0);
(*(DisplayTransformRcPtr *)dt)->setDisplay(name); if (use_look) {
} const char *look_output = LookTransform::GetLooksResultColorSpace(
config, config->getCurrentContext(), look);
void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) LookTransformRcPtr lt = LookTransform::Create();
{ lt->setSrc(input);
(*(DisplayTransformRcPtr *)dt)->setView(name); lt->setDst(look_output);
} lt->setLooks(look);
group->appendTransform(lt);
void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, /* Make further transforms aware of the color space change. */
OCIO_ConstTransformRcPtr *t) input = look_output;
{ }
(*(DisplayTransformRcPtr *)dt)->setDisplayCC(*(ConstTransformRcPtr *)t);
}
void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, /* Add view and display transform. */
OCIO_ConstTransformRcPtr *t) DisplayViewTransformRcPtr dvt = DisplayViewTransform::Create();
{ dvt->setSrc(input);
(*(DisplayTransformRcPtr *)dt)->setLinearCC(*(ConstTransformRcPtr *)t); dvt->setLooksBypass(use_look);
} dvt->setView(view);
dvt->setDisplay(display);
group->appendTransform(dvt);
void OCIOImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks) /* Gamma. */
{ if (exponent != 1.0f) {
(*(DisplayTransformRcPtr *)dt)->setLooksOverride(looks); 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, /* Create processor from transform. This is the moment were OCIO validates
bool enabled) * the entire transform, no need to check for the validity of inputs above. */
{ ConstProcessorRcPtr *p = OBJECT_GUARDED_NEW(ConstProcessorRcPtr);
(*(DisplayTransformRcPtr *)dt)->setLooksOverrideEnabled(enabled);
}
void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) try {
{ *p = config->getProcessor(group);
OBJECT_GUARDED_DELETE((DisplayTransformRcPtr *)dt, DisplayTransformRcPtr);
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, OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data,
@@ -805,8 +741,14 @@ OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data,
{ {
try { try {
void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__); void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
PackedImageDesc *id = new (mem) PackedImageDesc( PackedImageDesc *id = new (mem) PackedImageDesc(data,
data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); width,
height,
numChannels,
BIT_DEPTH_F32,
chanStrideBytes,
xStrideBytes,
yStrideBytes);
return (OCIO_PackedImageDesc *)id; return (OCIO_PackedImageDesc *)id;
} }
@@ -822,96 +764,6 @@ void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *id)
OBJECT_GUARDED_DELETE((PackedImageDesc *)id, PackedImageDesc); 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) const char *OCIOImpl::getVersionString(void)
{ {
return GetVersion(); return GetVersion();

View File

@@ -76,36 +76,30 @@ class IOCIOImpl {
virtual OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, virtual OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName, const char *srcName,
const char *dstName) = 0; const char *dstName) = 0;
virtual OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, virtual void processorRelease(OCIO_ConstProcessorRcPtr *processor) = 0;
OCIO_ConstTransformRcPtr *transform) = 0;
virtual void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) = 0; virtual OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *p) = 0;
virtual void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, virtual void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img) = 0; OCIO_PackedImageDesc *img) = 0;
virtual void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; virtual void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
virtual void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; OCIO_PackedImageDesc *img) = 0;
virtual void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; virtual void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) = 0;
virtual void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel) = 0;
virtual void processorRelease(OCIO_ConstProcessorRcPtr *p) = 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 *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) = 0;
virtual const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) = 0; virtual const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) = 0;
virtual const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) = 0; virtual const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) = 0;
virtual OCIO_DisplayTransformRcPtr *createDisplayTransform(void) = 0; virtual OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
virtual void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *input,
const char *name) = 0; const char *view,
virtual void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; const char *display,
virtual void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; const char *look,
virtual void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, const float scale,
OCIO_ConstTransformRcPtr *et) = 0; const float exponent) = 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_PackedImageDesc *createOCIO_PackedImageDesc(float *data, virtual OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data,
long width, long width,
@@ -117,39 +111,31 @@ class IOCIOImpl {
virtual void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p) = 0; virtual void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p) = 0;
virtual OCIO_GroupTransformRcPtr *createGroupTransform(void) = 0; /* Optional GPU support. */
virtual void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward) = 0; virtual bool supportGPUShader()
virtual void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, {
OCIO_ConstTransformRcPtr *transform) = 0; return false;
virtual void groupTransformRelease(OCIO_GroupTransformRcPtr *gt) = 0; }
virtual bool gpuDisplayShaderBind(OCIO_ConstConfigRcPtr * /*config*/,
virtual OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void) = 0; const char * /*input*/,
virtual void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name) = 0; const char * /*view*/,
virtual void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct) = 0; const char * /*display*/,
const char * /*look*/,
virtual OCIO_ExponentTransformRcPtr *createExponentTransform(void) = 0; OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
virtual void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float /*scale*/,
const float *exponent) = 0; const float /*exponent*/,
virtual void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) = 0; const float /*dither*/,
const bool /*use_predivide*/,
virtual OCIO_MatrixTransformRcPtr *createMatrixTransform(void) = 0; const bool /*use_overlay*/)
virtual void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, {
const float *m44, return false;
const float *offset4) = 0; }
virtual void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) = 0; virtual void gpuDisplayShaderUnbind(void)
{
virtual void matrixTransformScale(float *m44, float *offset4, const float *scale4) = 0; }
virtual void gpuCacheFree(void)
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;
virtual const char *getVersionString(void) = 0; virtual const char *getVersionString(void) = 0;
virtual int getVersionHex(void) = 0; virtual int getVersionHex(void) = 0;
@@ -206,30 +192,28 @@ class FallbackImpl : public IOCIOImpl {
OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName, const char *srcName,
const char *dstName); const char *dstName);
OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, void processorRelease(OCIO_ConstProcessorRcPtr *processor);
OCIO_ConstTransformRcPtr *transform);
void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); OCIO_PackedImageDesc *img);
void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void processorRelease(OCIO_ConstProcessorRcPtr *p); void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs);
OCIO_DisplayTransformRcPtr *createDisplayTransform(void); OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *input,
void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *view,
void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *display,
void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); const char *look,
void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); const float scale,
void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks); const float exponent);
void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled);
void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt);
OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data,
long width, long width,
@@ -241,38 +225,6 @@ class FallbackImpl : public IOCIOImpl {
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); 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); const char *getVersionString(void);
int getVersionHex(void); int getVersionHex(void);
}; };
@@ -327,30 +279,28 @@ class OCIOImpl : public IOCIOImpl {
OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config,
const char *srcName, const char *srcName,
const char *dstName); const char *dstName);
OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, void processorRelease(OCIO_ConstProcessorRcPtr *processor);
OCIO_ConstTransformRcPtr *transform);
void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); OCIO_PackedImageDesc *img);
void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); void cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorApplyRGBA(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void processorRelease(OCIO_ConstProcessorRcPtr *p); void cpuProcessorApplyRGBA_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel);
void cpuProcessorRelease(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs);
const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs);
OCIO_DisplayTransformRcPtr *createDisplayTransform(void); OCIO_ConstProcessorRcPtr *createDisplayProcessor(OCIO_ConstConfigRcPtr *config,
void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *input,
void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *view,
void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); const char *display,
void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); const char *look,
void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); const float scale,
void displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr *dt, const char *looks); const float exponent);
void displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr *dt, bool enabled);
void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt);
OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data,
long width, long width,
@@ -362,37 +312,20 @@ class OCIOImpl : public IOCIOImpl {
void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
OCIO_GroupTransformRcPtr *createGroupTransform(void); bool supportGPUShader();
void groupTransformSetDirection(OCIO_GroupTransformRcPtr *gt, const bool forward); bool gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
void groupTransformPushBack(OCIO_GroupTransformRcPtr *gt, OCIO_ConstTransformRcPtr *transform); const char *input,
void groupTransformRelease(OCIO_GroupTransformRcPtr *gt); const char *view,
const char *display,
OCIO_ColorSpaceTransformRcPtr *createColorSpaceTransform(void); const char *look,
void colorSpaceTransformSetSrc(OCIO_ColorSpaceTransformRcPtr *ct, const char *name); OCIO_CurveMappingSettings *curve_mapping_settings,
void colorSpaceTransformRelease(OCIO_ColorSpaceTransformRcPtr *ct); const float scale,
const float exponent,
OCIO_ExponentTransformRcPtr *createExponentTransform(void); const float dither,
void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); const bool use_predivide,
void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); const bool use_overlay);
void gpuDisplayShaderUnbind(void);
OCIO_MatrixTransformRcPtr *createMatrixTransform(void); void gpuCacheFree(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); const char *getVersionString(void);
int getVersionHex(void); int getVersionHex(void);

View File

@@ -31,8 +31,10 @@
*/ */
#include <limits> #include <limits>
#include <list>
#include <sstream> #include <sstream>
#include <string.h> #include <string.h>
#include <vector>
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(push) # pragma warning(push)
@@ -53,24 +55,24 @@ using namespace OCIO_NAMESPACE;
#include "ocio_impl.h" #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_glsl[];
extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[]; extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
/* **** OpenGL drawing routines using GLSL for color space transform ***** */ /* **** 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 /* Curve mapping parameters
* *
* See documentation for OCIO_CurveMappingSettings to get fields descriptions. * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
* (this ones pretty much copies stuff from C structure.) * (this ones pretty much copies stuff from C structure.)
*/ */
struct OCIO_GLSLCurveMappingParameters { struct OCIO_GPUCurveMappingParameters {
float curve_mapping_mintable[4]; float curve_mapping_mintable[4];
float curve_mapping_range[4]; float curve_mapping_range[4];
float curve_mapping_ext_in_x[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. */ /** WARNING: Needs to be 16byte aligned. Used as UBO data. */
}; };
struct OCIO_GLSLShader { struct OCIO_GPUShader {
/** Cache IDs */ /* GPU shader. */
std::string cacheId; struct GPUShader *shader = NULL;
struct GPUShader *shader;
/** Uniform locations. */ /** Uniform locations. */
int dither_loc; int scale_loc = 0;
int overlay_loc; int exponent_loc = 0;
int predivide_loc; int dither_loc = 0;
int curve_mapping_loc; int overlay_loc = 0;
int ubo_bind; int predivide_loc = 0;
/** Error checking. */ int ubo_bind = 0;
bool valid;
/* Destructor. */
~OCIO_GPUShader()
{
if (shader) {
GPU_shader_free(shader);
}
}
}; };
struct OCIO_GLSLLut3d { struct OCIO_GPULutTexture {
/** Cache IDs */ GPUTexture *texture = NULL;
std::string cacheId; std::string sampler_name;
/** OpenGL Texture handles. NULL if not allocated. */
GPUTexture *texture;
GPUTexture *texture_display;
GPUTexture *texture_dummy;
/** Error checking. */
bool valid;
}; };
struct OCIO_GLSLCurveMappping { struct OCIO_GPUUniform {
/** Cache IDs */ GpuShaderDesc::UniformData data;
size_t cacheId; std::string name;
};
struct OCIO_GPUTextures {
/** LUT Textures */
std::vector<OCIO_GPULutTexture> luts;
/* Dummy in case of no overlay. */
GPUTexture *dummy = NULL;
/* 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_GPUCurveMappping {
/** GPU Uniform Buffer handle. 0 if not allocated. */ /** GPU Uniform Buffer handle. 0 if not allocated. */
GPUUniformBuf *buffer; GPUUniformBuf *buffer = NULL;
/** OpenGL Texture handles. 0 if not allocated. */ /** OpenGL Texture handles. 0 if not allocated. */
GPUTexture *texture; GPUTexture *texture = NULL;
/* To detect when to update the uniforms and textures. */
size_t cache_id = 0;
/* Destructor. */
~OCIO_GPUCurveMappping()
{
if (texture) {
GPU_texture_free(texture);
}
if (buffer) {
GPU_uniformbuf_free(buffer);
}
}
};
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. */ /** Error checking. */
bool valid; bool valid = false;
}; };
struct OCIO_GLSLCacheHandle { static const int SHADER_CACHE_MAX_SIZE = 4;
size_t cache_id; std::list<OCIO_GPUDisplayShader> SHADER_CACHE;
void *data;
};
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];
};
static OCIO_GLSLDrawState *allocateOpenGLState(void)
{
return (OCIO_GLSLDrawState *)MEM_callocN(sizeof(OCIO_GLSLDrawState), "OCIO OpenGL State struct");
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name Shader /** \name Shader
* \{ */ * \{ */
static void updateGLSLShader(OCIO_GLSLShader *shader, static bool createGPUShader(OCIO_GPUShader &shader,
ConstProcessorRcPtr *processor_scene_to_ui, OCIO_GPUTextures &textures,
ConstProcessorRcPtr *processpr_ui_to_display, const GpuShaderDescRcPtr &shaderdesc_to_scene_linear,
GpuShaderDesc *shader_desc, const GpuShaderDescRcPtr &shaderdesc_to_display,
const std::string &cache_id) 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; std::ostringstream os;
{ {
/* Fragment shader */ /* Fragment shader */
@@ -170,146 +201,222 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
os << "#define texture2D texture\n"; os << "#define texture2D texture\n";
os << "#define texture3D texture\n"; os << "#define texture3D texture\n";
shader_desc->setFunctionName("OCIO_to_display_linear_with_look"); if (use_curve_mapping) {
os << (*processor_scene_to_ui)->getGpuShaderText(*shader_desc) << "\n"; os << "#define USE_CURVE_MAPPING\n";
}
shader_desc->setFunctionName("OCIO_to_display_encoded"); os << shaderdesc_to_scene_linear->getShaderText() << "\n";
os << (*processpr_ui_to_display)->getGpuShaderText(*shader_desc) << "\n"; os << shaderdesc_to_display->getShaderText() << "\n";
os << datatoc_gpu_shader_display_transform_glsl; os << datatoc_gpu_shader_display_transform_glsl;
} }
shader->shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl, shader.shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl,
os.str().c_str(), os.str().c_str(),
NULL, NULL,
NULL, NULL,
NULL, NULL,
"OCIOShader"); "OCIOShader");
if (shader->shader) { if (shader.shader == NULL) {
shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither"); return false;
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");
GPU_shader_bind(shader->shader);
/* 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);
} }
shader->cacheId = cache_id; shader.scale_loc = GPU_shader_get_uniform(shader.shader, "scale");
shader->valid = (shader->shader != NULL); 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");
static void ensureGLSLShader(OCIO_GLSLShader **shader_ptr, GPU_shader_bind(shader.shader);
ConstProcessorRcPtr *processor_scene_to_ui,
ConstProcessorRcPtr *processpr_ui_to_display, /* Set texture bind point uniform once. This is saved by the shader. */
GpuShaderDesc *shader_desc, GPUShader *sh = shader.shader;
const std::string &cache_id) 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);
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); /* Set LUT textures. */
for (int i = 0; i < textures.luts.size(); i++) {
updateGLSLShader(shader, processor_scene_to_ui, processpr_ui_to_display, shader_desc, cache_id); GPU_shader_uniform_int(sh,
GPU_shader_get_uniform(sh, textures.luts[i].sampler_name.c_str()),
*shader_ptr = shader; TEXTURE_SLOT_LUTS_OFFSET + i);
}
static void freeGLSLShader(OCIO_GLSLShader *shader)
{
if (shader->shader) {
GPU_shader_free(shader->shader);
} }
OBJECT_GUARDED_DELETE(shader, OCIO_GLSLShader); /* Set uniforms. */
for (OCIO_GPUUniform &uniform : textures.uniforms) {
const GpuShaderDesc::UniformData &data = uniform.data;
const char *name = name;
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());
}
}
return true;
} }
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name Lut3D /** \name Textures
* \{ */ * \{ */
static void updateGLSLLut3d(OCIO_GLSLLut3d *lut3d, static bool addGPUUniform(OCIO_GPUTextures &textures,
ConstProcessorRcPtr *processor_scene_to_ui, const GpuShaderDescRcPtr &shader_desc,
ConstProcessorRcPtr *processpr_ui_to_display, int index)
GpuShaderDesc *shader_desc,
const std::string &cache_id)
{ {
if (lut3d->cacheId == cache_id) OCIO_GPUUniform uniform;
return; uniform.name = shader_desc->getUniform(index, uniform.data);
if (uniform.data.m_type == UNIFORM_UNKNOWN) {
float *lut_data = (float *)MEM_mallocN(LUT3D_TEXTURE_SIZE, __func__); return false;
ConstProcessorRcPtr *ocio_processors[2] = {processor_scene_to_ui, processpr_ui_to_display};
for (int i = 0; i < 2; i++) {
ConstProcessorRcPtr *processor = ocio_processors[i];
GPUTexture *texture = (&lut3d->texture)[i];
(*processor)->getGpuLut3D(lut_data, *shader_desc);
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));
} }
MEM_freeN(lut_data); textures.uniforms.push_back(uniform);
return true;
lut3d->cacheId = cache_id;
} }
static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr, static bool addGPULut2D(OCIO_GPUTextures &textures,
ConstProcessorRcPtr *processor_scene_to_ui, const GpuShaderDescRcPtr &shader_desc,
ConstProcessorRcPtr *processpr_ui_to_display, int index)
GpuShaderDesc *shaderDesc,
const std::string &cache_id)
{ {
if (*lut3d_ptr != NULL) { const char *texture_name = NULL;
return; const char *sampler_name = NULL;
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 == NULL || sampler_name == NULL || width == 0 || height == 0 ||
values == NULL) {
return false;
} }
OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d); eGPUTextureFormat format = (channel == GpuShaderCreator::TEXTURE_RGB_CHANNEL) ? GPU_RGB16F :
GPU_R16F;
int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE}; OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_2d(texture_name, width, height, 0, format, values);
if (lut.texture == NULL) {
return false;
}
lut3d->texture = GPU_texture_create_3d( GPU_texture_filter_mode(lut.texture, interpolation != INTERP_NEAREST);
"OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, GPU_DATA_FLOAT, NULL); GPU_texture_wrap_mode(lut.texture, false, true);
GPU_texture_filter_mode(lut3d->texture, true);
GPU_texture_wrap_mode(lut3d->texture, false, true);
lut3d->texture_display = GPU_texture_create_3d( lut.sampler_name = sampler_name;
"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); textures.luts.push_back(lut);
return true;
updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id);
lut3d->valid = (lut3d->texture && lut3d->texture_display);
*lut3d_ptr = lut3d;
} }
static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d) static bool addGPULut3D(OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shader_desc,
int index)
{ {
GPU_texture_free(lut3d->texture); const char *texture_name = NULL;
GPU_texture_free(lut3d->texture_display); const char *sampler_name = NULL;
GPU_texture_free(lut3d->texture_dummy); unsigned int edgelen = 0;
Interpolation interpolation = INTERP_LINEAR;
shader_desc->get3DTexture(index, texture_name, sampler_name, edgelen, interpolation);
OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d); const float *values;
shader_desc->get3DTextureValues(index, values);
if (texture_name == NULL || sampler_name == NULL || edgelen == 0 || values == NULL) {
return 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 == NULL) {
return false;
}
GPU_texture_filter_mode(lut.texture, interpolation != INTERP_NEAREST);
GPU_texture_wrap_mode(lut.texture, false, true);
lut.sampler_name = sampler_name;
textures.luts.push_back(lut);
return true;
}
static bool createGPUTextures(OCIO_GPUTextures &textures,
const GpuShaderDescRcPtr &shaderdesc_to_scene_linear,
const GpuShaderDescRcPtr &shaderdesc_to_display)
{
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;
}
}
return true;
} }
/** \} */ /** \} */
@@ -317,72 +424,47 @@ static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name Curve Mapping /** \name Curve Mapping
* \{ */ * \{ */
static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings) static bool createGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings)
{ {
int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1; if (curve_mapping_settings) {
/* Do not initialize. Only if used. */ int lut_size = curve_mapping_settings->lut_size;
curvemap->texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, NULL);
GPU_texture_filter_mode(curvemap->texture, false); curvemap.texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, NULL);
GPU_texture_wrap_mode(curvemap->texture, false, true); GPU_texture_filter_mode(curvemap.texture, false);
GPU_texture_wrap_mode(curvemap.texture, false, true);
curvemap.buffer = GPU_uniformbuf_create(sizeof(OCIO_GPUCurveMappingParameters));
if (curvemap.texture == NULL || curvemap.buffer == NULL) {
return false;
}
}
return true;
} }
/* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */ static void updateGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
static void ensureGLSLCurveMapping(OCIO_GLSLCurveMappping **curvemap_ptr, OCIO_CurveMappingSettings *curve_mapping_settings)
OCIO_CurveMappingSettings *curve_mapping_settings)
{ {
if (*curvemap_ptr != NULL) { /* Test if we need to update. The caller ensures the curve_mapping_settings
* changes when its contents changes. */
if (curve_mapping_settings == NULL || curvemap.cache_id == curve_mapping_settings->cache_id) {
return; return;
} }
OCIO_GLSLCurveMappping *curvemap = OBJECT_GUARDED_NEW(OCIO_GLSLCurveMappping); curvemap.cache_id = curve_mapping_settings->cache_id;
/* Texture. */
allocateCurveMappingTexture(curvemap, curve_mapping_settings);
/* Uniform buffer object. */
curvemap->buffer = GPU_uniformbuf_create(sizeof(OCIO_GLSLCurveMappingParameters));
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);
OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping);
}
static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap,
OCIO_CurveMappingSettings *curve_mapping_settings,
size_t cacheId)
{
/* No need to continue if curvemapping is not used. Just use whatever is in this cache. */
if (curve_mapping_settings == NULL)
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);
}
/* Update texture. */ /* Update texture. */
int offset[3] = {0, 0, 0}; int offset[3] = {0, 0, 0};
int extent[3] = {curve_mapping_settings->lut_size, 0, 0}; int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
const float *pixels = curve_mapping_settings->lut; const float *pixels = curve_mapping_settings->lut;
GPU_texture_update_sub( 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. */ /* Update uniforms. */
OCIO_GLSLCurveMappingParameters data; OCIO_GPUCurveMappingParameters data;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
data.curve_mapping_range[i] = curve_mapping_settings->range[i]; data.curve_mapping_range[i] = curve_mapping_settings->range[i];
data.curve_mapping_mintable[i] = curve_mapping_settings->mintable[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_lut_size = curve_mapping_settings->lut_size;
data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate; data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate;
GPU_uniformbuf_update(curvemap->buffer, &data); GPU_uniformbuf_update(curvemap.buffer, &data);
curvemap->cacheId = cacheId;
} }
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \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;
}
static OCIO_GLSLCacheHandle *cacheSearch(OCIO_GLSLCacheHandle cache[SHADER_CACHE_SIZE],
size_t cache_id)
{
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];
}
cache[0] = found_item;
return &cache[0];
}
}
/* 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];
}
/* Copy last to front and let the caller initialize it. */
cache[0] = last_item;
return &cache[0];
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name OCIO GLSL Implementation
* \{ */
/* Detect if we can support GLSL drawing */
bool OCIOImpl::supportGLSLDraw()
{ {
/* Minimum supported version 3.3 does meet all requirements. */ /* Minimum supported version 3.3 does meet all requirements. */
return true; return true;
} }
static OCIO_GPUDisplayShader &getGPUDisplayShader(
OCIO_ConstConfigRcPtr *config,
const char *input,
const char *view,
const char *display,
const char *look,
OCIO_CurveMappingSettings *curve_mapping_settings)
{
/* Find existing shader in cache. */
const bool use_curve_mapping = (curve_mapping_settings != NULL);
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);
}
return *it;
}
}
/* Remove least recently used element from cache. */
if (SHADER_CACHE.size() >= SHADER_CACHE_MAX_SIZE) {
SHADER_CACHE.pop_back();
}
/* 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;
}
}
/* Free processors. */
if (processor_to_scene_linear) {
OCIO_processorRelease(processor_to_scene_linear);
}
if (processor_to_display) {
OCIO_processorRelease(processor_to_display);
}
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. * All LUT allocating baking and shader compilation happens here.
* *
* Once this function is called, callee could start drawing images * Once this function is called, callee could start drawing images
* using regular 2D texture. * using regular 2D texture.
* *
* When all drawing is finished, finishGLSLDraw shall be called to * When all drawing is finished, gpuDisplayShaderUnbind must be called to
* restore OpenGL context to its pre-GLSL draw state. * restore GPU context to its previous state.
*/ */
bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
OCIO_ConstProcessorRcPtr *ocio_processor_scene_to_ui, const char *input,
OCIO_ConstProcessorRcPtr *ocio_processor_ui_to_display, const char *view,
OCIO_CurveMappingSettings *curve_mapping_settings, const char *display,
float dither, const char *look,
bool use_predivide, OCIO_CurveMappingSettings *curve_mapping_settings,
bool use_overlay) 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; /* Get GPU shader from cache or create new one. */
ConstProcessorRcPtr processpr_ui_to_display = *( OCIO_GPUDisplayShader &display_shader = getGPUDisplayShader(
ConstProcessorRcPtr *)ocio_processor_ui_to_display; config, input, view, display, look, curve_mapping_settings);
bool use_curve_mapping = curve_mapping_settings != NULL; if (!display_shader.valid) {
if (!processor_scene_to_ui || !processor_scene_to_ui) {
return false; return false;
} }
/* Create state if needed. */ /* Verify the shader is valid. */
OCIO_GLSLDrawState *state; OCIO_GPUTextures &textures = display_shader.textures;
if (!*state_r) OCIO_GPUShader &shader = display_shader.shader;
*state_r = allocateOpenGLState(); OCIO_GPUCurveMappping &curvemap = display_shader.curvemap;
state = *state_r;
/* Compute cache IDs. */ /* Update and bind curve mapping data. */
GpuShaderDesc shaderDesc; if (curve_mapping_settings) {
shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3); updateGPUCurveMapping(curvemap, curve_mapping_settings);
shaderDesc.setFunctionName("OCIODisplay"); GPU_uniformbuf_bind(curvemap.buffer, shader.ubo_bind);
shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE); GPU_texture_bind(curvemap.texture, TEXTURE_SLOT_CURVE_MAPPING);
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);
/* Bind UBO. */
GPU_uniformbuf_bind(shader_curvemap->buffer, shader->ubo_bind);
/* TODO(fclem): remove remains of IMM. */
immBindShader(shader->shader);
/* 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);
return true;
} }
return false; /* 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);
}
/* TODO(fclem): remove remains of IMM. */
immBindShader(shader.shader);
/* 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 true;
} }
void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/) void OCIOImpl::gpuDisplayShaderUnbind()
{ {
immUnbindProgram(); immUnbindProgram();
} }
void OCIOImpl::freeGLState(OCIO_GLSLDrawState *state) void OCIOImpl::gpuCacheFree()
{ {
for (int i = 0; i < SHADER_CACHE_SIZE; i++) { SHADER_CACHE.clear();
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);
} }
/** \} */ /** \} */

View File

@@ -39,8 +39,8 @@ roles:
# Non-color data # Non-color data
data: Non-Color data: Non-Color
# CIE XYZ color space # For interop between configs, and to determine XYZ for rendering
XYZ: XYZ aces_interchange: Linear ACES
# Specifed by OCIO, not used in Blender # Specifed by OCIO, not used in Blender
color_timing: Filmic Log color_timing: Filmic Log
@@ -97,7 +97,10 @@ colorspaces:
isdata: false isdata: false
allocation: lg2 allocation: lg2
allocationvars: [-8.5, 5] allocationvars: [-8.5, 5]
to_reference: !<FileTransform> {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} from_reference: !<GroupTransform>
children:
- !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
- !<FileTransform> {src: xyz_to_aces.spimtx, interpolation: linear}
- !<ColorSpace> - !<ColorSpace>
name: nuke_rec709 name: nuke_rec709

View File

@@ -1,3 +0,0 @@
0.9525523959 0.0000000000 0.0000936786 0
0.3439664498 0.7281660966 -0.072132546 0
0.0000000000 0.0000000000 1.0088251844 0

View File

@@ -1,3 +0,0 @@
0.4395770431 0.3839148879 0.1765103489 0.0
0.0895979404 0.8147120476 0.0956883803 0.0
0.0174174830 0.1087378338 0.8738504052 0.0

View File

@@ -0,0 +1,3 @@
1.0498110175 0.0000000000 -0.0000974845 0
-0.4959030231 1.3733130458 0.0982400361 0
0.0000000000 0.0000000000 0.9912520182 0

View File

@@ -32,6 +32,7 @@ extern "C" {
struct ImBuf; struct ImBuf;
struct OCIO_ConstProcessorRcPtr; struct OCIO_ConstProcessorRcPtr;
struct OCIO_ConstCPUProcessorRcPtr;
extern float imbuf_luma_coefficients[3]; extern float imbuf_luma_coefficients[3];
extern float imbuf_xyz_to_rgb[3][3]; extern float imbuf_xyz_to_rgb[3][3];
@@ -46,8 +47,8 @@ typedef struct ColorSpace {
char name[MAX_COLORSPACE_NAME]; char name[MAX_COLORSPACE_NAME];
char description[MAX_COLORSPACE_DESCRIPTION]; char description[MAX_COLORSPACE_DESCRIPTION];
struct OCIO_ConstProcessorRcPtr *to_scene_linear; struct OCIO_ConstCPUProcessorRcPtr *to_scene_linear;
struct OCIO_ConstProcessorRcPtr *from_scene_linear; struct OCIO_ConstCPUProcessorRcPtr *from_scene_linear;
bool is_invertible; bool is_invertible;
bool is_data; bool is_data;
@@ -66,8 +67,8 @@ typedef struct ColorManagedDisplay {
char name[MAX_COLORSPACE_NAME]; char name[MAX_COLORSPACE_NAME];
ListBase views; /* LinkData.data -> ColorManagedView */ ListBase views; /* LinkData.data -> ColorManagedView */
struct OCIO_ConstProcessorRcPtr *to_scene_linear; struct OCIO_ConstCPUProcessorRcPtr *to_scene_linear;
struct OCIO_ConstProcessorRcPtr *from_scene_linear; struct OCIO_ConstCPUProcessorRcPtr *from_scene_linear;
} ColorManagedDisplay; } ColorManagedDisplay;
typedef struct ColorManagedView { typedef struct ColorManagedView {

View File

@@ -101,40 +101,26 @@ static float imbuf_linear_srgb_to_xyz[3][3] = {{0.0f}};
static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER; static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER;
typedef struct ColormanageProcessor { typedef struct ColormanageProcessor {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *cpu_processor;
CurveMapping *curve_mapping; CurveMapping *curve_mapping;
bool is_data_result; bool is_data_result;
} ColormanageProcessor; } ColormanageProcessor;
static struct global_glsl_state { static struct global_gpu_state {
/* Actual processor used for GLSL baked LUTs. */ /* GPU shader currently bound. */
/* UI colorspace here refers to the display linear color space, bool gpu_shader_bound;
* 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. */
OCIO_ConstProcessorRcPtr *processor_scene_to_ui;
OCIO_ConstProcessorRcPtr *processor_ui_to_display;
/* Settings of processor for comparison. */
char look[MAX_COLORSPACE_NAME];
char view[MAX_COLORSPACE_NAME];
char display[MAX_COLORSPACE_NAME];
char input[MAX_COLORSPACE_NAME];
float exposure, gamma;
/* Curve mapping. */
CurveMapping *curve_mapping, *orig_curve_mapping; CurveMapping *curve_mapping, *orig_curve_mapping;
bool use_curve_mapping; bool use_curve_mapping;
int curve_mapping_timestamp; int curve_mapping_timestamp;
OCIO_CurveMappingSettings curve_mapping_settings; OCIO_CurveMappingSettings curve_mapping_settings;
} global_gpu_state = {NULL};
/* Container for GLSL state needed for OCIO module. */
struct OCIO_GLSLDrawState *ocio_glsl_state;
} global_glsl_state = {NULL};
static struct global_color_picking_state { static struct global_color_picking_state {
/* Cached processor for color picking conversion. */ /* Cached processor for color picking conversion. */
OCIO_ConstProcessorRcPtr *processor_to; OCIO_ConstCPUProcessorRcPtr *cpu_processor_to;
OCIO_ConstProcessorRcPtr *processor_from; OCIO_ConstCPUProcessorRcPtr *cpu_processor_from;
bool failed; bool failed;
} global_color_picking_state = {NULL}; } global_color_picking_state = {NULL};
@@ -609,11 +595,10 @@ static void colormanage_free_config(void)
/* free precomputer processors */ /* free precomputer processors */
if (colorspace->to_scene_linear) { if (colorspace->to_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)colorspace->to_scene_linear); OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)colorspace->to_scene_linear);
} }
if (colorspace->from_scene_linear) { if (colorspace->from_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)colorspace->from_scene_linear); OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)colorspace->from_scene_linear);
} }
/* free color space itself */ /* free color space itself */
@@ -631,11 +616,10 @@ static void colormanage_free_config(void)
/* free precomputer processors */ /* free precomputer processors */
if (display->to_scene_linear) { if (display->to_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)display->to_scene_linear); OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)display->to_scene_linear);
} }
if (display->from_scene_linear) { if (display->from_scene_linear) {
OCIO_processorRelease((OCIO_ConstProcessorRcPtr *)display->from_scene_linear); OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)display->from_scene_linear);
} }
/* free list of views */ /* free list of views */
@@ -727,35 +711,25 @@ void colormanagement_init(void)
void colormanagement_exit(void) void colormanagement_exit(void)
{ {
if (global_glsl_state.processor_scene_to_ui) { OCIO_gpuCacheFree();
OCIO_processorRelease(global_glsl_state.processor_scene_to_ui);
if (global_gpu_state.curve_mapping) {
BKE_curvemapping_free(global_gpu_state.curve_mapping);
} }
if (global_glsl_state.processor_ui_to_display) { if (global_gpu_state.curve_mapping_settings.lut) {
OCIO_processorRelease(global_glsl_state.processor_ui_to_display); MEM_freeN(global_gpu_state.curve_mapping_settings.lut);
} }
if (global_glsl_state.curve_mapping) { if (global_color_picking_state.cpu_processor_to) {
BKE_curvemapping_free(global_glsl_state.curve_mapping); OCIO_cpuProcessorRelease(global_color_picking_state.cpu_processor_to);
} }
if (global_glsl_state.curve_mapping_settings.lut) { if (global_color_picking_state.cpu_processor_from) {
MEM_freeN(global_glsl_state.curve_mapping_settings.lut); OCIO_cpuProcessorRelease(global_color_picking_state.cpu_processor_from);
} }
if (global_glsl_state.ocio_glsl_state) { memset(&global_gpu_state, 0, sizeof(global_gpu_state));
OCIO_freeOGLState(global_glsl_state.ocio_glsl_state);
}
if (global_color_picking_state.processor_to) {
OCIO_processorRelease(global_color_picking_state.processor_to);
}
if (global_color_picking_state.processor_from) {
OCIO_processorRelease(global_color_picking_state.processor_from);
}
memset(&global_glsl_state, 0, sizeof(global_glsl_state));
memset(&global_color_picking_state, 0, sizeof(global_color_picking_state)); memset(&global_color_picking_state, 0, sizeof(global_color_picking_state));
colormanage_free_config(); colormanage_free_config();
@@ -777,6 +751,12 @@ static bool colormanage_compatible_look(ColorManagedLook *look, const char *view
return (look->view[0] == 0 || (view_name && STREQ(look->view, view_name))); return (look->view[0] == 0 || (view_name && STREQ(look->view, view_name)));
} }
static bool colormanage_use_look(const char *look, const char *view_name)
{
ColorManagedLook *look_descr = colormanage_look_get_named(look);
return (look_descr->is_noop == false && colormanage_compatible_look(look_descr, view_name));
}
void colormanage_cache_free(ImBuf *ibuf) void colormanage_cache_free(ImBuf *ibuf)
{ {
if (ibuf->display_buffer_flags) { if (ibuf->display_buffer_flags) {
@@ -852,95 +832,31 @@ static ColorSpace *display_transform_get_colorspace(
return NULL; return NULL;
} }
static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *look, static OCIO_ConstCPUProcessorRcPtr *create_display_buffer_processor(const char *look,
const char *view_transform, const char *view_transform,
const char *display, const char *display,
float exposure, float exposure,
float gamma, float gamma,
const char *from_colorspace, const char *from_colorspace)
const bool linear_output)
{ {
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_DisplayTransformRcPtr *dt; const bool use_look = colormanage_use_look(look, view_transform);
OCIO_ConstProcessorRcPtr *processor; const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure);
ColorManagedLook *look_descr = colormanage_look_get_named(look); const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / MAX2(FLT_EPSILON, gamma);
dt = OCIO_createDisplayTransform(); OCIO_ConstProcessorRcPtr *processor = OCIO_createDisplayProcessor(
config, from_colorspace, view_transform, display, (use_look) ? look : "", scale, exponent);
OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace);
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
if (look_descr->is_noop == false && colormanage_compatible_look(look_descr, view_transform)) {
OCIO_displayTransformSetLooksOverrideEnabled(dt, true);
OCIO_displayTransformSetLooksOverride(dt, look);
}
/* fstop exposure control */
if (exposure != 0.0f) {
OCIO_MatrixTransformRcPtr *mt;
float gain = powf(2.0f, exposure);
const float scale4f[] = {gain, gain, gain, 1.0f};
float m44[16], offset4[4];
OCIO_matrixTransformScale(m44, offset4, scale4f);
mt = OCIO_createMatrixTransform();
OCIO_matrixTransformSetValue(mt, m44, offset4);
OCIO_displayTransformSetLinearCC(dt, (OCIO_ConstTransformRcPtr *)mt);
OCIO_matrixTransformRelease(mt);
}
/* post-display gamma transform */
if (gamma != 1.0f) {
OCIO_ExponentTransformRcPtr *et;
float exponent = 1.0f / MAX2(FLT_EPSILON, gamma);
const float exponent4f[] = {exponent, exponent, exponent, exponent};
et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, exponent4f);
OCIO_displayTransformSetDisplayCC(dt, (OCIO_ConstTransformRcPtr *)et);
OCIO_exponentTransformRelease(et);
}
OCIO_GroupTransformRcPtr *gt = OCIO_createGroupTransform();
OCIO_groupTransformSetDirection(gt, true);
OCIO_groupTransformPushBack(gt, (OCIO_ConstTransformRcPtr *)dt);
if (linear_output) {
/* TODO use correct function display. */
OCIO_ExponentTransformRcPtr *et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, (float[4]){2.2f, 2.2f, 2.2f, 1.0f});
OCIO_groupTransformPushBack(gt, (OCIO_ConstTransformRcPtr *)et);
OCIO_exponentTransformRelease(et);
}
processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *)gt);
OCIO_groupTransformRelease(gt);
OCIO_displayTransformRelease(dt);
OCIO_configRelease(config); OCIO_configRelease(config);
return processor; if (processor == NULL) {
} return NULL;
}
static OCIO_ConstProcessorRcPtr *create_display_encoded_buffer_processor( OCIO_ConstCPUProcessorRcPtr *cpu_processor = OCIO_processorGetCPUProcessor(processor);
const char *UNUSED(display)) OCIO_processorRelease(processor);
{
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_ConstProcessorRcPtr *processor;
/* TODO use correct function display. */ return cpu_processor;
OCIO_ExponentTransformRcPtr *et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, (float[4]){1.0f / 2.2f, 1.0f / 2.2f, 1.0f / 2.2f, 1.0f});
processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *)et);
OCIO_exponentTransformRelease(et);
OCIO_configRelease(config);
return processor;
} }
static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace,
@@ -956,43 +872,54 @@ static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const cha
return processor; return processor;
} }
static OCIO_ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace) static OCIO_ConstCPUProcessorRcPtr *colorspace_to_scene_linear_cpu_processor(
ColorSpace *colorspace)
{ {
if (colorspace->to_scene_linear == NULL) { if (colorspace->to_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock); BLI_mutex_lock(&processor_lock);
if (colorspace->to_scene_linear == NULL) { if (colorspace->to_scene_linear == NULL) {
OCIO_ConstProcessorRcPtr *to_scene_linear; OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
to_scene_linear = create_colorspace_transform_processor(colorspace->name, colorspace->name, global_role_scene_linear);
global_role_scene_linear);
colorspace->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *)to_scene_linear; if (processor != NULL) {
colorspace->to_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
} }
BLI_mutex_unlock(&processor_lock); BLI_mutex_unlock(&processor_lock);
} }
return (OCIO_ConstProcessorRcPtr *)colorspace->to_scene_linear; return (OCIO_ConstCPUProcessorRcPtr *)colorspace->to_scene_linear;
} }
static OCIO_ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace) static OCIO_ConstCPUProcessorRcPtr *colorspace_from_scene_linear_cpu_processor(
ColorSpace *colorspace)
{ {
if (colorspace->from_scene_linear == NULL) { if (colorspace->from_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock); BLI_mutex_lock(&processor_lock);
if (colorspace->from_scene_linear == NULL) { if (colorspace->from_scene_linear == NULL) {
OCIO_ConstProcessorRcPtr *from_scene_linear; OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear, global_role_scene_linear, colorspace->name);
colorspace->name);
colorspace->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *)from_scene_linear; if (processor != NULL) {
colorspace->from_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
} }
BLI_mutex_unlock(&processor_lock); BLI_mutex_unlock(&processor_lock);
} }
return (OCIO_ConstProcessorRcPtr *)colorspace->from_scene_linear; return (OCIO_ConstCPUProcessorRcPtr *)colorspace->from_scene_linear;
} }
static OCIO_ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display) static OCIO_ConstCPUProcessorRcPtr *display_from_scene_linear_processor(
ColorManagedDisplay *display)
{ {
if (display->from_scene_linear == NULL) { if (display->from_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock); BLI_mutex_lock(&processor_lock);
@@ -1011,16 +938,20 @@ static OCIO_ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManage
OCIO_configRelease(config); OCIO_configRelease(config);
} }
display->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *)processor; if (processor != NULL) {
display->from_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
} }
BLI_mutex_unlock(&processor_lock); BLI_mutex_unlock(&processor_lock);
} }
return (OCIO_ConstProcessorRcPtr *)display->from_scene_linear; return (OCIO_ConstCPUProcessorRcPtr *)display->from_scene_linear;
} }
static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display) static OCIO_ConstCPUProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display)
{ {
if (display->to_scene_linear == NULL) { if (display->to_scene_linear == NULL) {
BLI_mutex_lock(&processor_lock); BLI_mutex_lock(&processor_lock);
@@ -1039,13 +970,17 @@ static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedD
OCIO_configRelease(config); OCIO_configRelease(config);
} }
display->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *)processor; if (processor != NULL) {
display->to_scene_linear = (struct OCIO_ConstCPUProcessorRcPtr *)
OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
} }
BLI_mutex_unlock(&processor_lock); BLI_mutex_unlock(&processor_lock);
} }
return (OCIO_ConstProcessorRcPtr *)display->to_scene_linear; return (OCIO_ConstCPUProcessorRcPtr *)display->to_scene_linear;
} }
void IMB_colormanagement_init_default_view_settings( void IMB_colormanagement_init_default_view_settings(
@@ -2168,7 +2103,7 @@ void IMB_colormanagement_transform_v4(float pixel[4],
*/ */
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace) void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace)
{ {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) { if (!colorspace) {
/* should never happen */ /* should never happen */
@@ -2176,17 +2111,17 @@ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpac
return; return;
} }
processor = colorspace_to_scene_linear_processor(colorspace); processor = colorspace_to_scene_linear_cpu_processor(colorspace);
if (processor) { if (processor != NULL) {
OCIO_processorApplyRGB(processor, pixel); OCIO_cpuProcessorApplyRGB(processor, pixel);
} }
} }
/* same as above, but converts colors in opposite direction */ /* same as above, but converts colors in opposite direction */
void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace) void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace)
{ {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) { if (!colorspace) {
/* should never happen */ /* should never happen */
@@ -2194,10 +2129,10 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac
return; return;
} }
processor = colorspace_from_scene_linear_processor(colorspace); processor = colorspace_from_scene_linear_cpu_processor(colorspace);
if (processor) { if (processor != NULL) {
OCIO_processorApplyRGB(processor, pixel); OCIO_cpuProcessorApplyRGB(processor, pixel);
} }
} }
@@ -2205,7 +2140,7 @@ void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4],
bool predivide, bool predivide,
ColorSpace *colorspace) ColorSpace *colorspace)
{ {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) { if (!colorspace) {
/* should never happen */ /* should never happen */
@@ -2213,14 +2148,14 @@ void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4],
return; return;
} }
processor = colorspace_to_scene_linear_processor(colorspace); processor = colorspace_to_scene_linear_cpu_processor(colorspace);
if (processor) { if (processor != NULL) {
if (predivide) { if (predivide) {
OCIO_processorApplyRGBA_predivide(processor, pixel); OCIO_cpuProcessorApplyRGBA_predivide(processor, pixel);
} }
else { else {
OCIO_processorApplyRGBA(processor, pixel); OCIO_cpuProcessorApplyRGBA(processor, pixel);
} }
} }
} }
@@ -2232,7 +2167,7 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
struct ColorSpace *colorspace, struct ColorSpace *colorspace,
bool predivide) bool predivide)
{ {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *processor;
if (!colorspace) { if (!colorspace) {
/* should never happen */ /* should never happen */
@@ -2240,9 +2175,9 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
return; return;
} }
processor = colorspace_to_scene_linear_processor(colorspace); processor = colorspace_to_scene_linear_cpu_processor(colorspace);
if (processor) { if (processor != NULL) {
OCIO_PackedImageDesc *img; OCIO_PackedImageDesc *img;
img = OCIO_createOCIO_PackedImageDesc(buffer, img = OCIO_createOCIO_PackedImageDesc(buffer,
@@ -2254,10 +2189,10 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
(size_t)channels * sizeof(float) * width); (size_t)channels * sizeof(float) * width);
if (predivide) { if (predivide) {
OCIO_processorApply_predivide(processor, img); OCIO_cpuProcessorApply_predivide(processor, img);
} }
else { else {
OCIO_processorApply(processor, img); OCIO_cpuProcessorApply(processor, img);
} }
OCIO_PackedImageDescRelease(img); OCIO_PackedImageDescRelease(img);
@@ -2278,10 +2213,10 @@ void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer,
* without precision or performance loss at minimal memory usage. */ * without precision or performance loss at minimal memory usage. */
BLI_assert(ibuf->rect && ibuf->rect_float == NULL); BLI_assert(ibuf->rect && ibuf->rect_float == NULL);
OCIO_ConstProcessorRcPtr *processor = NULL; OCIO_ConstCPUProcessorRcPtr *processor = NULL;
if (compress_as_srgb && ibuf->rect_colorspace && if (compress_as_srgb && ibuf->rect_colorspace &&
!IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) { !IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) {
processor = colorspace_to_scene_linear_processor(ibuf->rect_colorspace); processor = colorspace_to_scene_linear_cpu_processor(ibuf->rect_colorspace);
} }
/* TODO(brecht): make this multi-threaded, or at least process in batches. */ /* TODO(brecht): make this multi-threaded, or at least process in batches. */
@@ -2294,12 +2229,12 @@ void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer,
const unsigned char *in = in_buffer + in_offset * 4; const unsigned char *in = in_buffer + in_offset * 4;
unsigned char *out = out_buffer + out_offset * 4; unsigned char *out = out_buffer + out_offset * 4;
if (processor) { if (processor != NULL) {
/* Convert to scene linear, to sRGB and premultiply. */ /* Convert to scene linear, to sRGB and premultiply. */
for (int x = 0; x < width; x++, in += 4, out += 4) { for (int x = 0; x < width; x++, in += 4, out += 4) {
float pixel[4]; float pixel[4];
rgba_uchar_to_float(pixel, in); rgba_uchar_to_float(pixel, in);
OCIO_processorApplyRGB(processor, pixel); OCIO_cpuProcessorApplyRGB(processor, pixel);
linearrgb_to_srgb_v3_v3(pixel, pixel); linearrgb_to_srgb_v3_v3(pixel, pixel);
if (use_premultiply) { if (use_premultiply) {
mul_v3_fl(pixel, pixel[3]); mul_v3_fl(pixel, pixel[3]);
@@ -2390,15 +2325,19 @@ void IMB_colormanagement_imbuf_to_float_texture(float *out_buffer,
*/ */
void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]) void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3])
{ {
if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { if (!global_color_picking_state.cpu_processor_to && !global_color_picking_state.failed) {
/* Create processor if none exists. */ /* Create processor if none exists. */
BLI_mutex_lock(&processor_lock); BLI_mutex_lock(&processor_lock);
if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { if (!global_color_picking_state.cpu_processor_to && !global_color_picking_state.failed) {
global_color_picking_state.processor_to = create_colorspace_transform_processor( OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
global_role_scene_linear, global_role_color_picking); global_role_scene_linear, global_role_color_picking);
if (!global_color_picking_state.processor_to) { if (processor != NULL) {
global_color_picking_state.cpu_processor_to = OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
else {
global_color_picking_state.failed = true; global_color_picking_state.failed = true;
} }
} }
@@ -2406,22 +2345,26 @@ void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3])
BLI_mutex_unlock(&processor_lock); BLI_mutex_unlock(&processor_lock);
} }
if (global_color_picking_state.processor_to) { if (global_color_picking_state.cpu_processor_to) {
OCIO_processorApplyRGB(global_color_picking_state.processor_to, pixel); OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_to, pixel);
} }
} }
void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3])
{ {
if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { if (!global_color_picking_state.cpu_processor_from && !global_color_picking_state.failed) {
/* Create processor if none exists. */ /* Create processor if none exists. */
BLI_mutex_lock(&processor_lock); BLI_mutex_lock(&processor_lock);
if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { if (!global_color_picking_state.cpu_processor_from && !global_color_picking_state.failed) {
global_color_picking_state.processor_from = create_colorspace_transform_processor( OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(
global_role_color_picking, global_role_scene_linear); global_role_color_picking, global_role_scene_linear);
if (!global_color_picking_state.processor_from) { if (processor != NULL) {
global_color_picking_state.cpu_processor_from = OCIO_processorGetCPUProcessor(processor);
OCIO_processorRelease(processor);
}
else {
global_color_picking_state.failed = true; global_color_picking_state.failed = true;
} }
} }
@@ -2429,8 +2372,8 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3])
BLI_mutex_unlock(&processor_lock); BLI_mutex_unlock(&processor_lock);
} }
if (global_color_picking_state.processor_from) { if (global_color_picking_state.cpu_processor_from) {
OCIO_processorApplyRGB(global_color_picking_state.processor_from, pixel); OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_from, pixel);
} }
} }
@@ -2456,24 +2399,20 @@ void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3])
*/ */
void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display) void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display)
{ {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *processor = display_from_scene_linear_processor(display);
processor = display_from_scene_linear_processor(display); if (processor != NULL) {
OCIO_cpuProcessorApplyRGB(processor, pixel);
if (processor) {
OCIO_processorApplyRGB(processor, pixel);
} }
} }
/* same as above, but converts color in opposite direction */ /* same as above, but converts color in opposite direction */
void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display) void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display)
{ {
OCIO_ConstProcessorRcPtr *processor; OCIO_ConstCPUProcessorRcPtr *processor = display_to_scene_linear_processor(display);
processor = display_to_scene_linear_processor(display); if (processor != NULL) {
OCIO_cpuProcessorApplyRGB(processor, pixel);
if (processor) {
OCIO_processorApplyRGB(processor, pixel);
} }
} }
@@ -3833,13 +3772,13 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(
cm_processor->is_data_result = display_space->is_data; cm_processor->is_data_result = display_space->is_data;
} }
cm_processor->processor = create_display_buffer_processor(applied_view_settings->look, cm_processor->cpu_processor = create_display_buffer_processor(
applied_view_settings->view_transform, applied_view_settings->look,
display_settings->display_device, applied_view_settings->view_transform,
applied_view_settings->exposure, display_settings->display_device,
applied_view_settings->gamma, applied_view_settings->exposure,
global_role_scene_linear, applied_view_settings->gamma,
false); global_role_scene_linear);
if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
cm_processor->curve_mapping = BKE_curvemapping_copy(applied_view_settings->curve_mapping); cm_processor->curve_mapping = BKE_curvemapping_copy(applied_view_settings->curve_mapping);
@@ -3860,7 +3799,12 @@ ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *f
color_space = colormanage_colorspace_get_named(to_colorspace); color_space = colormanage_colorspace_get_named(to_colorspace);
cm_processor->is_data_result = color_space->is_data; cm_processor->is_data_result = color_space->is_data;
cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); OCIO_ConstProcessorRcPtr *processor = create_colorspace_transform_processor(from_colorspace,
to_colorspace);
if (processor != NULL) {
cm_processor->cpu_processor = OCIO_processorGetCPUProcessor(processor);
}
OCIO_processorRelease(processor);
return cm_processor; return cm_processor;
} }
@@ -3871,8 +3815,8 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor,
BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
} }
if (cm_processor->processor) { if (cm_processor->cpu_processor) {
OCIO_processorApplyRGBA(cm_processor->processor, pixel); OCIO_cpuProcessorApplyRGBA(cm_processor->cpu_processor, pixel);
} }
} }
@@ -3883,8 +3827,8 @@ void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_p
BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
} }
if (cm_processor->processor) { if (cm_processor->cpu_processor) {
OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel); OCIO_cpuProcessorApplyRGBA_predivide(cm_processor->cpu_processor, pixel);
} }
} }
@@ -3894,8 +3838,8 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor,
BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); BKE_curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
} }
if (cm_processor->processor) { if (cm_processor->cpu_processor) {
OCIO_processorApplyRGB(cm_processor->processor, pixel); OCIO_cpuProcessorApplyRGB(cm_processor->cpu_processor, pixel);
} }
} }
@@ -3940,7 +3884,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor,
} }
} }
if (cm_processor->processor && channels >= 3) { if (cm_processor->cpu_processor && channels >= 3) {
OCIO_PackedImageDesc *img; OCIO_PackedImageDesc *img;
/* apply OCIO processor */ /* apply OCIO processor */
@@ -3953,10 +3897,10 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor,
(size_t)channels * sizeof(float) * width); (size_t)channels * sizeof(float) * width);
if (predivide) { if (predivide) {
OCIO_processorApply_predivide(cm_processor->processor, img); OCIO_cpuProcessorApply_predivide(cm_processor->cpu_processor, img);
} }
else { else {
OCIO_processorApply(cm_processor->processor, img); OCIO_cpuProcessorApply(cm_processor->cpu_processor, img);
} }
OCIO_PackedImageDescRelease(img); OCIO_PackedImageDescRelease(img);
@@ -3986,8 +3930,8 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
if (cm_processor->curve_mapping) { if (cm_processor->curve_mapping) {
BKE_curvemapping_free(cm_processor->curve_mapping); BKE_curvemapping_free(cm_processor->curve_mapping);
} }
if (cm_processor->processor) { if (cm_processor->cpu_processor) {
OCIO_processorRelease(cm_processor->processor); OCIO_cpuProcessorRelease(cm_processor->cpu_processor);
} }
MEM_freeN(cm_processor); MEM_freeN(cm_processor);
@@ -3995,19 +3939,6 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
/* **** OpenGL drawing routines using GLSL for color space transform ***** */ /* **** OpenGL drawing routines using GLSL for color space transform ***** */
static bool check_glsl_display_processor_changed(
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *from_colorspace)
{
return !(global_glsl_state.exposure == view_settings->exposure &&
global_glsl_state.gamma == view_settings->gamma &&
STREQ(global_glsl_state.look, view_settings->look) &&
STREQ(global_glsl_state.view, view_settings->view_transform) &&
STREQ(global_glsl_state.display, display_settings->display_device) &&
STREQ(global_glsl_state.input, from_colorspace));
}
static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping, static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping,
OCIO_CurveMappingSettings *curve_mapping_settings) OCIO_CurveMappingSettings *curve_mapping_settings)
{ {
@@ -4041,94 +3972,60 @@ static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping,
curve_mapping_settings->cache_id = (size_t)curve_mapping + curve_mapping->changed_timestamp; curve_mapping_settings->cache_id = (size_t)curve_mapping + curve_mapping->changed_timestamp;
} }
static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings, static OCIO_CurveMappingSettings *update_glsl_curve_mapping(
const ColorManagedDisplaySettings *display_settings, const ColorManagedViewSettings *view_settings)
const char *from_colorspace)
{ {
bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0; /* Using curve mapping? */
bool need_update = false; const bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0;
if (!use_curve_mapping) {
need_update = global_glsl_state.processor_scene_to_ui == NULL || return NULL;
check_glsl_display_processor_changed(
view_settings, display_settings, from_colorspace) ||
use_curve_mapping != global_glsl_state.use_curve_mapping;
if (use_curve_mapping && need_update == false) {
need_update |= view_settings->curve_mapping->changed_timestamp !=
global_glsl_state.curve_mapping_timestamp ||
view_settings->curve_mapping != global_glsl_state.orig_curve_mapping;
} }
/* Update state if there's no processor yet or /* Already up to date? */
* processor settings has been changed. OCIO_CurveMappingSettings *curve_mapping_settings = &global_gpu_state.curve_mapping_settings;
*/ if (view_settings->curve_mapping->changed_timestamp ==
if (need_update) { global_gpu_state.curve_mapping_timestamp &&
OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings; view_settings->curve_mapping == global_gpu_state.orig_curve_mapping) {
CurveMapping *new_curve_mapping = NULL; return curve_mapping_settings;
/* Store settings of processor for further comparison. */
BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.display, display_settings->display_device, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.input, from_colorspace, MAX_COLORSPACE_NAME);
global_glsl_state.exposure = view_settings->exposure;
global_glsl_state.gamma = view_settings->gamma;
/* We're using curve mapping's address as a cache ID,
* so we need to make sure re-allocation gives new address here.
* We do this by allocating new curve mapping before freeing old one. */
if (use_curve_mapping) {
new_curve_mapping = BKE_curvemapping_copy(view_settings->curve_mapping);
}
if (global_glsl_state.curve_mapping) {
BKE_curvemapping_free(global_glsl_state.curve_mapping);
MEM_freeN(curve_mapping_settings->lut);
global_glsl_state.curve_mapping = NULL;
curve_mapping_settings->lut = NULL;
}
/* Fill in OCIO's curve mapping settings. */
if (use_curve_mapping) {
curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings);
global_glsl_state.curve_mapping = new_curve_mapping;
global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp;
global_glsl_state.orig_curve_mapping = view_settings->curve_mapping;
global_glsl_state.use_curve_mapping = true;
}
else {
global_glsl_state.orig_curve_mapping = NULL;
global_glsl_state.use_curve_mapping = false;
}
/* Free old processor, if any. */
if (global_glsl_state.processor_scene_to_ui) {
OCIO_processorRelease(global_glsl_state.processor_scene_to_ui);
}
if (global_glsl_state.processor_ui_to_display) {
OCIO_processorRelease(global_glsl_state.processor_ui_to_display);
}
/* We're using display OCIO processor, no RGB curves yet. */
global_glsl_state.processor_scene_to_ui = create_display_buffer_processor(
global_glsl_state.look,
global_glsl_state.view,
global_glsl_state.display,
global_glsl_state.exposure,
global_glsl_state.gamma,
global_glsl_state.input,
true);
global_glsl_state.processor_ui_to_display = create_display_encoded_buffer_processor(
global_glsl_state.display);
} }
/* Need to update. */
CurveMapping *new_curve_mapping = NULL;
/* We're using curve mapping's address as a cache ID,
* so we need to make sure re-allocation gives new address here.
* We do this by allocating new curve mapping before freeing old one. */
if (use_curve_mapping) {
new_curve_mapping = BKE_curvemapping_copy(view_settings->curve_mapping);
}
if (global_gpu_state.curve_mapping) {
BKE_curvemapping_free(global_gpu_state.curve_mapping);
MEM_freeN(curve_mapping_settings->lut);
global_gpu_state.curve_mapping = NULL;
curve_mapping_settings->lut = NULL;
}
/* Fill in OCIO's curve mapping settings. */
if (use_curve_mapping) {
curve_mapping_to_ocio_settings(new_curve_mapping, &global_gpu_state.curve_mapping_settings);
global_gpu_state.curve_mapping = new_curve_mapping;
global_gpu_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp;
global_gpu_state.orig_curve_mapping = view_settings->curve_mapping;
global_gpu_state.use_curve_mapping = true;
}
else {
global_gpu_state.orig_curve_mapping = NULL;
global_gpu_state.use_curve_mapping = false;
}
return curve_mapping_settings;
} }
bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings)) bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings))
{ {
return OCIO_supportGLSLDraw(); return OCIO_supportGPUShader();
} }
/** /**
@@ -4165,27 +4062,40 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(
applied_view_settings = &default_view_settings; applied_view_settings = &default_view_settings;
} }
/* Make sure OCIO processor is up-to-date. */ /* Ensure curve mapping is up to data. */
update_glsl_display_processor(applied_view_settings, OCIO_CurveMappingSettings *curve_mapping_settings = update_glsl_curve_mapping(
display_settings, applied_view_settings);
from_colorspace ? from_colorspace->name :
global_role_scene_linear);
if (global_glsl_state.processor_scene_to_ui == NULL) { /* GPU shader parameters. */
/* Happens when requesting non-existing color space or LUT in the const char *input = from_colorspace ? from_colorspace->name : global_role_scene_linear;
* configuration file does not exist. const char *view = applied_view_settings->view_transform;
*/ const char *display = display_settings->display_device;
return false; const bool use_look = colormanage_use_look(applied_view_settings->look,
} applied_view_settings->view_transform);
const char *look = (use_look) ? applied_view_settings->look : "";
const float exposure = applied_view_settings->exposure;
const float gamma = applied_view_settings->gamma;
const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure);
const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / MAX2(FLT_EPSILON, gamma);
return OCIO_setupGLSLDraw( OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
&global_glsl_state.ocio_glsl_state,
global_glsl_state.processor_scene_to_ui, /* Bind shader. Internally GPU shaders are created and cached on demand. */
global_glsl_state.processor_ui_to_display, global_gpu_state.gpu_shader_bound = OCIO_gpuDisplayShaderBind(config,
global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL, input,
dither, view,
predivide, display,
do_overlay_merge); look,
curve_mapping_settings,
scale,
exponent,
dither,
predivide,
do_overlay_merge);
OCIO_configRelease(config);
return global_gpu_state.gpu_shader_bound;
} }
/* Configures GLSL shader for conversion from scene linear to display space */ /* Configures GLSL shader for conversion from scene linear to display space */
@@ -4225,8 +4135,9 @@ bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, float dither, bo
/* Finish GLSL-based display space conversion */ /* Finish GLSL-based display space conversion */
void IMB_colormanagement_finish_glsl_draw(void) void IMB_colormanagement_finish_glsl_draw(void)
{ {
if (global_glsl_state.ocio_glsl_state != NULL) { if (global_gpu_state.gpu_shader_bound) {
OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state); OCIO_gpuDisplayShaderUnbind();
global_gpu_state.gpu_shader_bound = false;
} }
} }