diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index b4430ee48fd..8b290570b2a 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -117,6 +117,28 @@ class RENDER_PT_color_management_working_space(RenderButtonsPanel, Panel): col.prop(scene.sequencer_colorspace_settings, "name", text="Sequencer") +class RENDER_PT_color_management_advanced(RenderButtonsPanel, Panel): + bl_label = "Advanced" + bl_parent_id = "RENDER_PT_color_management" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = { + 'BLENDER_RENDER', + 'BLENDER_EEVEE', + 'BLENDER_WORKBENCH', + } + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + scene = context.scene + + col = layout.column() + col.active = scene.view_settings.support_emulation + col.prop(scene.display_settings, "emulation") + + class RENDER_PT_color_management_curves(RenderButtonsPanel, Panel): bl_label = "Curves" bl_parent_id = "RENDER_PT_color_management" @@ -1139,10 +1161,11 @@ classes = ( RENDER_PT_opengl_film, RENDER_PT_hydra_debug, RENDER_PT_color_management, - RENDER_PT_color_management_working_space, RENDER_PT_color_management_curves, RENDER_PT_color_management_white_balance_presets, RENDER_PT_color_management_white_balance, + RENDER_PT_color_management_working_space, + RENDER_PT_color_management_advanced, ) if __name__ == "__main__": # only for live edit. diff --git a/source/blender/blenkernel/intern/colortools.cc b/source/blender/blenkernel/intern/colortools.cc index 0eecb9a53fe..e2854fd1653 100644 --- a/source/blender/blenkernel/intern/colortools.cc +++ b/source/blender/blenkernel/intern/colortools.cc @@ -1881,12 +1881,14 @@ void BKE_color_managed_display_settings_init(ColorManagedDisplaySettings *settin const char *display_name = IMB_colormanagement_display_get_default_name(); STRNCPY_UTF8(settings->display_device, display_name); + settings->emulation = COLORMANAGE_DISPLAY_EMULATION_AUTO; } void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_settings, const ColorManagedDisplaySettings *settings) { STRNCPY_UTF8(new_settings->display_device, settings->display_device); + new_settings->emulation = settings->emulation; } void BKE_color_managed_view_settings_init(ColorManagedViewSettings *view_settings, diff --git a/source/blender/gpu/vulkan/vk_device.hh b/source/blender/gpu/vulkan/vk_device.hh index f865ed9933f..64268f47cc0 100644 --- a/source/blender/gpu/vulkan/vk_device.hh +++ b/source/blender/gpu/vulkan/vk_device.hh @@ -458,7 +458,8 @@ class VKDevice : public NonCopyable { Shader *vk_backbuffer_blit_sh_get() { if (vk_backbuffer_blit_sh_ == nullptr) { -/* See display_as_extended_srgb in libocio_display_processor.cc for details on this choice. */ + /* See #system_extended_srgb_transfer_function in libocio_display_processor.cc for + * details on this choice. */ #if defined(_WIN32) || defined(__APPLE__) vk_backbuffer_blit_sh_ = GPU_shader_create_from_info_name("vk_backbuffer_blit"); #else diff --git a/source/blender/imbuf/IMB_colormanagement.hh b/source/blender/imbuf/IMB_colormanagement.hh index b0e6fefb660..d20fae94b61 100644 --- a/source/blender/imbuf/IMB_colormanagement.hh +++ b/source/blender/imbuf/IMB_colormanagement.hh @@ -363,6 +363,8 @@ bool IMB_colormanagement_display_is_hdr(const ColorManagedDisplaySettings *displ const char *view_name); bool IMB_colormanagement_display_is_wide_gamut(const ColorManagedDisplaySettings *display_settings, const char *view_name); +bool IMB_colormanagement_display_support_emulation( + const ColorManagedDisplaySettings *display_settings, const char *view_name); /** \} */ diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index b3544ddce76..6aaf98b379a 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -780,6 +780,18 @@ void IMB_colormanagement_display_settings_from_ctx( } } +static bool get_display_emulation(const ColorManagedDisplaySettings &display_settings) +{ + switch (display_settings.emulation) { + case COLORMANAGE_DISPLAY_EMULATION_OFF: + return false; + case COLORMANAGE_DISPLAY_EMULATION_AUTO: + return true; + } + + return true; +} + static std::shared_ptr get_display_buffer_processor( const ColorManagedDisplaySettings &display_settings, const char *look, @@ -807,7 +819,9 @@ static std::shared_ptr get_display_buffer_processor( display_parameters.use_hdr_buffer = GPU_hdr_support(); display_parameters.use_hdr_display = IMB_colormanagement_display_is_hdr(&display_settings, view_transform); - display_parameters.use_display_emulation = target == DISPLAY_SPACE_DRAW; + display_parameters.use_display_emulation = (target == DISPLAY_SPACE_DRAW) ? + get_display_emulation(display_settings) : + false; return g_config->get_display_cpu_processor(display_parameters); } @@ -3056,6 +3070,17 @@ bool IMB_colormanagement_display_is_wide_gamut(const ColorManagedDisplaySettings return (view) ? view->gamut() != ocio::Gamut::Rec709 : false; } +bool IMB_colormanagement_display_support_emulation( + const ColorManagedDisplaySettings *display_settings, const char *view_name) +{ + const ocio::Display *display = g_config->get_display_by_name(display_settings->display_device); + if (display == nullptr) { + return false; + } + const ocio::View *view = display->get_view_by_name(view_name); + return (view) ? view->support_emulation() : false; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -4432,7 +4457,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space( display_parameters.use_hdr_buffer = GPU_hdr_support(); display_parameters.use_hdr_display = IMB_colormanagement_display_is_hdr( display_settings, display_parameters.view.c_str()); - display_parameters.use_display_emulation = true; + display_parameters.use_display_emulation = get_display_emulation(*display_settings); /* Bind shader. Internally GPU shaders are created and cached on demand. */ global_gpu_state.gpu_shader_bound = g_config->get_gpu_shader_binder().display_bind( diff --git a/source/blender/imbuf/opencolorio/OCIO_config.hh b/source/blender/imbuf/opencolorio/OCIO_config.hh index ac6c4462132..626bb83dd0f 100644 --- a/source/blender/imbuf/opencolorio/OCIO_config.hh +++ b/source/blender/imbuf/opencolorio/OCIO_config.hh @@ -9,7 +9,6 @@ #include "BLI_math_matrix_types.hh" #include "BLI_math_vector_types.hh" #include "BLI_string_ref.hh" -#include "DNA_windowmanager_types.h" namespace blender::ocio { diff --git a/source/blender/imbuf/opencolorio/OCIO_view.hh b/source/blender/imbuf/opencolorio/OCIO_view.hh index e1673fccf29..c322f081a01 100644 --- a/source/blender/imbuf/opencolorio/OCIO_view.hh +++ b/source/blender/imbuf/opencolorio/OCIO_view.hh @@ -55,6 +55,11 @@ class View { */ virtual bool is_hdr() const = 0; + /** + * Does this view transform support display emulation? + */ + virtual bool support_emulation() const = 0; + /** * Gamut of the display colorspace. */ diff --git a/source/blender/imbuf/opencolorio/intern/fallback/fallback_default_view.hh b/source/blender/imbuf/opencolorio/intern/fallback/fallback_default_view.hh index 0baa32ed466..130c418cb7c 100644 --- a/source/blender/imbuf/opencolorio/intern/fallback/fallback_default_view.hh +++ b/source/blender/imbuf/opencolorio/intern/fallback/fallback_default_view.hh @@ -36,6 +36,11 @@ class FallbackDefaultView : public View { return false; } + bool support_emulation() const override + { + return false; + } + Gamut gamut() const override { return Gamut::Rec709; diff --git a/source/blender/imbuf/opencolorio/intern/libocio/libocio_display.cc b/source/blender/imbuf/opencolorio/intern/libocio/libocio_display.cc index 9b46d2826e2..aaa59f544f0 100644 --- a/source/blender/imbuf/opencolorio/intern/libocio/libocio_display.cc +++ b/source/blender/imbuf/opencolorio/intern/libocio/libocio_display.cc @@ -3,6 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "libocio_display.hh" +#include "OCIO_display.hh" #if defined(WITH_OPENCOLORIO) @@ -73,6 +74,9 @@ LibOCIODisplay::LibOCIODisplay(const int index, const LibOCIOConfig &config) : c ocio_fallback_display_colorspace.reset(); } + bool support_emulation = config.get_color_space(OCIO_NAMESPACE::ROLE_INTERCHANGE_DISPLAY) != + nullptr; + views_.reserve(num_views); for (const int view_index : IndexRange(num_views)) { const char *view_name = ocio_config->getView(name_.c_str(), view_index); @@ -114,6 +118,11 @@ LibOCIODisplay::LibOCIODisplay(const int index, const LibOCIOConfig &config) : c is_hdr_ |= view_is_hdr; } + /* Detect if display emulation is supported. */ + bool view_support_emulation = support_emulation && ocio_display_colorspace && + ocio_display_colorspace->getReferenceSpaceType() == + OCIO_NAMESPACE::REFERENCE_SPACE_DISPLAY; + /* Detect gamut and transfer function through interop ID. When unknown, things * should still work correctly but may miss optimizations. */ Gamut gamut = Gamut::Unknown; @@ -179,6 +188,7 @@ LibOCIODisplay::LibOCIODisplay(const int index, const LibOCIOConfig &config) : c view_name, view_description, view_is_hdr, + view_support_emulation, gamut, transfer_function, display_colorspace); diff --git a/source/blender/imbuf/opencolorio/intern/libocio/libocio_view.hh b/source/blender/imbuf/opencolorio/intern/libocio/libocio_view.hh index c71ec05c947..7944fc667d9 100644 --- a/source/blender/imbuf/opencolorio/intern/libocio/libocio_view.hh +++ b/source/blender/imbuf/opencolorio/intern/libocio/libocio_view.hh @@ -20,6 +20,7 @@ class LibOCIOView : public View { StringRefNull name_; StringRefNull description_; bool is_hdr_ = false; + bool support_emulation_ = false; Gamut gamut_ = Gamut::Unknown; TransferFunction transfer_function_ = TransferFunction::Unknown; const LibOCIOColorSpace *display_colorspace_ = nullptr; @@ -29,12 +30,14 @@ class LibOCIOView : public View { const StringRefNull name, const StringRefNull description, const bool is_hdr, + const bool support_emulation, const Gamut gamut, const TransferFunction transfer_function, const LibOCIOColorSpace *display_colorspace) : name_(name), description_(description), is_hdr_(is_hdr), + support_emulation_(support_emulation), gamut_(gamut), transfer_function_(transfer_function), display_colorspace_(display_colorspace) @@ -57,6 +60,11 @@ class LibOCIOView : public View { return is_hdr_; } + bool support_emulation() const override + { + return support_emulation_; + } + Gamut gamut() const override { return gamut_; diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 8bf3ea1e1a4..529954a6aa3 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -211,12 +211,20 @@ typedef struct ColorManagedViewSettings { typedef struct ColorManagedDisplaySettings { char display_device[64]; + char emulation; + char _pad[7]; } ColorManagedDisplaySettings; typedef struct ColorManagedColorspaceSettings { char name[/*MAX_COLORSPACE_NAME*/ 64]; } ColorManagedColorspaceSettings; +/** #ColorManagedDisplaySettings.emulation */ +enum { + COLORMANAGE_DISPLAY_EMULATION_AUTO = 0, + COLORMANAGE_DISPLAY_EMULATION_OFF = 1, +}; + /** #ColorManagedViewSettings.flag */ enum { COLORMANAGE_VIEW_USE_CURVES = (1 << 0), diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index ac1a194a8c2..e57046cdc27 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -674,6 +674,20 @@ static bool rna_ColorManagedViewSettings_is_hdr_get(PointerRNA *ptr) view_settings->view_transform); } +static bool rna_ColorManagedViewSettings_support_emulation_get(PointerRNA *ptr) +{ + ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *)ptr->data; + if (GS(ptr->owner_id->name) != ID_SCE) { + return false; + } + const Scene *scene = reinterpret_cast(ptr->owner_id); + if (&scene->view_settings != view_settings) { + return false; + } + return IMB_colormanagement_display_support_emulation(&scene->display_settings, + view_settings->view_transform); +} + static int rna_ViewSettings_only_view_look_editable(const PointerRNA *ptr, const char **r_info) { ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *)ptr->data; @@ -1353,6 +1367,24 @@ static void rna_def_colormanage(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem emulation_items[] = { + {COLORMANAGE_DISPLAY_EMULATION_OFF, + "OFF", + 0, + "Off", + "Directly output image as produced by OpenColorIO. This is not correct in general, but " + "may be used when the system configuration and actual display device is known to match " + "the chosen display"}, + {COLORMANAGE_DISPLAY_EMULATION_AUTO, + "AUTO", + 0, + "Automatic", + "Display images consistent with most other applications, to preview images and video for " + "export. A best effort is made to emulate the chosen display on the actual display " + "device."}, + {0, nullptr, 0, nullptr, nullptr}, + }; + static const EnumPropertyItem look_items[] = { {0, "NONE", 0, "None", "Do not modify image in an artistic manner"}, {0, nullptr, 0, nullptr, nullptr}, @@ -1389,6 +1421,15 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_update( prop, NC_WINDOW, "rna_ColorManagedDisplaySettings_display_device_update"); + prop = RNA_def_property(srna, "emulation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, emulation_items); + RNA_def_property_ui_text( + prop, + "Display Emulation", + "Control how images in the chosen display are mapped to the physical display"); + RNA_def_property_update( + prop, NC_WINDOW, "rna_ColorManagedDisplaySettings_display_device_update"); + /* ** View Settings ** */ srna = RNA_def_struct(brna, "ColorManagedViewSettings", nullptr); RNA_def_struct_path_func(srna, "rna_ColorManagedViewSettings_path"); @@ -1495,6 +1536,16 @@ static void rna_def_colormanage(BlenderRNA *brna) prop, "Is HDR", "The display and view transform supports high dynamic range colors"); RNA_def_property_boolean_funcs(prop, "rna_ColorManagedViewSettings_is_hdr_get", nullptr); + prop = RNA_def_property(srna, "support_emulation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, + "Support Emulation", + "The display and view transform supports automatic emulation for another display device, " + "using the display color spaces mechanism in OpenColorIO v2 configurations"); + RNA_def_property_boolean_funcs( + prop, "rna_ColorManagedViewSettings_support_emulation_get", nullptr); + /* ** Color-space ** */ srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", nullptr); RNA_def_struct_path_func(srna, "rna_ColorManagedInputColorspaceSettings_path");