diff options
-rw-r--r-- | source/blender/blenkernel/intern/colortools.c | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 42 |
2 files changed, 41 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 315035c1bc2..f82b8b6675c 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1805,6 +1805,7 @@ void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings) { if (settings->curve_mapping) { BKE_curvemapping_free(settings->curve_mapping); + settings->curve_mapping = NULL; } } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index b2e1cb17946..704d1c3155e 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -93,6 +93,7 @@ struct GPUViewport { /* Color management. */ ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; + CurveMapping *orig_curve_mapping; float dither; /* TODO(fclem) the uvimage display use the viewport but do not set any view transform for the * moment. The end goal would be to let the GPUViewport do the color management. */ @@ -552,8 +553,43 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport, ColorManagedDisplaySettings *display_settings, float dither) { - memcpy(&viewport->view_settings, view_settings, sizeof(*view_settings)); - memcpy(&viewport->display_settings, display_settings, sizeof(*display_settings)); + /** + * HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene + * and the viewport stays cached (see T75443). But this means the OCIO curvemapping caching + * (which is based on CurveMap pointer address) cannot operate correctly and it will create + * a different OCIO processor for each viewport. We try to only realloc the curvemap copy if + * needed to avoid uneeded cache invalidation. + */ + if (view_settings->curve_mapping) { + if (viewport->view_settings.curve_mapping) { + if (view_settings->curve_mapping->changed_timestamp != + viewport->view_settings.curve_mapping->changed_timestamp) { + BKE_color_managed_view_settings_free(&viewport->view_settings); + } + } + } + + if (viewport->orig_curve_mapping != view_settings->curve_mapping) { + viewport->orig_curve_mapping = view_settings->curve_mapping; + BKE_color_managed_view_settings_free(&viewport->view_settings); + } + /* Don't copy the curve mapping already. */ + CurveMapping *tmp_curve_mapping = view_settings->curve_mapping; + CurveMapping *tmp_curve_mapping_vp = viewport->view_settings.curve_mapping; + view_settings->curve_mapping = NULL; + viewport->view_settings.curve_mapping = NULL; + + BKE_color_managed_view_settings_copy(&viewport->view_settings, view_settings); + /* Restore. */ + view_settings->curve_mapping = tmp_curve_mapping; + viewport->view_settings.curve_mapping = tmp_curve_mapping_vp; + /* Only copy curvemapping if needed. Avoid uneeded OCIO cache miss. */ + if (tmp_curve_mapping && viewport->view_settings.curve_mapping == NULL) { + BKE_color_managed_view_settings_free(&viewport->view_settings); + viewport->view_settings.curve_mapping = BKE_curvemapping_copy(tmp_curve_mapping); + } + + BKE_color_managed_display_settings_copy(&viewport->display_settings, display_settings); viewport->dither = dither; viewport->do_color_management = true; } @@ -923,5 +959,7 @@ void GPU_viewport_free(GPUViewport *viewport) DRW_instance_data_list_free(viewport->idatalist); MEM_freeN(viewport->idatalist); + BKE_color_managed_view_settings_free(&viewport->view_settings); + MEM_freeN(viewport); } |