From a14aae842fcc2a06951da34eef512cb9a66a21a9 Mon Sep 17 00:00:00 2001 From: Bernard Laberge Date: Fri, 24 Apr 2026 16:28:18 -0400 Subject: [PATCH] Add DesktopVideoDevice::colorProfile() on macOS Signed-off-by: Bernard Laberge --- src/lib/app/RvCommon/DesktopVideoDevice.cpp | 50 +++++++++++++++++++ .../RvCommon/RvCommon/DesktopVideoDevice.h | 2 +- src/lib/ip/OCIONodes/OCIOIPNode.cpp | 11 +++- src/lib/ip/OCIONodes/OCIONodes/OCIOIPNode.h | 1 + 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/lib/app/RvCommon/DesktopVideoDevice.cpp b/src/lib/app/RvCommon/DesktopVideoDevice.cpp index 2e2740c5c..2448f04a5 100644 --- a/src/lib/app/RvCommon/DesktopVideoDevice.cpp +++ b/src/lib/app/RvCommon/DesktopVideoDevice.cpp @@ -13,6 +13,11 @@ #include #endif +#ifdef PLATFORM_DARWIN +#include +#include +#endif + #include #include #include @@ -916,6 +921,51 @@ namespace Rv } #endif +#ifdef PLATFORM_DARWIN + TwkApp::VideoDevice::ColorProfile DesktopVideoDevice::colorProfile() const + { + // + // Get the display's color sync profile + // + + CGDirectDisplayID displayIDs[20]; + uint32_t displayCount = 0; + CGGetOnlineDisplayList(20, displayIDs, &displayCount); + + if (m_screen < 0 || m_screen >= static_cast(displayCount)) + { + m_colorProfile = ColorProfile(); + return m_colorProfile; + } + + CGDirectDisplayID cgScreen = displayIDs[m_screen]; + + if (ColorSyncProfileRef iccRef = ColorSyncProfileCreateWithDisplayID(cgScreen)) + { + m_colorProfile.type = ICCProfile; + + CFStringRef desc = ColorSyncProfileCopyDescriptionString(iccRef); + CFIndex n = CFStringGetLength(desc); + std::vector buffer(n * 4 + 1); + CFStringGetCString(desc, &buffer.front(), buffer.size(), kCFStringEncodingUTF8); + m_colorProfile.description = &buffer.front(); + + CFURLRef url = ColorSyncProfileGetURL(iccRef, NULL); + CFStringRef urlstr = CFURLGetString(url); + buffer.resize(CFStringGetLength(urlstr) * 4 + 1); + CFStringGetCString(urlstr, &buffer.front(), buffer.size(), kCFStringEncodingUTF8); + + m_colorProfile.url = &buffer.front(); + } + else + { + m_colorProfile = ColorProfile(); + } + + return m_colorProfile; + } +#endif + std::vector DesktopVideoDevice::createDesktopVideoDevices(TwkApp::VideoModule* module, const QTGLVideoDevice* shareDevice) { std::vector devices; diff --git a/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h b/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h index 394804930..d176a45c4 100644 --- a/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h +++ b/src/lib/app/RvCommon/RvCommon/DesktopVideoDevice.h @@ -247,7 +247,7 @@ namespace Rv private: void addDataFormatAtDepth(size_t depth, DesktopStereoMode m); -#ifdef PLATFORM_WINDOWS +#if defined(PLATFORM_WINDOWS) || defined(PLATFORM_DARWIN) virtual ColorProfile colorProfile() const; #endif diff --git a/src/lib/ip/OCIONodes/OCIOIPNode.cpp b/src/lib/ip/OCIONodes/OCIOIPNode.cpp index d42f62d92..06088a229 100644 --- a/src/lib/ip/OCIONodes/OCIOIPNode.cpp +++ b/src/lib/ip/OCIONodes/OCIOIPNode.cpp @@ -231,6 +231,8 @@ namespace IPCore updateContext(); updateFunction(); + + m_initialized = true; } void OCIOIPNode::updateContext() @@ -352,7 +354,10 @@ namespace IPCore boost::hash string_hash; string inName = stringProp("ocio.inColorSpace", m_state->linear); - if (inName.empty()) + // synlinearize/syndisplay build their pipeline from file/URL + // transforms, so an empty input color space is valid for those modes. + const bool needsInColorSpace = ociofunction != "synlinearize" && ociofunction != "syndisplay"; + if (inName.empty() && needsInColorSpace) return; try @@ -436,6 +441,8 @@ namespace IPCore string inTransformURL = stringProp("inTransform.url", ""); if (inTransformURL.empty() && (!m_inTransformData || m_inTransformData->size() == 0)) { + if (!m_initialized) + return; TWK_THROW_EXC_STREAM("Either inTransform.url or inTransform.data property " "needs to be set for synlinearize function"); } @@ -481,6 +488,8 @@ namespace IPCore const string outTransformURL = stringProp("outTransform.url", ""); if (outTransformURL.empty()) { + if (!m_initialized) + return; TWK_THROW_EXC_STREAM("outTransform.url property needs to " "be set for syndisplay function"); } diff --git a/src/lib/ip/OCIONodes/OCIONodes/OCIOIPNode.h b/src/lib/ip/OCIONodes/OCIONodes/OCIOIPNode.h index bf16e53ee..18271da8a 100644 --- a/src/lib/ip/OCIONodes/OCIONodes/OCIOIPNode.h +++ b/src/lib/ip/OCIONodes/OCIONodes/OCIOIPNode.h @@ -72,6 +72,7 @@ namespace IPCore std::vector m_3DLUTs; OCIOState* m_state{nullptr}; bool m_useRawConfig{false}; + bool m_initialized{false}; // synlinearize/syndisplay functions StringProperty* m_inTransformURL{nullptr};