aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kodi.xcodeproj/project.pbxproj16
-rw-r--r--addons/resource.language.en_gb/resources/strings.po183
-rw-r--r--addons/skin.estuary/1080i/VideoOSD.xml9
-rw-r--r--configure.ac30
-rw-r--r--system/settings/settings.xml143
-rw-r--r--system/shaders/output.glsl9
-rw-r--r--xbmc/GUIInfoManager.cpp15
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt2
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp519
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h165
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp115
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h12
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in1
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h10
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp46
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h16
-rw-r--r--xbmc/guiinfo/GUIInfoLabels.h1
-rw-r--r--xbmc/guilib/GUIWindowManager.cpp7
-rw-r--r--xbmc/guilib/WindowIDs.h1
-rw-r--r--xbmc/input/ButtonTranslator.cpp1
-rw-r--r--xbmc/settings/DisplaySettings.cpp64
-rw-r--r--xbmc/settings/DisplaySettings.h6
-rw-r--r--xbmc/settings/SettingConditions.cpp3
-rw-r--r--xbmc/settings/Settings.cpp12
-rw-r--r--xbmc/settings/Settings.h2
-rw-r--r--xbmc/video/dialogs/CMakeLists.txt2
-rw-r--r--xbmc/video/dialogs/GUIDialogCMSSettings.cpp248
-rw-r--r--xbmc/video/dialogs/GUIDialogCMSSettings.h51
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoOSD.cpp1
-rw-r--r--xbmc/video/dialogs/Makefile1
30 files changed, 1677 insertions, 14 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index 75270de200..e733c3f034 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -464,6 +464,10 @@
7CAA469119427AED00008885 /* PosixDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAA468E19427AED00008885 /* PosixDirectory.cpp */; };
7CAA57471C8AF6C20032A326 /* DebugRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */; };
7CAA57481C8AF6C20032A326 /* DebugRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */; };
+ 7CAEF0CE1D0E9E3800B1316C /* ColorManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */; };
+ 7CAEF0CF1D0E9E3800B1316C /* ColorManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */; };
+ 7CAEF0D21D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */; };
+ 7CAEF0D31D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */; };
7CBEBB8412912BA400431822 /* fstrcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 7CBEBB8212912BA300431822 /* fstrcmp.c */; };
7CC30DB116291A5C003E7579 /* MusicThumbLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CC30DAF16291A5C003E7579 /* MusicThumbLoader.cpp */; };
7CC30DC016291C2C003E7579 /* VideoThumbLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CC30DBE16291C2C003E7579 /* VideoThumbLoader.cpp */; };
@@ -3016,6 +3020,10 @@
7CAA468F19427AED00008885 /* PosixDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PosixDirectory.h; sourceTree = "<group>"; };
7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebugRenderer.cpp; sourceTree = "<group>"; };
7CAA57461C8AF6C20032A326 /* DebugRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugRenderer.h; sourceTree = "<group>"; };
+ 7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorManager.cpp; sourceTree = "<group>"; };
+ 7CAEF0CD1D0E9E3800B1316C /* ColorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorManager.h; sourceTree = "<group>"; };
+ 7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogCMSSettings.cpp; sourceTree = "<group>"; };
+ 7CAEF0D11D0E9F0D00B1316C /* GUIDialogCMSSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogCMSSettings.h; sourceTree = "<group>"; };
7CBEBB8212912BA300431822 /* fstrcmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fstrcmp.c; sourceTree = "<group>"; };
7CC30DAF16291A5C003E7579 /* MusicThumbLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicThumbLoader.cpp; sourceTree = "<group>"; };
7CC30DB016291A5C003E7579 /* MusicThumbLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicThumbLoader.h; sourceTree = "<group>"; };
@@ -5985,6 +5993,8 @@
children = (
18B7C8FE12942761009E7A26 /* GUIDialogAudioSubtitleSettings.cpp */,
18B7C8FF12942761009E7A26 /* GUIDialogAudioSubtitleSettings.h */,
+ 7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */,
+ 7CAEF0D11D0E9F0D00B1316C /* GUIDialogCMSSettings.h */,
886328150E07B37200BB3DAB /* GUIDialogFullScreenInfo.cpp */,
886328160E07B37200BB3DAB /* GUIDialogFullScreenInfo.h */,
7C4E6F701829AA9700F1068F /* GUIDialogSubtitles.cpp */,
@@ -8114,6 +8124,8 @@
E38E166B0D25F9FA00618676 /* VideoShaders */,
7CAA204F1079C8160096DE39 /* BaseRenderer.cpp */,
7CAA20501079C8160096DE39 /* BaseRenderer.h */,
+ 7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */,
+ 7CAEF0CD1D0E9E3800B1316C /* ColorManager.h */,
7CAA57461C8AF6C20032A326 /* DebugRenderer.h */,
7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */,
7C921F8F1CD603C600684D0B /* FrameBufferObject.cpp */,
@@ -10539,9 +10551,11 @@
7C8FC6EE1829A4580045153D /* DirectoryProvider.cpp in Sources */,
7C4E6F721829AA9700F1068F /* GUIDialogSubtitles.cpp in Sources */,
7C140989183224B8009F9411 /* ISetting.cpp in Sources */,
+ 7CAEF0D21D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */,
7C14098C183224B8009F9411 /* ISettingControl.cpp in Sources */,
68AE5BDF1C92421800C4D527 /* AddonButtonMap.cpp in Sources */,
7C14098F183224B8009F9411 /* Setting.cpp in Sources */,
+ 7CAEF0CE1D0E9E3800B1316C /* ColorManager.cpp in Sources */,
DF56EF241A798A5E00CAAEFB /* HttpRangeUtils.cpp in Sources */,
7C140992183224B8009F9411 /* SettingCategoryAccess.cpp in Sources */,
7C140995183224B8009F9411 /* SettingConditions.cpp in Sources */,
@@ -11274,6 +11288,7 @@
E49913A6174E5F2100741B6D /* HTTPWebinterfaceAddonsHandler.cpp in Sources */,
E49913A7174E5F2100741B6D /* HTTPWebinterfaceHandler.cpp in Sources */,
DFD7175C1C0A031B0025D964 /* IOSEAGLView.mm in Sources */,
+ 7CAEF0CF1D0E9E3800B1316C /* ColorManager.cpp in Sources */,
E49913A8174E5F2100741B6D /* IHTTPRequestHandler.cpp in Sources */,
3994425C1A8DD8D0006C39E9 /* ProgressJob.cpp in Sources */,
E49913A9174E5F2100741B6D /* NetworkLinux.cpp in Sources */,
@@ -11427,6 +11442,7 @@
E4991438174E604700741B6D /* Atomics.cpp in Sources */,
E4991439174E604700741B6D /* Event.cpp in Sources */,
E499143B174E604700741B6D /* SystemClock.cpp in Sources */,
+ 7CAEF0D31D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */,
E499143C174E604700741B6D /* Thread.cpp in Sources */,
E499143D174E604700741B6D /* Timer.cpp in Sources */,
E499143E174E605900741B6D /* AlarmClock.cpp in Sources */,
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 3cb54266c4..df5eb44a62 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -18502,7 +18502,188 @@ msgctxt "#36552"
msgid "Defines the number of presentation buffers used by the graphics driver. Select 2 if the driver uses double buffering or 3 for triple buffering."
msgstr ""
-#empty strings from id 36553 to 36597
+#: system/settings/settings.xml
+msgctxt "#36560"
+msgid "Colour management"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Colour management" with label #36560
+#: system/settings/settings.xml
+msgctxt "#36561"
+msgid "Reproduce video colours accurately using a display profile or a 3D lookup table."
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36562"
+msgid "Colour management mode"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Colour management mode" with label #36562
+#: system/settings/settings.xml
+msgctxt "#36563"
+msgid "Use a precalculated 3D lookup table for video colour correction, or calculate the transformation for each video from a profile of your display. A precalculated 3D lookup table is preferred as it allows you to take advantage of the advanced features and high precision in ArgyllCMS. Display profile based correction is useful for testing different parameters, or emulating display settings that you don't have a 3D LUT prepared for."
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36564"
+msgid "3D LUT"
+msgstr ""
+
+#. Description of setting "System -> Video output -> 3D LUT" with label #36564
+#: system/settings/settings.xml
+msgctxt "#36565"
+msgid "TODO: 3D LUT filename description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36566"
+msgid "ICC display profile"
+msgstr ""
+
+#. Description of setting "System -> Video output -> ICC display profile" with label #36566
+#: system/settings/settings.xml
+msgctxt "#36567"
+msgid "TODO: ICC display profile filename description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36568"
+msgid "Whitepoint"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Whitepoint" with label #36568
+#: system/settings/settings.xml
+msgctxt "#36569"
+msgid "TODO: Whitepoint selection description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36570"
+msgid "Primaries"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Primaries" with label #36570
+#: system/settings/settings.xml
+msgctxt "#36571"
+msgid "TODO: Primary coordinates description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36572"
+msgid "Gamma mode"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Gamma mode" with label #36572
+#: system/settings/settings.xml
+msgctxt "#36573"
+msgid "TODO: Gamma mode description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36574"
+msgid "Gamma"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Gamma" with label #36574
+#: system/settings/settings.xml
+msgctxt "#36575"
+msgid "TODO: Gamma description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36576"
+msgid "Lookup table size"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Lookup table size" with label #36576
+#: system/settings/settings.xml
+msgctxt "#36577"
+msgid "TODO: Lookup table size description"
+msgstr ""
+
+# Dialog title for 3D LUT file picker
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#36580"
+msgid "3D LUT file"
+msgstr ""
+
+# Dialog title for ICC display profile file picker
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#36581"
+msgid "ICC Profile"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+#. gamma type labels
+msgctxt "#36582"
+msgid "BT.1886"
+msgstr ""
+
+msgctxt "#36583"
+msgid "Input offset"
+msgstr ""
+
+msgctxt "#36584"
+msgid "Output offset"
+msgstr ""
+
+msgctxt "#36585"
+msgid "Absolute"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogCMSSettings.cpp
+#. whitepoint labels
+msgctxt "#36586"
+msgid "D65 (standard)"
+msgstr ""
+
+msgctxt "#36587"
+msgid "D93 (Japanese NTSC)"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogCMSSettings.cpp
+#. primaries labels
+msgctxt "#36588"
+msgid "Automatic"
+msgstr ""
+
+msgctxt "#36589"
+msgid "HDTV (BT.709)"
+msgstr ""
+
+msgctxt "#36590"
+msgid "SDTV (SMPTE C)"
+msgstr ""
+
+msgctxt "#36591"
+msgid "NTSC 1953 (BT.470 M)"
+msgstr ""
+
+msgctxt "#36592"
+msgid "PAL/SECAM 1975 (BT.470 B/G)"
+msgstr ""
+
+msgctxt "#36593"
+msgid "HDTV 1988 (SMPTE 240M)"
+msgstr ""
+
+#: xbmc/video/dialogs/GUIDialogCMSSettings.cpp
+#. 3D LUT size labels
+msgctxt "#36594"
+msgid "16x16x16"
+msgstr ""
+
+msgctxt "#36595"
+msgid "64x64x64"
+msgstr ""
+
+msgctxt "#36596"
+msgid "256x256x256"
+msgstr ""
+
+msgctxt "#36597"
+msgid "%1.2f"
+msgstr ""
#. Description of setting with label #36099 "Dither"
#: system/settings/settings.xml
diff --git a/addons/skin.estuary/1080i/VideoOSD.xml b/addons/skin.estuary/1080i/VideoOSD.xml
index 4bb00929a1..667f513766 100644
--- a/addons/skin.estuary/1080i/VideoOSD.xml
+++ b/addons/skin.estuary/1080i/VideoOSD.xml
@@ -22,7 +22,7 @@
<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
<control type="group">
<top>900</top>
- <visible>!Window.IsVisible(fullscreeninfo) + !Window.IsActive(osdaudiosettings) + !Window.IsActive(osdvideosettings) + !Window.IsActive(PVROSDChannels) + !Window.IsActive(PVROSDGuide)</visible>
+ <visible>!Window.IsVisible(fullscreeninfo) + !Window.IsActive(osdaudiosettings) + !Window.IsActive(osdvideosettings) + !Window.IsActive(osdcmssettings) + !Window.IsActive(PVROSDChannels) + !Window.IsActive(PVROSDGuide)</visible>
<animation effect="fade" end="100" time="200">WindowOpen</animation>
<animation effect="fade" time="200">VisibleChange</animation>
<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
@@ -310,6 +310,13 @@
<label>$LOCALIZE[13395]</label>
<onclick>ActivateWindow(osdvideosettings)</onclick>
</control>
+ <control type="button" id="11105">
+ <width>470</width>
+ <include>DefaultSettingButton</include>
+ <label>$LOCALIZE[36560]</label>
+ <onclick>ActivateWindow(osdcmssettings)</onclick>
+ <visible>System.HasCMS</visible>
+ </control>
<control type="button" id="11103">
<width>470</width>
<include>DefaultSettingButton</include>
diff --git a/configure.ac b/configure.ac
index 7a0d3ec31c..d498f958b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -208,6 +208,9 @@ libusb_disabled="== libusb disabled. Plug and play USB device support will not b
libusb_disabled_udev_found="== libusb disabled. =="
libcec_enabled="== libcec enabled. =="
libcec_disabled="== libcec disabled. CEC adapter support will not be available. =="
+lcms2_enabled="== lcms2 enabled. =="
+lcms2_not_found="== Could not find lcms2. ICC profile support will not be available. =="
+lcms2_disabled="== lcms2 disabled. ICC profile support will not be available. =="
libbluetooth_not_found="== Could not find libbluetooth. Bluetooth support will not be available =="
libbluetooth_enabled="== libbluetooth enabled. =="
libbluetooth_disabled="== libbluetooth disabled. Bluetooth support will not be available. =="
@@ -442,6 +445,12 @@ AC_ARG_ENABLE([libcec],
[use_libcec=$enableval],
[use_libcec=auto])
+AC_ARG_ENABLE([lcms2],
+ [AS_HELP_STRING([--enable-lcms2],
+ [enable lcms2 support (default is auto)])],
+ [use_lcms2=$enableval],
+ [use_lcms2=auto])
+
AC_ARG_ENABLE([libbluetooth],
[AS_HELP_STRING([--enable-libbluetooth],
[enable libbluetooth support (default is auto)])],
@@ -1444,6 +1453,21 @@ else
AC_MSG_NOTICE($libcec_disabled)
fi
+# lcms2
+if test "$use_lcms2" = "auto"; then
+ PKG_CHECK_MODULES([LCMS2],[lcms2],,[use_lcms2="no";AC_MSG_RESULT($lcms2_not_found)])
+elif test "$use_lcms2" = "yes" ; then
+ PKG_CHECK_MODULES([LCMS2],[lcms2],,[use_lcms2="no";AC_MSG_ERROR($lcms2_not_found)])
+else
+ AC_MSG_NOTICE($lcms2_disabled)
+fi
+
+if test "x$use_lcms2" != "xno"; then
+ USE_LCMS2=1;INCLUDES="$INCLUDES $LCMS2_CFLAGS";LIBS="$LIBS $LCMS2_LIBS"
+ AC_DEFINE([HAVE_LCMS2],[1],["Define to 1 if lcms2 is installed"])
+ AC_MSG_NOTICE($lcms2_enabled)
+fi
+
# libbluetooth
USE_LIBBLUETOOTH=0
if test "$use_libbluetooth" = "auto"; then
@@ -2074,6 +2098,12 @@ else
final_message="$final_message\n libcec support:\tNo"
fi
+if test "x$use_lcms2" != "xno"; then
+ final_message="$final_message\n lcms2 support:\tYes"
+else
+ final_message="$final_message\n lcms2 support:\tNo"
+fi
+
if test "x$use_libbluetooth" != "xno"; then
final_message="$final_message\n libbluetooth support:\tYes"
else
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 53a4fe31b5..c9d3c9dbe5 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -1999,6 +1999,149 @@
</dependencies>
<control type="spinner" format="integer" />
</setting>
+ <setting id="videoscreen.cmsenabled" type="boolean" label="36560" help="36561">
+ <requirement>HAS_GL</requirement>
+ <level>3</level>
+ <default>false</default>
+ <control type="toggle" />
+ </setting>
+ <setting id="videoscreen.cmsmode" type="integer" label="36562" help="36563">
+ <requirement>HAS_GL</requirement>
+ <level>3</level>
+ <default>0</default>
+ <constraints>
+ <options>cmsmodes</options>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ </dependencies>
+ <control type="list" format="integer"/>
+ </setting>
+ <setting id="videoscreen.cms3dlut" type="string" label="36564" help="36565">
+ <requirement>
+ <and>
+ <condition>HAS_GL</condition>
+ </and>
+ </requirement>
+ <level>3</level>
+ <default></default>
+ <constraints>
+ <allowempty>true</allowempty>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">0</dependency>
+ </dependencies>
+ <control type="button" format="action" />
+ </setting>
+ <setting id="videoscreen.displayprofile" type="string" label="36566" help="36567">
+ <requirement>
+ <and>
+ <condition>HAS_GL</condition>
+ <condition>HAVE_LCMS2</condition>
+ </and>
+ </requirement>
+ <level>3</level>
+ <default></default>
+ <constraints>
+ <allowempty>true</allowempty>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+ </dependencies>
+ <control type="button" format="action" />
+ </setting>
+ <setting id="videoscreen.cmswhitepoint" type="integer" label="36568" help="36569">
+ <requirement>
+ <and>
+ <condition>HAS_GL</condition>
+ <condition>HAVE_LCMS2</condition>
+ </and>
+ </requirement>
+ <level>3</level>
+ <default>0</default>
+ <constraints>
+ <options>cmswhitepoints</options>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+ </dependencies>
+ <control type="list" format="integer"/>
+ </setting>
+ <setting id="videoscreen.cmsprimaries" type="integer" label="36570" help="36571">
+ <requirement>
+ <and>
+ <condition>HAS_GL</condition>
+ <condition>HAVE_LCMS2</condition>
+ </and>
+ </requirement>
+ <level>3</level>
+ <default>0</default>
+ <constraints>
+ <options>cmsprimaries</options>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+ </dependencies>
+ <control type="list" format="integer"/>
+ </setting>
+ <setting id="videoscreen.cmsgammamode" type="integer" label="36572" help="36573">
+ <requirement>
+ <and>
+ <condition>HAS_GL</condition>
+ <condition>HAVE_LCMS2</condition>
+ </and>
+ </requirement>
+ <level>3</level>
+ <default>0</default>
+ <constraints>
+ <options>cmsgammamodes</options>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+ </dependencies>
+ <control type="list" format="integer"/>
+ </setting>
+ <setting id="videoscreen.cmsgamma" type="integer" label="36574" help="36575">
+ <requirement>
+ <and>
+ <condition>HAS_GL</condition>
+ <condition>HAVE_LCMS2</condition>
+ </and>
+ </requirement>
+ <level>3</level>
+ <default>220</default>
+ <constraints>
+ <minimum>160</minimum>
+ <step>005</step>
+ <maximum>280</maximum>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+ <dependency type="visible" setting="videoscreen.cmsgammamode" operator="!is">0</dependency>
+ </dependencies>
+ <control type="spinner" format="integer" />
+ </setting>
+ <setting id="videoscreen.cmslutsize" type="integer" label="36576" help="36577">
+ <requirement>HAS_GL</requirement>
+ <level>3</level>
+ <default>6</default>
+ <constraints>
+ <minimum>4</minimum>
+ <step>1</step>
+ <maximum>8</maximum>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+ <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+ </dependencies>
+ <control type="spinner" format="integer" />
+ </setting>
</group>
<group id="2" label="14232">
<setting id="videoscreen.stereoscopicmode" type="integer" label="36500" help="36539">
diff --git a/system/shaders/output.glsl b/system/shaders/output.glsl
index c95c9488f2..a0c69c5e94 100644
--- a/system/shaders/output.glsl
+++ b/system/shaders/output.glsl
@@ -3,11 +3,20 @@ uniform sampler2D m_dither;
uniform float m_ditherquant;
uniform vec2 m_dithersize;
#endif
+#if defined(KODI_3DLUT)
+uniform float m_CLUTsize;
+uniform sampler3D m_CLUT;
+#endif
void main()
{
vec4 rgb = process();
+#if defined(KODI_3DLUT)
+ // FIXME: can this be optimized?
+ rgb = texture3D(m_CLUT, (rgb.rgb*(m_CLUTsize-1.0) + 0.5) / m_CLUTsize);
+#endif
+
#if defined(XBMC_FULLRANGE)
#if __VERSION__ <= 120
rgb = (rgb-(16.0/255.0)) * 255.0/219.0;
diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index 7d42106e0e..ba2b1e9217 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -768,6 +768,12 @@ const infomap weather[] = {{ "isfetched", WEATHER_IS_FETCHED },
/// Returns true if ADSP is supported from Kodi
/// \note normally always true
/// }
+/// \table_row3{ <b>`System.HasCMS`</b>,
+/// \anchor System_HasCMS
+/// _boolean_,
+/// Returns true if colour management is supported from Kodi
+/// \note currently only supported for OpenGL
+/// }
/// \table_row3{ <b>`System.HasModalDialog`</b>,
/// \anchor System_HasModalDialog
/// _boolean_,
@@ -1182,7 +1188,8 @@ const infomap system_labels[] = {{ "hasnetwork", SYSTEM_ETHERNET_LINK_ACT
{ "haspvr", SYSTEM_HAS_PVR },
{ "startupwindow", SYSTEM_STARTUP_WINDOW },
{ "stereoscopicmode", SYSTEM_STEREOSCOPIC_MODE },
- { "hasadsp", SYSTEM_HAS_ADSP }};
+ { "hasadsp", SYSTEM_HAS_ADSP },
+ { "hascms", SYSTEM_HAS_CMS }};
/// \page modules__General__List_of_gui_access
/// @{
@@ -6786,6 +6793,12 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
bReturn = true;
else if (condition == SYSTEM_HAS_ADSP)
bReturn = true;
+ else if (condition == SYSTEM_HAS_CMS)
+#ifdef HAS_GL
+ bReturn = true;
+#else
+ bReturn = false;
+#endif
else if (condition == SYSTEM_ISMASTER)
bReturn = CProfilesManager::GetInstance().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && g_passwordManager.bMasterUser;
else if (condition == SYSTEM_ISFULLSCREEN)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
index 4426735c03..3a1eb557c8 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
@@ -2,6 +2,7 @@ enable_language(CXX ASM)
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" )
set(SOURCES BaseRenderer.cpp
+ ColorManager.cpp
OverlayRenderer.cpp
OverlayRendererGUI.cpp
OverlayRendererUtil.cpp
@@ -11,6 +12,7 @@ set(SOURCES BaseRenderer.cpp
DebugRenderer.cpp)
set(HEADERS BaseRenderer.h
+ ColorManager.h
OverlayRenderer.h
OverlayRendererGUI.h
OverlayRendererUtil.h
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp
new file mode 100644
index 0000000000..d38e245559
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2016 Lauri Mylläri
+ * http://kodi.org
+ *
+ * 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, 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <math.h>
+#include <string>
+
+#include "system.h"
+#include "ColorManager.h"
+#include "cores/VideoPlayer/VideoRenderers/RenderFlags.h"
+#include "filesystem/File.h"
+#include "settings/Settings.h"
+#include "utils/log.h"
+#include "utils/TimeUtils.h"
+
+using namespace XFILE;
+
+CColorManager::CColorManager()
+{
+ m_curVideoPrimaries = CMS_PRIMARIES_AUTO;
+ m_curClutSize = 0;
+ m_curCmsToken = 0;
+ m_curCmsMode = 0;
+ m_cur3dlutFile = "";
+ m_curIccProfile = "";
+#if defined(HAVE_LCMS2)
+ m_hProfile = NULL;
+#endif //defined(HAVE_LCMS2)
+}
+
+CColorManager::~CColorManager()
+{
+#if defined(HAVE_LCMS2)
+ if (m_hProfile)
+ {
+ cmsCloseProfile(m_hProfile);
+ m_hProfile = NULL;
+ }
+#endif //defined(HAVE_LCMS2)
+}
+
+bool CColorManager::IsEnabled()
+{
+ //TODO: check that the configuration is valid here (files exist etc)
+
+ return CSettings::GetInstance().GetBool("videoscreen.cmsenabled");
+}
+
+CMS_PRIMARIES videoFlagsToPrimaries(int flags)
+{
+ if (flags & CONF_FLAGS_COLPRI_BT709)
+ return CMS_PRIMARIES_BT709;
+ if (flags & CONF_FLAGS_COLPRI_170M)
+ return CMS_PRIMARIES_170M;
+ if (flags & CONF_FLAGS_COLPRI_BT470M)
+ return CMS_PRIMARIES_BT470M;
+ if (flags & CONF_FLAGS_COLPRI_BT470BG)
+ return CMS_PRIMARIES_BT470BG;
+ if (flags & CONF_FLAGS_COLPRI_240M)
+ return CMS_PRIMARIES_240M;
+ return CMS_PRIMARIES_BT709; // default to bt.709
+}
+
+bool CColorManager::GetVideo3dLut(int videoFlags, int *cmsToken, int *clutSize, uint16_t **clutData)
+{
+ CMS_PRIMARIES videoPrimaries = videoFlagsToPrimaries(videoFlags);
+ CLog::Log(LOGDEBUG, "video primaries: %d\n", (int)videoPrimaries);
+ switch (CSettings::GetInstance().GetInt("videoscreen.cmsmode"))
+ {
+ case CMS_MODE_3DLUT:
+ CLog::Log(LOGDEBUG, "ColorManager: CMS_MODE_3DLUT\n");
+ m_cur3dlutFile = CSettings::GetInstance().GetString("videoscreen.cms3dlut");
+ if (!Load3dLut(m_cur3dlutFile, clutData, clutSize))
+ return false;
+ m_curCmsMode = CMS_MODE_3DLUT;
+ break;
+
+ case CMS_MODE_PROFILE:
+ CLog::Log(LOGDEBUG, "ColorManager: CMS_MODE_PROFILE\n");
+#if defined(HAVE_LCMS2)
+ {
+ bool changed = false;
+ // check if display profile is not loaded, or has changed
+ if (m_curIccProfile != CSettings::GetInstance().GetString("videoscreen.displayprofile"))
+ {
+ changed = true;
+ // free old profile if there is one
+ if (m_hProfile)
+ cmsCloseProfile(m_hProfile);
+ // load profile
+ m_hProfile = LoadIccDisplayProfile(CSettings::GetInstance().GetString("videoscreen.displayprofile"));
+ if (!m_hProfile)
+ return false;
+ // detect blackpoint
+ if (cmsDetectBlackPoint(&m_blackPoint, m_hProfile, INTENT_PERCEPTUAL, 0))
+ {
+ CLog::Log(LOGDEBUG, "black point: %f\n", m_blackPoint.Y);
+ }
+ m_curIccProfile = CSettings::GetInstance().GetString("videoscreen.displayprofile");
+ }
+ // create gamma curve
+ cmsToneCurve* gammaCurve;
+ m_m_curIccGammaMode = (CMS_TRC_TYPE)CSettings::GetInstance().GetInt("videoscreen.cmsgammamode");
+ m_curIccGamma = CSettings::GetInstance().GetInt("videoscreen.cmsgamma");
+ gammaCurve =
+ CreateToneCurve(m_m_curIccGammaMode, m_curIccGamma/100.0f, m_blackPoint);
+
+ // create source profile
+ m_curIccWhitePoint = (CMS_WHITEPOINT)CSettings::GetInstance().GetInt("videoscreen.cmswhitepoint");
+ m_curIccPrimaries = (CMS_PRIMARIES)CSettings::GetInstance().GetInt("videoscreen.cmsprimaries");
+ CLog::Log(LOGDEBUG, "primaries setting: %d\n", (int)m_curIccPrimaries);
+ if (m_curIccPrimaries == CMS_PRIMARIES_AUTO) m_curIccPrimaries = videoPrimaries;
+ CLog::Log(LOGDEBUG, "source profile primaries: %d\n", (int)m_curIccPrimaries);
+ cmsHPROFILE sourceProfile =
+ CreateSourceProfile(m_curIccPrimaries, gammaCurve, m_curIccWhitePoint);
+
+ // link profiles
+ // TODO: intent selection, switch output to 16 bits?
+ cmsSetAdaptationState(0.0);
+ cmsHTRANSFORM deviceLink =
+ cmsCreateTransform(sourceProfile, TYPE_RGB_FLT,
+ m_hProfile, TYPE_RGB_FLT,
+ INTENT_ABSOLUTE_COLORIMETRIC, 0);
+
+ // sample the transformation
+ *clutSize = 1 << CSettings::GetInstance().GetInt("videoscreen.cmslutsize");
+ Create3dLut(deviceLink, clutData, clutSize);
+
+ // free gamma curve, source profile and transformation
+ cmsDeleteTransform(deviceLink);
+ cmsCloseProfile(sourceProfile);
+ cmsFreeToneCurve(gammaCurve);
+ }
+
+ m_curCmsMode = CMS_MODE_PROFILE;
+ break;
+#else //defined(HAVE_LCMS2)
+ return false;
+#endif //defined(HAVE_LCMS2)
+
+ default:
+ CLog::Log(LOGDEBUG, "ColorManager: unknown CMS mode %d\n", CSettings::GetInstance().GetInt("videoscreen.cmsmode"));
+ return false;
+ }
+
+ // set current state
+ m_curVideoPrimaries = videoPrimaries;
+ m_curClutSize = *clutSize;
+ *cmsToken = ++m_curCmsToken;
+ return true;
+}
+
+bool CColorManager::CheckConfiguration(int cmsToken, int flags)
+{
+ if (cmsToken != m_curCmsToken)
+ return false;
+ if (m_curCmsMode != CSettings::GetInstance().GetInt("videoscreen.cmsmode"))
+ return false; // CMS mode has changed
+ switch (m_curCmsMode)
+ {
+ case CMS_MODE_3DLUT:
+ if (m_cur3dlutFile != CSettings::GetInstance().GetString("videoscreen.cms3dlut"))
+ return false; // different 3dlut file selected
+ break;
+ case CMS_MODE_PROFILE:
+#if defined(HAVE_LCMS2)
+ if (m_curIccProfile != CSettings::GetInstance().GetString("videoscreen.displayprofile"))
+ return false; // different ICC profile selected
+ if (m_curIccWhitePoint != CSettings::GetInstance().GetInt("videoscreen.cmswhitepoint"))
+ return false; // whitepoint changed
+ {
+ CMS_PRIMARIES primaries = (CMS_PRIMARIES)CSettings::GetInstance().GetInt("videoscreen.cmsprimaries");
+ if (primaries == CMS_PRIMARIES_AUTO) primaries = videoFlagsToPrimaries(flags);
+ if (m_curIccPrimaries != primaries)
+ return false; // primaries changed
+ }
+ if (m_m_curIccGammaMode != (CMS_TRC_TYPE)CSettings::GetInstance().GetInt("videoscreen.cmsgammamode"))
+ return false; // gamma mode changed
+ if (m_curIccGamma != CSettings::GetInstance().GetInt("videoscreen.cmsgamma"))
+ return false; // effective gamma changed
+ if (m_curClutSize != 1 << CSettings::GetInstance().GetInt("videoscreen.cmslutsize"))
+ return false; // CLUT size changed
+ // TODO: check other parameters
+#else //defined(HAVE_LCMS2)
+ return true;
+#endif //defined(HAVE_LCMS2)
+ break;
+ default:
+ CLog::Log(LOGERROR, "%s: unexpected CMS mode: %d", __FUNCTION__, m_curCmsMode);
+ return false;
+ }
+ return true;
+}
+
+
+
+// madvr 3dlut file format support
+struct H3DLUT
+{
+ char signature[4]; // file signature; must be: '3DLT'
+ uint32_t fileVersion; // file format version number (currently "1")
+ char programName[32]; // name of the program that created the file
+ uint64_t programVersion; // version number of the program that created the file
+ uint32_t inputBitDepth[3]; // input bit depth per component (Y,Cb,Cr or R,G,B)
+ uint32_t inputColorEncoding; // input color encoding standard
+ uint32_t outputBitDepth; // output bit depth for all components (valid values are 8, 16 and 32)
+ uint32_t outputColorEncoding; // output color encoding standard
+ uint32_t parametersFileOffset;// number of bytes between the beginning of the file and array parametersData
+ uint32_t parametersSize; // size in bytes of the array parametersData
+ uint32_t lutFileOffset; // number of bytes between the beginning of the file and array lutData
+ uint32_t lutCompressionMethod;// type of compression used if any (0 = none, ...)
+ uint32_t lutCompressedSize; // size in bytes of the array lutData inside the file, whether compressed or not
+ uint32_t lutUncompressedSize; // true size in bytes of the array lutData when in memory for usage (outside the file)
+ // This header is followed by the char array 'parametersData', of length 'parametersSize',
+ // and by the array 'lutDataxx', of length 'lutCompressedSize'.
+};
+
+bool CColorManager::Probe3dLut(const std::string filename)
+{
+ struct H3DLUT header;
+ CFile lutFile;
+
+ if (!lutFile.Open(filename))
+ {
+ CLog::Log(LOGERROR, "%s: Could not open 3DLUT file: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ if (lutFile.Read(&header, sizeof(header)) < sizeof(header))
+ {
+ CLog::Log(LOGERROR, "%s: Could not read 3DLUT header: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ if ( !(header.signature[0]=='3'
+ && header.signature[1]=='D'
+ && header.signature[2]=='L'
+ && header.signature[3]=='T') )
+ {
+ CLog::Log(LOGERROR, "%s: Not a 3DLUT file: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ if ( header.fileVersion != 1
+ || header.lutCompressionMethod != 0
+ || header.inputColorEncoding != 0
+ || header.outputColorEncoding != 0 )
+ {
+ CLog::Log(LOGERROR, "%s: Unsupported 3DLUT file: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ lutFile.Close();
+ return true;
+}
+
+bool CColorManager::Load3dLut(const std::string filename, uint16_t **CLUT, int *CLUTsize)
+{
+ struct H3DLUT header;
+ CFile lutFile;
+
+ if (!lutFile.Open(filename))
+ {
+ CLog::Log(LOGERROR, "%s: Could not open 3DLUT file: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ if (lutFile.Read(&header, sizeof(header)) < sizeof(header))
+ {
+ CLog::Log(LOGERROR, "%s: Could not read 3DLUT header: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ int rSize = 1 << header.inputBitDepth[0];
+ int gSize = 1 << header.inputBitDepth[1];
+ int bSize = 1 << header.inputBitDepth[2];
+
+ if ( !((rSize == gSize) && (rSize == bSize)) )
+ {
+ CLog::Log(LOGERROR, "%s: Different channel resolutions unsupported: %s", __FUNCTION__, filename.c_str());
+ return false;
+ }
+
+ int lutsamples = rSize * gSize * bSize * 3;
+ *CLUTsize = rSize; // TODO: assumes cube
+ *CLUT = (uint16_t*)malloc(lutsamples * sizeof(uint16_t));
+
+ lutFile.Seek(header.lutFileOffset, SEEK_SET);
+
+ for (int rIndex=0; rIndex<rSize; rIndex++) {
+ for (int gIndex=0; gIndex<gSize; gIndex++) {
+ uint16_t input[bSize*3];
+ lutFile.Read(input, 3*bSize*sizeof(uint16_t));
+ int index = (rIndex + gIndex*rSize)*3;
+ for (int bIndex=0; bIndex<bSize; bIndex++) {
+ (*CLUT)[index+bIndex*rSize*gSize*3+0] = input[bIndex*3+2];
+ (*CLUT)[index+bIndex*rSize*gSize*3+1] = input[bIndex*3+1];
+ (*CLUT)[index+bIndex*rSize*gSize*3+2] = input[bIndex*3+0];
+ }
+ }
+ }
+
+ lutFile.Close();
+
+ return true;
+}
+
+
+
+#if defined(HAVE_LCMS2)
+// ICC profile support
+
+cmsHPROFILE CColorManager::LoadIccDisplayProfile(const std::string filename)
+{
+ cmsHPROFILE hProfile;
+
+ hProfile = cmsOpenProfileFromFile(filename.c_str(), "r");
+ if (!hProfile)
+ {
+ CLog::Log(LOGERROR, "ICC profile not found\n");
+ }
+ return hProfile;
+}
+
+
+cmsToneCurve* CColorManager::CreateToneCurve(CMS_TRC_TYPE gammaType, float gammaValue, cmsCIEXYZ blackPoint)
+{
+ const int tableSize = 1024;
+ cmsFloat32Number gammaTable[tableSize];
+
+ switch (gammaType)
+ {
+ case CMS_TRC_INPUT_OFFSET:
+ // calculate gamma to match effective gamma provided, then fall through to bt.1886
+ {
+ double effectiveGamma = gammaValue;
+ double gammaLow = effectiveGamma; // low limit for infinite contrast ratio
+ double gammaHigh = 3.2; // high limit for 2.4 gamma on 200:1 contrast ratio
+ double gammaGuess = 0.0;
+#define TARGET(gamma) (pow(0.5, (gamma)))
+#define GAIN(bkpt, gamma) (pow(1-pow((bkpt), 1/(gamma)), (gamma)))
+#define LIFT(bkpt, gamma) (pow((bkpt), 1/(gamma)) / (1-pow((bkpt), 1/(gamma))))
+#define HALFPT(bkpt, gamma) (GAIN(bkpt, gamma)*pow(0.5+LIFT(bkpt, gamma), gamma))
+ for (int i=0; i<3; i++)
+ {
+ // calculate 50% output for gammaLow and gammaHigh, compare to target 50% output
+ gammaGuess = gammaLow + (gammaHigh-gammaLow)
+ * ((HALFPT(blackPoint.Y, gammaLow)-TARGET(effectiveGamma))
+ / (HALFPT(blackPoint.Y, gammaLow)-HALFPT(blackPoint.Y, gammaHigh)));
+ if (HALFPT(blackPoint.Y, gammaGuess) < TARGET(effectiveGamma))
+ {
+ // guess is too high
+ // move low limit half way to guess
+ gammaLow = gammaLow + (gammaGuess-gammaLow)/2;
+ // set high limit to guess
+ gammaHigh = gammaGuess;
+ }
+ else
+ {
+ // guess is too low
+ // set low limit to guess
+ gammaLow = gammaGuess;
+ // move high limit half way to guess
+ gammaHigh = gammaHigh + (gammaGuess-gammaLow)/2;
+ }
+ }
+ gammaValue = gammaGuess;
+ CLog::Log(LOGINFO, "calculated technical gamma %0.3f (50%% target %0.4f, output %0.4f)\n",
+ gammaValue,
+ TARGET(effectiveGamma),
+ HALFPT(blackPoint.Y, gammaValue));
+#undef TARGET
+#undef GAIN
+#undef LIFT
+#undef HALFPT
+ }
+ // fall through to bt.1886 with calculated technical gamma
+
+ case CMS_TRC_BT1886:
+ {
+ double bkipow = pow(blackPoint.Y, 1.0/gammaValue);
+ double wtipow = 1.0;
+ double lift = bkipow / (wtipow - bkipow);
+ double gain = pow(wtipow - bkipow, gammaValue);
+ for (int i=0; i<tableSize; i++)
+ {
+ gammaTable[i] = gain * pow(((double) i)/(tableSize-1) + lift, gammaValue);
+ }
+ }
+ break;
+
+ case CMS_TRC_OUTPUT_OFFSET:
+ {
+ double gain = 1-blackPoint.Y;
+ // TODO: here gamma is adjusted to match absolute gamma output at 50%
+ // - is it a good idea or should the provided gamma be kept?
+ double adjustedGamma = log(gain/(gain+pow(2,-gammaValue)-1))/log(2);
+ for (int i=0; i<tableSize; i++)
+ {
+ gammaTable[i] = gain * pow(((double) i)/(tableSize-1), adjustedGamma) + blackPoint.Y;
+ }
+ }
+ break;
+
+ case CMS_TRC_ABSOLUTE:
+ {
+ for (int i=0; i<tableSize; i++)
+ {
+ gammaTable[i] = fmax(blackPoint.Y, pow(((double) i)/(tableSize-1), gammaValue));
+ }
+ }
+ break;
+
+ default:
+ CLog::Log(LOGERROR, "gamma type %d not implemented\n", gammaType);
+ }
+
+ cmsToneCurve* result = cmsBuildTabulatedToneCurveFloat(0,
+ tableSize,
+ gammaTable);
+ return result;
+}
+
+
+cmsHPROFILE CColorManager::CreateSourceProfile(CMS_PRIMARIES primaries, cmsToneCurve *gamma, CMS_WHITEPOINT whitepoint)
+{
+ cmsToneCurve* Gamma3[3];
+ cmsHPROFILE hProfile;
+ cmsCIExyY whiteCoords[] = {
+ { 0.3127, 0.3290, 1.0 }, // D65 as specified in BT.709
+ { 0.2830, 0.2980, 1.0 } // Japanese D93 - is there a definitive source? NHK? ARIB TR-B9?
+ };
+ cmsCIExyYTRIPLE primaryCoords[] = {
+ { 0.640, 0.330, 1.0, // auto setting, these should not be used (BT.709 just in case)
+ 0.300, 0.600, 1.0,
+ 0.150, 0.060, 1.0 },
+ { 0.640, 0.330, 1.0, // BT.709 (HDTV, sRGB)
+ 0.300, 0.600, 1.0,
+ 0.150, 0.060, 1.0 },
+ { 0.630, 0.340, 1.0, // SMPTE 170M (SDTV)
+ 0.310, 0.595, 1.0,
+ 0.155, 0.070, 1.0 },
+ { 0.670, 0.330, 1.0, // BT.470 M (obsolete NTSC 1953)
+ 0.210, 0.710, 1.0,
+ 0.140, 0.080, 1.0 },
+ { 0.640, 0.330, 1.0, // BT.470 B/G (obsolete PAL/SECAM 1975)
+ 0.290, 0.600, 1.0,
+ 0.150, 0.060, 1.0 },
+ { 0.630, 0.340, 1.0, // SMPTE 240M (obsolete HDTV 1988)
+ 0.310, 0.595, 1.0,
+ 0.155, 0.070, 1.0 }
+ };
+
+ Gamma3[0] = Gamma3[1] = Gamma3[2] = gamma;
+ hProfile = cmsCreateRGBProfile(&whiteCoords[whitepoint],
+ &primaryCoords[primaries],
+ Gamma3);
+ return hProfile;
+}
+
+
+bool CColorManager::Create3dLut(cmsHTRANSFORM transform, uint16_t **clutData, int *clutSize)
+{
+ const int lutResolution = *clutSize;
+ int lutsamples = lutResolution * lutResolution * lutResolution * 3;
+ *clutData = (uint16_t*)malloc(lutsamples * sizeof(uint16_t));
+
+ cmsFloat32Number input[3*lutResolution];
+ cmsFloat32Number output[3*lutResolution];
+
+#define clamp(x, l, h) ( ((x) < (l)) ? (l) : ( ((x) > (h)) ? (h) : (x) ) )
+#define videoToPC(x) ( clamp((((x)*255)-16)/219,0,1) )
+#define PCToVideo(x) ( (((x)*219)+16)/255 )
+// #define videoToPC(x) ( x )
+// #define PCToVideo(x) ( x )
+ for (int bIndex=0; bIndex<lutResolution; bIndex++) {
+ for (int gIndex=0; gIndex<lutResolution; gIndex++) {
+ for (int rIndex=0; rIndex<lutResolution; rIndex++) {
+ input[rIndex*3+0] = videoToPC(rIndex / (lutResolution-1.0));
+ input[rIndex*3+1] = videoToPC(gIndex / (lutResolution-1.0));
+ input[rIndex*3+2] = videoToPC(bIndex / (lutResolution-1.0));
+ }
+ int index = (bIndex*lutResolution*lutResolution + gIndex*lutResolution)*3;
+ cmsDoTransform(transform, input, output, lutResolution);
+ for (int i=0; i<lutResolution*3; i++) {
+ (*clutData)[index+i] = PCToVideo(output[i]) * 65535;
+ }
+ }
+ }
+
+ for (int y=0; y<lutResolution; y+=1)
+ {
+ int index = 3*(y*lutResolution*lutResolution + y*lutResolution + y);
+ CLog::Log(LOGDEBUG, " %d (%d): %d %d %d\n",
+ (int)round(y * 255 / (lutResolution-1.0)), y,
+ (int)round((*clutData)[index+0]),
+ (int)round((*clutData)[index+1]),
+ (int)round((*clutData)[index+2]));
+ }
+}
+
+
+#endif //defined(HAVE_LCMS2)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h
new file mode 100644
index 0000000000..edabb5c276
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 Lauri Mylläri
+ * http://kodi.org
+ *
+ * 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, 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#if defined(HAVE_LCMS2)
+#include "lcms2.h"
+#endif
+
+#include <string>
+
+enum CMS_MODE
+{
+ CMS_MODE_3DLUT,
+ CMS_MODE_PROFILE,
+ CMS_MODE_COUNT
+};
+
+enum CMS_WHITEPOINT
+{
+ CMS_WHITEPOINT_D65,
+ CMS_WHITEPOINT_D93,
+ CMS_WHITEPOINT_COUNT
+};
+
+enum CMS_PRIMARIES
+{
+ CMS_PRIMARIES_AUTO,
+ CMS_PRIMARIES_BT709, // HDTV
+ CMS_PRIMARIES_170M, // SDTV
+ CMS_PRIMARIES_BT470M, // old NTSC (1953)
+ CMS_PRIMARIES_BT470BG, // old PAL/SECAM (1975)
+ CMS_PRIMARIES_240M, // old HDTV (1988)
+ CMS_PRIMARIES_COUNT
+};
+
+enum CMS_TRC_TYPE
+{
+ CMS_TRC_BT1886,
+ CMS_TRC_INPUT_OFFSET,
+ CMS_TRC_OUTPUT_OFFSET,
+ CMS_TRC_ABSOLUTE,
+ CMS_TRC_COUNT
+};
+
+class CColorManager
+{
+public:
+ CColorManager();
+ virtual ~CColorManager();
+
+ /*!
+ \brief Check if user has requested color management
+ \return true on enabled, false otherwise
+ */
+ bool IsEnabled();
+
+ /*!
+ \brief Get a 3D LUT for video color correction
+ \param primaries video primaries (see CONF_FLAGS_COLPRI)
+ \param cmsToken pointer to a color manager configuration token
+ \param clutSize pointer to CLUT resolution
+ \param clutData pointer to CLUT data (caller to free memory afterwards)
+ \return true on success, false otherwise
+ */
+ bool GetVideo3dLut(int primaries, int *cmsToken, int *clutSize, uint16_t **clutData);
+
+ /*!
+ \brief Check if a 3D LUT is still valid
+ \param cmsToken pointer to a color manager configuration token
+ \param flags video renderer flags (see CONF_FLAGS_COLPRI)
+ \return true on valid, false if 3D LUT should be reloaded
+ */
+ bool CheckConfiguration(int cmsToken, int flags);
+
+private:
+ /*! \brief Check .3dlut file validity
+ \param filename full path and filename
+ \return true if the file can be loaded, false otherwise
+ */
+ bool Probe3dLut(const std::string filename);
+
+ /*! \brief Load a .3dlut file
+ \param filename full path and filename
+ \param clutSize pointer to CLUT resolution
+ \param clutData pointer to CLUT data
+ \return true on success, false otherwise
+ */
+ bool Load3dLut(const std::string filename, uint16_t **clutData, int *clutSize);
+
+
+#if defined(HAVE_LCMS2)
+ // ProbeIccDisplayProfile
+
+ // ProbeIccDeviceLink (?)
+
+
+ /* \brief Load an ICC display profile
+ \param filename full path and filename
+ \return display profile (cmsHPROFILE)
+ */
+ cmsHPROFILE LoadIccDisplayProfile(const std::string filename);
+
+ /* \brief Load an ICC device link
+ \param filename full path and filename
+ \return device link (cmsHTRANSFORM)
+ */
+ // LoadIccDeviceLink (?)
+
+
+ // create a gamma curve
+ cmsToneCurve* CreateToneCurve(CMS_TRC_TYPE gammaType, float gammaValue, cmsCIEXYZ blackPoint);
+
+ // create a source profile
+ cmsHPROFILE CreateSourceProfile(CMS_PRIMARIES primaries, cmsToneCurve *gamma, CMS_WHITEPOINT whitepoint);
+
+
+ /* \brief Create 3D LUT
+ Samples a cmsHTRANSFORM object to create a 3D LUT of specified resolution
+ \param transform cmsHTRANSFORM object to sample
+ \param resolution size of the 3D LUT to create
+ \param clut pointer to LUT data
+ */
+ bool Create3dLut(cmsHTRANSFORM transform, uint16_t **clutData, int *clutSize);
+
+ // keep current display profile loaded here
+ cmsHPROFILE m_hProfile;
+ cmsCIEXYZ m_blackPoint = { 0, 0, 0 };
+
+ // display parameters (gamma, input/output offset, primaries, whitepoint, intent?)
+ CMS_WHITEPOINT m_curIccWhitePoint;
+ CMS_PRIMARIES m_curIccPrimaries;
+ CMS_TRC_TYPE m_m_curIccGammaMode;
+ int m_curIccGamma; // gamma multiplied by 100
+#endif // defined(HAVE_LCMS2)
+
+ // current configuration:
+ CMS_PRIMARIES m_curVideoPrimaries;
+ int m_curClutSize;
+ int m_curCmsToken;
+ // (compare the following to system settings to see if configuration is still valid)
+ int m_curCmsMode;
+ std::string m_cur3dlutFile;
+ std::string m_curIccProfile;
+
+};
+
+
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
index 976dd36204..5b3636e704 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
@@ -157,6 +157,13 @@ CLinuxRendererGL::CLinuxRendererGL()
m_nonLinStretch = false;
m_nonLinStretchGui = false;
m_pixelRatio = 0.0f;
+
+ m_ColorManager.reset(new CColorManager());
+ m_tCLUTTex = 0;
+ m_CLUT = NULL;
+ m_CLUTsize = 0;
+ m_cmsToken = -1;
+ m_cmsOn = false;
}
CLinuxRendererGL::~CLinuxRendererGL()
@@ -300,6 +307,22 @@ bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsign
}
#endif
+ // load 3DLUT
+ if (m_ColorManager->IsEnabled())
+ {
+ if (!m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags))
+ {
+ CLog::Log(LOGDEBUG, "CMS configuration changed, reload LUT");
+ if (!LoadCLUT())
+ return false;
+ }
+ m_cmsOn = true;
+ }
+ else
+ {
+ m_cmsOn = false;
+ }
+
return true;
}
@@ -714,6 +737,8 @@ void CLinuxRendererGL::UpdateVideoFilter()
bool pixelRatioChanged = (CDisplaySettings::GetInstance().GetPixelRatio() > 1.001f || CDisplaySettings::GetInstance().GetPixelRatio() < 0.999f) !=
(m_pixelRatio > 1.001f || m_pixelRatio < 0.999f);
bool nonLinStretchChanged = false;
+ bool cmsChanged = (m_cmsOn != m_ColorManager->IsEnabled())
+ || (m_cmsOn && !m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags));
if (m_nonLinStretchGui != CDisplaySettings::GetInstance().IsNonLinearStretched() || pixelRatioChanged)
{
m_nonLinStretchGui = CDisplaySettings::GetInstance().IsNonLinearStretched();
@@ -733,7 +758,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
}
}
- if (m_scalingMethodGui == CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod && !nonLinStretchChanged)
+ if (m_scalingMethodGui == CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod && !nonLinStretchChanged && !cmsChanged)
return;
else
m_reloadShaders = 1;
@@ -743,6 +768,23 @@ void CLinuxRendererGL::UpdateVideoFilter()
if (m_nonLinStretch || nonLinStretchChanged)
m_reloadShaders = 1;
+ if (cmsChanged)
+ {
+ if (m_ColorManager->IsEnabled())
+ {
+ if (!m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags))
+ {
+ CLog::Log(LOGDEBUG, "CMS configuration changed, reload LUT");
+ LoadCLUT();
+ }
+ m_cmsOn = true;
+ }
+ else
+ {
+ m_cmsOn = false;
+ }
+ }
+
m_scalingMethodGui = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod;
m_scalingMethod = m_scalingMethodGui;
@@ -822,7 +864,13 @@ void CLinuxRendererGL::UpdateVideoFilter()
}
GLSLOutput *out;
- out = new GLSLOutput(3, m_useDithering, m_ditherDepth, false);
+ out = new GLSLOutput(3,
+ m_useDithering,
+ m_ditherDepth,
+ m_cmsOn ? m_fullRange : false,
+ m_cmsOn ? m_tCLUTTex : 0,
+ m_CLUTsize,
+ m_iFlags);
m_pVideoFilterShader = new ConvolutionFilterShader(m_scalingMethod, m_nonLinStretch, out);
if (!m_pVideoFilterShader->CompileAndLink())
{
@@ -891,11 +939,18 @@ void CLinuxRendererGL::LoadShaders(int field)
// if single pass, create GLSLOutput helper and pass it to YUV2RGB shader
GLSLOutput *out = nullptr;
if (m_renderQuality == RQ_SINGLEPASS)
- out = new GLSLOutput(3, m_useDithering, m_ditherDepth, false);
+ out = new GLSLOutput(3,
+ m_useDithering,
+ m_ditherDepth,
+ m_cmsOn ? m_fullRange : false,
+ m_cmsOn ? m_tCLUTTex : 0,
+ m_CLUTsize,
+ m_iFlags);
m_pYUVShader = new YUV2RGBProgressiveShader(m_textureTarget==GL_TEXTURE_RECTANGLE_ARB, m_iFlags, m_format,
m_nonLinStretch && m_renderQuality == RQ_SINGLEPASS,
out);
- m_pYUVShader->SetConvertFullColorRange(m_fullRange);
+ if (!m_cmsOn)
+ m_pYUVShader->SetConvertFullColorRange(m_fullRange);
CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
@@ -1008,6 +1063,8 @@ void CLinuxRendererGL::UnInit()
DeleteTexture(i);
}
+ DeleteCLUT();
+
// cleanup framebuffer object if it was in use
m_fbo.fbo.Cleanup();
m_bValidated = false;
@@ -2547,4 +2604,54 @@ CRenderInfo CLinuxRendererGL::GetRenderInfo()
return info;
}
+// Color management helpers
+
+bool CLinuxRendererGL::LoadCLUT()
+{
+ DeleteCLUT();
+
+ // load 3DLUT
+ if ( !m_ColorManager->GetVideo3dLut(m_iFlags, &m_cmsToken, &m_CLUTsize, &m_CLUT) )
+ {
+ CLog::Log(LOGERROR, "Error loading the LUT");
+ return false;
+ }
+
+ // create 3DLUT texture
+ CLog::Log(LOGDEBUG, "LinuxRendererGL: creating 3DLUT");
+ glGenTextures(1, &m_tCLUTTex);
+ glActiveTexture(GL_TEXTURE4);
+ if ( m_tCLUTTex <= 0 )
+ {
+ CLog::Log(LOGERROR, "Error creating 3DLUT texture");
+ return false;
+ }
+
+ // bind and set 3DLUT texture parameters
+ glBindTexture(GL_TEXTURE_3D, m_tCLUTTex);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ // load 3DLUT data
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16, m_CLUTsize, m_CLUTsize, m_CLUTsize, 0, GL_RGB, GL_UNSIGNED_SHORT, m_CLUT);
+ free(m_CLUT);
+ glActiveTexture(GL_TEXTURE0);
+ return true;
+}
+
+void CLinuxRendererGL::DeleteCLUT()
+{
+ if (m_tCLUTTex)
+ {
+ CLog::Log(LOGDEBUG, "LinuxRendererGL: deleting 3DLUT");
+ glDeleteTextures(1, &m_tCLUTTex);
+ m_tCLUTTex = 0;
+ }
+}
+
#endif
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
index e92010b5ef..35080389de 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
@@ -34,6 +34,7 @@
#include "RenderFormats.h"
#include "guilib/GraphicContext.h"
#include "BaseRenderer.h"
+#include "ColorManager.h"
#include "threads/Event.h"
@@ -280,6 +281,17 @@ protected:
bool m_nonLinStretch;
bool m_nonLinStretchGui;
float m_pixelRatio;
+
+ // color management
+ std::unique_ptr<CColorManager> m_ColorManager;
+ GLuint m_tCLUTTex;
+ uint16_t *m_CLUT;
+ int m_CLUTsize;
+ int m_cmsToken;
+ bool m_cmsOn;
+
+ bool LoadCLUT();
+ void DeleteCLUT();
};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in b/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in
index c02e4172a4..83547f6cf5 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in
@@ -1,4 +1,5 @@
SRCS = BaseRenderer.cpp
+SRCS += ColorManager.cpp
SRCS += OverlayRenderer.cpp
SRCS += OverlayRendererUtil.cpp
SRCS += OverlayRendererGUI.cpp
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h
index f65d4b2bcf..ac0dfe17e0 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h
@@ -52,11 +52,11 @@
/* defines color primaries */
#define CONF_FLAGS_COLPRI_MASK(a) ((a) & 0xe0)
-#define CONF_FLAGS_COLPRI_BT709 0x20
-#define CONF_FLAGS_COLPRI_BT470M 0x40
-#define CONF_FLAGS_COLPRI_BT470BG 0x60
-#define CONF_FLAGS_COLPRI_170M 0x80
-#define CONF_FLAGS_COLPRI_240M 0xa0
+#define CONF_FLAGS_COLPRI_BT709 0x20 // sRGB, HDTV (ITU-R BT.709)
+#define CONF_FLAGS_COLPRI_BT470M 0x40 // NTSC (1953) (FCC 1953, ITU-R BT.470 System M)
+#define CONF_FLAGS_COLPRI_BT470BG 0x60 // PAL/SECAM (1970) (EBU Tech. 3213, ITU-R BT.470 System B, G)
+#define CONF_FLAGS_COLPRI_170M 0x80 // NTSC (1987) (SMPTE RP 145 "SMPTE C", SMPTE 170M)
+#define CONF_FLAGS_COLPRI_240M 0xa0 // SMPTE-240M
/* defines chroma subsampling sample location */
#define CONF_FLAGS_CHROMA_MASK(a) ((a) & 0x0300)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp
index 72ffa0d44b..4d9f469f67 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp
@@ -28,23 +28,32 @@
using namespace Shaders;
-GLSLOutput::GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange)
+GLSLOutput::GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange, GLuint clutTex, int clutSize, unsigned videoflags)
{
// set member variable initial values
m_1stTexUnit = texunit;
m_uDither = m_1stTexUnit+0;
+ m_uCLUT = m_1stTexUnit+1;
+ m_flags = videoflags;
// textures
m_tDitherTex = 0;
+ m_tCLUTTex = clutTex;
// shader attribute handles
m_hDither = -1;
m_hDitherQuant = -1;
m_hDitherSize = -1;
+ m_hCLUT = -1;
+ m_hCLUTSize = -1;
m_dither = useDithering;
m_ditherDepth = ditherDepth;
m_fullRange = fullrange;
+ // make sure CMS is enabled - this allows us to keep the texture
+ // around to quickly switch between CMS on and off
+ m_3DLUT = clutTex > 0;
+ m_uCLUTSize = clutSize;
}
std::string GLSLOutput::GetDefines()
@@ -54,6 +63,10 @@ std::string GLSLOutput::GetDefines()
defines += "#define XBMC_DITHER\n";
if (m_fullRange)
defines += "#define XBMC_FULLRANGE\n";
+#ifdef HAS_GL
+ if (m_3DLUT)
+ defines += "#define KODI_3DLUT\n";
+#endif //HAS_GL
return defines;
}
@@ -69,6 +82,14 @@ void GLSLOutput::OnCompiledAndLinked(GLuint programHandle)
m_hDitherQuant = glGetUniformLocation(programHandle, "m_ditherquant");
m_hDitherSize = glGetUniformLocation(programHandle, "m_dithersize");
}
+ // 3DLUT
+ if (m_3DLUT)
+ {
+#ifdef HAS_GL
+ m_hCLUT = glGetUniformLocation(programHandle, "m_CLUT");
+ m_hCLUTSize = glGetUniformLocation(programHandle, "m_CLUTsize");
+#endif //HAS_GL
+ }
if (m_dither)
{
@@ -126,6 +147,22 @@ bool GLSLOutput::OnEnabled()
VerifyGLState();
}
+ if (m_3DLUT)
+ {
+#ifdef HAS_GL
+ // set texture units
+ glUniform1i(m_hCLUT, m_uCLUT);
+ glUniform1f(m_hCLUTSize, m_uCLUTSize);
+ VerifyGLState();
+
+ // bind textures
+ glActiveTexture(GL_TEXTURE0 + m_uCLUT);
+ glBindTexture(GL_TEXTURE_3D, m_tCLUTTex);
+ glActiveTexture(GL_TEXTURE0);
+ VerifyGLState();
+#endif //HAS_GL
+ }
+
VerifyGLState();
return true;
}
@@ -138,6 +175,13 @@ void GLSLOutput::OnDisabled()
glActiveTexture(GL_TEXTURE0 + m_uDither);
glDisable(GL_TEXTURE_2D);
}
+ if (m_3DLUT)
+ {
+#ifdef HAS_GL
+ glActiveTexture(GL_TEXTURE0 + m_uCLUT);
+ glDisable(GL_TEXTURE_3D);
+#endif //HAS_GL
+ }
glActiveTexture(GL_TEXTURE0);
VerifyGLState();
}
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h
index 8df84fba54..19d9069e97 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h
@@ -29,7 +29,14 @@ namespace Shaders
{
public:
// take the 1st available texture unit as a parameter
- GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange);
+ GLSLOutput(
+ int texunit,
+ bool useDithering,
+ unsigned int ditherDepth,
+ bool fullrange,
+ GLuint clutTex,
+ int clutSize,
+ unsigned videoflags);
std::string GetDefines();
void OnCompiledAndLinked(GLuint programHandle);
bool OnEnabled();
@@ -42,9 +49,13 @@ namespace Shaders
bool m_dither;
unsigned int m_ditherDepth;
bool m_fullRange;
+ bool m_3DLUT;
+ unsigned m_flags;
// first texture unit available to us
int m_1stTexUnit;
int m_uDither;
+ int m_uCLUT;
+ int m_uCLUTSize;
// defines
@@ -52,8 +63,11 @@ namespace Shaders
GLint m_hDither;
GLint m_hDitherQuant;
GLint m_hDitherSize;
+ GLint m_hCLUT;
+ GLint m_hCLUTSize;
// textures
GLuint m_tDitherTex;
+ GLuint m_tCLUTTex;
};
}
diff --git a/xbmc/guiinfo/GUIInfoLabels.h b/xbmc/guiinfo/GUIInfoLabels.h
index 96edafad9b..b0630efa23 100644
--- a/xbmc/guiinfo/GUIInfoLabels.h
+++ b/xbmc/guiinfo/GUIInfoLabels.h
@@ -435,6 +435,7 @@
#define SYSTEM_PROFILEAUTOLOGIN 1004
#define SYSTEM_HAS_ADSP 1005
+#define SYSTEM_HAS_CMS 1006
#define PVR_CONDITIONS_START 1100
#define PVR_IS_RECORDING (PVR_CONDITIONS_START)
diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp
index 0a952e3484..5835280d07 100644
--- a/xbmc/guilib/GUIWindowManager.cpp
+++ b/xbmc/guilib/GUIWindowManager.cpp
@@ -79,6 +79,9 @@
#include "dialogs/GUIDialogTextViewer.h"
#include "network/GUIDialogNetworkSetup.h"
#include "dialogs/GUIDialogMediaSource.h"
+#ifdef HAS_GL
+#include "video/dialogs/GUIDialogCMSSettings.h"
+#endif
#include "video/dialogs/GUIDialogVideoSettings.h"
#include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
#include "video/dialogs/GUIDialogVideoBookmarks.h"
@@ -213,6 +216,9 @@ void CGUIWindowManager::CreateWindows()
Add(new CGUIDialogSlider);
Add(new CGUIDialogMusicOSD);
Add(new CGUIDialogVisualisationPresetList);
+#ifdef HAS_GL
+ Add(new CGUIDialogCMSSettings);
+#endif
Add(new CGUIDialogVideoSettings);
Add(new CGUIDialogAudioSubtitleSettings);
Add(new CGUIDialogVideoBookmarks);
@@ -326,6 +332,7 @@ bool CGUIWindowManager::DestroyWindows()
Delete(WINDOW_DIALOG_LOCK_SETTINGS);
Delete(WINDOW_DIALOG_NETWORK_SETUP);
Delete(WINDOW_DIALOG_MEDIA_SOURCE);
+ Delete(WINDOW_DIALOG_CMS_OSD_SETTINGS);
Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
diff --git a/xbmc/guilib/WindowIDs.h b/xbmc/guilib/WindowIDs.h
index fcfcc5ddec..b5ab401b10 100644
--- a/xbmc/guilib/WindowIDs.h
+++ b/xbmc/guilib/WindowIDs.h
@@ -100,6 +100,7 @@
#define WINDOW_DIALOG_AUDIO_DSP_MANAGER 10154
#define WINDOW_DIALOG_AUDIO_DSP_OSD_SETTINGS 10155
#define WINDOW_DIALOG_KEYBOARD_TOUCH 10156
+#define WINDOW_DIALOG_CMS_OSD_SETTINGS 10157
#define WINDOW_MUSIC_PLAYLIST 10500
#define WINDOW_MUSIC_NAV 10502
diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp
index 7398fbf95e..b877126a44 100644
--- a/xbmc/input/ButtonTranslator.cpp
+++ b/xbmc/input/ButtonTranslator.cpp
@@ -353,6 +353,7 @@ static const ActionMapping windows[] =
{ "musicosd" , WINDOW_DIALOG_MUSIC_OSD },
{ "addonsettings" , WINDOW_DIALOG_ADDON_SETTINGS },
{ "visualisationpresetlist" , WINDOW_DIALOG_VIS_PRESET_LIST },
+ { "osdcmssettings" , WINDOW_DIALOG_CMS_OSD_SETTINGS },
{ "osdvideosettings" , WINDOW_DIALOG_VIDEO_OSD_SETTINGS },
{ "osdaudiosettings" , WINDOW_DIALOG_AUDIO_OSD_SETTINGS },
{ "audiodspmanager" , WINDOW_DIALOG_AUDIO_DSP_MANAGER },
diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
index 363757d131..c1cca7efdd 100644
--- a/xbmc/settings/DisplaySettings.cpp
+++ b/xbmc/settings/DisplaySettings.cpp
@@ -27,6 +27,8 @@
#include <utility>
#include <vector>
+#include "cores/VideoPlayer/VideoRenderers/ColorManager.h"
+#include "dialogs/GUIDialogFileBrowser.h"
#include "guilib/GraphicContext.h"
#include "guilib/gui3d.h"
#include "guilib/LocalizeStrings.h"
@@ -36,6 +38,7 @@
#include "settings/AdvancedSettings.h"
#include "settings/lib/Setting.h"
#include "settings/Settings.h"
+#include "storage/MediaManager.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
#include "utils/StringUtils.h"
@@ -221,6 +224,34 @@ void CDisplaySettings::Clear()
m_nonLinearStretched = false;
}
+void CDisplaySettings::OnSettingAction(const CSetting *setting)
+{
+ if (setting == NULL)
+ return;
+
+ const std::string &settingId = setting->GetId();
+ if (settingId == "videoscreen.cms3dlut")
+ {
+ std::string path = ((CSettingString*)setting)->GetValue();
+ VECSOURCES shares;
+ g_mediaManager.GetLocalDrives(shares);
+ if (CGUIDialogFileBrowser::ShowAndGetFile(shares, ".3dlut", g_localizeStrings.Get(36580), path))
+ {
+ ((CSettingString*)setting)->SetValue(path);
+ }
+ }
+ else if (settingId == "videoscreen.displayprofile")
+ {
+ std::string path = ((CSettingString*)setting)->GetValue();
+ VECSOURCES shares;
+ g_mediaManager.GetLocalDrives(shares);
+ if (CGUIDialogFileBrowser::ShowAndGetFile(shares, ".icc|.icm", g_localizeStrings.Get(36581), path))
+ {
+ ((CSettingString*)setting)->SetValue(path);
+ }
+ }
+}
+
bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
{
if (setting == NULL)
@@ -767,3 +798,36 @@ void CDisplaySettings::ClearCustomResolutions()
m_resolutions.erase(firstCustom, m_resolutions.end());
}
}
+
+void CDisplaySettings::SettingOptionsCmsModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+ list.push_back(std::make_pair(g_localizeStrings.Get(36580), CMS_MODE_3DLUT));
+#ifdef HAVE_LCMS2
+ list.push_back(std::make_pair(g_localizeStrings.Get(36581), CMS_MODE_PROFILE));
+#endif
+}
+
+void CDisplaySettings::SettingOptionsCmsWhitepointsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+ list.push_back(std::make_pair(g_localizeStrings.Get(36586), CMS_WHITEPOINT_D65));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36587), CMS_WHITEPOINT_D93));
+}
+
+void CDisplaySettings::SettingOptionsCmsPrimariesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+ list.push_back(std::make_pair(g_localizeStrings.Get(36588), CMS_PRIMARIES_AUTO));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36589), CMS_PRIMARIES_BT709));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36590), CMS_PRIMARIES_170M));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36591), CMS_PRIMARIES_BT470M));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36592), CMS_PRIMARIES_BT470BG));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36593), CMS_PRIMARIES_240M));
+}
+
+void CDisplaySettings::SettingOptionsCmsGammaModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+ list.push_back(std::make_pair(g_localizeStrings.Get(36582), CMS_TRC_BT1886));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36583), CMS_TRC_INPUT_OFFSET));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36584), CMS_TRC_OUTPUT_OFFSET));
+ list.push_back(std::make_pair(g_localizeStrings.Get(36585), CMS_TRC_ABSOLUTE));
+}
+
diff --git a/xbmc/settings/DisplaySettings.h b/xbmc/settings/DisplaySettings.h
index 729bd94386..cd0773b96e 100644
--- a/xbmc/settings/DisplaySettings.h
+++ b/xbmc/settings/DisplaySettings.h
@@ -42,6 +42,7 @@ public:
virtual bool Save(TiXmlNode *settings) const override;
virtual void Clear() override;
+ virtual void OnSettingAction(const CSetting *setting);
virtual bool OnSettingChanging(const CSetting *setting) override;
virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) override;
@@ -97,6 +98,11 @@ public:
static void SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
static void SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
static void SettingOptionsMonitorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void *data);
+ static void SettingOptionsCmsModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+ static void SettingOptionsCmsWhitepointsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+ static void SettingOptionsCmsPrimariesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+ static void SettingOptionsCmsGammaModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+
protected:
CDisplaySettings();
diff --git a/xbmc/settings/SettingConditions.cpp b/xbmc/settings/SettingConditions.cpp
index fede2136eb..7870ce0807 100644
--- a/xbmc/settings/SettingConditions.cpp
+++ b/xbmc/settings/SettingConditions.cpp
@@ -326,6 +326,9 @@ void CSettingConditions::Initialize()
m_simpleConditions.insert("has_dx");
m_simpleConditions.insert("hasdxva2");
#endif
+#ifdef HAVE_LCMS2
+ m_simpleConditions.insert("have_lcms2");
+#endif
if (g_application.IsStandAlone())
m_simpleConditions.insert("isstandalone");
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index 1d9e02bbbb..1e877cd6e3 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -341,6 +341,8 @@ const std::string CSettings::SETTING_VIDEOSCREEN_BLANKDISPLAYS = "videoscreen.bl
const std::string CSettings::SETTING_VIDEOSCREEN_STEREOSCOPICMODE = "videoscreen.stereoscopicmode";
const std::string CSettings::SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE = "videoscreen.preferedstereoscopicmode";
const std::string CSettings::SETTING_VIDEOSCREEN_NOOFBUFFERS = "videoscreen.noofbuffers";
+const std::string CSettings::SETTING_VIDEOSCREEN_3DLUT = "videoscreen.cms3dlut";
+const std::string CSettings::SETTING_VIDEOSCREEN_DISPLAYPROFILE = "videoscreen.displayprofile";
const std::string CSettings::SETTING_VIDEOSCREEN_GUICALIBRATION = "videoscreen.guicalibration";
const std::string CSettings::SETTING_VIDEOSCREEN_TESTPATTERN = "videoscreen.testpattern";
const std::string CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE = "videoscreen.limitedrange";
@@ -575,6 +577,10 @@ void CSettings::Uninitialize()
m_settingsManager->UnregisterSettingOptionsFiller("stereoscopicmodes");
m_settingsManager->UnregisterSettingOptionsFiller("preferedstereoscopicviewmodes");
m_settingsManager->UnregisterSettingOptionsFiller("monitors");
+ m_settingsManager->UnregisterSettingOptionsFiller("cmsmodes");
+ m_settingsManager->UnregisterSettingOptionsFiller("cmswhitepoints");
+ m_settingsManager->UnregisterSettingOptionsFiller("cmsprimaries");
+ m_settingsManager->UnregisterSettingOptionsFiller("cmsgammamodes");
m_settingsManager->UnregisterSettingOptionsFiller("videoseeksteps");
m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates");
m_settingsManager->UnregisterSettingOptionsFiller("startupwindows");
@@ -931,6 +937,10 @@ void CSettings::InitializeOptionFillers()
m_settingsManager->RegisterSettingOptionsFiller("stereoscopicmodes", CDisplaySettings::SettingOptionsStereoscopicModesFiller);
m_settingsManager->RegisterSettingOptionsFiller("preferedstereoscopicviewmodes", CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller);
m_settingsManager->RegisterSettingOptionsFiller("monitors", CDisplaySettings::SettingOptionsMonitorsFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("cmsmodes", CDisplaySettings::SettingOptionsCmsModesFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("cmswhitepoints", CDisplaySettings::SettingOptionsCmsWhitepointsFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("cmsprimaries", CDisplaySettings::SettingOptionsCmsPrimariesFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("cmsgammamodes", CDisplaySettings::SettingOptionsCmsGammaModesFiller);
m_settingsManager->RegisterSettingOptionsFiller("videoseeksteps", CSeekHandler::SettingOptionsSeekStepsFiller);
m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller);
m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller);
@@ -1029,6 +1039,8 @@ void CSettings::InitializeISettingCallbacks()
settingSet.insert(CSettings::SETTING_VIDEOSCREEN_SCREENMODE);
settingSet.insert(CSettings::SETTING_VIDEOSCREEN_MONITOR);
settingSet.insert(CSettings::SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE);
+ settingSet.insert(CSettings::SETTING_VIDEOSCREEN_3DLUT);
+ settingSet.insert(CSettings::SETTING_VIDEOSCREEN_DISPLAYPROFILE);
m_settingsManager->RegisterCallback(&CDisplaySettings::GetInstance(), settingSet);
settingSet.clear();
diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h
index f6d1d425bd..c81b347e59 100644
--- a/xbmc/settings/Settings.h
+++ b/xbmc/settings/Settings.h
@@ -298,6 +298,8 @@ public:
static const std::string SETTING_VIDEOSCREEN_STEREOSCOPICMODE;
static const std::string SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE;
static const std::string SETTING_VIDEOSCREEN_NOOFBUFFERS;
+ static const std::string SETTING_VIDEOSCREEN_3DLUT;
+ static const std::string SETTING_VIDEOSCREEN_DISPLAYPROFILE;
static const std::string SETTING_VIDEOSCREEN_GUICALIBRATION;
static const std::string SETTING_VIDEOSCREEN_TESTPATTERN;
static const std::string SETTING_VIDEOSCREEN_LIMITEDRANGE;
diff --git a/xbmc/video/dialogs/CMakeLists.txt b/xbmc/video/dialogs/CMakeLists.txt
index 38d6850581..d0a7df6e24 100644
--- a/xbmc/video/dialogs/CMakeLists.txt
+++ b/xbmc/video/dialogs/CMakeLists.txt
@@ -1,4 +1,5 @@
set(SOURCES GUIDialogAudioSubtitleSettings.cpp
+ GUIDialogCMSSettings.cpp
GUIDialogFullScreenInfo.cpp
GUIDialogSubtitles.cpp
GUIDialogTeletext.cpp
@@ -8,6 +9,7 @@ set(SOURCES GUIDialogAudioSubtitleSettings.cpp
GUIDialogVideoSettings.cpp)
set(HEADERS GUIDialogAudioSubtitleSettings.h
+ GUIDialogCMSSettings.h
GUIDialogFullScreenInfo.h
GUIDialogSubtitles.h
GUIDialogTeletext.h
diff --git a/xbmc/video/dialogs/GUIDialogCMSSettings.cpp b/xbmc/video/dialogs/GUIDialogCMSSettings.cpp
new file mode 100644
index 0000000000..64812c57f8
--- /dev/null
+++ b/xbmc/video/dialogs/GUIDialogCMSSettings.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2005-2016 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, 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 Kodi; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "system.h"
+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
+ #include "config.h"
+#endif
+
+#ifdef HAS_GL
+
+#include "cores/VideoPlayer/VideoRenderers/ColorManager.h"
+#include "FileItem.h"
+#include "GUIDialogCMSSettings.h"
+#include "GUIPassword.h"
+#include "addons/Skin.h"
+#include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "filesystem/Directory.h"
+#include "filesystem/File.h"
+#include "guilib/GUIWindowManager.h"
+#include "profiles/ProfilesManager.h"
+#include "settings/Settings.h"
+#include "settings/lib/Setting.h"
+#include "settings/lib/SettingsManager.h"
+#include "utils/log.h"
+#include "utils/URIUtils.h"
+#include "video/VideoDatabase.h"
+#include "utils/Variant.h"
+
+#include <vector>
+
+#define SETTING_VIDEO_CMSENABLE "videoscreen.cmsenabled"
+#define SETTING_VIDEO_CMSMODE "videoscreen.cmsmode"
+#define SETTING_VIDEO_CMS3DLUT "videoscreen.cms3dlut"
+#define SETTING_VIDEO_CMSWHITEPOINT "videoscreen.cmswhitepoint"
+#define SETTING_VIDEO_CMSPRIMARIES "videoscreen.cmsprimaries"
+#define SETTING_VIDEO_CMSGAMMAMODE "videoscreen.cmsgammamode"
+#define SETTING_VIDEO_CMSGAMMA "videoscreen.cmsgamma"
+#define SETTING_VIDEO_CMSLUTSIZE "videoscreen.cmslutsize"
+
+CGUIDialogCMSSettings::CGUIDialogCMSSettings()
+ : CGUIDialogSettingsManualBase(WINDOW_DIALOG_CMS_OSD_SETTINGS, "DialogSettings.xml")
+{ }
+
+CGUIDialogCMSSettings::~CGUIDialogCMSSettings()
+{ }
+
+void CGUIDialogCMSSettings::SetupView()
+{
+ CGUIDialogSettingsManualBase::SetupView();
+
+ SetHeading(36560);
+ SET_CONTROL_HIDDEN(CONTROL_SETTINGS_OKAY_BUTTON);
+ SET_CONTROL_HIDDEN(CONTROL_SETTINGS_CUSTOM_BUTTON);
+ SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON, 15067);
+}
+
+void CGUIDialogCMSSettings::InitializeSettings()
+{
+ CGUIDialogSettingsManualBase::InitializeSettings();
+
+ CSettingCategory *category = AddCategory("cms", -1);
+ if (category == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogCMSSettings: unable to setup settings");
+ return;
+ }
+
+ // get all necessary setting groups
+ CSettingGroup *groupColorManagement = AddGroup(category);
+ if (groupColorManagement == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogCMSSettings: unable to setup settings");
+ return;
+ }
+
+ bool usePopup = g_SkinInfo->HasSkinFile("DialogSlider.xml");
+
+ StaticIntegerSettingOptions entries;
+
+ // create "depsCmsEnabled" for settings depending on CMS being enabled
+ CSettingDependency dependencyCmsEnabled(SettingDependencyTypeEnable, m_settingsManager);
+ dependencyCmsEnabled.Or()
+ ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSENABLE, "true", SettingDependencyOperatorEquals, false, m_settingsManager)));
+ SettingDependencies depsCmsEnabled;
+ depsCmsEnabled.push_back(dependencyCmsEnabled);
+
+ // create "depsCms3dlut" for 3dlut settings
+ CSettingDependency dependencyCms3dlut(SettingDependencyTypeVisible, m_settingsManager);
+ dependencyCms3dlut.And()
+ ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSMODE, std::to_string(CMS_MODE_3DLUT), SettingDependencyOperatorEquals, false, m_settingsManager)));
+ SettingDependencies depsCms3dlut;
+ depsCms3dlut.push_back(dependencyCmsEnabled);
+ depsCms3dlut.push_back(dependencyCms3dlut);
+
+ // create "depsCmsIcc" for display settings with icc profile
+ CSettingDependency dependencyCmsIcc(SettingDependencyTypeVisible, m_settingsManager);
+ dependencyCmsIcc.And()
+ ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSMODE, std::to_string(CMS_MODE_PROFILE), SettingDependencyOperatorEquals, false, m_settingsManager)));
+ SettingDependencies depsCmsIcc;
+ depsCmsIcc.push_back(dependencyCmsEnabled);
+ depsCmsIcc.push_back(dependencyCmsIcc);
+
+ // create "depsCmsGamma" for effective gamma adjustment (not available with bt.1886)
+ CSettingDependency dependencyCmsGamma(SettingDependencyTypeVisible, m_settingsManager);
+ dependencyCmsGamma.And()
+ ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSGAMMAMODE, std::to_string(CMS_TRC_BT1886), SettingDependencyOperatorEquals, true, m_settingsManager)));
+ SettingDependencies depsCmsGamma;
+ depsCmsGamma.push_back(dependencyCmsEnabled);
+ depsCmsGamma.push_back(dependencyCmsIcc);
+ depsCmsGamma.push_back(dependencyCmsGamma);
+
+ // color management settings
+ AddToggle(groupColorManagement, SETTING_VIDEO_CMSENABLE, 36560, 0, CSettings::GetInstance().GetBool(SETTING_VIDEO_CMSENABLE));
+
+ int currentMode = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSMODE);
+ entries.clear();
+ // entries.push_back(std::make_pair(16039, CMS_MODE_OFF)); // FIXME: get from CMS class
+ entries.push_back(std::make_pair(36580, CMS_MODE_3DLUT));
+#ifdef HAVE_LCMS2
+ entries.push_back(std::make_pair(36581, CMS_MODE_PROFILE));
+#endif
+ CSettingInt *settingCmsMode = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSMODE, 36562, 0, currentMode, entries);
+ settingCmsMode->SetDependencies(depsCmsEnabled);
+
+ std::string current3dLUT = CSettings::GetInstance().GetString(SETTING_VIDEO_CMS3DLUT);
+ CSettingString *settingCms3dlut = AddList(groupColorManagement, SETTING_VIDEO_CMS3DLUT, 36564, 0, current3dLUT, Cms3dLutsFiller, 36564);
+ settingCms3dlut->SetDependencies(depsCms3dlut);
+
+ // display settings
+ int currentWhitepoint = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSWHITEPOINT);
+ entries.clear();
+ entries.push_back(std::make_pair(36586, CMS_WHITEPOINT_D65));
+ entries.push_back(std::make_pair(36587, CMS_WHITEPOINT_D93));
+ CSettingInt *settingCmsWhitepoint = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSWHITEPOINT, 36568, 0, currentWhitepoint, entries);
+ settingCmsWhitepoint->SetDependencies(depsCmsIcc);
+
+ int currentPrimaries = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSPRIMARIES);
+ entries.clear();
+ entries.push_back(std::make_pair(36588, CMS_PRIMARIES_AUTO));
+ entries.push_back(std::make_pair(36589, CMS_PRIMARIES_BT709));
+ entries.push_back(std::make_pair(36590, CMS_PRIMARIES_170M));
+ entries.push_back(std::make_pair(36591, CMS_PRIMARIES_BT470M));
+ entries.push_back(std::make_pair(36592, CMS_PRIMARIES_BT470BG));
+ entries.push_back(std::make_pair(36593, CMS_PRIMARIES_240M));
+ CSettingInt *settingCmsPrimaries = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSPRIMARIES, 36570, 0, currentPrimaries, entries);
+ settingCmsPrimaries->SetDependencies(depsCmsIcc);
+
+ int currentGammaMode = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSGAMMAMODE);
+ entries.clear();
+ entries.push_back(std::make_pair(36582, CMS_TRC_BT1886));
+ entries.push_back(std::make_pair(36583, CMS_TRC_INPUT_OFFSET));
+ entries.push_back(std::make_pair(36584, CMS_TRC_OUTPUT_OFFSET));
+ entries.push_back(std::make_pair(36585, CMS_TRC_ABSOLUTE));
+ CSettingInt *settingCmsGammaMode = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSGAMMAMODE, 36572, 0, currentGammaMode, entries);
+ settingCmsGammaMode->SetDependencies(depsCmsIcc);
+
+ float currentGamma = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSGAMMA)/100.0f;
+ if (currentGamma == 0.0) currentGamma = 2.20;
+ CSettingNumber *settingCmsGamma = AddSlider(groupColorManagement, SETTING_VIDEO_CMSGAMMA, 36574, 0, currentGamma, 36597, 1.6, 0.05, 2.8, 36574, usePopup);
+ settingCmsGamma->SetDependencies(depsCmsGamma);
+
+ int currentLutSize = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSLUTSIZE);
+ entries.clear();
+ entries.push_back(std::make_pair(36594, 4));
+ entries.push_back(std::make_pair(36595, 6));
+ entries.push_back(std::make_pair(36596, 8));
+ CSettingInt *settingCmsLutSize = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSLUTSIZE, 36576, 0, currentLutSize, entries);
+ settingCmsLutSize->SetDependencies(depsCmsIcc);
+}
+
+void CGUIDialogCMSSettings::OnSettingChanged(const CSetting *setting)
+{
+ if (setting == NULL)
+ return;
+
+ CGUIDialogSettingsManualBase::OnSettingChanged(setting);
+
+ const std::string &settingId = setting->GetId();
+ if (settingId == SETTING_VIDEO_CMSENABLE)
+ CSettings::GetInstance().SetBool(SETTING_VIDEO_CMSENABLE, (static_cast<const CSettingBool*>(setting)->GetValue()));
+ else if (settingId == SETTING_VIDEO_CMSMODE)
+ CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSMODE, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+ else if (settingId == SETTING_VIDEO_CMS3DLUT)
+ CSettings::GetInstance().SetString(SETTING_VIDEO_CMS3DLUT, static_cast<std::string>(static_cast<const CSettingString*>(setting)->GetValue()));
+ else if (settingId == SETTING_VIDEO_CMSWHITEPOINT)
+ CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSWHITEPOINT, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+ else if (settingId == SETTING_VIDEO_CMSPRIMARIES)
+ CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSPRIMARIES, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+ else if (settingId == SETTING_VIDEO_CMSGAMMAMODE)
+ CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSGAMMAMODE, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+ else if (settingId == SETTING_VIDEO_CMSGAMMA)
+ CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSGAMMA, static_cast<float>(static_cast<const CSettingNumber*>(setting)->GetValue())*100);
+ else if (settingId == SETTING_VIDEO_CMSLUTSIZE)
+ CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSLUTSIZE, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+}
+
+bool CGUIDialogCMSSettings::OnBack(int actionID)
+{
+ Save();
+ return CGUIDialogSettingsBase::OnBack(actionID);
+}
+
+void CGUIDialogCMSSettings::Save()
+{
+ CLog::Log(LOGINFO, "CGUIDialogCMSSettings: Save() called");
+ CSettings::GetInstance().Save();
+}
+
+void CGUIDialogCMSSettings::Cms3dLutsFiller(
+ const CSetting *setting,
+ std::vector< std::pair<std::string, std::string> > &list,
+ std::string &current,
+ void *data)
+{
+ // get 3dLut directory from settings
+ CFileItemList items;
+
+ // list .3dlut files
+ std::string current3dlut = CSettings::GetInstance().GetString(SETTING_VIDEO_CMS3DLUT);
+ if (!current3dlut.empty())
+ current3dlut = URIUtils::GetDirectory(current3dlut);
+ XFILE::CDirectory::GetDirectory(current3dlut, items, ".3dlut");
+
+ for (int i = 0; i < items.Size(); i++)
+ {
+ list.push_back(make_pair(items[i]->GetLabel(), items[i]->GetPath()));
+ }
+}
+
+#endif //HAS_GL
diff --git a/xbmc/video/dialogs/GUIDialogCMSSettings.h b/xbmc/video/dialogs/GUIDialogCMSSettings.h
new file mode 100644
index 0000000000..ebd6c6e24d
--- /dev/null
+++ b/xbmc/video/dialogs/GUIDialogCMSSettings.h
@@ -0,0 +1,51 @@
+#pragma once
+
+/*
+ * Copyright (C) 2005-2014 Team XBMC
+ * http://xbmc.org
+ *
+ * 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, 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "settings/dialogs/GUIDialogSettingsManualBase.h"
+
+class CGUIDialogCMSSettings : public CGUIDialogSettingsManualBase
+{
+public:
+ CGUIDialogCMSSettings();
+ virtual ~CGUIDialogCMSSettings();
+
+protected:
+ // implementations of ISettingCallback
+ virtual void OnSettingChanged(const CSetting *setting) override;
+
+ // specialization of CGUIDialogSettingsBase
+ virtual bool AllowResettingSettings() const override { return false; }
+ virtual bool OnBack(int actionID) override;
+ virtual void Save() override;
+ virtual void SetupView() override;
+
+ // specialization of CGUIDialogSettingsManualBase
+ virtual void InitializeSettings() override;
+
+private:
+ bool m_viewModeChanged;
+ static void Cms3dLutsFiller(
+ const CSetting *setting,
+ std::vector< std::pair<std::string, std::string> > &list,
+ std::string &current,
+ void *data);
+};
diff --git a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp
index c1e99cfc12..e498e1fd47 100644
--- a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp
@@ -46,6 +46,7 @@ void CGUIDialogVideoOSD::FrameMove()
|| g_windowManager.IsWindowActive(WINDOW_DIALOG_AUDIO_OSD_SETTINGS)
|| g_windowManager.IsWindowActive(WINDOW_DIALOG_AUDIO_DSP_OSD_SETTINGS)
|| g_windowManager.IsWindowActive(WINDOW_DIALOG_VIDEO_OSD_SETTINGS)
+ || g_windowManager.IsWindowActive(WINDOW_DIALOG_CMS_OSD_SETTINGS)
|| g_windowManager.IsWindowActive(WINDOW_DIALOG_VIDEO_BOOKMARKS)
|| g_windowManager.IsWindowActive(WINDOW_DIALOG_PVR_OSD_CHANNELS)
|| g_windowManager.IsWindowActive(WINDOW_DIALOG_PVR_OSD_GUIDE)
diff --git a/xbmc/video/dialogs/Makefile b/xbmc/video/dialogs/Makefile
index 0480a6d859..fd27b660ec 100644
--- a/xbmc/video/dialogs/Makefile
+++ b/xbmc/video/dialogs/Makefile
@@ -1,4 +1,5 @@
SRCS=GUIDialogAudioSubtitleSettings.cpp \
+ GUIDialogCMSSettings.cpp \
GUIDialogFullScreenInfo.cpp \
GUIDialogSubtitles.cpp \
GUIDialogTeletext.cpp \