Merging r50049 through r50076 from trunk into soc-2011-tomato
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 21 Aug 2012 10:44:04 +0000 (10:44 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 21 Aug 2012 10:44:04 +0000 (10:44 +0000)
176 files changed:
CMakeLists.txt
SConstruct
build_files/cmake/Modules/FindOpenColorIO.cmake [new file with mode: 0644]
build_files/cmake/macros.cmake
build_files/scons/config/darwin-config.py
build_files/scons/config/linux-config.py
build_files/scons/config/win32-mingw-config.py
build_files/scons/config/win32-vc-config.py
build_files/scons/config/win64-mingw-config.py
build_files/scons/config/win64-vc-config.py
build_files/scons/tools/Blender.py
build_files/scons/tools/btools.py
intern/CMakeLists.txt
intern/SConscript
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_mesh.cpp
intern/cycles/blender/blender_object.cpp
intern/cycles/blender/blender_python.cpp
intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_session.h
intern/cycles/blender/blender_shader.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/blender/blender_util.h
intern/cycles/device/CMakeLists.txt
intern/cycles/device/device.cpp
intern/cycles/device/device.h
intern/cycles/device/device_cpu.cpp
intern/cycles/device/device_cuda.cpp
intern/cycles/device/device_multi.cpp
intern/cycles/device/device_opencl.cpp
intern/cycles/device/device_task.cpp [new file with mode: 0644]
intern/cycles/device/device_task.h [new file with mode: 0644]
intern/cycles/kernel/kernel.cpp
intern/cycles/kernel/kernel_compat_cpu.h
intern/cycles/kernel/kernel_globals.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_textures.h
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_image.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/buffers.cpp
intern/cycles/render/buffers.h
intern/cycles/render/camera.cpp
intern/cycles/render/camera.h
intern/cycles/render/graph.cpp
intern/cycles/render/image.cpp
intern/cycles/render/image.h
intern/cycles/render/light.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/render/scene.cpp
intern/cycles/render/scene.h
intern/cycles/render/session.cpp
intern/cycles/render/session.h
intern/cycles/render/tile.cpp
intern/cycles/render/tile.h
intern/cycles/util/util_math.h
intern/cycles/util/util_progress.h
intern/opencolorio/CMakeLists.txt [new file with mode: 0644]
intern/opencolorio/SConscript [new file with mode: 0644]
intern/opencolorio/ocio_capi.cpp [new file with mode: 0644]
intern/opencolorio/ocio_capi.h [new file with mode: 0644]
release/datafiles/colormanagement/config.ocio [new file with mode: 0644]
release/datafiles/colormanagement/luts/adx_adx10_to_cdd.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/adx_cdd_to_cid.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/adx_cid_to_rle.py [new file with mode: 0644]
release/datafiles/colormanagement/luts/adx_cid_to_rle.spi1d [new file with mode: 0644]
release/datafiles/colormanagement/luts/adx_exp_to_aces.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/lg10.spi1d [new file with mode: 0644]
release/datafiles/colormanagement/luts/logc800.py [new file with mode: 0644]
release/datafiles/colormanagement/luts/logc800.spi1d [new file with mode: 0644]
release/datafiles/colormanagement/luts/logc_to_aces.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/rec709.spi1d [new file with mode: 0644]
release/datafiles/colormanagement/luts/rec709_to_aces.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/rrt_ut33_dcdm.spi3d [new file with mode: 0644]
release/datafiles/colormanagement/luts/rrt_ut33_p3d60.spi3d [new file with mode: 0644]
release/datafiles/colormanagement/luts/rrt_ut33_p3dci.spi3d [new file with mode: 0644]
release/datafiles/colormanagement/luts/rrt_ut33_rec709.spi3d [new file with mode: 0644]
release/datafiles/colormanagement/luts/rrt_ut33_sRGB.spi3d [new file with mode: 0644]
release/datafiles/colormanagement/luts/slog.py [new file with mode: 0644]
release/datafiles/colormanagement/luts/slog.spi1d [new file with mode: 0644]
release/datafiles/colormanagement/luts/slog10.spi1d [new file with mode: 0644]
release/datafiles/colormanagement/luts/slog2.py [new file with mode: 0644]
release/datafiles/colormanagement/luts/slogf35_to_aces.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/slogf65_to_aces_3200.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/slogf65_to_aces_5500.spimtx [new file with mode: 0644]
release/datafiles/colormanagement/luts/spi_ocio_srgb_test.spi3d [new file with mode: 0644]
release/datafiles/colormanagement/luts/ten_bit_scale.spimtx [new file with mode: 0644]
release/datafiles/splash.png
release/scripts/startup/bl_ui/space_clip.py
release/scripts/startup/bl_ui/space_image.py
release/scripts/startup/bl_ui/space_info.py
release/scripts/startup/bl_ui/space_node.py
release/scripts/startup/bl_ui/space_sequencer.py
source/blender/blenkernel/BKE_colortools.h
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenlib/BLI_threads.h
source/blender/blenlib/intern/threads.c
source/blender/compositor/operations/COM_InpaintOperation.cpp
source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
source/blender/compositor/operations/COM_ViewerBaseOperation.h
source/blender/editors/include/ED_clip.h
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/render/render_internal.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_clip/clip_buttons.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_clip/space_clip.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_intern.h
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/space_node.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/IMB_colormanagement.h [new file with mode: 0644]
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/SConscript
source/blender/imbuf/intern/IMB_colormanagement_intern.h [new file with mode: 0644]
source/blender/imbuf/intern/IMB_filter.h
source/blender/imbuf/intern/allocimbuf.c
source/blender/imbuf/intern/colormanagement.c [new file with mode: 0644]
source/blender/imbuf/intern/divers.c
source/blender/imbuf/intern/filter.c
source/blender/makesdna/DNA_color_types.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_movieclip_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_color.c
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_movieclip.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_render.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_ui_api.c
source/blender/makesrna/intern/rna_wm.c
source/blender/render/extern/include/RE_engine.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/initrender.h
source/blender/render/intern/include/render_result.h
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/render_result.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_window.c
source/blenderplayer/CMakeLists.txt
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt

index 338135f498758cc4ebeb491aaab0ca8297c42d31..77af06f6260c2dda9c4244d64f26d43cbcb411c2 100644 (file)
@@ -131,6 +131,7 @@ option(WITH_FFTW3         "Enable FFTW3 support (Used for smoke and audio effect
 option(WITH_BULLET        "Enable Bullet (Physics Engine)" ON)
 option(WITH_GAMEENGINE    "Enable Game Engine" ON)
 option(WITH_PLAYER        "Build Player" OFF)
+option(WITH_OPENCOLORIO   "Enable OpenColorIO color management" ON)
 option(WITH_COMPOSITOR    "Enable the tile based nodal compositor" ON)
 option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" ON)
 
@@ -672,6 +673,24 @@ if(UNIX AND NOT APPLE)
                endif()
        endif()
 
+       if(WITH_OPENCOLORIO)
+               # use lib dir if available and nothing else specified
+               if(LIBDIR AND NOT OPENCOLORIO_ROOT_DIR)
+                       set(OPENCOLORIO_ROOT_DIR ${LIBDIR}/ocio)
+               endif()
+
+               find_package(OpenColorIO)
+
+               set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES})
+               set(OPENCOLORIO_LIBPATH)  # TODO, remove and reference the absolute path everywhere
+               set(OPENCOLORIO_DEFINITIONS)
+
+               if(NOT OPENCOLORIO_FOUND)
+                       set(WITH_OPENCOLORIO OFF)
+                       message(STATUS "OpenColorIO not found")
+               endif()
+       endif()
+
        # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
        set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++")
 
@@ -1015,6 +1034,14 @@ elseif(WIN32)
                        set(OPENIMAGEIO_DEFINITIONS)
                endif()
 
+               if(WITH_OPENCOLORIO)
+                       set(OPENCOLORIO ${LIBDIR}/opencolorio)
+                       set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
+                       set(OPENCOLORIO_LIBRARIES OpenColorIO)
+                       set_lib_path(OPENCOLORIO_LIBPATH "opencolorio/lib")
+                       set(OPENCOLORIO_DEFINITIONS)
+               endif()
+
                set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib")
 
                # MSVC only, Mingw doesnt need
@@ -1184,6 +1211,14 @@ elseif(WIN32)
                        set(OPENIMAGEIO_DEFINITIONS)
                endif()
                
+               if(WITH_OPENCOLORIO)
+                       set(OPENCOLORIO ${LIBDIR}/opencolorio)
+                       set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
+                       set(OPENCOLORIO_LIBRARIES OpenColorIO)
+                       set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
+                       set(OPENCOLORIO_DEFINITIONS)
+               endif()
+
                set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
 
                ## DISABLE - causes linking errors 
@@ -1430,6 +1465,14 @@ elseif(APPLE)
                set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD")
        endif()
 
+       if(WITH_OPENCOLORIO)
+               set(OPENCOLORIO ${LIBDIR}/opencolorio)
+               set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
+               set(OPENCOLORIO_LIBRARIES OpenColorIO tinyxml yaml-cpp)
+               set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
+               set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD")
+       endif()
+
        set(EXETYPE MACOSX_BUNDLE)
 
        set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
@@ -1804,6 +1847,7 @@ if(FIRST_RUN)
        info_cfg_option(WITH_INTERNATIONAL)
        info_cfg_option(WITH_INPUT_NDOF)
        info_cfg_option(WITH_CYCLES)
+       info_cfg_option(WITH_OPENCOLORIO)
 
        info_cfg_text("Compiler Options:")
        info_cfg_option(WITH_BUILDINFO)
index 7e6bcdf8747b33dfb730a38f594af17141f8b373..517f507ec61275efa40da7491b725e06082083fe 100644 (file)
@@ -719,6 +719,26 @@ if env['OURPLATFORM']!='darwin':
                     cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch)
                     scriptinstall.append(env.Install(dir=dir,source=cubin_file))
 
+    if env['WITH_BF_OCIO']:
+        colormanagement = os.path.join('release', 'datafiles', 'colormanagement')
+
+        for dp, dn, df in os.walk(colormanagement):
+            if '.svn' in dn:
+                dn.remove('.svn')
+            if '_svn' in dn:
+                dn.remove('_svn')
+
+            dir = os.path.join(env['BF_INSTALLDIR'], VERSION, 'datafiles')
+            dir += os.sep + os.path.basename(colormanagement) + dp[len(colormanagement):]
+
+            source = [os.path.join(dp, f) for f in df if not f.endswith(".pyc")]
+
+            # To ensure empty dirs are created too
+            if len(source) == 0:
+                env.Execute(Mkdir(dir))
+
+            scriptinstall.append(env.Install(dir=dir,source=source))
+
     if env['WITH_BF_INTERNATIONAL']:
         internationalpaths=['release' + os.sep + 'datafiles']
 
@@ -851,6 +871,9 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
     if env['WITH_BF_OIIO'] and env['OURPLATFORM'] != 'win32-mingw':
         dllsources.append('${LCGDIR}/openimageio/bin/OpenImageIO.dll')
 
+    if env['WITH_BF_OCIO'] and env['OURPLATFORM'] != 'win32-mingw':
+        dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll')
+
     dllsources.append('#source/icons/blender.exe.manifest')
 
     windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources)
diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake
new file mode 100644 (file)
index 0000000..78539ae
--- /dev/null
@@ -0,0 +1,71 @@
+# - Find OpenColorIO library
+# Find the native OpenColorIO includes and library
+# This module defines
+#  OPENCOLORIO_INCLUDE_DIRS, where to find OpenColorIO.h, Set when
+#                            OPENCOLORIO_INCLUDE_DIR is found.
+#  OPENCOLORIO_LIBRARIES, libraries to link against to use OpenColorIO.
+#  OPENCOLORIO_ROOT_DIR, The base directory to search for OpenColorIO.
+#                        This can also be an environment variable.
+#  OPENCOLORIO_FOUND, If false, do not try to use OpenColorIO.
+#
+# also defined, but not for general use are
+#  OPENCOLORIO_LIBRARY, where to find the OpenColorIO library.
+
+#=============================================================================
+# Copyright 2012 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If OPENCOLORIO_ROOT_DIR was defined in the environment, use it.
+IF(NOT OPENCOLORIO_ROOT_DIR AND NOT $ENV{OPENCOLORIO_ROOT_DIR} STREQUAL "")
+  SET(OPENCOLORIO_ROOT_DIR $ENV{OPENCOLORIO_ROOT_DIR})
+ENDIF()
+
+SET(_opencolorio_SEARCH_DIRS
+  ${OPENCOLORIO_ROOT_DIR}
+  /usr/local
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+)
+
+FIND_PATH(OPENCOLORIO_INCLUDE_DIR
+  NAMES
+    OpenColorIO/OpenColorIO.h
+  HINTS
+    ${_opencolorio_SEARCH_DIRS}
+  PATH_SUFFIXES
+    include
+)
+
+FIND_LIBRARY(OPENCOLORIO_LIBRARY
+  NAMES
+    OCIO OpenColorIO
+  HINTS
+    ${_opencolorio_SEARCH_DIRS}
+  PATH_SUFFIXES
+    lib64 lib
+  )
+
+# handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if 
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO DEFAULT_MSG
+    OPENCOLORIO_LIBRARY OPENCOLORIO_INCLUDE_DIR)
+
+IF(OPENCOLORIO_FOUND)
+  SET(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARY})
+  SET(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO_INCLUDE_DIR})
+ENDIF(OPENCOLORIO_FOUND)
+
+MARK_AS_ADVANCED(
+  OPENCOLORIO_INCLUDE_DIR
+  OPENCOLORIO_LIBRARY
+)
+
index 62e1e83326c7f4c069f880795f3892b4a8f9d1a3..f14e92047329d7c8a3ab7f59d86f4ef5e9b1fb24 100644 (file)
@@ -212,6 +212,9 @@ macro(SETUP_LIBDIRS)
        if(WITH_OPENIMAGEIO)
                link_directories(${OPENIMAGEIO_LIBPATH})
        endif()
+       if(WITH_OPENCOLORIO)
+               link_directories(${OPENCOLORIO_LIBPATH})
+       endif()
        if(WITH_IMAGE_OPENJPEG AND WITH_SYSTEM_OPENJPEG)
                link_directories(${OPENJPEG_LIBPATH})
        endif()
@@ -307,6 +310,9 @@ macro(setup_liblinks
        if(WITH_OPENIMAGEIO)
                target_link_libraries(${target} ${OPENIMAGEIO_LIBRARIES})
        endif()
+       if(WITH_OPENCOLORIO)
+               target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
+       endif()
        if(WITH_BOOST)
                target_link_libraries(${target} ${BOOST_LIBRARIES})
        endif()
index 1ce9416d5c403148956aaeae0ad2d26f23098220..afab4131de841053cad1ec39875f968b99ebf5f6 100644 (file)
@@ -287,6 +287,12 @@ BF_OIIO_INC = BF_OIIO + '/include'
 BF_OIIO_LIB = 'OpenImageIO'
 BF_OIIO_LIBPATH = BF_OIIO + '/lib'
 
+WITH_BF_OCIO = True
+BF_OCIO = LIBDIR + '/opencolorio'
+BF_OCIO_INC = BF_OCIO + '/include'
+BF_OCIO_LIB = 'OpenColorIO tinyxml yaml-cpp'
+BF_OCIO_LIBPATH = BF_OCIO + '/lib'
+
 WITH_BF_BOOST = True
 BF_BOOST = LIBDIR + '/boost'
 BF_BOOST_INC = BF_BOOST + '/include'
index e97c3b8b9d7825cb41221c80537161fa56b077b7..5c16baa2ee8d87f6abb54682e5e653fd7eef4c2d 100644 (file)
@@ -215,6 +215,16 @@ BF_OIIO_INC = BF_OIIO + '/include'
 BF_OIIO_LIB = 'OpenImageIO'
 BF_OIIO_LIBPATH = BF_OIIO + '/lib'
 
+WITH_BF_OCIO = True
+WITH_BF_STATICOCIO = False
+BF_OCIO = LIBDIR + '/ocio'
+if not os.path.exists(LCGDIR + '/ocio'):
+    WITH_BF_OCIO = False
+    BF_OCIO = '/usr'
+BF_OCIO_INC = BF_OCIO + '/include'
+BF_OCIO_LIB = 'OpenColorIO yaml-cpp tinyxml'
+BF_OCIO_LIBPATH = BF_OCIO + '/lib'
+
 WITH_BF_BOOST = True
 WITH_BF_STATICBOOST = False
 BF_BOOST = LIBDIR + '/boost'
index 723651971d04f7f6833ee0a6327a2f5e5bb9b377..f61b128fe9fb469b3e2af829ff27d3e024b8cbb6 100644 (file)
@@ -159,6 +159,12 @@ BF_OIIO_INC = BF_OIIO + '/include'
 BF_OIIO_LIB = 'OpenImageIO'
 BF_OIIO_LIBPATH = BF_OIIO + '/lib'
 
+WITH_BF_OCIO = False
+BF_OCIO = LIBDIR + '/opencolorio'
+BF_OCIO_INC = BF_OCIO + '/include'
+BF_OCIO_LIB = 'OpenColorIO'
+BF_OCIO_LIBPATH = BF_OCIO + '/lib'
+
 WITH_BF_BOOST = True
 BF_BOOST = LIBDIR + '/boost'
 BF_BOOST_INC = BF_BOOST + '/include'
index 452bbaaf54f9613e49c603f9616c291256b65b83..b77ff8e70e075def7a55cb746cebce91d182d5bb 100644 (file)
@@ -161,6 +161,12 @@ BF_OIIO_INC = '${BF_OIIO}/include'
 BF_OIIO_LIB = 'OpenImageIO'
 BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
 
+WITH_BF_OCIO = True
+BF_OCIO = '${LIBDIR}/opencolorio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB = 'OpenColorIO'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
 WITH_BF_BOOST = True
 BF_BOOST = '${LIBDIR}/boost'
 BF_BOOST_INC = '${BF_BOOST}/include'
index 272864392974f7746693404aacf0818ebe581e22..3eb9803c785a5cd891dc2a41d0102f2489cd5df5 100644 (file)
@@ -159,6 +159,12 @@ BF_OIIO_INC = '${BF_OIIO}/include'
 BF_OIIO_LIB = 'OpenImageIO'
 BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
 
+WITH_BF_OCIO = False
+BF_OCIO = LIBDIR + '/opencolorio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB = 'OpenColorIO'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
 WITH_BF_BOOST = True
 BF_BOOST = LIBDIR + '/boost'
 BF_BOOST_INC = BF_BOOST + '/include'
index b6a3c108cdb86736c8db4bf13a407d1d53735d12..4b719469c392a8e0e718807d38a4770df9bc65ed 100644 (file)
@@ -158,6 +158,13 @@ BF_OIIO_LIB = 'OpenImageIO'
 BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
 BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
 
+WITH_BF_OCIO = True
+BF_OCIO = '${LIBDIR}/opencolorio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB = 'OpenColorIO'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
 WITH_BF_BOOST = True
 BF_BOOST = '${LIBDIR}/boost'
 BF_BOOST_INC = '${BF_BOOST}/include'
index 56d13649cd1b075c4f375b6555f58d186054c8ef..40e9179f12b7cd669aa0926d32a17846a65471e5 100644 (file)
@@ -204,6 +204,11 @@ def setup_staticlibs(lenv):
         if lenv['WITH_BF_STATICOIIO']:
             statlibs += Split(lenv['BF_OIIO_LIB_STATIC'])
 
+    if lenv['WITH_BF_OCIO']:
+        libincs += Split(lenv['BF_OCIO_LIBPATH'])
+        if lenv['WITH_BF_STATICOCIO']:
+            statlibs += Split(lenv['BF_OCIO_LIB_STATIC'])
+
     if lenv['WITH_BF_BOOST']:
         libincs += Split(lenv['BF_BOOST_LIBPATH'])
         if lenv['WITH_BF_STATICBOOST']:
@@ -252,6 +257,10 @@ def setup_syslibs(lenv):
         if not lenv['WITH_BF_STATICOIIO']:
             syslibs += Split(lenv['BF_OIIO_LIB'])
 
+    if lenv['WITH_BF_OCIO']:
+        if not lenv['WITH_BF_STATICOCIO']:
+            syslibs += Split(lenv['BF_OCIO_LIB'])
+
     if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
         syslibs += Split(lenv['BF_OPENEXR_LIB'])
     if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
@@ -584,6 +593,9 @@ def AppIt(target=None, source=None, env=None):
         commands.getoutput(cmd)
         cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
         commands.getoutput(cmd)
+        if env['WITH_BF_OCIO']:
+            cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
+            commands.getoutput(cmd)
         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
         commands.getoutput(cmd)
 
index 2fa503f3f2622fcdfd555aa08b9f03d2a11b020d..633492ba0eeb6db871fa134946bf4590af0980e5 100644 (file)
@@ -163,6 +163,7 @@ def validate_arguments(args, bc):
             'WITH_BF_3DMOUSE', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC',
             'WITH_BF_CYCLES', 'WITH_BF_CYCLES_CUDA_BINARIES', 'BF_CYCLES_CUDA_NVCC', 'BF_CYCLES_CUDA_NVCC', 'WITH_BF_CYCLES_CUDA_THREADED_COMPILE',
             'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH',
+            'WITH_BF_OCIO', 'WITH_BF_STATICOCIO', 'BF_OCIO', 'BF_OCIO_INC', 'BF_OCIO_LIB', 'BF_OCIO_LIB_STATIC', 'BF_OCIO_LIBPATH',
             'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH',
             'WITH_BF_LIBMV'
             ]
@@ -575,6 +576,14 @@ def read_opts(env, cfg, args):
         ('BF_OIIO_LIBPATH', 'OIIO library path', ''),
         ('BF_OIIO_LIB_STATIC', 'OIIO static library', ''),
 
+        (BoolVariable('WITH_BF_OCIO', 'Build with OpenColorIO', False)),
+        (BoolVariable('WITH_BF_STATICOCIO', 'Staticly link to OpenColorIO', False)),
+        ('BF_OCIO', 'OCIO root path', ''),
+        ('BF_OCIO_INC', 'OCIO include path', ''),
+        ('BF_OCIO_LIB', 'OCIO library', ''),
+        ('BF_OCIO_LIBPATH', 'OCIO library path', ''),
+        ('BF_OCIO_LIB_STATIC', 'OCIO static library', ''),
+
         (BoolVariable('WITH_BF_BOOST', 'Build with Boost', False)),
         (BoolVariable('WITH_BF_STATICBOOST', 'Staticly link to boost', False)),
         ('BF_BOOST', 'Boost root path', ''),
index d520ffc87b4ec3fa9880232a22ca6b83f0717004..1609bd35fa6966695e6c243fd9e0e12152bcc505 100644 (file)
@@ -73,3 +73,7 @@ endif()
 if(WIN32)
        add_subdirectory(utfconv)
 endif()
+
+if(WITH_OPENCOLORIO)
+       add_subdirectory(opencolorio)
+endif()
index 53fc80b0317988560caabcd310f84287df410b80..f4771ccf6a7b30ab33a3480cef4a51d68af754c0 100644 (file)
@@ -30,3 +30,6 @@ if env['WITH_BF_BOOLEAN']:
 
 if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
     SConscript(['utfconv/SConscript'])
+
+if env['WITH_BF_OCIO']:
+    SConscript(['opencolorio/SConscript'])
index 7a22cba316e4aa345a34bbe5805b4d9169e1348b..c23f0196c2d60b288489460ca5490e71a3083608 100644 (file)
@@ -241,12 +241,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 min=1, max=4096,
                 default=1024,
                 )
-        cls.debug_min_size = IntProperty(
-                name="Min Size",
-                description="",
-                min=1, max=4096,
-                default=64,
+
+        cls.resolution_divider = IntProperty(
+                name="Resolution Divider",
+                description="Start viewport rendering with lower resolution which would be real resolution divided by two in power of this value",
+                min=1, max=512,
+                default=4,
                 )
+
         cls.debug_reset_timeout = FloatProperty(
                 name="Reset timeout",
                 description="",
index 5234db5255ef5327d4dcd3cc47bc593f5d24d0db..561ccbbe3d1610be4187cd1f9ddef92ed78210d2 100644 (file)
@@ -197,8 +197,13 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
 
         sub = col.column(align=True)
         sub.label(text="Tiles:")
-        sub.prop(cscene, "debug_tile_size")
-        sub.prop(cscene, "debug_min_size")
+
+        sub.prop(rd, "parts_x", text="X")
+        sub.prop(rd, "parts_y", text="Y")
+
+        subsub = sub.column()
+        subsub.enabled = not rd.use_border
+        subsub.prop(rd, "use_save_buffers")
 
         col = split.column()
 
@@ -208,6 +213,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
         sub.prop(cscene, "debug_use_spatial_splits")
         sub.prop(cscene, "use_cache")
 
+        sub.prop(cscene, "resolution_divider")
+
 
 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
     bl_label = "Layers"
index 16e4ceded89bfa7d0f29be860d32352617388d38..9764f24a89356667baa47caf44f35c4f28d850b3 100644 (file)
@@ -317,11 +317,11 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion)
                BL::Mesh::vertices_iterator v;
                AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST;
                Attribute *attr_M = mesh->attributes.add(std);
-               float3 *M = attr_M->data_float3();
+               float3 *M = attr_M->data_float3(), *cur_M;
                size_t i = 0;
 
-               for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < size; ++v, M++, i++)
-                       *M = get_float3(v->co());
+               for(b_mesh.vertices.begin(v), cur_M = M; v != b_mesh.vertices.end() && i < size; ++v, cur_M++, i++)
+                       *cur_M = get_float3(v->co());
 
                /* if number of vertices changed, or if coordinates stayed the same, drop it */
                if(i != size || memcmp(M, &mesh->verts[0], sizeof(float3)*size) == 0)
index eb9cc7bc4de34caaee44acd92ec4cfd220063879..813314f67a6a0582787bb5bb5baa2855500732da 100644 (file)
@@ -305,14 +305,17 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
        BL::Scene b_sce = b_scene;
        int particle_offset = 0;
 
-       for(; b_sce; b_sce = b_sce.background_set()) {
-               for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) {
+       bool cancel = false;
+
+       for(; b_sce && !cancel; b_sce = b_sce.background_set()) {
+               for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end() && !cancel; ++b_ob) {
                        bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
                        uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), object_is_light(*b_ob));
                        CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, ob_layer);
                        hide = hide || !(ob_layer & scene_layer);
 
                        if(!hide) {
+                               progress.set_status("Synchronizing object", (*b_ob).name());
 
                                int num_particles = object_count_particles(*b_ob);
 
@@ -354,10 +357,12 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
 
                                particle_offset += num_particles;
                        }
+
+                       cancel = progress.get_cancel();
                }
        }
 
-       if(!motion) {
+       if(!cancel && !motion) {
                sync_background_light();
 
                /* handle removed data and modified pointers */
index 4560c2f8543ea310c56a9cdbaa71e5d58f749649..96d5bb61ff8e394f8f4b1f742e4aa978d8e5bb7c 100644 (file)
@@ -80,6 +80,8 @@ static PyObject *create_func(PyObject *self, PyObject *args)
        /* create session */
        BlenderSession *session;
 
+       Py_BEGIN_ALLOW_THREADS
+
        if(rv3d) {
                /* interactive session */
                int width = region.width();
@@ -91,7 +93,9 @@ static PyObject *create_func(PyObject *self, PyObject *args)
                /* offline session */
                session = new BlenderSession(engine, userpref, data, scene);
        }
-       
+
+       Py_END_ALLOW_THREADS
+
        return PyLong_FromVoidPtr(session);
 }
 
@@ -136,9 +140,13 @@ static PyObject *draw_func(PyObject *self, PyObject *args)
 
 static PyObject *sync_func(PyObject *self, PyObject *value)
 {
+       Py_BEGIN_ALLOW_THREADS
+
        BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value);
        session->synchronize();
 
+       Py_END_ALLOW_THREADS
+
        Py_RETURN_NONE;
 }
 
index d09e43bd76d2a5f85bb32dad52855ca604c56db3..7b80c520e726131929db67110f6e3cfbd43cc2dc 100644 (file)
@@ -42,14 +42,13 @@ CCL_NAMESPACE_BEGIN
 BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_,
        BL::BlendData b_data_, BL::Scene b_scene_)
 : b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_),
-  b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL),
-  b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
+  b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL)
 {
        /* offline render */
-       BL::RenderSettings r = b_scene.render();
 
-       width = (int)(r.resolution_x()*r.resolution_percentage()/100);
-       height = (int)(r.resolution_y()*r.resolution_percentage()/100);
+       width = b_engine.resolution_x();
+       height = b_engine.resolution_y();
+
        background = true;
        last_redraw_time = 0.0f;
 
@@ -60,7 +59,7 @@ BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b
        BL::BlendData b_data_, BL::Scene b_scene_,
        BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_)
 : b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_),
-  b_v3d(b_v3d_), b_rv3d(b_rv3d_), b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
+  b_v3d(b_v3d_), b_rv3d(b_rv3d_)
 {
        /* 3d view render */
        width = width_;
@@ -80,17 +79,24 @@ BlenderSession::~BlenderSession()
 void BlenderSession::create_session()
 {
        SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
-       SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
+       SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
 
        /* reset status/progress */
        last_status = "";
        last_progress = -1.0f;
 
        /* create scene */
-       scene = new Scene(scene_params);
+       scene = new Scene(scene_params, session_params.device);
+
+       /* create session */
+       session = new Session(session_params);
+       session->scene = scene;
+       session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
+       session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
+       session->set_pause(BlenderSync::get_session_pause(b_scene, background));
 
        /* create sync */
-       sync = new BlenderSync(b_data, b_scene, scene, !background);
+       sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
        sync->sync_data(b_v3d, b_engine.camera_override());
 
        if(b_rv3d)
@@ -98,13 +104,6 @@ void BlenderSession::create_session()
        else
                sync->sync_camera(b_engine.camera_override(), width, height);
 
-       /* create session */
-       session = new Session(session_params);
-       session->scene = scene;
-       session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
-       session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
-       session->set_pause(BlenderSync::get_session_pause(b_scene, background));
-
        /* set buffer parameters */
        BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
        session->reset(buffer_params, session_params.samples);
@@ -177,35 +176,100 @@ static PassType get_pass_type(BL::RenderPass b_pass)
        return PASS_NONE;
 }
 
+static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername)
+{
+       RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername);
+       PointerRNA rrptr;
+       RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
+       return BL::RenderResult(rrptr);
+}
+
+static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false)
+{
+       RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel);
+}
+
+void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only)
+{
+       BufferParams& params = rtile.buffers->params;
+       int x = params.full_x - session->tile_manager.params.full_x;
+       int y = params.full_y - session->tile_manager.params.full_y;
+       int w = params.width;
+       int h = params.height;
+
+       /* get render result */
+       BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str());
+
+       /* can happen if the intersected rectangle gives 0 width or height */
+       if (b_rr.ptr.data == NULL) {
+               return;
+       }
+
+       BL::RenderResult::layers_iterator b_single_rlay;
+       b_rr.layers.begin(b_single_rlay);
+       BL::RenderLayer b_rlay = *b_single_rlay;
+
+       if (do_update_only) {
+               /* update only needed */
+               update_render_result(b_rr, b_rlay, rtile);
+               end_render_result(b_engine, b_rr, true);
+       }
+       else {
+               /* write result */
+               write_render_result(b_rr, b_rlay, rtile);
+               end_render_result(b_engine, b_rr);
+       }
+}
+
+void BlenderSession::write_render_tile(RenderTile& rtile)
+{
+       do_write_update_render_tile(rtile, false);
+}
+
+void BlenderSession::update_render_tile(RenderTile& rtile)
+{
+       do_write_update_render_tile(rtile, true);
+}
+
 void BlenderSession::render()
 {
+       /* set callback to write out render results */
+       session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
+       session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1);
+
        /* get buffer parameters */
-       SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
+       SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
        BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
-       int w = buffer_params.width, h = buffer_params.height;
-
-       /* create render result */
-       RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h);
-       PointerRNA rrptr;
-       RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
-       b_rr = BL::RenderResult(rrptr);
 
+       /* render each layer */
        BL::RenderSettings r = b_scene.render();
-       BL::RenderResult::layers_iterator b_iter;
-       BL::RenderLayers b_rr_layers(r.ptr);
+       BL::RenderSettings::layers_iterator b_iter;
        
-       /* render each layer */
-       for(b_rr.layers.begin(b_iter); b_iter != b_rr.layers.end(); ++b_iter) {
-               /* set layer */
-               b_rlay = *b_iter;
+       for(r.layers.begin(b_iter); b_iter != r.layers.end(); ++b_iter) {
+               b_rlay_name = b_iter->name();
+
+               /* temporary render result to find needed passes */
+               BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str());
+               BL::RenderResult::layers_iterator b_single_rlay;
+               b_rr.layers.begin(b_single_rlay);
+
+               /* layer will be missing if it was disabled in the UI */
+               if(b_single_rlay == b_rr.layers.end()) {
+                       end_render_result(b_engine, b_rr, true);
+                       continue;
+               }
+
+               BL::RenderLayer b_rlay = *b_single_rlay;
 
                /* add passes */
                vector<Pass> passes;
                Pass::add(PASS_COMBINED, passes);
 
                if(session_params.device.advanced_shading) {
+
+                       /* loop over passes */
                        BL::RenderLayer::passes_iterator b_pass_iter;
-                       
+
                        for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
                                BL::RenderPass b_pass(*b_pass_iter);
                                PassType pass_type = get_pass_type(b_pass);
@@ -217,13 +281,16 @@ void BlenderSession::render()
                        }
                }
 
+               /* free result without merging */
+               end_render_result(b_engine, b_rr, true);
+
                buffer_params.passes = passes;
                scene->film->tag_passes_update(scene, passes);
                scene->film->tag_update(scene);
                scene->integrator->tag_update(scene);
 
                /* update scene */
-               sync->sync_data(b_v3d, b_engine.camera_override(), b_iter->name().c_str());
+               sync->sync_data(b_v3d, b_engine.camera_override(), b_rlay_name.c_str());
 
                /* update session */
                int samples = sync->get_layer_samples();
@@ -235,19 +302,16 @@ void BlenderSession::render()
 
                if(session->progress.get_cancel())
                        break;
-
-               /* write result */
-               write_render_result();
        }
 
-       /* delete render result */
-       RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
+       /* clear callback */
+       session->write_render_tile_cb = NULL;
+       session->update_render_tile_cb = NULL;
 }
 
-void BlenderSession::write_render_result()
+void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only)
 {
-       /* get state */
-       RenderBuffers *buffers = session->buffers;
+       RenderBuffers *buffers = rtile.buffers;
 
        /* copy data from device */
        if(!buffers->copy_from_device())
@@ -255,41 +319,49 @@ void BlenderSession::write_render_result()
 
        BufferParams& params = buffers->params;
        float exposure = scene->film->exposure;
-       double total_time, sample_time;
-       int sample;
-
-       session->progress.get_sample(sample, total_time, sample_time);
 
        vector<float> pixels(params.width*params.height*4);
 
-       /* copy each pass */
-       BL::RenderLayer::passes_iterator b_iter;
-       
-       for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
-               BL::RenderPass b_pass(*b_iter);
+       if (!do_update_only) {
+               /* copy each pass */
+               BL::RenderLayer::passes_iterator b_iter;
+
+               for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
+                       BL::RenderPass b_pass(*b_iter);
 
-               /* find matching pass type */
-               PassType pass_type = get_pass_type(b_pass);
-               int components = b_pass.channels();
+                       /* find matching pass type */
+                       PassType pass_type = get_pass_type(b_pass);
+                       int components = b_pass.channels();
 
-               /* copy pixels */
-               if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0]))
-                       rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]);
+                       /* copy pixels */
+                       if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0]))
+                               rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]);
+               }
        }
 
        /* copy combined pass */
-       if(buffers->get_pass(PASS_COMBINED, exposure, sample, 4, &pixels[0]))
+       if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
                rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]);
 
        /* tag result as updated */
        RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
 }
 
+void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile)
+{
+       do_write_update_render_result(b_rr, b_rlay, rtile, false);
+}
+
+void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile)
+{
+       do_write_update_render_result(b_rr, b_rlay, rtile, true);
+}
+
 void BlenderSession::synchronize()
 {
        /* on session/scene parameter changes, we recreate session entirely */
        SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
-       SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
+       SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
 
        if(session->params.modified(session_params) ||
           scene->params.modified(scene_params))
@@ -364,7 +436,7 @@ bool BlenderSession::draw(int w, int h)
 
                /* reset if requested */
                if(reset) {
-                       SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
+                       SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
                        BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, w, h);
 
                        session->reset(buffer_params, session_params.samples);
@@ -387,11 +459,16 @@ void BlenderSession::get_status(string& status, string& substatus)
 
 void BlenderSession::get_progress(float& progress, double& total_time)
 {
-       double sample_time;
-       int sample;
+       double tile_time;
+       int tile, sample, samples_per_tile;
+       int tile_total = session->tile_manager.state.num_tiles;
+
+       session->progress.get_tile(tile, total_time, tile_time);
 
-       session->progress.get_sample(sample, total_time, sample_time);
-       progress = ((float)sample/(float)session->params.samples);
+       sample = session->progress.get_sample();
+       samples_per_tile = session->tile_manager.state.num_samples;
+
+       progress = ((float)sample/(float)(tile_total * samples_per_tile));
 }
 
 void BlenderSession::update_status_progress()
@@ -404,8 +481,13 @@ void BlenderSession::update_status_progress()
        get_status(status, substatus);
        get_progress(progress, total_time);
 
+       timestatus = b_scene.name();
+       if(b_rlay_name != "")
+               timestatus += ", "  + b_rlay_name;
+       timestatus += " | ";
+
        BLI_timestr(total_time, time_str);
-       timestatus = "Elapsed: " + string(time_str) + " | ";
+       timestatus += "Elapsed: " + string(time_str) + " | ";
 
        if(substatus.size() > 0)
                status += " | " + substatus;
@@ -435,7 +517,6 @@ void BlenderSession::tag_redraw()
 
                /* offline render, redraw if timeout passed */
                if(time_dt() - last_redraw_time > 1.0) {
-                       write_render_result();
                        engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
                        last_redraw_time = time_dt();
                }
index b98e3ffed54fc3c618fef57765364d2158b2189d..4666b5982e1162dae943caf7b705fb56d79b1963 100644 (file)
@@ -29,6 +29,8 @@ CCL_NAMESPACE_BEGIN
 
 class Scene;
 class Session;
+class RenderBuffers;
+class RenderTile;
 
 class BlenderSession {
 public:
@@ -46,7 +48,15 @@ public:
 
        /* offline render */
        void render();
-       void write_render_result();
+
+       void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
+       void write_render_tile(RenderTile& rtile);
+
+       /* update functions are used to update display buffer only after sample was rendered
+        * only needed for better visual feedback
+        */
+       void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
+       void update_render_tile(RenderTile& rtile);
 
        /* interactive updates */
        void synchronize();
@@ -72,13 +82,16 @@ public:
        BL::Scene b_scene;
        BL::SpaceView3D b_v3d;
        BL::RegionView3D b_rv3d;
-       BL::RenderResult b_rr;
-       BL::RenderLayer b_rlay;
+       string b_rlay_name;
 
        string last_status;
        float last_progress;
 
        int width, height;
+
+protected:
+       void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only);
+       void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
 };
 
 CCL_NAMESPACE_END
index 2c15a60dab61fa2685f5356d63b9c6f3ace3639c..7b1b4d5c6ba23fd72ef8d15b6377087cfae2a1dc 100644 (file)
@@ -404,6 +404,8 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
                        if(b_image)
                                image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
                        image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
+                       image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+                       image->projection_blend = b_image_node.projection_blend();
                        get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
                        node = image;
                        break;
index ae28453a69684858ac2db3d63718c2f338f54a70..d35c93ccbd2d23f999c49cf4cd078bb7a5c99842 100644 (file)
@@ -40,15 +40,17 @@ CCL_NAMESPACE_BEGIN
 
 /* Constructor */
 
-BlenderSync::BlenderSync(BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_)
-: b_data(b_data_), b_scene(b_scene_),
+BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
+: b_engine(b_engine_),
+  b_data(b_data_), b_scene(b_scene_),
   shader_map(&scene_->shaders),
   object_map(&scene_->objects),
   mesh_map(&scene_->meshes),
   light_map(&scene_->lights),
   world_map(NULL),
   world_recalc(false),
-  experimental(false)
+  experimental(false),
+  progress(progress_)
 {
        scene = scene_;
        preview = preview_;
@@ -287,7 +289,7 @@ bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background)
        return (background)? false: get_boolean(cscene, "preview_pause");
 }
 
-SessionParams BlenderSync::get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
+SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
 {
        SessionParams params;
        PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
@@ -341,25 +343,41 @@ SessionParams BlenderSync::get_session_params(BL::UserPreferences b_userpref, BL
                }
        }
 
+       /* tiles */
+       if(params.device.type != DEVICE_CPU && !background) {
+               printf("%d\n", get_int(cscene, "debug_tile_size"));
+
+               /* currently GPU could be much slower than CPU when using tiles,
+                * still need to be investigated, but meanwhile make it possible
+                * to work in viewport smoothly
+                */
+               int debug_tile_size = get_int(cscene, "debug_tile_size");
+
+               params.tile_size = make_int2(debug_tile_size, debug_tile_size);
+       }
+       else {
+               int tile_x = b_engine.tile_x();
+               int tile_y = b_engine.tile_y();
+
+               params.tile_size = make_int2(tile_x, tile_y);
+       }
+
+       params.resolution = 1 << get_int(cscene, "resolution_divider");
+
        /* other parameters */
        params.threads = b_scene.render().threads();
-       params.tile_size = get_int(cscene, "debug_tile_size");
-       params.min_size = get_int(cscene, "debug_min_size");
+
        params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");
        params.reset_timeout = get_float(cscene, "debug_reset_timeout");
        params.text_timeout = get_float(cscene, "debug_text_timeout");
 
        if(background) {
-               params.progressive = true;
-               params.min_size = INT_MAX;
+               params.progressive = false;
+               params.resolution = 1;
        }
        else
                params.progressive = true;
        
-       /* todo: multi device only works with single tiles now */
-       if(params.device.type == DEVICE_MULTI)
-               params.tile_size = INT_MAX;
-
        return params;
 }
 
index 6065235a278ba31e65b0dd98fe65e74b0e89a744..ac1fed060ee6a3f74368faf1134a8f7347343e9d 100644 (file)
@@ -49,7 +49,7 @@ class ShaderNode;
 
 class BlenderSync {
 public:
-       BlenderSync(BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_);
+       BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_);
        ~BlenderSync();
 
        /* sync */
@@ -61,7 +61,7 @@ public:
 
        /* get parameters */
        static SceneParams get_scene_params(BL::Scene b_scene, bool background);
-       static SessionParams get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
+       static SessionParams get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
        static bool get_session_pause(BL::Scene b_scene, bool background);
        static BufferParams get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height);
 
@@ -96,6 +96,7 @@ private:
        int object_count_particles(BL::Object b_ob);
 
        /* variables */
+       BL::RenderEngine b_engine;
        BL::BlendData b_data;
        BL::Scene b_scene;
 
@@ -130,6 +131,8 @@ private:
                bool use_localview;
                int samples;
        } render_layer;
+
+       Progress &progress;
 };
 
 /* we don't have spare bits for localview (normally 20-28)
index ebbd4e1221cf941bd4d9c7d091f44fd86cd04ef6..b08c1e7e765ac674457df49cabf5aa30cf3e9183 100644 (file)
@@ -40,9 +40,9 @@ void rna_Object_create_duplilist(void *ob, void *reports, void *sce);
 void rna_Object_free_duplilist(void *ob, void *reports);
 void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
 void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
-struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h);
+struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h, const char *layername);
 void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result);
-void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result);
+void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result, int cancel);
 int RE_engine_test_break(struct RenderEngine *engine);
 void RE_engine_update_stats(struct RenderEngine *engine, const char *stats, const char *info);
 void RE_engine_update_progress(struct RenderEngine *engine, float progress);
@@ -55,7 +55,6 @@ void rna_ColorRamp_eval(void *coba, float position, float color[4]);
 void rna_Scene_frame_set(void *scene, int frame, float subframe);
 void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
 void BKE_image_user_file_path(void *iuser, void *ima, char *path);
-
 }
 
 CCL_NAMESPACE_BEGIN
index 17072d230bb14defd7384513244c97c0592b27d5..6038abd815ef7c6079e3f95ac55d9428030248c0 100644 (file)
@@ -17,6 +17,7 @@ set(SRC
        device_multi.cpp
        device_network.cpp
        device_opencl.cpp
+       device_task.cpp
 )
 
 set(SRC_HEADERS
@@ -24,6 +25,7 @@ set(SRC_HEADERS
        device_memory.h
        device_intern.h
        device_network.h
+       device_task.h
 )
 
 add_definitions(-DGLEW_STATIC)
index 33040f287d10e85dd2572b8fc37fc1b3bb07660f..9a4d364a9b8e42133a2145f112c85cffe2b398de 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-/* Device Task */
-
-DeviceTask::DeviceTask(Type type_)
-: type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0),
-  sample(0), resolution(0),
-  shader_input(0), shader_output(0),
-  shader_eval_type(0), shader_x(0), shader_w(0)
-{
-}
-
-void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
-{
-       int num;
-
-       if(type == SHADER) {
-               num = (shader_w + max_size - 1)/max_size;
-       }
-       else {
-               max_size = max(1, max_size/w);
-               num = (h + max_size - 1)/max_size;
-       }
-
-       split(tasks, num);
-}
-
-void DeviceTask::split(list<DeviceTask>& tasks, int num)
-{
-       if(type == SHADER) {
-               num = min(shader_w, num);
-
-               for(int i = 0; i < num; i++) {
-                       int tx = shader_x + (shader_w/num)*i;
-                       int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
-
-                       DeviceTask task = *this;
-
-                       task.shader_x = tx;
-                       task.shader_w = tw;
-
-                       tasks.push_back(task);
-               }
-       }
-       else {
-               num = min(h, num);
-
-               for(int i = 0; i < num; i++) {
-                       int ty = y + (h/num)*i;
-                       int th = (i == num-1)? h - i*(h/num): h/num;
-
-                       DeviceTask task = *this;
-
-                       task.y = ty;
-                       task.h = th;
-
-                       tasks.push_back(task);
-               }
-       }
-}
-
 /* Device */
 
 void Device::pixels_alloc(device_memory& mem)
index b17abac2a1bf6434d684d36bf47a65f9abc4f339..2ee2e044618a03927518083a09ed3e4a370db948 100644 (file)
 #include <stdlib.h>
 
 #include "device_memory.h"
+#include "device_task.h"
 
 #include "util_list.h"
 #include "util_string.h"
-#include "util_task.h"
 #include "util_thread.h"
 #include "util_types.h"
 #include "util_vector.h"
@@ -33,6 +33,7 @@
 CCL_NAMESPACE_BEGIN
 
 class Progress;
+class RenderTile;
 
 /* Device Types */
 
@@ -67,32 +68,6 @@ public:
        }
 };
 
-/* Device Task */
-
-class DeviceTask : public Task {
-public:
-       typedef enum { PATH_TRACE, TONEMAP, SHADER } Type;
-       Type type;
-
-       int x, y, w, h;
-       device_ptr rng_state;
-       device_ptr rgba;
-       device_ptr buffer;
-       int sample;
-       int resolution;
-       int offset, stride;
-
-       device_ptr shader_input;
-       device_ptr shader_output;
-       int shader_eval_type;
-       int shader_x, shader_w;
-
-       DeviceTask(Type type = PATH_TRACE);
-
-       void split(list<DeviceTask>& tasks, int num);
-       void split_max_size(list<DeviceTask>& tasks, int max_size);
-};
-
 /* Device */
 
 class Device {
@@ -150,6 +125,10 @@ public:
        void server_run();
 #endif
 
+       /* multi device */
+       virtual void map_tile(Device *sub_device, RenderTile& tile) {}
+       virtual int device_number(Device *sub_device) { return 0; }
+
        /* static */
        static Device *create(DeviceInfo& info, bool background = true, int threads = 0);
 
index 070b20aec49d457427f5e753adecd130652e34fd..4c54671b0d0a494bfae406db723ab4d2f7a5393d 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "osl_shader.h"
 
+#include "buffers.h"
+
 #include "util_debug.h"
 #include "util_foreach.h"
 #include "util_function.h"
@@ -141,28 +143,56 @@ public:
                        OSLShader::thread_init(kg);
 #endif
 
-#ifdef WITH_OPTIMIZED_KERNEL
-               if(system_cpu_support_optimized()) {
-                       for(int y = task.y; y < task.y + task.h; y++) {
-                               for(int x = task.x; x < task.x + task.w; x++)
-                                       kernel_cpu_optimized_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
-                                               task.sample, x, y, task.offset, task.stride);
+               RenderTile tile;
+               
+               while(task.acquire_tile(this, tile)) {
+                       float *render_buffer = (float*)tile.buffer;
+                       uint *rng_state = (uint*)tile.rng_state;
+                       int start_sample = tile.start_sample;
+                       int end_sample = tile.start_sample + tile.num_samples;
 
-                               if(task_pool.cancelled())
-                                       break;
+#ifdef WITH_OPTIMIZED_KERNEL
+                       if(system_cpu_support_optimized()) {
+                               for(int sample = start_sample; sample < end_sample; sample++) {
+                                       if (task.get_cancel() || task_pool.cancelled())
+                                               break;
+
+                                       for(int y = tile.y; y < tile.y + tile.h; y++) {
+                                               for(int x = tile.x; x < tile.x + tile.w; x++) {
+                                                       kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state,
+                                                               sample, x, y, tile.offset, tile.stride);
+                                               }
+                                       }
+
+                                       tile.sample = sample + 1;
+
+                                       task.update_progress(tile);
+                               }
                        }
-               }
-               else
+                       else
 #endif
-               {
-                       for(int y = task.y; y < task.y + task.h; y++) {
-                               for(int x = task.x; x < task.x + task.w; x++)
-                                       kernel_cpu_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
-                                               task.sample, x, y, task.offset, task.stride);
-
-                               if(task_pool.cancelled())
-                                       break;
+                       {
+                               for(int sample = start_sample; sample < end_sample; sample++) {
+                                       if (task.get_cancel() || task_pool.cancelled())
+                                               break;
+
+                                       for(int y = tile.y; y < tile.y + tile.h; y++) {
+                                               for(int x = tile.x; x < tile.x + tile.w; x++) {
+                                                       kernel_cpu_path_trace(kg, render_buffer, rng_state,
+                                                               sample, x, y, tile.offset, tile.stride);
+                                               }
+                                       }
+
+                                       tile.sample = sample + 1;
+
+                                       task.update_progress(tile);
+                               }
                        }
+
+                       task.release_tile(tile);
+
+                       if(task_pool.cancelled())
+                               break;
                }
 
 #ifdef WITH_OSL
@@ -228,8 +258,7 @@ public:
                /* split task into smaller ones, more than number of threads for uneven
                 * workloads where some parts of the image render slower than others */
                list<DeviceTask> tasks;
-
-               task.split(tasks, TaskScheduler::num_threads()*10);
+               task.split(tasks, TaskScheduler::num_threads()+1);
 
                foreach(DeviceTask& task, tasks)
                        task_pool.push(new CPUDeviceTask(this, task));
index 357f99145b218c4b4bdada8b5710fba42936d722..c8dcfdc2f3d7cc4292d7997e89866f33df5b1a20 100644 (file)
@@ -23,6 +23,8 @@
 #include "device.h"
 #include "device_intern.h"
 
+#include "buffers.h"
+
 #include "util_cuda.h"
 #include "util_debug.h"
 #include "util_map.h"
@@ -37,6 +39,7 @@ CCL_NAMESPACE_BEGIN
 class CUDADevice : public Device
 {
 public:
+       TaskPool task_pool;
        CUdevice cuDevice;
        CUcontext cuContext;
        CUmodule cuModule;
@@ -192,6 +195,8 @@ public:
 
        ~CUDADevice()
        {
+               task_pool.stop();
+
                cuda_push_context();
                cuda_assert(cuCtxDetach(cuContext))
        }
@@ -466,13 +471,13 @@ public:
                }
        }
 
-       void path_trace(DeviceTask& task)
+       void path_trace(RenderTile& rtile, int sample)
        {
                cuda_push_context();
 
                CUfunction cuPathTrace;
-               CUdeviceptr d_buffer = cuda_device_ptr(task.buffer);
-               CUdeviceptr d_rng_state = cuda_device_ptr(task.rng_state);
+               CUdeviceptr d_buffer = cuda_device_ptr(rtile.buffer);
+               CUdeviceptr d_rng_state = cuda_device_ptr(rtile.rng_state);
 
                /* get kernel function */
                cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"))
@@ -486,29 +491,28 @@ public:
                cuda_assert(cuParamSetv(cuPathTrace, offset, &d_rng_state, sizeof(d_rng_state)))
                offset += sizeof(d_rng_state);
 
-               int sample = task.sample;
                offset = align_up(offset, __alignof(sample));
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.sample))
-               offset += sizeof(task.sample);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, sample))
+               offset += sizeof(sample);
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.x))
-               offset += sizeof(task.x);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.x))
+               offset += sizeof(rtile.x);
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.y))
-               offset += sizeof(task.y);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.y))
+               offset += sizeof(rtile.y);
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.w))
-               offset += sizeof(task.w);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.w))
+               offset += sizeof(rtile.w);
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.h))
-               offset += sizeof(task.h);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.h))
+               offset += sizeof(rtile.h);
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.offset))
-               offset += sizeof(task.offset);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.offset))
+               offset += sizeof(rtile.offset);
 
-               cuda_assert(cuParamSeti(cuPathTrace, offset, task.stride))
-               offset += sizeof(task.stride);
+               cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.stride))
+               offset += sizeof(rtile.stride);
 
                cuda_assert(cuParamSetSize(cuPathTrace, offset))
 
@@ -520,23 +524,25 @@ public:
                int xthreads = 8;
                int ythreads = 8;
 #endif
-               int xblocks = (task.w + xthreads - 1)/xthreads;
-               int yblocks = (task.h + ythreads - 1)/ythreads;
+               int xblocks = (rtile.w + xthreads - 1)/xthreads;
+               int yblocks = (rtile.h + ythreads - 1)/ythreads;
 
                cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1))
                cuda_assert(cuFuncSetBlockShape(cuPathTrace, xthreads, ythreads, 1))
                cuda_assert(cuLaunchGrid(cuPathTrace, xblocks, yblocks))
 
+               cuda_assert(cuCtxSynchronize())
+
                cuda_pop_context();
        }
 
-       void tonemap(DeviceTask& task)
+       void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
        {
                cuda_push_context();
 
                CUfunction cuFilmConvert;
-               CUdeviceptr d_rgba = map_pixels(task.rgba);
-               CUdeviceptr d_buffer = cuda_device_ptr(task.buffer);
+               CUdeviceptr d_rgba = map_pixels(rgba);
+               CUdeviceptr d_buffer = cuda_device_ptr(buffer);
 
                /* get kernel function */
                cuda_assert(cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_tonemap"))
@@ -820,27 +826,71 @@ public:
                Device::draw_pixels(mem, y, w, h, dy, width, height, transparent);
        }
 
-       void task_add(DeviceTask& task)
+       void thread_run(DeviceTask *task)
        {
-               if(task.type == DeviceTask::TONEMAP)
-                       tonemap(task);
-               else if(task.type == DeviceTask::PATH_TRACE)
-                       path_trace(task);
-               else if(task.type == DeviceTask::SHADER)
-                       shader(task);
+               if(task->type == DeviceTask::PATH_TRACE) {
+                       RenderTile tile;
+                       
+                       /* keep rendering tiles until done */
+                       while(task->acquire_tile(this, tile)) {
+                               int start_sample = tile.start_sample;
+                               int end_sample = tile.start_sample + tile.num_samples;
+
+                               for(int sample = start_sample; sample < end_sample; sample++) {
+                                       if (task->get_cancel())
+                                               break;
+
+                                       path_trace(tile, sample);
+
+                                       tile.sample = sample + 1;
+
+                                       task->update_progress(tile);
+                               }
+
+                               task->release_tile(tile);
+                       }
+               }
+               else if(task->type == DeviceTask::SHADER) {
+                       shader(*task);
+
+                       cuda_push_context();
+                       cuda_assert(cuCtxSynchronize())
+                       cuda_pop_context();
+               }
        }
 
-       void task_wait()
+       class CUDADeviceTask : public DeviceTask {
+       public:
+               CUDADeviceTask(CUDADevice *device, DeviceTask& task)
+               : DeviceTask(task)
+               {
+                       run = function_bind(&CUDADevice::thread_run, device, this);
+               }
+       };
+
+       void task_add(DeviceTask& task)
        {
-               cuda_push_context();
+               if(task.type == DeviceTask::TONEMAP) {
+                       /* must be done in main thread due to opengl access */
+                       tonemap(task, task.buffer, task.rgba);
 
-               cuda_assert(cuCtxSynchronize())
+                       cuda_push_context();
+                       cuda_assert(cuCtxSynchronize())
+                       cuda_pop_context();
+               }
+               else {
+                       task_pool.push(new CUDADeviceTask(this, task));
+               }
+       }
 
-               cuda_pop_context();
+       void task_wait()
+       {
+               task_pool.wait_work();
        }
 
        void task_cancel()
        {
+               task_pool.cancel();
        }
 };
 
index 83e69b98f5d41e9ca1886851552fc77d14921d88..546ffe5e4b9651aac25310428db02d85a234affe 100644 (file)
@@ -23,6 +23,8 @@
 #include "device_intern.h"
 #include "device_network.h"
 
+#include "buffers.h"
+
 #include "util_foreach.h"
 #include "util_list.h"
 #include "util_map.h"
@@ -255,6 +257,30 @@ public:
                rgba.device_pointer = tmp;
        }
 
+       void map_tile(Device *sub_device, RenderTile& tile)
+       {
+               foreach(SubDevice& sub, devices) {
+                       if(sub.device == sub_device) {
+                               if(tile.buffer) tile.buffer = sub.ptr_map[tile.buffer];
+                               if(tile.rng_state) tile.rng_state = sub.ptr_map[tile.rng_state];
+                               if(tile.rgba) tile.rgba = sub.ptr_map[tile.rgba];
+                       }
+               }
+       }
+
+       int device_number(Device *sub_device)
+       {
+               int i = 0;
+
+               foreach(SubDevice& sub, devices) {
+                       if(sub.device == sub_device)
+                               return i;
+                       i++;
+               }
+
+               return -1;
+       }
+
        void task_add(DeviceTask& task)
        {
                list<DeviceTask> tasks;
@@ -266,7 +292,6 @@ public:
                                tasks.pop_front();
 
                                if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer];
-                               if(task.rng_state) subtask.rng_state = sub.ptr_map[task.rng_state];
                                if(task.rgba) subtask.rgba = sub.ptr_map[task.rgba];
                                if(task.shader_input) subtask.shader_input = sub.ptr_map[task.shader_input];
                                if(task.shader_output) subtask.shader_output = sub.ptr_map[task.shader_output];
index c9ec7c75063cbfac3047a225465abc353821d8a6..3c78b4895ae6d4a07bfba0359bfc01224c0382ce 100644 (file)
@@ -25,6 +25,8 @@
 #include "device.h"
 #include "device_intern.h"
 
+#include "buffers.h"
+
 #include "util_foreach.h"
 #include "util_map.h"
 #include "util_math.h"
@@ -41,6 +43,7 @@ CCL_NAMESPACE_BEGIN
 class OpenCLDevice : public Device
 {
 public:
+       TaskPool task_pool;
        cl_context cxContext;
        cl_command_queue cqCommandQueue;
        cl_platform_id cpPlatform;
@@ -435,6 +438,8 @@ public:
 
        ~OpenCLDevice()
        {
+               task_pool.stop();
+
                if(null_mem)
                        clReleaseMemObject(CL_MEM_PTR(null_mem));
 
@@ -540,19 +545,19 @@ public:
                return global_size + ((r == 0)? 0: group_size - r);
        }
 
-       void path_trace(DeviceTask& task)
+       void path_trace(RenderTile& rtile, int sample)
        {
                /* cast arguments to cl types */
                cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
-               cl_mem d_buffer = CL_MEM_PTR(task.buffer);
-               cl_mem d_rng_state = CL_MEM_PTR(task.rng_state);
-               cl_int d_x = task.x;
-               cl_int d_y = task.y;
-               cl_int d_w = task.w;
-               cl_int d_h = task.h;
-               cl_int d_sample = task.sample;
-               cl_int d_offset = task.offset;
-               cl_int d_stride = task.stride;
+               cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
+               cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state);
+               cl_int d_x = rtile.x;
+               cl_int d_y = rtile.y;
+               cl_int d_w = rtile.w;
+               cl_int d_h = rtile.h;
+               cl_int d_sample = sample;
+               cl_int d_offset = rtile.offset;
+               cl_int d_stride = rtile.stride;
 
                /* sample arguments */
                int narg = 0;
@@ -613,12 +618,12 @@ public:
                return err;
        }
 
-       void tonemap(DeviceTask& task)
+       void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
        {
                /* cast arguments to cl types */
                cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
-               cl_mem d_rgba = CL_MEM_PTR(task.rgba);
-               cl_mem d_buffer = CL_MEM_PTR(task.buffer);
+               cl_mem d_rgba = CL_MEM_PTR(rgba);
+               cl_mem d_buffer = CL_MEM_PTR(buffer);
                cl_int d_x = task.x;
                cl_int d_y = task.y;
                cl_int d_w = task.w;
@@ -667,30 +672,57 @@ public:
                opencl_assert(clFinish(cqCommandQueue));
        }
 
-       void task_add(DeviceTask& maintask)
+       void thread_run(DeviceTask *task)
        {
-               list<DeviceTask> tasks;
+               if(task->type == DeviceTask::TONEMAP) {
+                       tonemap(*task, task->buffer, task->rgba);
+               }
+               else if(task->type == DeviceTask::PATH_TRACE) {
+                       RenderTile tile;
+                       
+                       /* keep rendering tiles until done */
+                       while(task->acquire_tile(this, tile)) {
+                               int start_sample = tile.start_sample;
+                               int end_sample = tile.start_sample + tile.num_samples;
 
-               /* arbitrary limit to work around apple ATI opencl issue */
-               if(platform_name == "Apple")
-                       maintask.split_max_size(tasks, 76800);
-               else
-                       tasks.push_back(maintask);
+                               for(int sample = start_sample; sample < end_sample; sample++) {
+                                       if (task->get_cancel())
+                                               break;
+
+                                       path_trace(tile, sample);
+
+                                       tile.sample = sample + 1;
 
-               foreach(DeviceTask& task, tasks) {
-                       if(task.type == DeviceTask::TONEMAP)
-                               tonemap(task);
-                       else if(task.type == DeviceTask::PATH_TRACE)
-                               path_trace(task);
+                                       task->update_progress(tile);
+                               }
+
+                               task->release_tile(tile);
+                       }
                }
        }
 
+       class OpenCLDeviceTask : public DeviceTask {
+       public:
+               OpenCLDeviceTask(OpenCLDevice *device, DeviceTask& task)
+               : DeviceTask(task)
+               {
+                       run = function_bind(&OpenCLDevice::thread_run, device, this);
+               }
+       };
+
+       void task_add(DeviceTask& task)
+       {
+               task_pool.push(new OpenCLDeviceTask(this, task));
+       }
+
        void task_wait()
        {
+               task_pool.wait_work();
        }
 
        void task_cancel()
        {
+               task_pool.cancel();
        }
 };
 
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
new file mode 100644 (file)
index 0000000..c85e182
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "device_task.h"
+
+#include "util_algorithm.h"
+#include "util_time.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Device Task */
+
+DeviceTask::DeviceTask(Type type_)
+: type(type_), x(0), y(0), w(0), h(0), rgba(0), buffer(0),
+  sample(0), num_samples(1), resolution(0),
+  shader_input(0), shader_output(0),
+  shader_eval_type(0), shader_x(0), shader_w(0)
+{
+       last_update_time = time_dt();
+}
+
+void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
+{
+       int num;
+
+       if(type == SHADER) {
+               num = (shader_w + max_size - 1)/max_size;
+       }
+       else {
+               max_size = max(1, max_size/w);
+               num = (h + max_size - 1)/max_size;
+       }
+
+       split(tasks, num);
+}
+
+void DeviceTask::split(list<DeviceTask>& tasks, int num)
+{
+       if(type == SHADER) {
+               num = min(shader_w, num);
+
+               for(int i = 0; i < num; i++) {
+                       int tx = shader_x + (shader_w/num)*i;
+                       int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
+
+                       DeviceTask task = *this;
+
+                       task.shader_x = tx;
+                       task.shader_w = tw;
+
+                       tasks.push_back(task);
+               }
+       }
+       else if(type == PATH_TRACE) {
+               for(int i = 0; i < num; i++)
+                       tasks.push_back(*this);
+       }
+       else {
+               num = min(h, num);
+
+               for(int i = 0; i < num; i++) {
+                       int ty = y + (h/num)*i;
+                       int th = (i == num-1)? h - i*(h/num): h/num;
+
+                       DeviceTask task = *this;
+
+                       task.y = ty;
+                       task.h = th;
+
+                       tasks.push_back(task);
+               }
+       }
+}
+
+void DeviceTask::update_progress(RenderTile &rtile)
+{
+       if (type != PATH_TRACE)
+               return;
+
+       if(update_progress_sample)
+               update_progress_sample();
+
+       if(update_tile_sample) {
+               double current_time = time_dt();
+
+               if (current_time - last_update_time >= 1.0f) {
+                       update_tile_sample(rtile);
+
+                       last_update_time = current_time;
+               }
+       }
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
new file mode 100644 (file)
index 0000000..cfb3d8d
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __DEVICE_TASK_H__
+#define __DEVICE_TASK_H__
+
+#include "device_memory.h"
+
+#include "util_function.h"
+#include "util_list.h"
+#include "util_task.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Device Task */
+
+class Device;
+class RenderBuffers;
+class RenderTile;
+class Tile;
+
+class DeviceTask : public Task {
+public:
+       typedef enum { PATH_TRACE, TONEMAP, SHADER } Type;
+       Type type;
+
+       int x, y, w, h;
+       device_ptr rgba;
+       device_ptr buffer;
+       int sample;
+       int num_samples;
+       int resolution;
+       int offset, stride;
+
+       device_ptr shader_input;
+       device_ptr shader_output;
+       int shader_eval_type;
+       int shader_x, shader_w;
+
+       DeviceTask(Type type = PATH_TRACE);
+
+       void split(list<DeviceTask>& tasks, int num);
+       void split_max_size(list<DeviceTask>& tasks, int max_size);
+
+       void update_progress(RenderTile &rtile);
+
+       boost::function<bool(Device *device, RenderTile&)> acquire_tile;
+       boost::function<void(void)> update_progress_sample;
+       boost::function<void(RenderTile&)> update_tile_sample;
+       boost::function<void(RenderTile&)> release_tile;
+       boost::function<bool(void)> get_cancel;
+
+protected:
+       double last_update_time;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __DEVICE_TASK_H__ */
+
index 667db1e5f03a953aa764766fef4b8af44c5ee560..62d79bdd9463cd4d3334bc8a989f94aeaac41232 100644 (file)
@@ -87,14 +87,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
        else if(strstr(name, "__tex_image_float")) {
                texture_image_float4 *tex = NULL;
                int id = atoi(name + strlen("__tex_image_float_"));
+               int array_index = id;
 
-               switch(id) {
-                       case 95: tex = &kg->__tex_image_float_095; break;
-                       case 96: tex = &kg->__tex_image_float_096; break;
-                       case 97: tex = &kg->__tex_image_float_097; break;
-                       case 98: tex = &kg->__tex_image_float_098; break;
-                       case 99: tex = &kg->__tex_image_float_099; break;
-                       default: break;
+               if (array_index >= 0 && array_index < MAX_FLOAT_IMAGES) {
+                       tex = &kg->texture_float_images[array_index];
                }
 
                if(tex) {
@@ -106,104 +102,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
        else if(strstr(name, "__tex_image")) {
                texture_image_uchar4 *tex = NULL;
                int id = atoi(name + strlen("__tex_image_"));
+               int array_index = id - MAX_FLOAT_IMAGES;
 
-               switch(id) {
-                       case 0: tex = &kg->__tex_image_000; break;
-                       case 1: tex = &kg->__tex_image_001; break;
-                       case 2: tex = &kg->__tex_image_002; break;
-                       case 3: tex = &kg->__tex_image_003; break;
-                       case 4: tex = &kg->__tex_image_004; break;
-                       case 5: tex = &kg->__tex_image_005; break;
-                       case 6: tex = &kg->__tex_image_006; break;
-                       case 7: tex = &kg->__tex_image_007; break;
-                       case 8: tex = &kg->__tex_image_008; break;
-                       case 9: tex = &kg->__tex_image_009; break;
-                       case 10: tex = &kg->__tex_image_010; break;
-                       case 11: tex = &kg->__tex_image_011; break;
-                       case 12: tex = &kg->__tex_image_012; break;
-                       case 13: tex = &kg->__tex_image_013; break;
-                       case 14: tex = &kg->__tex_image_014; break;
-                       case 15: tex = &kg->__tex_image_015; break;
-                       case 16: tex = &kg->__tex_image_016; break;
-                       case 17: tex = &kg->__tex_image_017; break;
-                       case 18: tex = &kg->__tex_image_018; break;
-                       case 19: tex = &kg->__tex_image_019; break;
-                       case 20: tex = &kg->__tex_image_020; break;
-                       case 21: tex = &kg->__tex_image_021; break;
-                       case 22: tex = &kg->__tex_image_022; break;
-                       case 23: tex = &kg->__tex_image_023; break;
-                       case 24: tex = &kg->__tex_image_024; break;
-                       case 25: tex = &kg->__tex_image_025; break;
-                       case 26: tex = &kg->__tex_image_026; break;
-                       case 27: tex = &kg->__tex_image_027; break;
-                       case 28: tex = &kg->__tex_image_028; break;
-                       case 29: tex = &kg->__tex_image_029; break;
-                       case 30: tex = &kg->__tex_image_030; break;
-                       case 31: tex = &kg->__tex_image_031; break;
-                       case 32: tex = &kg->__tex_image_032; break;
-                       case 33: tex = &kg->__tex_image_033; break;
-                       case 34: tex = &kg->__tex_image_034; break;
-                       case 35: tex = &kg->__tex_image_035; break;
-                       case 36: tex = &kg->__tex_image_036; break;
-                       case 37: tex = &kg->__tex_image_037; break;
-                       case 38: tex = &kg->__tex_image_038; break;
-                       case 39: tex = &kg->__tex_image_039; break;
-                       case 40: tex = &kg->__tex_image_040; break;
-                       case 41: tex = &kg->__tex_image_041; break;
-                       case 42: tex = &kg->__tex_image_042; break;
-                       case 43: tex = &kg->__tex_image_043; break;
-                       case 44: tex = &kg->__tex_image_044; break;
-                       case 45: tex = &kg->__tex_image_045; break;
-                       case 46: tex = &kg->__tex_image_046; break;
-                       case 47: tex = &kg->__tex_image_047; break;
-                       case 48: tex = &kg->__tex_image_048; break;
-                       case 49: tex = &kg->__tex_image_049; break;
-                       case 50: tex = &kg->__tex_image_050; break;
-                       case 51: tex = &kg->__tex_image_051; break;
-                       case 52: tex = &kg->__tex_image_052; break;
-                       case 53: tex = &kg->__tex_image_053; break;
-                       case 54: tex = &kg->__tex_image_054; break;
-                       case 55: tex = &kg->__tex_image_055; break;
-                       case 56: tex = &kg->__tex_image_056; break;
-                       case 57: tex = &kg->__tex_image_057; break;
-                       case 58: tex = &kg->__tex_image_058; break;
-                       case 59: tex = &kg->__tex_image_059; break;
-                       case 60: tex = &kg->__tex_image_060; break;
-                       case 61: tex = &kg->__tex_image_061; break;
-                       case 62: tex = &kg->__tex_image_062; break;
-                       case 63: tex = &kg->__tex_image_063; break;
-                       case 64: tex = &kg->__tex_image_064; break;
-                       case 65: tex = &kg->__tex_image_065; break;
-                       case 66: tex = &kg->__tex_image_066; break;
-                       case 67: tex = &kg->__tex_image_067; break;
-                       case 68: tex = &kg->__tex_image_068; break;
-                       case 69: tex = &kg->__tex_image_069; break;
-                       case 70: tex = &kg->__tex_image_070; break;
-                       case 71: tex = &kg->__tex_image_071; break;
-                       case 72: tex = &kg->__tex_image_072; break;
-                       case 73: tex = &kg->__tex_image_073; break;
-                       case 74: tex = &kg->__tex_image_074; break;
-                       case 75: tex = &kg->__tex_image_075; break;
-                       case 76: tex = &kg->__tex_image_076; break;
-                       case 77: tex = &kg->__tex_image_077; break;
-                       case 78: tex = &kg->__tex_image_078; break;
-                       case 79: tex = &kg->__tex_image_079; break;
-                       case 80: tex = &kg->__tex_image_080; break;
-                       case 81: tex = &kg->__tex_image_081; break;
-                       case 82: tex = &kg->__tex_image_082; break;
-                       case 83: tex = &kg->__tex_image_083; break;
-                       case 84: tex = &kg->__tex_image_084; break;
-                       case 85: tex = &kg->__tex_image_085; break;
-                       case 86: tex = &kg->__tex_image_086; break;
-                       case 87: tex = &kg->__tex_image_087; break;
-                       case 88: tex = &kg->__tex_image_088; break;
-                       case 89: tex = &kg->__tex_image_089; break;
-                       case 90: tex = &kg->__tex_image_090; break;
-                       case 91: tex = &kg->__tex_image_091; break;
-                       case 92: tex = &kg->__tex_image_092; break;
-                       case 93: tex = &kg->__tex_image_093; break;
-                       case 94: tex = &kg->__tex_image_094; break;
-                       default: break;
+               if (array_index >= 0 && array_index < MAX_BYTE_IMAGES) {
+                       tex = &kg->texture_byte_images[array_index];
                }
 
                if(tex) {
index cc8f1f3323bbe913572e583270385b21685a70e9..45f653a686c0ac2588b6f55fca761b4e56446f1e 100644 (file)
@@ -158,7 +158,7 @@ typedef texture_image<uchar4> texture_image_uchar4;
 #define kernel_tex_fetch_m128(tex, index) (kg->tex.fetch_m128(index))
 #define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index))
 #define kernel_tex_interp(tex, t, size) (kg->tex.interp(t, size))
-#define kernel_tex_image_interp(tex, x, y) (kg->tex.interp(x, y))
+#define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y))
 
 #define kernel_data (kg->__data)
 
index a99fffbc519e6deb4e9153a887ba037d8c0f3811..1e56c11ab90f7f1341f833ebc2e092dcda73088b 100644 (file)
@@ -35,10 +35,15 @@ CCL_NAMESPACE_BEGIN
 
 #ifdef __KERNEL_CPU__
 
+#define MAX_BYTE_IMAGES   512
+#define MAX_FLOAT_IMAGES  5
+
 typedef struct KernelGlobals {
+       texture_image_uchar4 texture_byte_images[MAX_BYTE_IMAGES];
+       texture_image_float4 texture_float_images[MAX_FLOAT_IMAGES];
 
 #define KERNEL_TEX(type, ttype, name) ttype name;
-#define KERNEL_IMAGE_TEX(type, ttype, name) ttype name;
+#define KERNEL_IMAGE_TEX(type, ttype, name)
 #include "kernel_textures.h"
 
        KernelData __data;
index f5188345948de24bf972a01173c1c252fa1ef118..8d983a4ec75f80ea19639f4c9fdc7cd8efcca38f 100644 (file)
@@ -693,7 +693,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
                if(kernel_data.integrator.use_ambient_occlusion) {
                        int num_samples = kernel_data.integrator.ao_samples;
                        float num_samples_inv = 1.0f/num_samples;
-                       float ao_factor = kernel_data.background.ao_factor/num_samples;
+                       float ao_factor = kernel_data.background.ao_factor;
 
                        for(int j = 0; j < num_samples; j++) {
                                /* todo: solve correlation */
index c1b8eed3dff52c54f610f4fb466e28286825bd21..4855a948c6efe505ad1a26e8d87f72c651b0b4d2 100644 (file)
@@ -66,12 +66,14 @@ KERNEL_TEX(float, texture_float, __filter_table)
 /* sobol */
 KERNEL_TEX(uint, texture_uint, __sobol_directions)
 
+/* full-float image */
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_000)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_001)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_002)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_003)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_004)
+
 /* image */
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_000)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_001)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_002)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_003)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_004)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_005)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_006)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_007)
@@ -162,13 +164,11 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_091)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_092)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_093)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_094)
-
-/* full-float image */
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_095)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_096)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_097)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_098)
-KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_099)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_095)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_096)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_097)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_098)
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_099)
 
 /* packed image (opencl) */
 KERNEL_TEX(uchar4, texture_uchar4, __tex_image_packed)
index 8901e5e9628cbc7f948356c38a6bc691524e2984..56a40620765ebdb1f5cf23bc6e71bf2d837fe9bf 100644 (file)
@@ -220,6 +220,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
                        case NODE_TEX_IMAGE:
                                svm_node_tex_image(kg, sd, stack, node);
                                break;
+                       case NODE_TEX_IMAGE_BOX:
+                               svm_node_tex_image_box(kg, sd, stack, node);
+                               break;
                        case NODE_TEX_ENVIRONMENT:
                                svm_node_tex_environment(kg, sd, stack, node);
                                break;
index 3b2b9204d864ed81b09c629af492f93fb390aef7..662419418e3f10399189bb59eb0658abc3552447 100644 (file)
@@ -50,7 +50,7 @@ __device_inline float svm_image_texture_frac(float x, int *ix)
        return x - (float)i;
 }
 
-__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
+__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb)
 {
        uint4 info = kernel_tex_fetch(__tex_image_packed_info, id);
        uint width = info.x;
@@ -82,15 +82,24 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
        r += ty*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + niy*width);
        r += ty*tx*svm_image_texture_read(kg, offset + nix + niy*width);
 
+       if(srgb) {
+               r.x = color_srgb_to_scene_linear(r.x);
+               r.y = color_srgb_to_scene_linear(r.y);
+               r.z = color_srgb_to_scene_linear(r.z);
+       }
+
        return r;
 }
 
 #else
 
-__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
+__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb)
 {
        float4 r;
 
+#ifdef __KERNEL_CPU__
+       r = kernel_tex_image_interp(id, x, y);
+#else
        /* not particularly proud of this massive switch, what are the
         * alternatives?
         * - use a single big 1D texture, and do our own lookup/filtering
@@ -101,11 +110,11 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
         * we still need some for other storage */
 
        switch(id) {
-               case 0: r = kernel_tex_image_interp(__tex_image_000, x, y); break;
-               case 1: r = kernel_tex_image_interp(__tex_image_001, x, y); break;
-               case 2: r = kernel_tex_image_interp(__tex_image_002, x, y); break;
-               case 3: r = kernel_tex_image_interp(__tex_image_003, x, y); break;
-               case 4: r = kernel_tex_image_interp(__tex_image_004, x, y); break;
+               case 0: r = kernel_tex_image_interp(__tex_image_float_000, x, y); break;
+               case 1: r = kernel_tex_image_interp(__tex_image_float_001, x, y); break;
+               case 2: r = kernel_tex_image_interp(__tex_image_float_002, x, y); break;
+               case 3: r = kernel_tex_image_interp(__tex_image_float_003, x, y); break;
+               case 4: r = kernel_tex_image_interp(__tex_image_float_004, x, y); break;
                case 5: r = kernel_tex_image_interp(__tex_image_005, x, y); break;
                case 6: r = kernel_tex_image_interp(__tex_image_006, x, y); break;
                case 7: r = kernel_tex_image_interp(__tex_image_007, x, y); break;
@@ -196,15 +205,22 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
                case 92: r = kernel_tex_image_interp(__tex_image_092, x, y); break;
                case 93: r = kernel_tex_image_interp(__tex_image_093, x, y); break;
                case 94: r = kernel_tex_image_interp(__tex_image_094, x, y); break;
-               case 95: r = kernel_tex_image_interp(__tex_image_float_095, x, y); break;
-               case 96: r = kernel_tex_image_interp(__tex_image_float_096, x, y); break;
-               case 97: r = kernel_tex_image_interp(__tex_image_float_097, x, y); break;
-               case 98: r = kernel_tex_image_interp(__tex_image_float_098, x, y); break;
-               case 99: r = kernel_tex_image_interp(__tex_image_float_099, x, y); break;
+               case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break;
+               case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break;
+               case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break;
+               case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
+               case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
                default: 
                        kernel_assert(0);
                        return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
        }
+#endif
+
+       if(srgb) {
+               r.x = color_srgb_to_scene_linear(r.x);
+               r.y = color_srgb_to_scene_linear(r.y);
+               r.z = color_srgb_to_scene_linear(r.z);
+       }
 
        return r;
 }
@@ -219,21 +235,102 @@ __device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack
        decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
 
        float3 co = stack_load_float3(stack, co_offset);
-       float4 f = svm_image_texture(kg, id, co.x, co.y);
-       float3 r = make_float3(f.x, f.y, f.z);
+       float4 f = svm_image_texture(kg, id, co.x, co.y, srgb);
 
-       if(srgb) {
-               r.x = color_srgb_to_scene_linear(r.x);
-               r.y = color_srgb_to_scene_linear(r.y);
-               r.z = color_srgb_to_scene_linear(r.z);
+       if(stack_valid(out_offset))
+               stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
+       if(stack_valid(alpha_offset))
+               stack_store_float(stack, alpha_offset, f.w);
+}
+
+__device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+{
+       /* get object space normal */
+       float3 N = sd->N;
+
+       N = sd->N;
+       if(sd->object != ~0)
+               object_inverse_normal_transform(kg, sd, &N);
+
+       /* project from direction vector to barycentric coordinates in triangles */
+       N.x = fabsf(N.x);
+       N.y = fabsf(N.y);
+       N.z = fabsf(N.z);
+
+       N /= (N.x + N.y + N.z);
+
+       /* basic idea is to think of this as a triangle, each corner representing
+        * one of the 3 faces of the cube. in the corners we have single textures,
+        * in between we blend between two textures, and in the middle we a blend
+        * between three textures.
+        *
+        * the Nxyz values are the barycentric coordinates in an equilateral
+        * triangle, which in case of blending in the middle has a smaller
+        * equilateral triangle where 3 textures blend. this divides things into
+        * 7 zones, with an if() test for each zone */
+
+       float3 weight = make_float3(0.0f, 0.0f, 0.0f);
+       float blend = __int_as_float(node.w);
+       float limit = 0.5f*(1.0f + blend);
+
+       /* first test for corners with single texture */
+       if(N.x > limit*(N.x + N.y) && N.x > limit*(N.x + N.z)) {
+               weight.x = 1.0f;
+       }
+       else if(N.y > limit*(N.x + N.y) && N.y > limit*(N.y + N.z)) {
+               weight.y = 1.0f;
        }
+       else if(N.z > limit*(N.x + N.z) && N.z > limit*(N.y + N.z)) {
+               weight.z = 1.0f;
+       }
+       else if(blend > 0.0f) {
+               /* in case of blending, test for mixes between two textures */
+               if(N.z < (1.0f - limit)*(N.y + N.x)) {
+                       weight.x = N.x/(N.x + N.y);
+                       weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+                       weight.y = 1.0f - weight.x;
+               }
+               else if(N.x < (1.0f - limit)*(N.y + N.z)) {
+                       weight.y = N.y/(N.y + N.z);
+                       weight.y = clamp((weight.y - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+                       weight.z = 1.0f - weight.y;
+               }
+               else if(N.y < (1.0f - limit)*(N.x + N.z)) {
+                       weight.x = N.x/(N.x + N.z);
+                       weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+                       weight.z = 1.0f - weight.x;
+               }
+               else {
+                       /* last case, we have a mix between three */
+                       weight.x = ((2.0f - limit)*N.x + (limit - 1.0f))/(2.0f*limit - 1.0f);
+                       weight.y = ((2.0f - limit)*N.y + (limit - 1.0f))/(2.0f*limit - 1.0f);
+                       weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f);
+               }
+       }
+
+       /* now fetch textures */
+       uint co_offset, out_offset, alpha_offset, srgb;
+       decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
+
+       float3 co = stack_load_float3(stack, co_offset);
+       uint id = node.y;
+
+       float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+       if(weight.x > 0.0f)
+               f += weight.x*svm_image_texture(kg, id, co.y, co.z, srgb);
+       if(weight.y > 0.0f)
+               f += weight.y*svm_image_texture(kg, id, co.x, co.z, srgb);
+       if(weight.z > 0.0f)
+               f += weight.z*svm_image_texture(kg, id, co.y, co.x, srgb);
 
        if(stack_valid(out_offset))
-               stack_store_float3(stack, out_offset, r);
+               stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
        if(stack_valid(alpha_offset))
                stack_store_float(stack, alpha_offset, f.w);
 }
 
+
 __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
 {
        uint id = node.y;
@@ -252,17 +349,10 @@ __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float
        else
                uv = direction_to_mirrorball(co);
 
-       float4 f = svm_image_texture(kg, id, uv.x, uv.y);
-       float3 r = make_float3(f.x, f.y, f.z);
-
-       if(srgb) {
-               r.x = color_srgb_to_scene_linear(r.x);
-               r.y = color_srgb_to_scene_linear(r.y);
-               r.z = color_srgb_to_scene_linear(r.z);
-       }
+       float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb);
 
        if(stack_valid(out_offset))
-               stack_store_float3(stack, out_offset, r);
+               stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
        if(stack_valid(alpha_offset))
                stack_store_float(stack, alpha_offset, f.w);
 }
index cbff0c099ea37de296c15210a4b6f25917e26943..65e6c050b838b09ff4903e54b93b888fa67b0f77 100644 (file)
@@ -40,6 +40,7 @@ typedef enum NodeType {
        NODE_MIX_CLOSURE,
        NODE_JUMP,
        NODE_TEX_IMAGE,
+       NODE_TEX_IMAGE_BOX,
        NODE_TEX_SKY,
        NODE_GEOMETRY,
        NODE_LIGHT_PATH,
index a79a3591e0f4fa584de00d38ff5147a323cb2a56..51568f6532319fe6419f12a41a7a4205c036af2a 100644 (file)
@@ -74,6 +74,29 @@ int BufferParams::get_passes_size()
        return align_up(size, 4);
 }
 
+/* Render Buffer Task */
+
+RenderTile::RenderTile()
+{
+       x = 0;
+       y = 0;
+       w = 0;
+       h = 0;
+
+       start_sample = 0;
+       num_samples = 0;
+       resolution = 0;
+
+       offset = 0;
+       stride = 0;
+
+       buffer = 0;
+       rng_state = 0;
+       rgba = 0;
+
+       buffers = NULL;
+}
+
 /* Render Buffers */
 
 RenderBuffers::RenderBuffers(Device *device_)
@@ -135,7 +158,7 @@ bool RenderBuffers::copy_from_device()
        return true;
 }
 
-bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels)
+bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
 {
        int pass_offset = 0;
 
index 78712ed89ef1318fa3c979400920bfb96b899350..ee0d78a1cd8f3e53b3194e8bd70b7915eeb2aad9 100644 (file)
@@ -67,12 +67,11 @@ class RenderBuffers {
 public:
        /* buffer parameters */
        BufferParams params;
+
        /* float buffer */
        device_vector<float> buffer;
        /* random number generator state */
        device_vector<uint> rng_state;
-       /* mutex, must be locked manually by callers */
-       thread_mutex mutex;
 
        RenderBuffers(Device *device);
        ~RenderBuffers();
@@ -80,7 +79,7 @@ public:
        void reset(Device *device, BufferParams& params);
 
        bool copy_from_device();
-       bool get_pass(PassType type, float exposure, int sample, int components, float *pixels);
+       bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels);
 
 protected:
        void device_free();
@@ -105,8 +104,6 @@ public:
        bool transparent;
        /* byte buffer for tonemapped result */
        device_vector<uchar4> rgba;
-       /* mutex, must be locked manually by callers */
-       thread_mutex mutex;
 
        DisplayBuffer(Device *device);
        ~DisplayBuffer();
@@ -124,6 +121,28 @@ protected:
        Device *device;
 };
 
+/* Render Tile
+ * Rendering task on a buffer */
+
+class RenderTile {
+public:
+       int x, y, w, h;
+       int start_sample;
+       int num_samples;
+       int sample;
+       int resolution;
+       int offset;
+       int stride;
+
+       device_ptr buffer;
+       device_ptr rng_state;
+       device_ptr rgba;
+
+       RenderBuffers *buffers;
+
+       RenderTile();
+};
+
 CCL_NAMESPACE_END
 
 #endif /* __BUFFERS_H__ */
index 55a0f23f8d0d866883fccedef09c884eaf5c9be7..272ddb89b0c3d50d77ab3b681183c5b9fb47fb8a 100644 (file)
@@ -75,6 +75,7 @@ Camera::Camera()
 
        need_update = true;
        need_device_update = true;
+       previous_motion = -1;
 }
 
 Camera::~Camera()
@@ -140,8 +141,19 @@ void Camera::update()
 
 void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
 {
+       Scene::MotionType need_motion = scene->need_motion();
+
        update();
 
+       if (previous_motion != need_motion) {
+               /* scene's motion model could have been changed since
+                * previous device camera update
+                * this could happen for example in case when one render
+                * layer has got motion pass and another not
+                */
+               need_device_update = true;
+       }
+
        if(!need_device_update)
                return;
        
@@ -159,7 +171,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
        kcam->worldtocamera = transform_inverse(cameratoworld);
 
        /* camera motion */
-       Scene::MotionType need_motion = scene->need_motion();
        kcam->have_motion = 0;
 
        if(need_motion == Scene::MOTION_PASS) {
@@ -226,6 +237,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
        kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
 
        need_device_update = false;
+       previous_motion = need_motion;
 }
 
 void Camera::device_free(Device *device, DeviceScene *dscene)
index d2a3cce181708980bec5a55e86b7c5a3191371b1..a539510029f7d26ffbcbb1fc8e940b575ea54261 100644 (file)
@@ -91,6 +91,7 @@ public:
        /* update */
        bool need_update;
        bool need_device_update;
+       int previous_motion;
 
        /* functions */
        Camera();
index 18e802b610de4be2701e2efe3db915cfeb332b45..ce715ad38939bac5b87682c0d1ac90254c156894 100644 (file)
@@ -402,6 +402,20 @@ void ShaderGraph::clean()
        /* break cycles */
        break_cycles(output(), visited, on_stack);
 
+       /* disconnect unused nodes */
+       foreach(ShaderNode *node, nodes) {
+               if(!visited[node->id]) {
+                       foreach(ShaderInput *to, node->inputs) {
+                               ShaderOutput *from = to->link;
+
+                               if (from) {
+                                       to->link = NULL;
+                                       from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
+                               }
+                       }
+               }
+       }
+
        /* remove unused nodes */
        foreach(ShaderNode *node, nodes) {
                if(visited[node->id])
index 1af0972ecf9580317f9e8f0035b229d3d8810429..4ee024dd52a2a293df167a2db01df80b84daddbf 100644 (file)
@@ -36,6 +36,10 @@ ImageManager::ImageManager()
        need_update = true;
        pack_images = false;
        osl_texture_system = NULL;
+
+       tex_num_images = TEX_NUM_IMAGES;
+       tex_num_float_images = TEX_NUM_FLOAT_IMAGES;
+       tex_image_byte_start = TEX_IMAGE_BYTE_START;
 }
 
 ImageManager::~ImageManager()
@@ -56,6 +60,13 @@ void ImageManager::set_osl_texture_system(void *texture_system)
        osl_texture_system = texture_system;
 }
 
+void ImageManager::set_extended_image_limits(void)
+{
+       tex_num_images = TEX_EXTENDED_NUM_IMAGES;
+       tex_num_float_images = TEX_EXTENDED_NUM_FLOAT_IMAGES;
+       tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START;
+}
+
 static bool is_float_image(const string& filename)
 {
        ImageInput *in = ImageInput::create(filename);
@@ -97,7 +108,7 @@ int ImageManager::add_image(const string& filename, bool& is_float)
                for(slot = 0; slot < float_images.size(); slot++) {
                        if(float_images[slot] && float_images[slot]->filename == filename) {
                                float_images[slot]->users++;
-                               return slot+TEX_IMAGE_FLOAT_START;
+                               return slot;
                        }
                }
 
@@ -110,8 +121,8 @@ int ImageManager::add_image(const string& filename, bool& is_float)
                if(slot == float_images.size()) {
                        /* max images limit reached */
                        if(float_images.size() == TEX_NUM_FLOAT_IMAGES) {
-                               printf("ImageManager::add_image: byte image limit reached %d, skipping '%s'\n",
-                                      TEX_NUM_IMAGES, filename.c_str());
+                               printf("ImageManager::add_image: float image limit reached %d, skipping '%s'\n",
+                                      tex_num_float_images, filename.c_str());
                                return -1;
                        }
 
@@ -125,14 +136,12 @@ int ImageManager::add_image(const string& filename, bool& is_float)
                img->users = 1;
 
                float_images[slot] = img;
-               /* report slot out of total set of textures */
-               slot += TEX_IMAGE_FLOAT_START;
        }
        else {
                for(slot = 0; slot < images.size(); slot++) {
                        if(images[slot] && images[slot]->filename == filename) {
                                images[slot]->users++;
-                               return slot;
+                               return slot+tex_image_byte_start;
                        }
                }
 
@@ -144,9 +153,9 @@ int ImageManager::add_image(const string& filename, bool& is_float)
 
                if(slot == images.size()) {
                        /* max images limit reached */
-                       if(images.size() == TEX_NUM_IMAGES) {
+                       if(images.size() == tex_num_images) {
                                printf("ImageManager::add_image: byte image limit reached %d, skipping '%s'\n",
-                                      TEX_NUM_IMAGES, filename.c_str());
+                                      tex_num_images, filename.c_str());
                                return -1;
                        }
 
@@ -160,6 +169,8 @@ int ImageManager::add_image(const string& filename, bool& is_float)
                img->users = 1;
 
                images[slot] = img;
+
+               slot += tex_image_byte_start;
        }
        need_update = true;
 
@@ -340,20 +351,20 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
        Image *img;
        bool is_float;
 
-       if(slot < TEX_IMAGE_FLOAT_START) {
-               img = images[slot];
+       if(slot >= tex_image_byte_start) {
+               img = images[slot - tex_image_byte_start];
                is_float = false;
        }
        else {
-               img = float_images[slot - TEX_IMAGE_FLOAT_START];
+               img = float_images[slot];
                is_float = true;
        }
 
        if(is_float) {
-               string filename = path_filename(float_images[slot - TEX_IMAGE_FLOAT_START]->filename);
+               string filename = path_filename(float_images[slot]->filename);
                progress->set_status("Updating Images", "Loading " + filename);
 
-               device_vector<float4>& tex_img = dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START];
+               device_vector<float4>& tex_img = dscene->tex_float_image[slot];
 
                if(tex_img.device_pointer)
                        device->tex_free(tex_img);
@@ -377,10 +388,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
                        device->tex_alloc(name.c_str(), tex_img, true, true);
        }
        else {
-               string filename = path_filename(images[slot]->filename);
+               string filename = path_filename(images[slot - tex_image_byte_start]->filename);
                progress->set_status("Updating Images", "Loading " + filename);
 
-               device_vector<uchar4>& tex_img = dscene->tex_image[slot];
+               device_vector<uchar4>& tex_img = dscene->tex_image[slot - tex_image_byte_start];
 
                if(tex_img.device_pointer)
                        device->tex_free(tex_img);
@@ -412,12 +423,12 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl
        Image *img;
        bool is_float;
 
-       if(slot < TEX_IMAGE_FLOAT_START) {
-               img = images[slot];
+       if(slot >= tex_image_byte_start) {
+               img = images[slot - tex_image_byte_start];
                is_float = false;
        }
        else {
-               img = float_images[slot - TEX_IMAGE_FLOAT_START];
+               img = float_images[slot];
                is_float = true;
        }
 
@@ -429,18 +440,18 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl
 #endif
                }
                else if(is_float) {
-                       device->tex_free(dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START]);
-                       dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START].clear();
+                       device->tex_free(dscene->tex_float_image[slot]);
+                       dscene->tex_float_image[slot].clear();
 
-                       delete float_images[slot - TEX_IMAGE_FLOAT_START];
-                       float_images[slot - TEX_IMAGE_FLOAT_START] = NULL;
+                       delete float_images[slot];
+                       float_images[slot] = NULL;
                }
                else {
-                       device->tex_free(dscene->tex_image[slot]);
-                       dscene->tex_image[slot].clear();
+                       device->tex_free(dscene->tex_image[slot - tex_image_byte_start]);
+                       dscene->tex_image[slot - tex_image_byte_start].clear();
 
-                       delete images[slot];
-                       images[slot] = NULL;
+                       delete images[slot - tex_image_byte_start];
+                       images[slot - tex_image_byte_start] = NULL;
                }
        }
 }
@@ -457,11 +468,11 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
                        continue;
 
                if(images[slot]->users == 0) {
-                       device_free_image(device, dscene, slot);
+                       device_free_image(device, dscene, slot + tex_image_byte_start);
                }
                else if(images[slot]->need_load) {
                        if(!osl_texture_system) 
-                               pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
+                               pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + tex_image_byte_start, &progress));
                }
        }
 
@@ -470,11 +481,11 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
                        continue;
 
                if(float_images[slot]->users == 0) {
-                       device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
+                       device_free_image(device, dscene, slot);
                }
                else if(float_images[slot]->need_load) {
                        if(!osl_texture_system) 
-                               pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + TEX_IMAGE_FLOAT_START, &progress));
+                               pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
                }
        }
 
@@ -526,9 +537,9 @@ void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progr
 void ImageManager::device_free(Device *device, DeviceScene *dscene)
 {
        for(size_t slot = 0; slot < images.size(); slot++)
-               device_free_image(device, dscene, slot);
+               device_free_image(device, dscene, slot + tex_image_byte_start);
        for(size_t slot = 0; slot < float_images.size(); slot++)
-               device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
+               device_free_image(device, dscene, slot);
 
        device->tex_free(dscene->tex_image_packed);
        dscene->tex_image_packed.clear();
index ef046cfcafbe365acd48aa853d8c192678f879b5..04a705c27bf14cb45c233cb0fdaa5a99137cc913 100644 (file)
@@ -28,8 +28,11 @@ CCL_NAMESPACE_BEGIN
 
 #define TEX_NUM_FLOAT_IMAGES   5
 #define TEX_NUM_IMAGES                 95
-#define TEX_IMAGE_MAX                  (TEX_NUM_IMAGES + TEX_NUM_FLOAT_IMAGES)
-#define TEX_IMAGE_FLOAT_START  TEX_NUM_IMAGES
+#define TEX_IMAGE_BYTE_START   TEX_NUM_FLOAT_IMAGES
+
+#define TEX_EXTENDED_NUM_FLOAT_IMAGES  5
+#define TEX_EXTENDED_NUM_IMAGES                        512
+#define TEX_EXTENDED_IMAGE_BYTE_START  TEX_EXTENDED_NUM_FLOAT_IMAGES
 
 /* color to use when textures are not found */
 #define TEX_IMAGE_MISSING_R 1
@@ -55,9 +58,15 @@ public:
        void set_osl_texture_system(void *texture_system);
        void set_pack_images(bool pack_images_);
 
+       void set_extended_image_limits(void);
+
        bool need_update;
 
 private:
+       int tex_num_images;
+       int tex_num_float_images;
+       int tex_image_byte_start;
+
        struct Image {
                string filename;
 
index d00b242d153bf590b42e4edbcf3f0fba655e7e81..9d221d56efbe367b68c733e03be8f1a1327ce662 100644 (file)
@@ -289,8 +289,14 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
                /* CDF */
                device->tex_alloc("__light_distribution", dscene->light_distribution);
        }
-       else
+       else {
+               kintegrator->num_distribution = 0;
+               kintegrator->pdf_triangles = 0.0f;
+               kintegrator->pdf_lights = 0.0f;
+               kintegrator->num_all_lights = 0;
+
                dscene->light_distribution.clear();
+       }
 }
 
 void LightManager::device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
index 250570e1d65ce2c4c4b3d5f3466f0b4051c6fb12..43d6e2c7aacfe743c5019569c0b2127bce864508 100644 (file)
@@ -112,7 +112,18 @@ static ShaderEnum color_space_init()
        return enm;
 }
 
+static ShaderEnum image_projection_init()
+{
+       ShaderEnum enm;
+
+       enm.insert("Flat", 0);
+       enm.insert("Box", 1);
+
+       return enm;
+}
+
 ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
+ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
 
 ImageTextureNode::ImageTextureNode()
 : TextureNode("image_texture")
@@ -122,6 +133,8 @@ ImageTextureNode::ImageTextureNode()
        is_float = false;
        filename = "";
        color_space = ustring("Color");
+       projection = ustring("Flat");;
+       projection_blend = 0.0f;
 
        add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV);
        add_output("Color", SHADER_SOCKET_COLOR);
@@ -169,13 +182,25 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
                        tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset);
                }
 
-               compiler.add_node(NODE_TEX_IMAGE,
-                       slot,
-                       compiler.encode_uchar4(
-                               vector_offset,
-                               color_out->stack_offset,
-                               alpha_out->stack_offset,
-                               srgb));
+               if(projection == "Flat") {
+                       compiler.add_node(NODE_TEX_IMAGE,
+                               slot,
+                               compiler.encode_uchar4(
+                                       vector_offset,
+                                       color_out->stack_offset,
+                                       alpha_out->stack_offset,
+                                       srgb));
+               }
+               else {
+                       compiler.add_node(NODE_TEX_IMAGE_BOX,
+                               slot,
+                               compiler.encode_uchar4(
+                                       vector_offset,
+                                       color_out->stack_offset,
+                                       alpha_out->stack_offset,
+                                       srgb),
+                               __float_as_int(projection_blend));
+               }
        
                if(vector_offset != vector_in->stack_offset)
                        compiler.stack_clear_offset(vector_in->type, vector_offset);
@@ -205,7 +230,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
 
 /* Environment Texture */
 
-static ShaderEnum projection_init()
+static ShaderEnum env_projection_init()
 {
        ShaderEnum enm;
 
@@ -216,7 +241,7 @@ static ShaderEnum projection_init()
 }
 
 ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
-ShaderEnum EnvironmentTextureNode::projection_enum = projection_init();
+ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
 
 EnvironmentTextureNode::EnvironmentTextureNode()
 : TextureNode("environment_texture")
index efd814e4ae6c687098f56e37d7a492cc6fa0938a..ed283492d7b885afa9612f57265eaad03cd9a37e 100644 (file)
@@ -70,8 +70,11 @@ public:
        bool is_float;
        string filename;
        ustring color_space;
+       ustring projection;
+       float projection_blend;
 
        static ShaderEnum color_space_enum;
+       static ShaderEnum projection_enum;
 };
 
 class EnvironmentTextureNode : public TextureNode {
index 45c8a05c27df501b32fc48e8ad5c7027086b3c02..33ebd7a59eff3d932a193b4167cbfa263a9b5232 100644 (file)
@@ -37,7 +37,7 @@
 
 CCL_NAMESPACE_BEGIN
 
-Scene::Scene(const SceneParams& params_)
+Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
 : params(params_)
 {
        device = NULL;
@@ -53,6 +53,9 @@ Scene::Scene(const SceneParams& params_)
        integrator = new Integrator();
        image_manager = new ImageManager();
        shader_manager = ShaderManager::create(this);
+
+       if (device_info_.type == DEVICE_CPU)
+               image_manager->set_extended_image_limits();
 }
 
 Scene::~Scene()
index 8b9944cb76e27b2c4fd7d87d103b1e503321dba7..1a9540b319d20466e4e5b0e233f4def133304751 100644 (file)
@@ -37,6 +37,7 @@ class AttributeRequestSet;
 class Background;
 class Camera;
 class Device;
+class DeviceInfo;
 class Film;
 class Filter;
 class Integrator;
@@ -97,8 +98,8 @@ public:
        device_vector<uint> sobol_directions;
 
        /* images */
-       device_vector<uchar4> tex_image[TEX_NUM_IMAGES];
-       device_vector<float4> tex_float_image[TEX_NUM_FLOAT_IMAGES];
+       device_vector<uchar4> tex_image[TEX_EXTENDED_NUM_IMAGES];
+       device_vector<float4> tex_float_image[TEX_EXTENDED_NUM_FLOAT_IMAGES];
 
        /* opencl images */
        device_vector<uchar4> tex_image_packed;
@@ -179,7 +180,7 @@ public:
        /* mutex must be locked manually by callers */
        thread_mutex mutex;
 
-       Scene(const SceneParams& params);
+       Scene(const SceneParams& params, const DeviceInfo& device_info);
        ~Scene();
 
        void device_update(Device *device, Progress& progress);
index a9f7e5beb567fc73466b9f097fcd2a93d9dc6485..2fb1f49e563328f17b104dcd51de53791eed0c7e 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util_foreach.h"
 #include "util_function.h"
+#include "util_math.h"
 #include "util_opengl.h"
 #include "util_task.h"
 #include "util_time.h"
@@ -35,15 +36,23 @@ CCL_NAMESPACE_BEGIN
 
 Session::Session(const SessionParams& params_)
 : params(params_),
-  tile_manager(params.progressive, params.samples, params.tile_size, params.min_size)
+  tile_manager(params.progressive, params.samples, params.tile_size, params.resolution,
+       (params.background)? 1: max(params.device.multi_devices.size(), 1))
 {
        device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
 
        TaskScheduler::init(params.threads);
 
        device = Device::create(params.device, params.background, params.threads);
-       buffers = new RenderBuffers(device);
-       display = new DisplayBuffer(device);
+
+       if(params.background) {
+               buffers = NULL;
+               display = NULL;
+       }
+       else {
+               buffers = new RenderBuffers(device);
+               display = new DisplayBuffer(device);
+       }
 
        session_thread = NULL;
        scene = NULL;
@@ -52,7 +61,6 @@ Session::Session(const SessionParams& params_)
        reset_time = 0.0;
        preview_time = 0.0;
        paused_time = 0.0;
-       sample = 0;
 
        delayed_reset.do_reset = false;
        delayed_reset.samples = 0;
@@ -81,7 +89,7 @@ Session::~Session()
                wait();
        }
 
-       if(params.output_path != "") {
+       if(display && params.output_path != "") {
                tonemap();
 
                progress.set_status("Writing Image", params.output_path);
@@ -118,8 +126,8 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples)
        /* block for buffer acces and reset immediately. we can't do this
         * in the thread, because we need to allocate an OpenGL buffer, and
         * that only works in the main thread */
-       thread_scoped_lock display_lock(display->mutex);
-       thread_scoped_lock buffers_lock(buffers->mutex);
+       thread_scoped_lock display_lock(display_mutex);
+       thread_scoped_lock buffers_lock(buffers_mutex);
 
        display_outdated = true;
        reset_time = time_dt();
@@ -135,7 +143,7 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples)
 bool Session::draw_gpu(BufferParams& buffer_params)
 {
        /* block for buffer access */
-       thread_scoped_lock display_lock(display->mutex);
+       thread_scoped_lock display_lock(display_mutex);
 
        /* first check we already rendered something */
        if(gpu_draw_ready) {
@@ -145,7 +153,7 @@ bool Session::draw_gpu(BufferParams& buffer_params)
                        /* for CUDA we need to do tonemapping still, since we can
                         * only access GL buffers from the main thread */
                        if(gpu_need_tonemap) {
-                               thread_scoped_lock buffers_lock(buffers->mutex);
+                               thread_scoped_lock buffers_lock(buffers_mutex);
                                tonemap();
                                gpu_need_tonemap = false;
                                gpu_need_tonemap_cond.notify_all();
@@ -226,23 +234,18 @@ void Session::run_gpu()
                        /* buffers mutex is locked entirely while rendering each
                         * sample, and released/reacquired on each iteration to allow
                         * reset and draw in between */
-                       thread_scoped_lock buffers_lock(buffers->mutex);
+                       thread_scoped_lock buffers_lock(buffers_mutex);
 
                        /* update status and timing */
                        update_status_time();
 
                        /* path trace */
-                       foreach(Tile& tile, tile_manager.state.tiles) {
-                               path_trace(tile);
-
-                               device->task_wait();
+                       path_trace();
 
-                               if(device->error_message() != "")
-                                       progress.set_cancel(device->error_message());
+                       device->task_wait();
 
-                               if(progress.get_cancel())
-                                       break;
-                       }
+                       if(device->error_message() != "")
+                               progress.set_cancel(device->error_message());
 
                        /* update status and timing */
                        update_status_time();
@@ -289,7 +292,7 @@ void Session::reset_cpu(BufferParams& buffer_params, int samples)
 
 bool Session::draw_cpu(BufferParams& buffer_params)
 {
-       thread_scoped_lock display_lock(display->mutex);
+       thread_scoped_lock display_lock(display_mutex);
 
        /* first check we already rendered something */
        if(display->draw_ready()) {
@@ -308,13 +311,101 @@ bool Session::draw_cpu(BufferParams& buffer_params)
        return false;
 }
 
+bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
+{
+       if(progress.get_cancel())
+               return false;
+
+       thread_scoped_lock tile_lock(tile_mutex);
+
+       /* get next tile from manager */
+       Tile tile;
+       int device_num = device->device_number(tile_device);
+
+       if(!tile_manager.next_tile(tile, device_num))
+               return false;
+       
+       /* fill render tile */
+       rtile.x = tile_manager.state.buffer.full_x + tile.x;
+       rtile.y = tile_manager.state.buffer.full_y + tile.y;
+       rtile.w = tile.w;
+       rtile.h = tile.h;
+       rtile.start_sample = tile_manager.state.sample;
+       rtile.num_samples = tile_manager.state.num_samples;
+       rtile.resolution = tile_manager.state.resolution;
+
+       tile_lock.unlock();
+
+       /* in case of a permant buffer, return it, otherwise we will allocate
+        * a new temporary buffer */
+       if(!write_render_tile_cb) {
+               tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
+
+               rtile.buffer = buffers->buffer.device_pointer;
+               rtile.rng_state = buffers->rng_state.device_pointer;
+               rtile.rgba = display->rgba.device_pointer;
+               rtile.buffers = buffers;
+
+               device->map_tile(tile_device, rtile);
+
+               return true;
+       }
+
+       /* fill buffer parameters */
+       BufferParams buffer_params = tile_manager.params;
+       buffer_params.full_x = rtile.x;
+       buffer_params.full_y = rtile.y;
+       buffer_params.width = rtile.w;
+       buffer_params.height = rtile.h;
+
+       buffer_params.get_offset_stride(rtile.offset, rtile.stride);
+
+       /* allocate buffers */
+       RenderBuffers *tilebuffers = new RenderBuffers(tile_device);
+       tilebuffers->reset(tile_device, buffer_params);
+
+       rtile.buffer = tilebuffers->buffer.device_pointer;
+       rtile.rng_state = tilebuffers->rng_state.device_pointer;
+       rtile.rgba = 0;
+       rtile.buffers = tilebuffers;
+
+       return true;
+}
+
+void Session::update_tile_sample(RenderTile& rtile)
+{
+       thread_scoped_lock tile_lock(tile_mutex);
+
+       if(update_render_tile_cb) {
+               /* todo: optimize this by making it thread safe and removing lock */
+
+               update_render_tile_cb(rtile);
+       }
+
+       update_status_time();
+}
+
+void Session::release_tile(RenderTile& rtile)
+{
+       thread_scoped_lock tile_lock(tile_mutex);
+
+       if(write_render_tile_cb) {
+               /* todo: optimize this by making it thread safe and removing lock */
+               write_render_tile_cb(rtile);
+
+               delete rtile.buffers;
+       }
+
+       update_status_time();
+}
+
 void Session::run_cpu()
 {
        {
                /* reset once to start */
                thread_scoped_lock reset_lock(delayed_reset.mutex);
-               thread_scoped_lock buffers_lock(buffers->mutex);
-               thread_scoped_lock display_lock(display->mutex);
+               thread_scoped_lock buffers_lock(buffers_mutex);
+               thread_scoped_lock display_lock(display_mutex);
 
                reset_(delayed_reset.params, delayed_reset.samples);
                delayed_reset.do_reset = false;
@@ -364,7 +455,7 @@ void Session::run_cpu()
                        /* buffers mutex is locked entirely while rendering each
                         * sample, and released/reacquired on each iteration to allow
                         * reset and draw in between */
-                       thread_scoped_lock buffers_lock(buffers->mutex);
+                       thread_scoped_lock buffers_lock(buffers_mutex);
 
                        /* update scene */
                        update_scene();
@@ -379,8 +470,7 @@ void Session::run_cpu()
                        update_status_time();
 
                        /* path trace */
-                       foreach(Tile& tile, tile_manager.state.tiles)
-                               path_trace(tile);
+                       path_trace();
 
                        /* update status and timing */
                        update_status_time();
@@ -396,8 +486,8 @@ void Session::run_cpu()
 
                {
                        thread_scoped_lock reset_lock(delayed_reset.mutex);
-                       thread_scoped_lock buffers_lock(buffers->mutex);
-                       thread_scoped_lock display_lock(display->mutex);
+                       thread_scoped_lock buffers_lock(buffers_mutex);
+                       thread_scoped_lock display_lock(display_mutex);
 
                        if(delayed_reset.do_reset) {
                                /* reset rendering if request from main thread */
@@ -442,6 +532,9 @@ void Session::run()
 
        /* run */
        if(!progress.get_cancel()) {
+               /* reset number of rendered samples */
+               progress.reset_sample();
+
                if(device_use_gl)
                        run_gpu();
                else
@@ -465,10 +558,12 @@ bool Session::draw(BufferParams& buffer_params)
 
 void Session::reset_(BufferParams& buffer_params, int samples)
 {
-       if(buffer_params.modified(buffers->params)) {
-               gpu_draw_ready = false;
-               buffers->reset(device, buffer_params);
-               display->reset(device, buffer_params);
+       if(buffers) {
+               if(buffer_params.modified(buffers->params)) {
+                       gpu_draw_ready = false;
+                       buffers->reset(device, buffer_params);
+                       display->reset(device, buffer_params);
+               }
        }
 
        tile_manager.reset(buffer_params, samples);
@@ -476,7 +571,6 @@ void Session::reset_(BufferParams& buffer_params, int samples)
        start_time = time_dt();
        preview_time = 0.0;
        paused_time = 0.0;
-       sample = 0;
 
        if(!params.background)
                progress.set_start_time(start_time + paused_time);
@@ -532,8 +626,6 @@ void Session::update_scene()
 {
        thread_scoped_lock scene_lock(scene->mutex);
 
-       progress.set_status("Updating Scene");
-
        /* update camera if dimensions changed for progressive render. the camera
         * knows nothing about progressive or cropped rendering, it just gets the
         * image dimensions passed in */
@@ -548,20 +640,47 @@ void Session::update_scene()
        }
 
        /* update scene */
-       if(scene->need_update())
+       if(scene->need_update()) {
+               progress.set_status("Updating Scene");
                scene->device_update(device, progress);
+       }
 }
 
 void Session::update_status_time(bool show_pause, bool show_done)
 {
        int sample = tile_manager.state.sample;
        int resolution = tile_manager.state.resolution;
+       int num_tiles = tile_manager.state.num_tiles;
+       int tile = tile_manager.state.num_rendered_tiles;
 
        /* update status */
        string status, substatus;
 
-       if(!params.progressive)
-               substatus = "Path Tracing";
+       if(!params.progressive) {
+               substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles);
+
+               if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL ||
+                       (params.device.type == DEVICE_CPU && num_tiles == 1)) {
+                       /* when rendering on GPU multithreading happens within single tile, as in
+                        * tiles are handling sequentially and in this case we could display
+                        * currently rendering sample number
+                        * this helps a lot from feedback point of view.
+                        * also display the info on CPU, when using 1 tile only
+                        */
+
+                       int sample = progress.get_sample(), num_samples = tile_manager.state.num_samples;
+
+                       if(tile > 1) {
+                               /* sample counter is global for all tiles, subtract samples
+                                * from already finished tiles to get sample counter for
+                                * current tile only
+                                */
+                               sample -= (tile - 1) * num_samples;
+                       }
+
+                       substatus += string_printf(", Sample %d/%d", sample, num_samples);
+               }
+       }
        else if(params.samples == INT_MAX)
                substatus = string_printf("Path Tracing Sample %d", sample+1);
        else
@@ -580,28 +699,29 @@ void Session::update_status_time(bool show_pause, bool show_done)
        if(preview_time == 0.0 && resolution == 1)
                preview_time = time_dt();
        
-       double sample_time = (sample == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample);
+       double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample);
 
        /* negative can happen when we pause a bit before rendering, can discard that */
        if(preview_time < 0.0) preview_time = 0.0;
 
-       progress.set_sample(sample + 1, sample_time);
+       progress.set_tile(tile, tile_time);
+}
+
+void Session::update_progress_sample()
+{
+       progress.increment_sample();
 }
 
-void Session::path_trace(Tile& tile)
+void Session::path_trace()
 {
        /* add path trace task */
        DeviceTask task(DeviceTask::PATH_TRACE);
-
-       task.x = tile_manager.state.buffer.full_x + tile.x;
-       task.y = tile_manager.state.buffer.full_y + tile.y;
-       task.w = tile.w;
-       task.h = tile.h;
-       task.buffer = buffers->buffer.device_pointer;
-       task.rng_state = buffers->rng_state.device_pointer;
-       task.sample = tile_manager.state.sample;
-       task.resolution = tile_manager.state.resolution;
-       tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
+       
+       task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
+       task.release_tile = function_bind(&Session::release_tile, this, _1);
+       task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
+       task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
+       task.update_progress_sample = function_bind(&Session::update_progress_sample, this);
 
        device->task_add(task);
 }
index 90616f011ea3af64d6e90f621a1717ce76539004..7b01357a2b7a6ffcc28f4aacafd6edaed83cfc14 100644 (file)
@@ -47,8 +47,8 @@ public:
        bool progressive;
        bool experimental;
        int samples;
-       int tile_size;
-       int min_size;
+       int2 tile_size;
+       int resolution;
        int threads;
 
        double cancel_timeout;
@@ -63,8 +63,8 @@ public:
                progressive = false;
                experimental = false;
                samples = INT_MAX;
-               tile_size = 64;
-               min_size = 64;
+               tile_size = make_int2(64, 64);
+               resolution = 4;
                threads = 0;
 
                cancel_timeout = 0.1;
@@ -81,7 +81,7 @@ public:
                && progressive == params.progressive
                && experimental == params.experimental
                && tile_size == params.tile_size
-               && min_size == params.min_size
+               && resolution == params.resolution
                && threads == params.threads
                && cancel_timeout == params.cancel_timeout
                && reset_timeout == params.reset_timeout
@@ -102,7 +102,10 @@ public:
        DisplayBuffer *display;
        Progress progress;
        SessionParams params;
-       int sample;
+       TileManager tile_manager;
+
+       boost::function<void(RenderTile&)> write_render_tile_cb;
+       boost::function<void(RenderTile&)> update_render_tile_cb;
 
        Session(const SessionParams& params);
        ~Session();
@@ -130,7 +133,7 @@ protected:
        void update_status_time(bool show_pause = false, bool show_done = false);
 
        void tonemap();
-       void path_trace(Tile& tile);
+       void path_trace();
        void reset_(BufferParams& params, int samples);
 
        void run_cpu();
@@ -141,7 +144,12 @@ protected:
        bool draw_gpu(BufferParams& params);
        void reset_gpu(BufferParams& params, int samples);
 
-       TileManager tile_manager;
+       bool acquire_tile(Device *tile_device, RenderTile& tile);
+       void update_tile_sample(RenderTile& tile);
+       void release_tile(RenderTile& tile);
+
+       void update_progress_sample();
+
        bool device_use_gl;
 
        thread *session_thread;
@@ -155,6 +163,9 @@ protected:
        bool pause;
        thread_condition_variable pause_cond;
        thread_mutex pause_mutex;
+       thread_mutex tile_mutex;
+       thread_mutex buffers_mutex;
+       thread_mutex display_mutex;
 
        bool kernels_loaded;
 
index 04e48d44029e3973813c595a02e77f94ff2af41b..b4156fd9471ef5b5e0ecc73dd3dd91488d81283f 100644 (file)
 #include "tile.h"
 
 #include "util_algorithm.h"
+#include "util_types.h"
 
 CCL_NAMESPACE_BEGIN
 
-TileManager::TileManager(bool progressive_, int samples_, int tile_size_, int min_size_)
+TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int resolution_, int num_devices_)
 {
        progressive = progressive_;
        tile_size = tile_size_;
-       min_size = min_size_;
+       resolution = resolution_;
+       num_devices = num_devices_;
 
        BufferParams buffer_params;
        reset(buffer_params, 0);
@@ -36,34 +38,24 @@ TileManager::~TileManager()
 {
 }
 
-void TileManager::reset(BufferParams& params_, int samples_)
+void TileManager::reset(BufferParams& params_, int num_samples_)
 {
        params = params_;
 
-       start_resolution = 1;
-
-       int w = params.width, h = params.height;
-
-       if(min_size != INT_MAX) {
-               while(w*h > min_size*min_size) {
-                       w = max(1, w/2); 
-                       h = max(1, h/2); 
-
-                       start_resolution *= 2;
-               }
-       }
-
-       samples = samples_;
+       num_samples = num_samples_;
 
        state.buffer = BufferParams();
        state.sample = -1;
-       state.resolution = start_resolution;
+       state.num_tiles = 0;
+       state.num_rendered_tiles = 0;
+       state.num_samples = 0;
+       state.resolution = resolution;
        state.tiles.clear();
 }
 
-void TileManager::set_samples(int samples_)
+void TileManager::set_samples(int num_samples_)
 {
-       samples = samples_;
+       num_samples = num_samples_;
 }
 
 void TileManager::set_tiles()
@@ -71,24 +63,34 @@ void TileManager::set_tiles()
        int resolution = state.resolution;
        int image_w = max(1, params.width/resolution);
        int image_h = max(1, params.height/resolution);
-       int tile_w = (tile_size >= image_w)? 1: (image_w + tile_size - 1)/tile_size;
-       int tile_h = (tile_size >= image_h)? 1: (image_h + tile_size - 1)/tile_size;
-       int sub_w = image_w/tile_w;
-       int sub_h = image_h/tile_h;
 
        state.tiles.clear();
 
-       for(int tile_y = 0; tile_y < tile_h; tile_y++) {
-               for(int tile_x = 0; tile_x < tile_w; tile_x++) {
-                       int x = tile_x * sub_w;
-                       int y = tile_y * sub_h;
-                       int w = (tile_x == tile_w-1)? image_w - x: sub_w;
-                       int h = (tile_y == tile_h-1)? image_h - y: sub_h;
+       int num = min(image_h, num_devices);
+
+       for(int device = 0; device < num; device++) {
+               int device_y = (image_h/num)*device;
+               int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;
+
+               int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
+               int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;
+               int sub_w = (image_w + tile_w - 1)/tile_w;
+               int sub_h = (device_h + tile_h - 1)/tile_h;
 
-                       state.tiles.push_back(Tile(x, y, w, h));
+               for(int tile_y = 0; tile_y < tile_h; tile_y++) {
+                       for(int tile_x = 0; tile_x < tile_w; tile_x++) {
+                               int x = tile_x * sub_w;
+                               int y = tile_y * sub_h;
+                               int w = (tile_x == tile_w-1)? image_w - x: sub_w;
+                               int h = (tile_y == tile_h-1)? device_h - y: sub_h;
+
+                               state.tiles.push_back(Tile(x, y + device_y, w, h, device));
+                       }
                }
        }
 
+       state.num_tiles = state.tiles.size();
+
        state.buffer.width = image_w;
        state.buffer.height = image_h;
 
@@ -98,9 +100,74 @@ void TileManager::set_tiles()
        state.buffer.full_height = max(1, params.full_height/resolution);
 }
 
+list<Tile>::iterator TileManager::next_center_tile(int device)
+{
+       list<Tile>::iterator iter, best = state.tiles.end();
+
+       int resolution = state.resolution;
+       int image_w = max(1, params.width/resolution);
+       int image_h = max(1, params.height/resolution);
+
+       int num = min(image_h, num_devices);
+
+       int device_y = (image_h / num) * device;
+       int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num;
+
+       int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1;
+       int64_t mindist = (int64_t) image_w * (int64_t) device_h;
+
+       /* find center of rendering tiles, image center counts for 1 too */
+       for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
+               if(iter->rendering) {
+                       Tile &cur_tile = *iter;
+                       centx += cur_tile.x + cur_tile.w / 2;
+                       centy += cur_tile.y + cur_tile.h / 2;
+                       tot++;
+               }
+       }
+
+       centx /= tot;
+       centy /= tot;
+
+       /* closest of the non-rendering tiles */
+       for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
+               if(iter->device == device && iter->rendering == false) {
+                       Tile &cur_tile = *iter;
+
+                       int64_t distx = centx - (cur_tile.x + cur_tile.w / 2);
+                       int64_t disty = centy - (cur_tile.y + cur_tile.h / 2);
+                       distx = (int64_t) sqrt((double)distx * distx + disty * disty);
+
+                       if(distx < mindist) {
+                               best = iter;
+                               mindist = distx;
+                       }
+               }
+       }
+
+       return best;
+}
+
+bool TileManager::next_tile(Tile& tile, int device)
+{
+       list<Tile>::iterator tile_it;
+
+       tile_it = next_center_tile(device);
+
+       if(tile_it != state.tiles.end()) {
+               tile_it->rendering = true;
+               tile = *tile_it;
+               state.num_rendered_tiles++;
+
+               return true;
+       }
+
+       return false;
+}
+
 bool TileManager::done()
 {
-       return (state.sample+1 >= samples && state.resolution == 1);
+       return (state.sample+state.num_samples >= num_samples && state.resolution == 1);
 }
 
 bool TileManager::next()
@@ -111,10 +178,17 @@ bool TileManager::next()
        if(progressive && state.resolution > 1) {
                state.sample = 0;
                state.resolution /= 2;
+               state.num_samples = 1;
                set_tiles();
        }
        else {
                state.sample++;
+
+               if(progressive)
+                       state.num_samples = 1;
+               else
+                       state.num_samples = num_samples;
+
                state.resolution = 1;
                set_tiles();
        }
index b6e610c8d90247976fa658b7a33aff2cee18bd55..29f2b1ef9f9d24a5087357a88edc677bd5634d5e 100644 (file)
@@ -31,9 +31,14 @@ CCL_NAMESPACE_BEGIN
 class Tile {
 public:
        int x, y, w, h;
+       int device;
+       bool rendering;
 
-       Tile(int x_, int y_, int w_, int h_)
-       : x(x_), y(y_), w(w_), h(h_) {}
+       Tile()
+       {}
+
+       Tile(int x_, int y_, int w_, int h_, int device_)
+       : x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {}
 };
 
 /* Tile Manager */
@@ -45,27 +50,34 @@ public:
        struct State {
                BufferParams buffer;
                int sample;
+               int num_samples;
                int resolution;
+               int num_tiles;
+               int num_rendered_tiles;
                list<Tile> tiles;
        } state;
 
-       TileManager(bool progressive, int samples, int tile_size, int min_size);
+       TileManager(bool progressive, int num_samples, int2 tile_size, int resolution, int num_devices = 1);
        ~TileManager();
 
-       void reset(BufferParams& params, int samples);
-       void set_samples(int samples);
+       void reset(BufferParams& params, int num_samples);
+       void set_samples(int num_samples);
        bool next();
+       bool next_tile(Tile& tile, int device = 0);
        bool done();
 
 protected:
        void set_tiles();
 
        bool progressive;
-       int samples;
-       int tile_size;
-       int min_size;
+       int num_samples;
+       int2 tile_size;
+       int resolution;
+       int num_devices;
 
        int start_resolution;
+
+       list<Tile>::iterator next_center_tile(int device = 0);
 };
 
 CCL_NAMESPACE_END
index a6bc478ee64d79dbddafde7ae8ce0927be461a94..71a5dedeaa45f0e426b5a8c3cbcc80986cdd1b14 100644 (file)
@@ -277,6 +277,11 @@ __device_inline float cross(const float2 a, const float2 b)
 
 #ifndef __KERNEL_OPENCL__
 
+__device_inline bool operator==(const int2 a, const int2 b)
+{
+       return (a.x == b.x && a.y == b.y);
+}
+
 __device_inline float len(const float2 a)
 {
        return sqrtf(dot(a, a));
index c63aa841c5206567b118c37af050b696a9afcd30..ab9ab7243e957e333c8f823c9982b58e915278b1 100644 (file)
@@ -36,10 +36,11 @@ class Progress {
 public:
        Progress()
        {
+               tile = 0;
                sample = 0;
                start_time = time_dt();
                total_time = 0.0f;
-               sample_time = 0.0f;
+               tile_time = 0.0f;
                status = "Initializing";
                substatus = "";
                update_cb = NULL;
@@ -57,8 +58,10 @@ public:
        {
                thread_scoped_lock lock(progress.progress_mutex);
 
-               progress.get_sample(sample, total_time, sample_time);
                progress.get_status(status, substatus);
+               progress.get_tile(tile, total_time, tile_time);
+
+               sample = progress.get_sample();
 
                return *this;
        }
@@ -90,7 +93,7 @@ public:
                cancel_cb = function;
        }
 
-       /* sample and timing information */
+       /* tile and timing information */
 
        void set_start_time(double start_time_)
        {
@@ -99,22 +102,41 @@ public:
                start_time = start_time_;
        }
 
-       void set_sample(int sample_, double sample_time_)
+       void set_tile(int tile_, double tile_time_)
        {
                thread_scoped_lock lock(progress_mutex);
 
-               sample = sample_;
+               tile = tile_;
                total_time = time_dt() - start_time;
-               sample_time = sample_time_;
+               tile_time = tile_time_;
        }
 
-       void get_sample(int& sample_, double& total_time_, double& sample_time_)
+       void get_tile(int& tile_, double& total_time_, double& tile_time_)
        {
                thread_scoped_lock lock(progress_mutex);
 
-               sample_ = sample;
+               tile_ = tile;
                total_time_ = (total_time > 0.0)? total_time: 0.0;
-               sample_time_ = sample_time;
+               tile_time_ = tile_time;
+       }
+
+       void reset_sample()
+       {
+               thread_scoped_lock lock(progress_mutex);
+
+               sample = 0;
+       }
+
+       void increment_sample()
+       {
+               thread_scoped_lock lock(progress_mutex);
+
+               sample++;
+       }
+
+       int get_sample()
+       {
+               return sample;
        }
 
        /* status messages */
@@ -170,11 +192,12 @@ protected:
        boost::function<void(void)> update_cb;
        boost::function<void(void)> cancel_cb;
 
-       int sample;
+       int tile;    /* counter for rendered tiles */
+       int sample;  /* counter of rendered samples, global for all tiles */
 
        double start_time;
        double total_time;
-       double sample_time;
+       double tile_time;
 
        string status;
        string substatus;
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3ad2e91
--- /dev/null
@@ -0,0 +1,49 @@
+# ***** 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.
+#
+# The Original Code is Copyright (C) 2012, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Sergey Sharybin.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+       .
+       ${OPENCOLORIO_INCLUDE_DIRS}
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+       ocio_capi.cpp
+       ocio_capi.h
+)
+
+add_definitions(
+)
+
+if(WIN32 AND NOT MINGW)
+       list(APPEND INC
+               ${BOOST_INCLUDE_DIR}
+       )
+endif()
+
+blender_add_lib(bf_intern_opencolorio "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript
new file mode 100644 (file)
index 0000000..ef814ed
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+Import('env')
+
+sources = env.Glob('*.cpp')
+
+incs = '.'
+incs += ' ' + env['BF_OCIO_INC']
+
+if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
+    incs += ' ' + env['BF_BOOST_INC']
+
+env.BlenderLib( 'bf_intern_opencolorio', sources, Split(incs), [], libtype=['extern','player'], priority=[10, 185])
diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp
new file mode 100644 (file)
index 0000000..15ef0dd
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Xavier Thomas
+ *                 Lukas Toene
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <iostream>
+
+#include <OpenColorIO/OpenColorIO.h>
+
+
+#define OCIO_CAPI_IMPLEMENTATION
+#include "ocio_capi.h"
+
+#ifdef NDEBUG
+#  define OCIO_abort()
+#else
+#  include <stdlib.h>
+#  define OCIO_abort() abort()
+#endif
+
+static void OCIO_reportError(const char *err)
+{
+       std::cerr << "OpenColorIO Error: " << err << std::endl;
+
+       OCIO_abort();
+}
+
+static void OCIO_reportException(Exception &exception)
+{
+       OCIO_reportError(exception.what());
+}
+
+ConstConfigRcPtr *OCIO_getCurrentConfig(void)
+{
+       ConstConfigRcPtr *config =  new ConstConfigRcPtr();
+       try {
+               *config = GetCurrentConfig();
+
+               if(*config)
+                       return config;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+void OCIO_setCurrentConfig(const ConstConfigRcPtr *config)
+{
+       try {
+               SetCurrentConfig(*config);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+}
+
+ConstConfigRcPtr *OCIO_configCreateFromEnv(void)
+{
+       ConstConfigRcPtr *config =  new ConstConfigRcPtr();
+
+       try {
+               *config = Config::CreateFromEnv();
+
+               if (*config)
+                       return config;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+
+ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename)
+{
+       ConstConfigRcPtr *config =  new ConstConfigRcPtr();
+
+       try {
+               *config = Config::CreateFromFile(filename);
+
+               if (*config)
+                       return config;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+void OCIO_configRelease(ConstConfigRcPtr *config)
+{
+       delete config;
+}
+
+int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config)
+{
+       try {
+               return (*config)->getNumColorSpaces();
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return 0;
+}
+
+const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index)
+{
+       try {
+               return (*config)->getColorSpaceNameByIndex(index);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name)
+{
+       ConstColorSpaceRcPtr *cs =  new ConstColorSpaceRcPtr();
+
+       try {
+               *cs = (*config)->getColorSpace(name);
+
+               if (*cs)
+                       return cs;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+               delete cs;
+       }
+
+       return NULL;
+}
+
+int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name)
+{
+       try {
+               return (*config)->getIndexForColorSpace(name);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return -1;
+}
+
+const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config)
+{
+       try {
+               return (*config)->getDefaultDisplay();
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+int OCIO_configGetNumDisplays(ConstConfigRcPtr* config)
+{
+       try {
+               return (*config)->getNumDisplays();
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return 0;
+}
+
+const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index)
+{
+       try {
+               return (*config)->getDisplay(index);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display)
+{
+       try {
+               return (*config)->getDefaultView(display);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display)
+{
+       try {
+               return (*config)->getNumViews(display);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return 0;
+}
+
+const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index)
+{
+       try {
+               return (*config)->getView(display, index);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view)
+{
+       try {
+               return (*config)->getDisplayColorSpaceName(display, view);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs)
+{
+       delete cs;
+}
+
+ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName)
+{
+       ConstProcessorRcPtr *p =  new ConstProcessorRcPtr();
+
+       try {
+               *p = (*config)->getProcessor(srcName, dstName);
+
+               if (*p)
+                       return p;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return 0;
+}
+
+ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform)
+{
+       ConstProcessorRcPtr *p =  new ConstProcessorRcPtr();
+
+       try {
+               *p = (*config)->getProcessor(*transform);
+
+               if (*p)
+                       return p;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img)
+{
+       try {
+               (*processor)->apply(*img);
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+}
+
+void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel)
+{
+       (*processor)->applyRGB(pixel);
+}
+
+void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel)
+{
+       (*processor)->applyRGBA(pixel);
+}
+
+void OCIO_processorRelease(ConstProcessorRcPtr *p)
+{
+       delete p;
+}
+
+const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs)
+{
+       return (*cs)->getName();
+}
+
+const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs)
+{
+       return (*cs)->getDescription();
+}
+
+const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs)
+{
+       return (*cs)->getFamily();
+}
+
+DisplayTransformRcPtr *OCIO_createDisplayTransform(void)
+{
+       DisplayTransformRcPtr *dt =  new DisplayTransformRcPtr();
+
+       *dt = DisplayTransform::Create();
+
+       return dt;
+}
+
+void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name)
+{
+       (*dt)->setInputColorSpaceName(name);
+}
+
+void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name)
+{
+       (*dt)->setDisplay(name);
+}
+
+void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name)
+{
+       (*dt)->setView(name);
+}
+
+void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
+{
+       (*dt)->setDisplayCC(*t);
+}
+
+void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
+{
+       (*dt)->setLinearCC(*t);
+}
+
+void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt)
+{
+       delete dt;
+       dt = NULL;
+}
+
+PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels,
+                                                                                       long chanStrideBytes, long xStrideBytes, long yStrideBytes)
+{
+       try {
+               PackedImageDesc *id = new PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
+
+               return id;
+       }
+       catch (Exception &exception) {
+               OCIO_reportException(exception);
+       }
+
+       return NULL;
+}
+
+void OCIO_packedImageDescRelease(PackedImageDesc* id)
+{
+       delete id;
+       id = NULL;
+}
+
+ExponentTransformRcPtr *OCIO_createExponentTransform(void)
+{
+       ExponentTransformRcPtr *et =  new ExponentTransformRcPtr();
+
+       *et = ExponentTransform::Create();
+
+       return et;
+}
+
+void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent)
+{
+       (*et)->setValue(exponent);
+}
+
+void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et)
+{
+       delete et;
+}
+
+MatrixTransformRcPtr *OCIO_createMatrixTransform(void)
+{
+       MatrixTransformRcPtr *mt = new MatrixTransformRcPtr();
+
+       *mt = MatrixTransform::Create();
+
+       return mt;
+}
+
+void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
+{
+       (*mt)->setValue(m44, offset4);
+}
+
+void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt)
+{
+       delete mt;
+}
+
+void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f)
+{
+       MatrixTransform::Scale(m44, offset4, scale4f);
+}
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
new file mode 100644 (file)
index 0000000..9941291
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Xavier Thomas
+ *                 Lukas Toene
+ *                 Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OCIO_CAPI_H__
+#define __OCIO_CAPI_H__
+
+
+
+#ifdef __cplusplus
+using namespace OCIO_NAMESPACE;
+extern "C" {
+#endif
+
+#define OCIO_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+
+#ifndef OCIO_CAPI_IMPLEMENTATION
+       #define OCIO_ROLE_SCENE_LINEAR  "scene_linear"
+       #define OCIO_ROLE_COLOR_PICKING "color_picking"
+       #define OCIO_ROLE_TEXTURE_PAINT "texture_paint"
+
+       OCIO_DECLARE_HANDLE(ConstConfigRcPtr);
+       OCIO_DECLARE_HANDLE(ConstColorSpaceRcPtr);
+       OCIO_DECLARE_HANDLE(ConstProcessorRcPtr);
+       OCIO_DECLARE_HANDLE(ConstContextRcPtr);
+       OCIO_DECLARE_HANDLE(PackedImageDesc);
+       OCIO_DECLARE_HANDLE(DisplayTransformRcPtr);
+       OCIO_DECLARE_HANDLE(ConstTransformRcPtr);
+       OCIO_DECLARE_HANDLE(ExponentTransformRcPtr);
+       OCIO_DECLARE_HANDLE(MatrixTransformRcPtr);
+#endif
+
+
+ConstConfigRcPtr *OCIO_getCurrentConfig(void);
+void OCIO_setCurrentConfig(const ConstConfigRcPtr *config);
+
+ConstConfigRcPtr *OCIO_configCreateFromEnv(void);
+ConstConfigRcPtr *OCIO_configCreateFromFile(const char* filename);
+
+void OCIO_configRelease(ConstConfigRcPtr *config);
+
+int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config);
+const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index);
+ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name);
+int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name);
+
+void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs);
+
+const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config);
+int         OCIO_configGetNumDisplays(ConstConfigRcPtr *config);
+const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index);
+const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display);
+int         OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display);
+const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index);
+const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view);
+
+ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName);
+ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform);
+
+void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img);
+void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel);
+void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel);
+
+void OCIO_processorRelease(ConstProcessorRcPtr *p);
+
+const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs);
+const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs);
+const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs);
+
+DisplayTransformRcPtr *OCIO_createDisplayTransform(void);
+void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name);
+void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name);
+void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name);
+void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *et);
+void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *et);
+void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt);
+
+PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels,
+                                            long chanStrideBytes, long xStrideBytes, long yStrideBytes);
+
+void OCIO_packedImageDescRelease(PackedImageDesc *p);
+
+ExponentTransformRcPtr *OCIO_createExponentTransform(void);
+void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent);
+void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et);
+
+MatrixTransformRcPtr *OCIO_createMatrixTransform(void);
+void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *et, const float *m44, const float *offset4);
+void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt);
+
+void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //OCIO_CAPI_H
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
new file mode 100644 (file)
index 0000000..8b73303
--- /dev/null
@@ -0,0 +1,298 @@
+ocio_profile_version: 1
+
+search_path: luts
+strictparsing: true
+luma: [0.2126, 0.7152, 0.0722]
+
+description: RRT version ut33
+
+roles:
+  color_picking: raw
+  color_timing: adx10
+  compositing_log: adx10
+  data: raw
+  default: raw
+  matte_paint: raw
+  reference: aces
+  scene_linear: rec709
+  texture_paint: raw
+
+displays:
+  p3dci:
+    - !<View> {name: Raw, colorspace: raw}
+    - !<View> {name: Log, colorspace: adx10}
+    - !<View> {name: RRT, colorspace: rrt_p3dci}
+  sRGB:
+    - !<View> {name: Raw, colorspace: raw}
+    - !<View> {name: Log, colorspace: adx10}
+    - !<View> {name: RRT, colorspace: rrt_srgb}
+    - !<View> {name: SPI Film, colorspace: srgb8}
+    - !<View> {name: SPI Log, colorspace: lg10}
+    - !<View> {name: Nuke rec709, colorspace: nuke_rec709}
+  xyz:
+    - !<View> {name: Raw, colorspace: raw}
+    - !<View> {name: Log, colorspace: adx10}
+    - !<View> {name: RRT, colorspace: rrt_xyz}
+
+active_displays: [sRGB, p3dci, xyz]
+active_views: [RRT, Log, SPI Film, SPI Log, Raw]
+
+colorspaces:
+  - !<ColorSpace>
+    name: aces
+    family: aces
+    equalitygroup:
+    bitdepth: 32f
+    isdata: false
+    allocation: lg2
+    allocationvars: [-8.5, 5]
+
+  - !<ColorSpace>
+    name: raw
+    family: raw
+    equalitygroup:
+    bitdepth: 32f
+    isdata: true
+    allocation: uniform
+    allocationvars: [0, 1]
+
+  - !<ColorSpace>
+    name: adx10
+    family: adx
+    equalitygroup:
+    bitdepth: 10ui
+    description: |
+      Film Scan, using the 10-bit Academy Density Encoding
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: adx_adx10_to_cdd.spimtx}
+        - !<FileTransform> {src: adx_cdd_to_cid.spimtx}
+        - !<FileTransform> {src: adx_cid_to_rle.spi1d, interpolation: linear}
+        - !<LogTransform> {base: 10, direction: inverse}
+        - !<FileTransform> {src: adx_exp_to_aces.spimtx}
+
+  - !<ColorSpace>
+    name: adx16
+    family: adx
+    equalitygroup:
+    bitdepth: 16ui
+    description: |
+      Film Scan, using the 16-bit Academy Density Encoding
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: adx_adx16_to_cdd.spimtx}
+        - !<FileTransform> {src: adx_cdd_to_cid.spimtx}
+        - !<FileTransform> {src: adx_cid_to_rle.spi1d, interpolation: linear}
+        - !<LogTransform> {base: 10, direction: inverse}
+        - !<FileTransform> {src: adx_exp_to_aces.spimtx}
+
+  - !<ColorSpace>
+    name: slogf35
+    family: sony
+    equalitygroup:
+    bitdepth: 10ui
+    description: |
+      Sony 10-bit S-Log, with f35 color primaries
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: slog10.spi1d, interpolation: linear}
+        - !<FileTransform> {src: slogf35_to_aces.spimtx, interpolation: linear}
+
+  - !<ColorSpace>
+    name: slogf65_3200
+    family: sony
+    equalitygroup:
+    bitdepth: 10ui
+    description: |
+      Sony 10-bit S-Log, with f65 color primaries
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: slog10.spi1d, interpolation: linear}
+        - !<FileTransform> {src: slogf65_to_aces_3200.spimtx, interpolation: linear}
+
+  - !<ColorSpace>
+    name: slogf65_5500
+    family: sony
+    equalitygroup:
+    bitdepth: 10ui
+    description: |
+      Sony 10-bit S-Log, with f65 color primaries
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: slog10.spi1d, interpolation: linear}
+        - !<FileTransform> {src: slogf65_to_aces_5500.spimtx, interpolation: linear}
+
+  - !<ColorSpace>
+    name: logc
+    family: arri
+    equalitygroup:
+    bitdepth: 10ui
+    description: |
+      Arri Alexa LogC, V3, Exposure Index 800
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: logc800.spi1d, interpolation: linear}
+        - !<FileTransform> {src: logc_to_aces.spimtx}
+
+  - !<ColorSpace>
+    name: log
+    family: log
+    equalitygroup:
+    bitdepth: 32f
+    description: |
+      A mathematically idealized log space, which spans the dynamic range
+      currently being utilized by the ACES RRT. Note: this does not correspond
+      to scanned plates, adx10 is preferred for that purpose.
+
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    from_reference: !<GroupTransform>
+      children:
+        - !<AllocationTransform> {allocation: lg2, vars: [-8.5, 5]}
+
+  - !<ColorSpace>
+    name: rec709
+    family: ""
+    equalitygroup: ""
+    bitdepth: 32f
+    description: |
+      Rec. 709 (Full Range), Blender native internal space
+    isdata: false
+    allocation: uniform
+    allocationvars: [-0.125, 1.125]
+    to_reference: !<FileTransform> {src: rec709_to_aces.spimtx, interpolation: nearest}
+
+  - !<ColorSpace>
+    name: rrt_srgb
+    family: rrt
+    equalitygroup:
+    bitdepth: 32f
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    from_reference: !<GroupTransform>
+      children:
+        - !<AllocationTransform> {allocation: lg2, vars: [-8.5, 5]}
+        - !<FileTransform> {src: rrt_ut33_sRGB.spi3d, interpolation: tetrahedral}
+
+  - !<ColorSpace>
+    name: rrt_rec709
+    family: rrt
+    equalitygroup:
+    bitdepth: 32f
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    from_reference: !<GroupTransform>
+      children:
+        - !<AllocationTransform> {allocation: lg2, vars: [-8.5, 5]}
+        - !<FileTransform> {src: rrt_ut33_rec709.spi3d, interpolation: tetrahedral}
+
+  - !<ColorSpace>
+    name: rrt_p3dci
+    family: rrt
+    equalitygroup:
+    bitdepth: 32f
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    from_reference: !<GroupTransform>
+      children:
+        - !<AllocationTransform> {allocation: lg2, vars: [-8.5, 5]}
+        - !<FileTransform> {src: rrt_ut33_p3dci.spi3d, interpolation: tetrahedral}
+
+  - !<ColorSpace>
+    name: rrt_p3d60
+    family: rrt
+    equalitygroup:
+    bitdepth: 32f
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    from_reference: !<GroupTransform>
+      children:
+        - !<AllocationTransform> {allocation: lg2, vars: [-8.5, 5]}
+        - !<FileTransform> {src: rrt_ut33_p3d60.spi3d, interpolation: tetrahedral}
+
+  - !<ColorSpace>
+    name: rrt_xyz
+    family: rrt
+    equalitygroup:
+    bitdepth: 32f
+    isdata: false
+    allocation: uniform
+    allocationvars: [0, 1]
+    from_reference: !<GroupTransform>
+      children:
+        - !<AllocationTransform> {allocation: lg2, vars: [-8.5, 5]}
+        - !<FileTransform> {src: rrt_ut33_dcdm.spi3d, interpolation: tetrahedral}
+
+  # spi-vfx
+  - !<ColorSpace>
+    name: lg10
+    family: lg
+    equalitygroup:
+    bitdepth: 10ui
+    description: |
+      lg10 : conversion from film log
+    isdata: false
+    allocation: uniform
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: lg10.spi1d, interpolation: nearest}
+        - !<FileTransform> {src: rec709_to_aces.spimtx, interpolation: nearest}
+
+  - !<ColorSpace>
+    name: srgb8
+    family: srgb
+    equalitygroup:
+    bitdepth: 8ui
+    description: |
+      srgb8 :rgb display space for the srgb standard.
+    isdata: false
+    allocation: uniform
+    from_reference: !<GroupTransform>
+      children:
+        - !<ColorSpaceTransform> {src: aces, dst: lg10}
+        - !<FileTransform> {src: spi_ocio_srgb_test.spi3d, interpolation: linear}
+
+  # nuke-default
+  - !<ColorSpace>
+    name: nuke_rec709
+    family: ""
+    equalitygroup: ""
+    bitdepth: 32f
+    description: |
+      Rec. 709 (Full Range) Display Space
+    isdata: false
+    allocation: uniform
+    allocationvars: [-0.125, 1.125]
+    to_reference: !<GroupTransform>
+      children:
+        - !<FileTransform> {src: rec709.spi1d, interpolation: linear}
+        - !<FileTransform> {src: rec709_to_aces.spimtx, interpolation: nearest}
diff --git a/release/datafiles/colormanagement/luts/adx_adx10_to_cdd.spimtx b/release/datafiles/colormanagement/luts/adx_adx10_to_cdd.spimtx
new file mode 100644 (file)
index 0000000..b1c5c9e
--- /dev/null
@@ -0,0 +1,4 @@
+2.046 0.0 0.0 -12451.65
+0.0 2.046 0.0 -12451.65
+0.0 0.0 2.046 -12451.65
+
diff --git a/release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx b/release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx
new file mode 100644 (file)
index 0000000..348eafa
--- /dev/null
@@ -0,0 +1,4 @@
+8.191875 0.0 0.0 -12451.65
+0.0 8.191875 0.0 -12451.65
+0.0 0.0 8.191875 -12451.65
+
diff --git a/release/datafiles/colormanagement/luts/adx_cdd_to_cid.spimtx b/release/datafiles/colormanagement/luts/adx_cdd_to_cid.spimtx
new file mode 100644 (file)
index 0000000..21eff95
--- /dev/null
@@ -0,0 +1,4 @@
+0.75573 0.22197 0.02230 0
+0.05901 0.96928 -0.02829 0
+0.16134 0.07406 0.76460 0
+
diff --git a/release/datafiles/colormanagement/luts/adx_cid_to_rle.py b/release/datafiles/colormanagement/luts/adx_cid_to_rle.py
new file mode 100644 (file)
index 0000000..c226d4f
--- /dev/null
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+
+import math, numpy
+
+"""
+
+const float REF_PT = (7120.0 - 1520.0) / 8000.0 * (100.0 / 55.0) - log10(0.18);
+
+const float LUT_1D[11][2] = {
+       {-0.190000000000000, -6.000000000000000},
+       { 0.010000000000000, -2.721718645000000},
+       { 0.028000000000000, -2.521718645000000},
+       { 0.054000000000000, -2.321718645000000},
+       { 0.095000000000000, -2.121718645000000},
+       { 0.145000000000000, -1.921718645000000},
+       { 0.220000000000000, -1.721718645000000},
+       { 0.300000000000000, -1.521718645000000},
+       { 0.400000000000000, -1.321718645000000},
+       { 0.500000000000000, -1.121718645000000},
+       { 0.600000000000000, -0.926545676714876}
+};
+
+       // Convert Channel Independent Density values to Relative Log Exposure values
+       float logE[3];
+       if ( cid[0] <= 0.6) logE[0] = interpolate1D( LUT_1D, cid[0]);
+       if ( cid[1] <= 0.6) logE[1] = interpolate1D( LUT_1D, cid[1]);
+       if ( cid[2] <= 0.6) logE[2] = interpolate1D( LUT_1D, cid[2]);
+
+       if ( cid[0] > 0.6) logE[0] = ( 100.0 / 55.0) * cid[0] - REF_PT;
+       if ( cid[1] > 0.6) logE[1] = ( 100.0 / 55.0) * cid[1] - REF_PT;
+       if ( cid[2] > 0.6) logE[2] = ( 100.0 / 55.0) * cid[2] - REF_PT;
+"""
+
+
+def interpolate1D(x, xp, fp):
+    return numpy.interp(x, xp, fp)
+
+LUT_1D_xp = [-0.190000000000000, 
+              0.010000000000000,
+              0.028000000000000,
+              0.054000000000000,
+              0.095000000000000,
+              0.145000000000000,
+              0.220000000000000,
+              0.300000000000000,
+              0.400000000000000,
+              0.500000000000000,
+              0.600000000000000]
+
+LUT_1D_fp = [-6.000000000000000, 
+             -2.721718645000000,
+             -2.521718645000000,
+             -2.321718645000000,
+             -2.121718645000000,
+             -1.921718645000000,
+             -1.721718645000000,
+             -1.521718645000000,
+             -1.321718645000000,
+             -1.121718645000000,
+             -0.926545676714876]
+
+REF_PT = (7120.0 - 1520.0) / 8000.0 * (100.0 / 55.0) - math.log(0.18, 10.0)
+
+def cid_to_rle(x):
+    if x <= 0.6:
+        return interpolate1D(x, LUT_1D_xp, LUT_1D_fp)
+    return (100.0 / 55.0) * x - REF_PT
+
+def WriteSPI1D(filename, fromMin, fromMax, data):
+    f = file(filename,'w')
+    f.write("Version 1\n")
+    f.write("From %s %s\n" % (fromMin, fromMax))
+    f.write("Length %d\n" % len(data))
+    f.write("Components 1\n")
+    f.write("{\n")
+    for value in data:
+        f.write("        %s\n" % value)
+    f.write("}\n")
+    f.close()
+
+def Fit(value, fromMin, fromMax, toMin, toMax):
+    if fromMin == fromMax:
+        raise ValueError("fromMin == fromMax")
+    return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin
+
+NUM_SAMPLES = 2**12
+RANGE = (-0.19, 3.0)
+data = []
+for i in xrange(NUM_SAMPLES):
+    x = i/(NUM_SAMPLES-1.0)
+    x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1])
+    data.append(cid_to_rle(x))
+
+WriteSPI1D('adx_cid_to_rle.spi1d', RANGE[0], RANGE[1], data)
+
diff --git a/release/datafiles/colormanagement/luts/adx_cid_to_rle.spi1d b/release/datafiles/colormanagement/luts/adx_cid_to_rle.spi1d
new file mode 100644 (file)
index 0000000..26b5ae9
--- /dev/null
@@ -0,0 +1,4102 @@
+Version 1
+From -0.19 3.0
+Length 4096
+Components 1
+{
+        -6.0
+        -5.98723111414
+        -5.97446222827
+        -5.96169334241
+        -5.94892445654
+        -5.93615557068
+        -5.92338668482
+        -5.91061779895
+        -5.89784891309
+        -5.88508002723
+        -5.87231114136
+        -5.8595422555
+        -5.84677336963
+        -5.83400448377
+        -5.82123559791
+        -5.80846671204
+        -5.79569782618
+        -5.78292894032
+        -5.77016005445
+        -5.75739116859
+        -5.74462228272
+        -5.73185339686
+        -5.719084511
+        -5.70631562513
+        -5.69354673927
+        -5.68077785341
+        -5.66800896754
+        -5.65524008168
+        -5.64247119581
+        -5.62970230995
+        -5.61693342409
+        -5.60416453822
+        -5.59139565236
+        -5.57862676649
+        -5.56585788063
+        -5.55308899477
+        -5.5403201089
+        -5.52755122304
+        -5.51478233718
+        -5.50201345131
+        -5.48924456545
+        -5.47647567958
+        -5.46370679372
+        -5.45093790786
+        -5.43816902199
+        -5.42540013613
+        -5.41263125027
+        -5.3998623644
+        -5.38709347854
+        -5.37432459267
+        -5.36155570681
+        -5.34878682095
+        -5.33601793508
+        -5.32324904922
+        -5.31048016335
+        -5.29771127749
+        -5.28494239163
+        -5.27217350576
+        -5.2594046199
+        -5.24663573404
+        -5.23386684817
+        -5.22109796231
+        -5.20832907644
+        -5.19556019058
+        -5.18279130472
+        -5.17002241885
+        -5.15725353299
+        -5.14448464713
+        -5.13171576126
+        -5.1189468754
+        -5.10617798953
+        -5.09340910367
+        -5.08064021781
+        -5.06787133194
+        -5.05510244608
+        -5.04233356022
+        -5.02956467435
+        -5.01679578849
+        -5.00402690262
+        -4.99125801676
+        -4.9784891309
+        -4.96572024503
+        -4.95295135917
+        -4.9401824733
+        -4.92741358744
+        -4.91464470158
+        -4.90187581571
+        -4.88910692985
+        -4.87633804399
+        -4.86356915812
+        -4.85080027226
+        -4.83803138639
+        -4.82526250053
+        -4.81249361467
+        -4.7997247288
+        -4.78695584294
+        -4.77418695708
+        -4.76141807121
+        -4.74864918535
+        -4.73588029948
+        -4.72311141362
+        -4.71034252776
+        -4.69757364189
+        -4.68480475603
+        -4.67203587017
+        -4.6592669843
+        -4.64649809844
+        -4.63372921257
+        -4.62096032671
+        -4.60819144085
+        -4.59542255498
+        -4.58265366912
+        -4.56988478325
+        -4.55711589739
+        -4.54434701153
+        -4.53157812566
+        -4.5188092398
+        -4.50604035394
+        -4.49327146807
+        -4.48050258221
+        -4.46773369634
+        -4.45496481048
+        -4.44219592462
+        -4.42942703875
+        -4.41665815289
+        -4.40388926703
+        -4.39112038116
+        -4.3783514953
+        -4.36558260943
+        -4.35281372357
+        -4.34004483771
+        -4.32727595184
+        -4.31450706598
+        -4.30173818011
+        -4.28896929425
+        -4.27620040839
+        -4.26343152252
+        -4.25066263666
+        -4.2378937508
+        -4.22512486493
+        -4.21235597907
+        -4.1995870932
+        -4.18681820734
+        -4.17404932148
+        -4.16128043561
+        -4.14851154975
+        -4.13574266389
+        -4.12297377802
+        -4.11020489216
+        -4.09743600629
+        -4.08466712043
+        -4.07189823457
+        -4.0591293487
+        -4.04636046284
+        -4.03359157698
+        -4.02082269111
+        -4.00805380525
+        -3.99528491938
+        -3.98251603352
+        -3.96974714766
+        -3.95697826179
+        -3.94420937593
+        -3.93144049006
+        -3.9186716042
+        -3.90590271834
+        -3.89313383247
+        -3.88036494661
+        -3.86759606075
+        -3.85482717488
+        -3.84205828902
+        -3.82928940315
+        -3.81652051729
+        -3.80375163143
+        -3.79098274556
+        -3.7782138597
+        -3.76544497384
+        -3.75267608797
+        -3.73990720211
+        -3.72713831624
+        -3.71436943038
+        -3.70160054452
+        -3.68883165865
+        -3.67606277279
+        -3.66329388693
+        -3.65052500106
+        -3.6377561152
+        -3.62498722933
+        -3.61221834347
+        -3.59944945761
+        -3.58668057174
+        -3.57391168588
+        -3.56114280001
+        -3.54837391415
+        -3.53560502829
+        -3.52283614242
+        -3.51006725656
+        -3.4972983707
+        -3.48452948483
+        -3.47176059897
+        -3.4589917131
+        -3.44622282724
+        -3.43345394138
+        -3.42068505551
+        -3.40791616965
+        -3.39514728379
+        -3.38237839792
+        -3.36960951206
+        -3.35684062619
+        -3.34407174033
+        -3.33130285447
+        -3.3185339686
+        -3.30576508274
+        -3.29299619687
+        -3.28022731101
+        -3.26745842515
+        -3.25468953928
+        -3.24192065342
+        -3.22915176756
+        -3.21638288169
+        -3.20361399583
+        -3.19084510996
+        -3.1780762241
+        -3.16530733824
+        -3.15253845237
+        -3.13976956651
+        -3.12700068065
+        -3.11423179478
+        -3.10146290892
+        -3.08869402305
+        -3.07592513719
+        -3.06315625133
+        -3.05038736546
+        -3.0376184796
+        -3.02484959374
+        -3.01208070787
+        -2.99931182201
+        -2.98654293614
+        -2.97377405028
+        -2.96100516442
+        -2.94823627855
+        -2.93546739269
+        -2.92269850682
+        -2.90992962096
+        -2.8971607351
+        -2.88439184923
+        -2.87162296337
+        -2.85885407751
+        -2.84608519164
+        -2.83331630578
+        -2.82054741991
+        -2.80777853405
+        -2.79500964819
+        -2.78224076232
+        -2.76947187646
+        -2.7567029906
+        -2.74393410473
+        -2.73116521887
+        -2.71946657608
+        -2.71081103409
+        -2.7021554921
+        -2.69349995011
+        -2.68484440813
+        -2.67618886614
+        -2.66753332415
+        -2.65887778216
+        -2.65022224017
+        -2.64156669818
+        -2.63291115619
+        -2.6242556142
+        -2.61560007221
+        -2.60694453023
+        -2.59828898824
+        -2.58963344625
+        -2.58097790426
+        -2.57232236227
+        -2.56366682028
+        -2.55501127829
+        -2.5463557363
+        -2.53770019431
+        -2.52904465233
+        -2.52079819793
+        -2.51480589963
+        -2.50881360133
+        -2.50282130303
+        -2.49682900473
+        -2.49083670643
+        -2.48484440813
+        -2.47885210983
+        -2.47285981153
+        -2.46686751323
+        -2.46087521493
+        -2.45488291663
+        -2.44889061833
+        -2.44289832003
+        -2.43690602173
+        -2.43091372343
+        -2.42492142513
+        -2.41892912683
+        -2.41293682853
+        -2.40694453023
+        -2.40095223193
+        -2.39495993363
+        -2.38896763533
+        -2.38297533703
+        -2.37698303873
+        -2.37099074043
+        -2.36499844213
+        -2.35900614383
+        -2.35301384553
+        -2.34702154723
+        -2.34102924893
+        -2.33503695063
+        -2.32904465233
+        -2.32305235403
+        -2.31876441766
+        -2.31496442361
+        -2.31116442957
+        -2.30736443552
+        -2.30356444148
+        -2.29976444744
+        -2.29596445339
+        -2.29216445935
+        -2.2883644653
+        -2.28456447126
+        -2.28076447722
+        -2.27696448317
+        -2.27316448913
+        -2.26936449508
+        -2.26556450104
+        -2.261764507
+        -2.25796451295
+        -2.25416451891
+        -2.25036452487
+        -2.24656453082
+        -2.24276453678
+        -2.23896454273
+        -2.23516454869
+        -2.23136455465
+        -2.2275645606
+        -2.22376456656
+        -2.21996457251
+        -2.21616457847
+        -2.21236458443
+        -2.20856459038
+        -2.20476459634
+        -2.20096460229
+        -2.19716460825
+        -2.19336461421
+        -2.18956462016
+        -2.18576462612
+        -2.18196463208
+        -2.17816463803
+        -2.17436464399
+        -2.17056464994
+        -2.1667646559
+        -2.16296466186
+        -2.15916466781
+        -2.15536467377
+        -2.15156467972
+        -2.14776468568
+        -2.14396469164
+        -2.14016469759
+        -2.13636470355
+        -2.1325647095
+        -2.12876471546
+        -2.12496472142
+        -2.12126443255
+        -2.11814843743
+        -2.11503244231
+        -2.1119164472
+        -2.10880045208
+        -2.10568445697
+        -2.10256846185
+        -2.09945246673
+        -2.09633647162
+        -2.0932204765
+        -2.09010448139
+        -2.08698848627
+        -2.08387249115
+        -2.08075649604
+        -2.07764050092
+        -2.07452450581
+        -2.07140851069
+        -2.06829251557
+        -2.06517652046
+        -2.06206052534
+        -2.05894453023
+        -2.05582853511
+        -2.05271253999
+        -2.04959654488
+        -2.04648054976
+        -2.04336455465
+        -2.04024855953
+        -2.03713256441
+        -2.0340165693
+        -2.03090057418
+        -2.02778457907
+        -2.02466858395
+        -2.02155258883
+        -2.01843659372
+        -2.0153205986
+        -2.01220460349
+        -2.00908860837
+        -2.00597261325
+        -2.00285661814
+        -1.99974062302
+        -1.99662462791
+        -1.99350863279
+        -1.99039263767
+        -1.98727664256
+        -1.98416064744
+        -1.98104465233
+        -1.97792865721
+        -1.97481266209
+        -1.97169666698
+        -1.96858067186
+        -1.96546467675
+        -1.96234868163
+        -1.95923268651
+        -1.9561166914
+        -1.95300069628
+        -1.94988470117
+        -1.94676870605
+        -1.94365271093
+        -1.94053671582
+        -1.9374207207
+        -1.93430472559
+        -1.93118873047
+        -1.92807273535
+        -1.92495674024
+        -1.92184074512
+        -1.919722715
+        -1.91764538493
+        -1.91556805485
+        -1.91349072477
+        -1.91141339469
+        -1.90933606462
+        -1.90725873454
+        -1.90518140446
+        -1.90310407439
+        -1.90102674431
+        -1.89894941423
+        -1.89687208415
+        -1.89479475408
+        -1.892717424
+        -1.89064009392
+        -1.88856276384
+        -1.88648543377
+        -1.88440810369
+        -1.88233077361
+        -1.88025344353
+        -1.87817611346
+        -1.87609878338
+        -1.8740214533
+        -1.87194412323
+        -1.86986679315
+        -1.86778946307
+        -1.86571213299
+        -1.86363480292
+        -1.86155747284
+        -1.85948014276
+        -1.85740281268
+        -1.85532548261
+        -1.85324815253
+        -1.85117082245
+        -1.84909349237
+        -1.8470161623
+        -1.84493883222
+        -1.84286150214
+        -1.84078417207
+        -1.83870684199
+        -1.83662951191
+        -1.83455218183
+        -1.83247485176
+        -1.83039752168
+        -1.8283201916
+        -1.82624286152
+        -1.82416553145
+        -1.82208820137
+        -1.82001087129
+        -1.81793354121
+        -1.81585621114
+        -1.81377888106
+        -1.81170155098
+        -1.80962422091
+        -1.80754689083
+        -1.80546956075
+        -1.80339223067
+        -1.8013149006
+        -1.79923757052
+        -1.79716024044
+        -1.79508291036
+        -1.79300558029
+        -1.79092825021
+        -1.78885092013
+        -1.78677359005
+        -1.78469625998
+        -1.7826189299
+        -1.78054159982
+        -1.77846426975
+        -1.77638693967
+        -1.77430960959
+        -1.77223227951
+        -1.77015494944
+        -1.76807761936
+        -1.76600028928
+        -1.7639229592
+        -1.76184562913
+        -1.75976829905
+        -1.75769096897
+        -1.75561363889
+        -1.75353630882
+        -1.75145897874
+        -1.74938164866
+        -1.74730431859
+        -1.74522698851
+        -1.74314965843
+        -1.74107232835
+        -1.73899499828
+        -1.7369176682
+        -1.73484033812
+        -1.73276300804
+        -1.73068567797
+        -1.72860834789
+        -1.72653101781
+        -1.72445368774
+        -1.72237635766
+        -1.72038775367
+        -1.71844025672
+        -1.71649275977
+        -1.71454526283
+        -1.71259776588
+        -1.71065026893
+        -1.70870277198
+        -1.70675527504
+        -1.70480777809
+        -1.70286028114
+        -1.70091278419
+        -1.69896528725
+        -1.6970177903
+        -1.69507029335
+        -1.6931227964
+        -1.69117529946
+        -1.68922780251
+        -1.68728030556
+        -1.68533280861
+        -1.68338531167
+        -1.68143781472
+        -1.67949031777
+        -1.67754282082
+        -1.67559532388
+        -1.67364782693
+        -1.67170032998
+        -1.66975283303
+        -1.66780533609
+        -1.66585783914
+        -1.66391034219
+        -1.66196284524
+        -1.6600153483
+        -1.65806785135
+        -1.6561203544
+        -1.65417285745
+        -1.65222536051
+        -1.65027786356
+        -1.64833036661
+        -1.64638286966
+        -1.64443537272
+        -1.64248787577
+        -1.64054037882
+        -1.63859288187
+        -1.63664538493
+        -1.63469788798
+        -1.63275039103
+        -1.63080289408
+        -1.62885539714
+        -1.62690790019
+        -1.62496040324
+        -1.62301290629
+        -1.62106540935
+        -1.6191179124
+        -1.61717041545
+        -1.6152229185
+        -1.61327542156
+        -1.61132792461
+        -1.60938042766
+        -1.60743293071
+        -1.60548543377
+        -1.60353793682
+        -1.60159043987
+        -1.59964294292
+        -1.59769544598
+        -1.59574794903
+        -1.59380045208
+        -1.59185295513
+        -1.58990545819
+        -1.58795796124
+        -1.58601046429
+        -1.58406296734
+        -1.5821154704
+        -1.58016797345
+        -1.5782204765
+        -1.57627297955
+        -1.57432548261
+        -1.57237798566
+        -1.57043048871
+        -1.56848299176
+        -1.56653549482
+        -1.56458799787
+        -1.56264050092
+        -1.56069300397
+        -1.55874550703
+        -1.55679801008
+        -1.55485051313
+        -1.55290301618
+        -1.55095551924
+        -1.54900802229
+        -1.54706052534
+        -1.54511302839
+        -1.54316553145
+        -1.5412180345
+        -1.53927053755
+        -1.5373230406
+        -1.53537554366
+        -1.53342804671
+        -1.53148054976
+        -1.52953305281
+        -1.52758555587
+        -1.52563805892
+        -1.52369056197
+        -1.52174306502
+        -1.52018018346
+        -1.5186221859
+        -1.51706418835
+        -1.51550619079
+        -1.51394819323
+        -1.51239019567
+        -1.51083219811
+        -1.50927420056
+        -1.507716203
+        -1.50615820544
+        -1.50460020788
+        -1.50304221032
+        -1.50148421277
+        -1.49992621521
+        -1.49836821765
+        -1.49681022009
+        -1.49525222253
+        -1.49369422498
+        -1.49213622742
+        -1.49057822986
+        -1.4890202323
+        -1.48746223474
+        -1.48590423719
+        -1.48434623963
+        -1.48278824207
+        -1.48123024451
+        -1.47967224695
+        -1.4781142494
+        -1.47655625184
+        -1.47499825428
+        -1.47344025672
+        -1.47188225916
+        -1.47032426161
+        -1.46876626405
+        -1.46720826649
+        -1.46565026893
+        -1.46409227137
+        -1.46253427382
+        -1.46097627626
+        -1.4594182787
+        -1.45786028114
+        -1.45630228358
+        -1.45474428603
+        -1.45318628847
+        -1.45162829091
+        -1.45007029335
+        -1.44851229579
+        -1.44695429824
+        -1.44539630068
+        -1.44383830312
+        -1.44228030556
+        -1.440722308
+        -1.43916431045
+        -1.43760631289
+        -1.43604831533
+        -1.43449031777
+        -1.43293232021
+        -1.43137432266
+        -1.4298163251
+        -1.42825832754
+        -1.42670032998
+        -1.42514233242
+        -1.42358433487
+        -1.42202633731
+        -1.42046833975
+        -1.41891034219
+        -1.41735234463
+        -1.41579434708
+        -1.41423634952
+        -1.41267835196
+        -1.4111203544
+        -1.40956235684
+        -1.40800435929
+        -1.40644636173
+        -1.40488836417
+        -1.40333036661
+        -1.40177236905
+        -1.4002143715
+        -1.39865637394
+        -1.39709837638
+        -1.39554037882
+        -1.39398238126
+        -1.39242438371
+        -1.39086638615
+        -1.38930838859
+        -1.38775039103
+        -1.38619239347
+        -1.38463439592
+        -1.38307639836
+        -1.3815184008
+        -1.37996040324
+        -1.37840240568
+        -1.37684440813
+        -1.37528641057
+        -1.37372841301
+        -1.37217041545
+        -1.37061241789
+        -1.36905442034
+        -1.36749642278
+        -1.36593842522
+        -1.36438042766
+        -1.3628224301
+        -1.36126443255
+        -1.35970643499
+        -1.35814843743
+        -1.35659043987
+        -1.35503244231
+        -1.35347444476
+        -1.3519164472
+        -1.35035844964
+        -1.34880045208
+        -1.34724245452
+        -1.34568445697
+        -1.34412645941
+        -1.34256846185
+        -1.34101046429
+        -1.33945246673
+        -1.33789446918
+        -1.33633647162
+        -1.33477847406
+        -1.3332204765
+        -1.33166247894
+        -1.33010448139
+        -1.32854648383
+        -1.32698848627
+        -1.32543048871
+        -1.32387249115
+        -1.3223144936
+        -1.32075649604
+        -1.31919849848
+        -1.31764050092
+        -1.31608250336
+        -1.31452450581
+        -1.31296650825
+        -1.31140851069
+        -1.30985051313
+        -1.30829251557
+        -1.30673451802
+        -1.30517652046
+        -1.3036185229
+        -1.30206052534
+        -1.30050252778
+        -1.29894453023
+        -1.29738653267
+        -1.29582853511
+        -1.29427053755
+        -1.29271253999
+        -1.29115454244
+        -1.28959654488
+        -1.28803854732
+        -1.28648054976
+        -1.2849225522
+        -1.28336455465
+        -1.28180655709
+        -1.28024855953
+        -1.27869056197
+        -1.27713256441
+        -1.27557456686
+        -1.2740165693
+        -1.27245857174
+        -1.27090057418
+        -1.26934257662
+        -1.26778457907
+        -1.26622658151
+        -1.26466858395
+        -1.26311058639
+        -1.26155258883
+        -1.25999459128
+        -1.25843659372
+        -1.25687859616
+        -1.2553205986
+        -1.25376260104
+        -1.25220460349
+        -1.25064660593
+        -1.24908860837
+        -1.24753061081
+        -1.24597261325
+        -1.2444146157
+        -1.24285661814
+        -1.24129862058
+        -1.23974062302
+        -1.23818262546
+        -1.23662462791
+        -1.23506663035
+        -1.23350863279
+        -1.23195063523
+        -1.23039263767
+        -1.22883464012
+        -1.22727664256
+        -1.225718645
+        -1.22416064744
+        -1.22260264988
+        -1.22104465233
+        -1.21948665477
+        -1.21792865721
+        -1.21637065965
+        -1.21481266209
+        -1.21325466454
+        -1.21169666698
+        -1.21013866942
+        -1.20858067186
+        -1.2070226743
+        -1.20546467675
+        -1.20390667919
+        -1.20234868163
+        -1.20079068407
+        -1.19923268651
+        -1.19767468896
+        -1.1961166914
+        -1.19455869384
+        -1.19300069628
+        -1.19144269872
+        -1.18988470117
+        -1.18832670361
+        -1.18676870605
+        -1.18521070849
+        -1.18365271093
+        -1.18209471338
+        -1.18053671582
+        -1.17897871826
+        -1.1774207207
+        -1.17586272314
+        -1.17430472559
+        -1.17274672803
+        -1.17118873047
+        -1.16963073291
+        -1.16807273535
+        -1.1665147378
+        -1.16495674024
+        -1.16339874268
+        -1.16184074512
+        -1.16028274756
+        -1.15872475001
+        -1.15716675245
+        -1.15560875489
+        -1.15405075733
+        -1.15249275977
+        -1.15093476222
+        -1.14937676466
+        -1.1478187671
+        -1.14626076954
+        -1.14470277198
+        -1.14314477443
+        -1.14158677687
+        -1.14002877931
+        -1.13847078175
+        -1.13691278419
+        -1.13535478664
+        -1.13379678908
+        -1.13223879152
+        -1.13068079396
+        -1.1291227964
+        -1.12756479885
+        -1.12600680129
+        -1.12444880373
+        -1.12289080617
+        -1.12134212084
+        -1.1198217258
+        -1.11830133076
+        -1.11678093572
+        -1.11526054068
+        -1.11374014564
+        -1.1122197506
+        -1.11069935556
+        -1.10917896052
+        -1.10765856548
+        -1.10613817044
+        -1.1046177754
+        -1.10309738036
+        -1.10157698532
+        -1.10005659028
+        -1.09853619524
+        -1.0970158002
+        -1.09549540516
+        -1.09397501012
+        -1.09245461508
+        -1.09093422004
+        -1.089413825
+        -1.08789342996
+        -1.08637303492
+        -1.08485263988
+        -1.08333224484
+        -1.0818118498
+        -1.08029145476
+        -1.07877105972
+        -1.07725066468
+        -1.07573026964
+        -1.0742098746
+        -1.07268947956
+        -1.07116908452
+        -1.06964868948
+        -1.06812829444
+        -1.0666078994
+        -1.06508750436
+        -1.06356710932
+        -1.06204671428
+        -1.06052631924
+        -1.0590059242
+        -1.05748552916
+        -1.05596513412
+        -1.05444473908
+        -1.05292434404
+        -1.051403949
+        -1.04988355396
+        -1.04836315892
+        -1.04684276388
+        -1.04532236884
+        -1.0438019738
+        -1.04228157876
+        -1.04076118372
+        -1.03924078868
+        -1.03772039364
+        -1.0361999986
+        -1.03467960356
+        -1.03315920852
+        -1.03163881348
+        -1.03011841844
+        -1.0285980234
+        -1.02707762836
+        -1.02555723332
+        -1.02403683828
+        -1.02251644324
+        -1.0209960482
+        -1.01947565316
+        -1.01795525812
+        -1.01643486309
+        -1.01491446805
+        -1.01339407301
+        -1.01187367797
+        -1.01035328293
+        -1.00883288789
+        -1.00731249285
+        -1.00579209781
+        -1.00427170277
+        -1.00275130773
+        -1.00123091269
+        -0.999710517646
+        -0.998190122606
+        -0.996669727567
+        -0.995149332527
+        -0.993628937487
+        -0.992108542447
+        -0.990588147407
+        -0.989067752367
+        -0.987547357327
+        -0.986026962287
+        -0.984506567248
+        -0.982986172208
+        -0.981465777168
+        -0.979945382128
+        -0.978424987088
+        -0.976904592048
+        -0.975384197008
+        -0.973863801968
+        -0.972343406929
+        -0.970823011889
+        -0.969302616849
+        -0.967782221809
+        -0.966261826769
+        -0.964741431729
+        -0.963221036689
+        -0.961700641649
+        -0.96018024661
+        -0.95865985157
+        -0.95713945653
+        -0.95561906149
+        -0.95409866645
+        -0.95257827141
+        -0.95105787637
+        -0.94953748133
+        -0.948017086291
+        -0.946496691251
+        -0.944976296211
+        -0.943455901171
+        -0.941935506131
+        -0.940415111091
+        -0.938894716051
+        -0.937374321011
+        -0.935853925972
+        -0.934333530932
+        -0.932813135892
+        -0.931292740852
+        -0.929772345812
+        -0.928251950772
+        -0.926731555732
+        -0.925302475472
+        -0.923886114055
+        -0.922469752639
+        -0.921053391223
+        -0.919637029806
+        -0.91822066839
+        -0.916804306974
+        -0.915387945557
+        -0.913971584141
+        -0.912555222724
+        -0.911138861308
+        -0.909722499892
+        -0.908306138475
+        -0.906889777059
+        -0.905473415643
+        -0.904057054226
+        -0.90264069281
+        -0.901224331394
+        -0.899807969977
+        -0.898391608561
+        -0.896975247144
+        -0.895558885728
+        -0.894142524312
+        -0.892726162895
+        -0.891309801479
+        -0.889893440063
+        -0.888477078646
+        -0.88706071723
+        -0.885644355814
+        -0.884227994397
+        -0.882811632981
+        -0.881395271564
+        -0.879978910148
+        -0.878562548732
+        -0.877146187315
+        -0.875729825899
+        -0.874313464483
+        -0.872897103066
+        -0.87148074165
+        -0.870064380234
+        -0.868648018817
+        -0.867231657401
+        -0.865815295984
+        -0.864398934568
+        -0.862982573152
+        -0.861566211735
+        -0.860149850319
+        -0.858733488903
+        -0.857317127486
+        -0.85590076607
+        -0.854484404654
+        -0.853068043237
+        -0.851651681821
+        -0.850235320405
+        -0.848818958988
+        -0.847402597572
+        -0.845986236155
+        -0.844569874739
+        -0.843153513323
+        -0.841737151906
+        -0.84032079049
+        -0.838904429074
+        -0.837488067657
+        -0.836071706241
+        -0.834655344825
+        -0.833238983408
+        -0.831822621992
+        -0.830406260575
+        -0.828989899159
+        -0.827573537743
+        -0.826157176326
+        -0.82474081491
+        -0.823324453494
+        -0.821908092077
+        -0.820491730661
+        -0.819075369245
+        -0.817659007828
+        -0.816242646412
+        -0.814826284995
+        -0.813409923579
+        -0.811993562163
+        -0.810577200746
+        -0.80916083933
+        -0.807744477914
+        -0.806328116497
+        -0.804911755081
+        -0.803495393665
+        -0.802079032248
+        -0.800662670832
+        -0.799246309416
+        -0.797829947999
+        -0.796413586583
+        -0.794997225166
+        -0.79358086375
+        -0.792164502334
+        -0.790748140917
+        -0.789331779501
+        -0.787915418085
+        -0.786499056668
+        -0.785082695252
+        -0.783666333836
+        -0.782249972419
+        -0.780833611003
+        -0.779417249586
+        -0.77800088817
+        -0.776584526754
+        -0.775168165337
+        -0.773751803921
+        -0.772335442505
+        -0.770919081088
+        -0.769502719672
+        -0.768086358256
+        -0.766669996839
+        -0.765253635423
+        -0.763837274006
+        -0.76242091259
+        -0.761004551174
+        -0.759588189757
+        -0.758171828341
+        -0.756755466925
+        -0.755339105508
+        -0.753922744092
+        -0.752506382676
+        -0.751090021259
+        -0.749673659843
+        -0.748257298426
+        -0.74684093701
+        -0.745424575594
+        -0.744008214177
+        -0.742591852761
+        -0.741175491345
+        -0.739759129928
+        -0.738342768512
+        -0.736926407096
+        -0.735510045679
+        -0.734093684263
+        -0.732677322847
+        -0.73126096143
+        -0.729844600014
+        -0.728428238597
+        -0.727011877181
+        -0.725595515765
+        -0.724179154348
+        -0.722762792932
+        -0.721346431516
+        -0.719930070099
+        -0.718513708683
+        -0.717097347267
+        -0.71568098585
+        -0.714264624434
+        -0.712848263017
+        -0.711431901601
+        -0.710015540185
+        -0.708599178768
+        -0.707182817352
+        -0.705766455936
+        -0.704350094519
+        -0.702933733103
+        -0.701517371687
+        -0.70010101027
+        -0.698684648854
+        -0.697268287437
+        -0.695851926021
+        -0.694435564605
+        -0.693019203188
+        -0.691602841772
+        -0.690186480356
+        -0.688770118939
+        -0.687353757523
+        -0.685937396107
+        -0.68452103469
+        -0.683104673274
+        -0.681688311858
+        -0.680271950441
+        -0.678855589025
+        -0.677439227608
+        -0.676022866192
+        -0.674606504776
+        -0.673190143359
+        -0.671773781943
+        -0.670357420527
+        -0.66894105911
+        -0.667524697694
+        -0.666108336278
+        -0.664691974861
+        -0.663275613445
+        -0.661859252028
+        -0.660442890612
+        -0.659026529196
+        -0.657610167779
+        -0.656193806363
+        -0.654777444947
+        -0.65336108353
+        -0.651944722114
+        -0.650528360698
+        -0.649111999281
+        -0.647695637865
+        -0.646279276448
+        -0.644862915032
+        -0.643446553616
+        -0.642030192199
+        -0.640613830783
+        -0.639197469367
+        -0.63778110795
+        -0.636364746534
+        -0.634948385118
+        -0.633532023701
+        -0.632115662285
+        -0.630699300868
+        -0.629282939452
+        -0.627866578036
+        -0.626450216619
+        -0.625033855203
+        -0.623617493787
+        -0.62220113237
+        -0.620784770954
+        -0.619368409538
+        -0.617952048121
+        -0.616535686705
+        -0.615119325289
+        -0.613702963872
+        -0.612286602456
+        -0.610870241039
+        -0.609453879623
+        -0.608037518207
+        -0.60662115679
+        -0.605204795374
+        -0.603788433958
+        -0.602372072541
+        -0.600955711125
+        -0.599539349709
+        -0.598122988292
+        -0.596706626876
+        -0.595290265459
+        -0.593873904043
+        -0.592457542627
+        -0.59104118121
+        -0.589624819794
+        -0.588208458378
+        -0.586792096961
+        -0.585375735545
+        -0.583959374129
+        -0.582543012712
+        -0.581126651296
+        -0.579710289879
+        -0.578293928463
+        -0.576877567047
+        -0.57546120563
+        -0.574044844214
+        -0.572628482798
+        -0.571212121381
+        -0.569795759965
+        -0.568379398549
+        -0.566963037132
+        -0.565546675716
+        -0.5641303143
+        -0.562713952883
+        -0.561297591467
+        -0.55988123005
+        -0.558464868634
+        -0.557048507218
+        -0.555632145801
+        -0.554215784385
+        -0.552799422969
+        -0.551383061552
+        -0.549966700136
+        -0.54855033872
+        -0.547133977303
+        -0.545717615887
+        -0.54430125447
+        -0.542884893054
+        -0.541468531638
+        -0.540052170221
+        -0.538635808805
+        -0.537219447389
+        -0.535803085972
+        -0.534386724556
+        -0.53297036314
+        -0.531554001723
+        -0.530137640307
+        -0.52872127889
+        -0.527304917474
+        -0.525888556058
+        -0.524472194641
+        -0.523055833225
+        -0.521639471809
+        -0.520223110392
+        -0.518806748976
+        -0.51739038756
+        -0.515974026143
+        -0.514557664727
+        -0.513141303311
+        -0.511724941894
+        -0.510308580478
+        -0.508892219061
+        -0.507475857645
+        -0.506059496229
+        -0.504643134812
+        -0.503226773396
+        -0.50181041198
+        -0.500394050563
+        -0.498977689147
+        -0.497561327731
+        -0.496144966314
+        -0.494728604898
+        -0.493312243481
+        -0.491895882065
+        -0.490479520649
+        -0.489063159232
+        -0.487646797816
+        -0.4862304364
+        -0.484814074983
+        -0.483397713567
+        -0.481981352151
+        -0.480564990734
+        -0.479148629318
+        -0.477732267901
+        -0.476315906485
+        -0.474899545069
+        -0.473483183652
+        -0.472066822236
+        -0.47065046082
+        -0.469234099403
+        -0.467817737987
+        -0.466401376571
+        -0.464985015154
+        -0.463568653738
+        -0.462152292321
+        -0.460735930905
+        -0.459319569489
+        -0.457903208072
+        -0.456486846656
+        -0.45507048524
+        -0.453654123823
+        -0.452237762407
+        -0.450821400991
+        -0.449405039574
+        -0.447988678158
+        -0.446572316742
+        -0.445155955325
+        -0.443739593909
+        -0.442323232492
+        -0.440906871076
+        -0.43949050966
+        -0.438074148243
+        -0.436657786827
+        -0.435241425411
+        -0.433825063994
+        -0.432408702578
+        -0.430992341162
+        -0.429575979745
+        -0.428159618329
+        -0.426743256912
+        -0.425326895496
+        -0.42391053408
+        -0.422494172663
+        -0.421077811247
+        -0.419661449831
+        -0.418245088414
+        -0.416828726998
+        -0.415412365582
+        -0.413996004165
+        -0.412579642749
+        -0.411163281332
+        -0.409746919916
+        -0.4083305585
+        -0.406914197083
+        -0.405497835667
+        -0.404081474251
+        -0.402665112834
+        -0.401248751418
+        -0.399832390002
+        -0.398416028585
+        -0.396999667169
+        -0.395583305753
+        -0.394166944336
+        -0.39275058292
+        -0.391334221503
+        -0.389917860087
+        -0.388501498671
+        -0.387085137254
+        -0.385668775838
+        -0.384252414422
+        -0.382836053005
+        -0.381419691589
+        -0.380003330173
+        -0.378586968756
+        -0.37717060734
+        -0.375754245923
+        -0.374337884507
+        -0.372921523091
+        -0.371505161674
+        -0.370088800258
+        -0.368672438842
+        -0.367256077425
+        -0.365839716009
+        -0.364423354593
+        -0.363006993176
+        -0.36159063176
+        -0.360174270343
+        -0.358757908927
+        -0.357341547511
+        -0.355925186094
+        -0.354508824678
+        -0.353092463262
+        -0.351676101845
+        -0.350259740429
+        -0.348843379013
+        -0.347427017596
+        -0.34601065618
+        -0.344594294763
+        -0.343177933347
+        -0.341761571931
+        -0.340345210514
+        -0.338928849098
+        -0.337512487682
+        -0.336096126265
+        -0.334679764849
+        -0.333263403433
+        -0.331847042016
+        -0.3304306806
+        -0.329014319184
+        -0.327597957767
+        -0.326181596351
+        -0.324765234934
+        -0.323348873518
+        -0.321932512102
+        -0.320516150685
+        -0.319099789269
+        -0.317683427853
+        -0.316267066436
+        -0.31485070502
+        -0.313434343604
+        -0.312017982187
+        -0.310601620771
+        -0.309185259354
+        -0.307768897938
+        -0.306352536522
+        -0.304936175105
+        -0.303519813689
+        -0.302103452273
+        -0.300687090856
+        -0.29927072944
+        -0.297854368024
+        -0.296438006607
+        -0.295021645191
+        -0.293605283774
+        -0.292188922358
+        -0.290772560942
+        -0.289356199525
+        -0.287939838109
+        -0.286523476693
+        -0.285107115276
+        -0.28369075386
+        -0.282274392444
+        -0.280858031027
+        -0.279441669611
+        -0.278025308195
+        -0.276608946778
+        -0.275192585362
+        -0.273776223945
+        -0.272359862529
+        -0.270943501113
+        -0.269527139696
+        -0.26811077828
+        -0.266694416864
+        -0.265278055447
+        -0.263861694031
+        -0.262445332615
+        -0.261028971198
+        -0.259612609782
+        -0.258196248365
+        -0.256779886949
+        -0.255363525533
+        -0.253947164116
+        -0.2525308027
+        -0.251114441284
+        -0.249698079867
+        -0.248281718451
+        -0.246865357035
+        -0.245448995618
+        -0.244032634202
+        -0.242616272785
+        -0.241199911369
+        -0.239783549953
+        -0.238367188536
+        -0.23695082712
+        -0.235534465704
+        -0.234118104287
+        -0.232701742871
+        -0.231285381455
+        -0.229869020038
+        -0.228452658622
+        -0.227036297205
+        -0.225619935789
+        -0.224203574373
+        -0.222787212956
+        -0.22137085154
+        -0.219954490124
+        -0.218538128707
+        -0.217121767291
+        -0.215705405875
+        -0.214289044458
+        -0.212872683042
+        -0.211456321626
+        -0.210039960209
+        -0.208623598793
+        -0.207207237376
+        -0.20579087596
+        -0.204374514544
+        -0.202958153127
+        -0.201541791711
+        -0.200125430295
+        -0.198709068878
+        -0.197292707462
+        -0.195876346046
+        -0.194459984629
+        -0.193043623213
+        -0.191627261796
+        -0.19021090038
+        -0.188794538964
+        -0.187378177547
+        -0.185961816131
+        -0.184545454715
+        -0.183129093298
+        -0.181712731882
+        -0.180296370466
+        -0.178880009049
+        -0.177463647633
+        -0.176047286216
+        -0.1746309248
+        -0.173214563384
+        -0.171798201967
+        -0.170381840551
+        -0.168965479135
+        -0.167549117718
+        -0.166132756302
+        -0.164716394886
+        -0.163300033469
+        -0.161883672053
+        -0.160467310637
+        -0.15905094922
+        -0.157634587804
+        -0.156218226387
+        -0.154801864971
+        -0.153385503555
+        -0.151969142138
+        -0.150552780722
+        -0.149136419306
+        -0.147720057889
+        -0.146303696473
+        -0.144887335057
+        -0.14347097364
+        -0.142054612224
+        -0.140638250807
+        -0.139221889391
+        -0.137805527975
+        -0.136389166558
+        -0.134972805142
+        -0.133556443726
+        -0.132140082309
+        -0.130723720893
+        -0.129307359477
+        -0.12789099806
+        -0.126474636644
+        -0.125058275227
+        -0.123641913811
+        -0.122225552395
+        -0.120809190978
+        -0.119392829562
+        -0.117976468146
+        -0.116560106729
+        -0.115143745313
+        -0.113727383897
+        -0.11231102248
+        -0.110894661064
+        -0.109478299647
+        -0.108061938231
+        -0.106645576815
+        -0.105229215398
+        -0.103812853982
+        -0.102396492566
+        -0.100980131149
+        -0.099563769733
+        -0.0981474083166
+        -0.0967310469002
+        -0.0953146854839
+        -0.0938983240675
+        -0.0924819626512
+        -0.0910656012348
+        -0.0896492398184
+        -0.0882328784021
+        -0.0868165169857
+        -0.0854001555694
+        -0.083983794153
+        -0.0825674327366
+        -0.0811510713203
+        -0.0797347099039
+        -0.0783183484875
+        -0.0769019870712
+        -0.0754856256548
+        -0.0740692642385
+        -0.0726529028221
+        -0.0712365414057
+        -0.0698201799894
+        -0.068403818573
+        -0.0669874571567
+        -0.0655710957403
+        -0.0641547343239
+        -0.0627383729076
+        -0.0613220114912
+        -0.0599056500748
+        -0.0584892886585
+        -0.0570729272421
+        -0.0556565658258
+        -0.0542402044094
+        -0.052823842993
+        -0.0514074815767
+        -0.0499911201603
+        -0.048574758744
+        -0.0471583973276
+        -0.0457420359112
+        -0.0443256744949
+        -0.0429093130785
+        -0.0414929516622
+        -0.0400765902458
+        -0.0386602288294
+        -0.0372438674131
+        -0.0358275059967
+        -0.0344111445803
+        -0.032994783164
+        -0.0315784217476
+        -0.0301620603313
+        -0.0287456989149
+        -0.0273293374985
+        -0.0259129760822
+        -0.0244966146658
+        -0.0230802532495
+        -0.0216638918331
+        -0.0202475304167
+        -0.0188311690004
+        -0.017414807584
+        -0.0159984461676
+        -0.0145820847513
+        -0.0131657233349
+        -0.0117493619186
+        -0.0103330005022
+        -0.00891663908584
+        -0.00750027766948
+        -0.00608391625311
+        -0.00466755483675
+        -0.00325119342039
+        -0.00183483200403
+        -0.00041847058767
+        0.000997890828692
+        0.00241425224505
+        0.00383061366141
+        0.00524697507778
+        0.00666333649414
+        0.0080796979105
+        0.00949605932686
+        0.0109124207432
+        0.0123287821596
+        0.0137451435759
+        0.0151615049923
+        0.0165778664087
+        0.017994227825
+        0.0194105892414
+        0.0208269506578
+        0.0222433120741
+        0.0236596734905
+        0.0250760349068
+        0.0264923963232
+        0.0279087577396
+        0.0293251191559
+        0.0307414805723
+        0.0321578419886
+        0.033574203405
+        0.0349905648214
+        0.0364069262377
+        0.0378232876541
+        0.0392396490705
+        0.0406560104868
+        0.0420723719032
+        0.0434887333195
+        0.0449050947359
+        0.0463214561523
+        0.0477378175686
+        0.049154178985
+        0.0505705404013
+        0.0519869018177
+        0.0534032632341
+        0.0548196246504
+        0.0562359860668
+        0.0576523474831
+        0.0590687088995
+        0.0604850703159
+        0.0619014317322
+        0.0633177931486
+        0.064734154565
+        0.0661505159813
+        0.0675668773977
+        0.068983238814
+        0.0703996002304
+        0.0718159616468
+        0.0732323230631
+        0.0746486844795
+        0.0760650458958
+        0.0774814073122
+        0.0788977687286
+        0.0803141301449
+        0.0817304915613
+        0.0831468529777
+        0.084563214394
+        0.0859795758104
+        0.0873959372267
+        0.0888122986431
+        0.0902286600595
+        0.0916450214758
+        0.0930613828922
+        0.0944777443085
+        0.0958941057249
+        0.0973104671413
+        0.0987268285576
+        0.100143189974
+        0.10155955139
+        0.102975912807
+        0.104392274223
+        0.105808635639
+        0.107224997056
+        0.108641358472
+        0.110057719889
+        0.111474081305
+        0.112890442721
+        0.114306804138
+        0.115723165554
+        0.11713952697
+        0.118555888387
+        0.119972249803
+        0.121388611219
+        0.122804972636
+        0.124221334052
+        0.125637695468
+        0.127054056885
+        0.128470418301
+        0.129886779718
+        0.131303141134
+        0.13271950255
+        0.134135863967
+        0.135552225383
+        0.136968586799
+        0.138384948216
+        0.139801309632
+        0.141217671048
+        0.142634032465
+        0.144050393881
+        0.145466755298
+        0.146883116714
+        0.14829947813
+        0.149715839547
+        0.151132200963
+        0.152548562379
+        0.153964923796
+        0.155381285212
+        0.156797646628
+        0.158214008045
+        0.159630369461
+        0.161046730878
+        0.162463092294
+        0.16387945371
+        0.165295815127
+        0.166712176543
+        0.168128537959
+        0.169544899376
+        0.170961260792
+        0.172377622208
+        0.173793983625
+        0.175210345041
+        0.176626706458
+        0.178043067874
+        0.17945942929
+        0.180875790707
+        0.182292152123
+        0.183708513539
+        0.185124874956
+        0.186541236372
+        0.187957597788
+        0.189373959205
+        0.190790320621
+        0.192206682037
+        0.193623043454
+        0.19503940487
+        0.196455766287
+        0.197872127703
+        0.199288489119
+        0.200704850536
+        0.202121211952
+        0.203537573368
+        0.204953934785
+        0.206370296201
+        0.207786657617
+        0.209203019034
+        0.21061938045
+        0.212035741867
+        0.213452103283
+        0.214868464699
+        0.216284826116
+        0.217701187532
+        0.219117548948
+        0.220533910365
+        0.221950271781
+        0.223366633197
+        0.224782994614
+        0.22619935603
+        0.227615717447
+        0.229032078863
+        0.230448440279
+        0.231864801696
+        0.233281163112
+        0.234697524528
+        0.236113885945
+        0.237530247361
+        0.238946608777
+        0.240362970194
+        0.24177933161
+        0.243195693026
+        0.244612054443
+        0.246028415859
+        0.247444777276
+        0.248861138692
+        0.250277500108
+        0.251693861525
+        0.253110222941
+        0.254526584357
+        0.255942945774
+        0.25735930719
+        0.258775668606
+        0.260192030023
+        0.261608391439
+        0.263024752856
+        0.264441114272
+        0.265857475688
+        0.267273837105
+        0.268690198521
+        0.270106559937
+        0.271522921354
+        0.27293928277
+        0.274355644186
+        0.275772005603
+        0.277188367019
+        0.278604728436
+        0.280021089852
+        0.281437451268
+        0.282853812685
+        0.284270174101
+        0.285686535517
+        0.287102896934
+        0.28851925835
+        0.289935619766
+        0.291351981183
+        0.292768342599
+        0.294184704016
+        0.295601065432
+        0.297017426848
+        0.298433788265
+        0.299850149681
+        0.301266511097
+        0.302682872514
+        0.30409923393
+        0.305515595346
+        0.306931956763
+        0.308348318179
+        0.309764679595
+        0.311181041012
+        0.312597402428
+        0.314013763845
+        0.315430125261
+        0.316846486677
+        0.318262848094
+        0.31967920951
+        0.321095570926
+        0.322511932343
+        0.323928293759
+        0.325344655175
+        0.326761016592
+        0.328177378008
+        0.329593739425
+        0.331010100841
+        0.332426462257
+        0.333842823674
+        0.33525918509
+        0.336675546506
+        0.338091907923
+        0.339508269339
+        0.340924630755
+        0.342340992172
+        0.343757353588
+        0.345173715005
+        0.346590076421
+        0.348006437837
+        0.349422799254
+        0.35083916067
+        0.352255522086
+        0.353671883503
+        0.355088244919
+        0.356504606335
+        0.357920967752
+        0.359337329168
+        0.360753690584
+        0.362170052001
+        0.363586413417
+        0.365002774834
+        0.36641913625
+        0.367835497666
+        0.369251859083
+        0.370668220499
+        0.372084581915
+        0.373500943332
+        0.374917304748
+        0.376333666164
+        0.377750027581
+        0.379166388997
+        0.380582750414
+        0.38199911183
+        0.383415473246
+        0.384831834663
+        0.386248196079
+        0.387664557495
+        0.389080918912
+        0.390497280328
+        0.391913641744
+        0.393330003161
+        0.394746364577
+        0.396162725994
+        0.39757908741
+        0.398995448826
+        0.400411810243
+        0.401828171659
+        0.403244533075
+        0.404660894492
+        0.406077255908
+        0.407493617324
+        0.408909978741
+        0.410326340157
+        0.411742701574
+        0.41315906299
+        0.414575424406
+        0.415991785823
+        0.417408147239
+        0.418824508655
+        0.420240870072
+        0.421657231488
+        0.423073592904
+        0.424489954321
+        0.425906315737
+        0.427322677153
+        0.42873903857
+        0.430155399986
+        0.431571761403
+        0.432988122819
+        0.434404484235
+        0.435820845652
+        0.437237207068
+        0.438653568484
+        0.440069929901
+        0.441486291317
+        0.442902652733
+        0.44431901415
+        0.445735375566
+        0.447151736983
+        0.448568098399
+        0.449984459815
+        0.451400821232
+        0.452817182648
+        0.454233544064
+        0.455649905481
+        0.457066266897
+        0.458482628313
+        0.45989898973
+        0.461315351146
+        0.462731712563
+        0.464148073979
+        0.465564435395
+        0.466980796812
+        0.468397158228
+        0.469813519644
+        0.471229881061
+        0.472646242477
+        0.474062603893
+        0.47547896531
+        0.476895326726
+        0.478311688142
+        0.479728049559
+        0.481144410975
+        0.482560772392
+        0.483977133808
+        0.485393495224
+        0.486809856641
+        0.488226218057
+        0.489642579473
+        0.49105894089
+        0.492475302306
+        0.493891663722
+        0.495308025139
+        0.496724386555
+        0.498140747972
+        0.499557109388
+        0.500973470804
+        0.502389832221
+        0.503806193637
+        0.505222555053
+        0.50663891647
+        0.508055277886
+        0.509471639302
+        0.510888000719
+        0.512304362135
+        0.513720723552
+        0.515137084968
+        0.516553446384
+        0.517969807801
+        0.519386169217
+        0.520802530633
+        0.52221889205
+        0.523635253466
+        0.525051614882
+        0.526467976299
+        0.527884337715
+        0.529300699132
+        0.530717060548
+        0.532133421964
+        0.533549783381
+        0.534966144797
+        0.536382506213
+        0.53779886763
+        0.539215229046
+        0.540631590462
+        0.542047951879
+        0.543464313295
+        0.544880674711
+        0.546297036128
+        0.547713397544
+        0.549129758961
+        0.550546120377
+        0.551962481793
+        0.55337884321
+        0.554795204626
+        0.556211566042
+        0.557627927459
+        0.559044288875
+        0.560460650291
+        0.561877011708
+        0.563293373124
+        0.564709734541
+        0.566126095957
+        0.567542457373
+        0.56895881879
+        0.570375180206
+        0.571791541622
+        0.573207903039
+        0.574624264455
+        0.576040625871
+        0.577456987288
+        0.578873348704
+        0.580289710121
+        0.581706071537
+        0.583122432953
+        0.58453879437
+        0.585955155786
+        0.587371517202
+        0.588787878619
+        0.590204240035
+        0.591620601451
+        0.593036962868
+        0.594453324284
+        0.5958696857
+        0.597286047117
+        0.598702408533
+        0.60011876995
+        0.601535131366
+        0.602951492782
+        0.604367854199
+        0.605784215615
+        0.607200577031
+        0.608616938448
+        0.610033299864
+        0.61144966128
+        0.612866022697
+        0.614282384113
+        0.61569874553
+        0.617115106946
+        0.618531468362
+        0.619947829779
+        0.621364191195
+        0.622780552611
+        0.624196914028
+        0.625613275444
+        0.62702963686
+        0.628445998277
+        0.629862359693
+        0.63127872111
+        0.632695082526
+        0.634111443942
+        0.635527805359
+        0.636944166775
+        0.638360528191
+        0.639776889608
+        0.641193251024
+        0.64260961244
+        0.644025973857
+        0.645442335273
+        0.646858696689
+        0.648275058106
+        0.649691419522
+        0.651107780939
+        0.652524142355
+        0.653940503771
+        0.655356865188
+        0.656773226604
+        0.65818958802
+        0.659605949437
+        0.661022310853
+        0.662438672269
+        0.663855033686
+        0.665271395102
+        0.666687756519
+        0.668104117935
+        0.669520479351
+        0.670936840768
+        0.672353202184
+        0.6737695636
+        0.675185925017
+        0.676602286433
+        0.678018647849
+        0.679435009266
+        0.680851370682
+        0.682267732099
+        0.683684093515
+        0.685100454931
+        0.686516816348
+        0.687933177764
+        0.68934953918
+        0.690765900597
+        0.692182262013
+        0.693598623429
+        0.695014984846
+        0.696431346262
+        0.697847707679
+        0.699264069095
+        0.700680430511
+        0.702096791928
+        0.703513153344
+        0.70492951476
+        0.706345876177
+        0.707762237593
+        0.709178599009
+        0.710594960426
+        0.712011321842
+        0.713427683258
+        0.714844044675
+        0.716260406091
+        0.717676767508
+        0.719093128924
+        0.72050949034
+        0.721925851757
+        0.723342213173
+        0.724758574589
+        0.726174936006
+        0.727591297422
+        0.729007658838
+        0.730424020255
+        0.731840381671
+        0.733256743088
+        0.734673104504
+        0.73608946592
+        0.737505827337
+        0.738922188753
+        0.740338550169
+        0.741754911586
+        0.743171273002
+        0.744587634418
+        0.746003995835
+        0.747420357251
+        0.748836718668
+        0.750253080084
+        0.7516694415
+        0.753085802917
+        0.754502164333
+        0.755918525749
+        0.757334887166
+        0.758751248582
+        0.760167609998
+        0.761583971415
+        0.763000332831
+        0.764416694247
+        0.765833055664
+        0.76724941708
+        0.768665778497
+        0.770082139913
+        0.771498501329
+        0.772914862746
+        0.774331224162
+        0.775747585578
+        0.777163946995
+        0.778580308411
+        0.779996669827
+        0.781413031244
+        0.78282939266
+        0.784245754077
+        0.785662115493
+        0.787078476909
+        0.788494838326
+        0.789911199742
+        0.791327561158
+        0.792743922575
+        0.794160283991
+        0.795576645407
+        0.796993006824
+        0.79840936824
+        0.799825729657
+        0.801242091073
+        0.802658452489
+        0.804074813906
+        0.805491175322
+        0.806907536738
+        0.808323898155
+        0.809740259571
+        0.811156620987
+        0.812572982404
+        0.81398934382
+        0.815405705237
+        0.816822066653
+        0.818238428069
+        0.819654789486
+        0.821071150902
+        0.822487512318
+        0.823903873735
+        0.825320235151
+        0.826736596567
+        0.828152957984
+        0.8295693194
+        0.830985680816
+        0.832402042233
+        0.833818403649
+        0.835234765066
+        0.836651126482
+        0.838067487898
+        0.839483849315
+        0.840900210731
+        0.842316572147
+        0.843732933564
+        0.84514929498
+        0.846565656396
+        0.847982017813
+        0.849398379229
+        0.850814740646
+        0.852231102062
+        0.853647463478
+        0.855063824895
+        0.856480186311
+        0.857896547727
+        0.859312909144
+        0.86072927056
+        0.862145631976
+        0.863561993393
+        0.864978354809
+        0.866394716226
+        0.867811077642
+       &nb