diff options
Diffstat (limited to 'source/blender/editors')
39 files changed, 841 insertions, 390 deletions
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 13c3b180230..28727c913cb 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -83,7 +83,7 @@ void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mas /* textures buffer */ int ED_space_clip_texture_buffer_supported(struct SpaceClip *sc); -int ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf); +int ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf, const unsigned char *display_buffer); void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc); void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 87f12b8ac9c..a50b33966c6 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -39,6 +39,7 @@ struct ToolSettings; struct uiBlock; struct wmWindowManager; struct ARegion; +struct Scene; /* image_edit.c, exported for transform */ struct Image *ED_space_image(struct SpaceImage *sima); @@ -77,7 +78,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C); /* UI level image (texture) updating... render calls own stuff (too) */ void ED_image_update_frame(const struct Main *mainp, int cfra); -void ED_image_draw_info(struct ARegion *ar, int color_manage, int channels, int x, int y, +void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf); #endif /* __ED_IMAGE_H__ */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 7f40024a056..b1bccfa32c5 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -282,10 +282,12 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active); int ED_view3d_context_activate(struct bContext *C); void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, - int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic); + int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic, int colormanage_background); -struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256]); -struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, int draw_background, char err_out[256]); +struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, + int draw_background, int colormanage_background, char err_out[256]); +struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, + int draw_background, int colormanage_background, char err_out[256]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index c6f58fdd70b..917153c9199 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -811,7 +811,7 @@ void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char * void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer); void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact); -void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr); +void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); void uiTemplateOperatorSearch(uiLayout *layout); @@ -831,6 +831,9 @@ void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct Poi void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int cmpact); +void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname); +void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname); + /* items */ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname); void uiItemEnumO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, const char *propname, int value); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 823f8d7be39..742aed4fbb1 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -75,6 +75,8 @@ #include "BPY_extern.h" +#include "IMB_colormanagement.h" + #include "interface_intern.h" #define MENU_WIDTH 120 @@ -2138,7 +2140,14 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor block->evil_C = (void *)C; /* XXX */ if (scn) { - block->color_profile = (scn->r.color_mgt_flag & R_COLOR_MANAGEMENT); + block->color_profile = TRUE; + + /* store display device name, don't lookup for transformations yet + * block could be used for non-color displays where looking up for transformation + * would slow down redraw, so only lookup for actual transform when it's indeed + * needed + */ + block->display_device = scn->display_settings.display_device; /* copy to avoid crash when scene gets deleted with ui still open */ block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings"); @@ -2575,6 +2584,25 @@ void ui_block_do_align(uiBlock *block) } } +struct ColorManagedDisplay *ui_block_display_get(uiBlock *block) +{ + return IMB_colormanagement_display_get_named(block->display_device); +} + +void ui_block_to_display_space_v3(uiBlock *block, float pixel[3]) +{ + struct ColorManagedDisplay *display = ui_block_display_get(block); + + IMB_colormanagement_scene_linear_to_display_v3(pixel, display); +} + +void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]) +{ + struct ColorManagedDisplay *display = ui_block_display_get(block); + + IMB_colormanagement_display_to_scene_linear_v3(pixel, display); +} + /** * \brief ui_def_but is the function that draws many button types * diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 77dbbc878a7..f535c3c3e2a 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -48,6 +48,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -1110,10 +1111,14 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) float v3[2], v1[2], v2[2], v1a[2], v2a[2]; int a; float pos, colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */ - + struct ColorManagedDisplay *display = NULL; + coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin); if (coba == NULL) return; - + + if (but->block->color_profile) + display = ui_block_display_get(but->block); + x1 = rect->xmin; y1 = rect->ymin; sizex = rect->xmax - x1; @@ -1146,8 +1151,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) for (a = 1; a <= sizex; a++) { pos = ((float)a) / (sizex - 1); do_colorband(coba, pos, colf); - if (but->block->color_profile != BLI_PR_NONE) - linearrgb_to_srgb_v3_v3(colf, colf); + if (display) + IMB_colormanagement_scene_linear_to_display_v3(colf, display); v1[0] = v2[0] = x1 + a; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b8a84e1638a..f7b22098835 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3162,13 +3162,15 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; } ui_get_but_vectorf(but, rgb); - rgb_to_hsv_compat_v(rgb, hsv); + if (color_profile && (int)but->a1) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_compat_v(rgb, hsv); /* relative position within box */ x = ((float)mx_fl - but->rect.xmin) / BLI_RCT_SIZE_X(&but->rect); @@ -3204,17 +3206,16 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, /* exception only for value strip - use the range set in but->min/max */ hsv[2] = y * (but->softmax - but->softmin) + but->softmin; - if (color_profile) - hsv[2] = srgb_to_linearrgb(hsv[2]); - - if (hsv[2] > but->softmax) - hsv[2] = but->softmax; break; default: assert(!"invalid hsv type"); } hsv_to_rgb_v(hsv, rgb); + + if (color_profile && (int)but->a1) + ui_block_to_scene_linear_v3(but->block, rgb); + copy_v3_v3(data->vec, rgb); data->draglastx = mx; @@ -3233,10 +3234,14 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; } ui_get_but_vectorf(but, rgb); + + if (color_profile && (int)but->a1) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_compat_v(rgb, hsv); switch ((int)but->a1) { @@ -3267,15 +3272,16 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF /* exception only for value strip - use the range set in but->min/max */ hsv[2] += ndof->rx * sensitivity; - if (color_profile) - hsv[2] = srgb_to_linearrgb(hsv[2]); - CLAMP(hsv[2], but->softmin, but->softmax); default: assert(!"invalid hsv type"); } - + hsv_to_rgb_v(hsv, rgb); + + if (color_profile && (int)but->a1) + ui_block_to_scene_linear_v3(but->block, rgb); + copy_v3_v3(data->vec, rgb); ui_set_but_vectorf(but, data->vec); } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index f6f12f98181..0921107b8e6 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -466,7 +466,7 @@ static void init_brush_icons(void) { \ bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \ datatoc_ ##name## _png_size, \ - IB_rect, "<brush icon>"); \ + IB_rect, NULL, "<brush icon>"); \ def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ IMB_freeImBuf(bbuf); \ } (void)0 @@ -520,7 +520,7 @@ static void init_internal_icons(void) char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons"); if (icondir) { BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); - bbuf = IMB_loadiffname(iconfilestr, IB_rect); /* if the image is missing bbuf will just be NULL */ + bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) { printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr); IMB_freeImBuf(bbuf); @@ -533,7 +533,7 @@ static void init_internal_icons(void) } if (bbuf == NULL) bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons_png, - datatoc_blender_icons_png_size, IB_rect, "<blender icons>"); + datatoc_blender_icons_png_size, IB_rect, NULL, "<blender icons>"); if (bbuf) { /* free existing texture if any */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 73e6427d1cb..928e1671cee 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -342,7 +342,12 @@ struct uiBlock { struct UnitSettings *unit; /* unit system, used a lot for numeric buttons so include here rather then fetching through the scene every time. */ float _hsv[3]; /* XXX, only access via ui_block_hsv_get() */ + char color_profile; /* color profile for correcting linear colors for display */ + + char *display_device; /* display devide name used to display this block, + * used by color widgets to transform colors from/to scene linear + */ }; typedef struct uiSafetyRct { @@ -392,6 +397,10 @@ extern void ui_bounds_block(uiBlock *block); extern void ui_block_translate(uiBlock *block, int x, int y); extern void ui_block_do_align(uiBlock *block); +extern struct ColorManagedDisplay *ui_block_display_get(uiBlock *block); +void ui_block_to_display_space_v3(uiBlock *block, float pixel[3]); +void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]); + /* interface_regions.c */ struct uiPopupBlockHandle { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index bf77e605d6e..ded5887f7f2 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -58,6 +58,8 @@ #include "UI_interface.h" +#include "IMB_colormanagement.h" + #include "interface_intern.h" #include "WM_api.h" @@ -75,7 +77,7 @@ /* ********************************************************** */ typedef struct Eyedropper { - short do_color_management; + struct ColorManagedDisplay *display; PointerRNA ptr; PropertyRNA *prop; @@ -89,8 +91,6 @@ typedef struct Eyedropper { static int eyedropper_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - const int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; - Eyedropper *eye; op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper"); @@ -106,7 +106,12 @@ static int eyedropper_init(bContext *C, wmOperator *op) return FALSE; } - eye->do_color_management = (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR); + if (RNA_property_subtype(eye->prop) == PROP_COLOR) { + const char *display_device; + + display_device = scene->display_settings.display_device; + eye->display = IMB_colormanagement_display_get_named(display_device); + } return TRUE; } @@ -194,9 +199,10 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3 /* to maintain alpha */ RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv); - /* convert from screen (srgb) space to linear rgb space */ - if (eye->do_color_management) { - srgb_to_linearrgb_v3_v3(col_conv, col); + /* convert from display space to linear rgb space */ + if (eye->display) { + copy_v3_v3(col_conv, col); + IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display); } else { copy_v3_v3(col_conv, col); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 59fa66b12af..dc9347b3852 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -66,6 +66,8 @@ #include "ED_screen.h" +#include "IMB_colormanagement.h" + #include "interface_intern.h" #define MENU_SEPR_HEIGHT 6 @@ -1893,11 +1895,15 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3]) { uiBut *bt; float *hsv = ui_block_hsv_get(block); + struct ColorManagedDisplay *display = NULL; /* this is to keep the H and S value when V is equal to zero * and we are working in HSV mode, of course! */ rgb_to_hsv_compat_v(rgb, hsv); + + if (block->color_profile) + display = ui_block_display_get(block); /* this updates button strings, is hackish... but button pointers are on stack of caller function */ for (bt = block->buttons.first; bt; bt = bt->next) { @@ -1913,12 +1919,11 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3]) /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */ - if (block->color_profile == BLI_PR_NONE) { - copy_v3_v3(rgb_gamma, rgb); - } - else { - /* make an sRGB version, for Hex code */ - linearrgb_to_srgb_v3_v3(rgb_gamma, rgb); + copy_v3_v3(rgb_gamma, rgb); + + if (display) { + /* make a display version, for Hex code */ + IMB_colormanagement_scene_linear_to_display_v3(rgb_gamma, display); } if (rgb_gamma[0] > 1.0f) rgb_gamma[0] = modf(rgb_gamma[0], &intpart); @@ -1997,9 +2002,9 @@ static void do_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl) hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2); /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */ - if (but->block->color_profile != BLI_PR_NONE) { + if (but->block->color_profile) { /* so we need to linearise it for Blender */ - srgb_to_linearrgb_v3_v3(rgb, rgb); + ui_block_to_scene_linear_v3(but->block, rgb); } ui_update_block_buts_rgb(but->block, rgb); @@ -2107,14 +2112,16 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper /* existence of profile means storage is in linear color space, with display correction */ /* XXX That tip message is not use anywhere! */ - if (block->color_profile == BLI_PR_NONE) { + if (!block->color_profile) { BLI_strncpy(tip, N_("Value in Display Color Space"), sizeof(tip)); copy_v3_v3(rgb_gamma, rgba); } else { BLI_strncpy(tip, N_("Value in Linear RGB Color Space"), sizeof(tip)); - /* make an sRGB version, for Hex code */ - linearrgb_to_srgb_v3_v3(rgb_gamma, rgba); + + /* make a display version, for Hex code */ + copy_v3_v3(rgb_gamma, rgba); + ui_block_to_display_space_v3(block, rgb_gamma); } /* sneaky way to check for alpha */ @@ -2239,7 +2246,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { - block->color_profile = BLI_PR_NONE; + block->color_profile = FALSE; } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 6a63e2b571f..79b9d313775 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2801,3 +2801,56 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) } } +/********************************* Color management *************************************/ + +void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname) +{ + PropertyRNA *prop; + PointerRNA colorspace_settings_ptr; + + prop = RNA_struct_find_property(ptr, propname); + + if (!prop) { + printf("%s: property not found: %s.%s\n", + __func__, RNA_struct_identifier(ptr->type), propname); + return; + } + + colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop); + + uiItemL(layout, "Color Space:", ICON_NONE); + uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); +} + +void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, const char *propname) +{ + PropertyRNA *prop; + PointerRNA view_transform_ptr; + uiLayout *col, *row; + ColorManagedViewSettings *view_settings; + + prop = RNA_struct_find_property(ptr, propname); + + if (!prop) { + printf("%s: property not found: %s.%s\n", + __func__, RNA_struct_identifier(ptr->type), propname); + return; + } + + view_transform_ptr = RNA_property_pointer_get(ptr, prop); + view_settings = view_transform_ptr.data; + + col = uiLayoutColumn(layout, FALSE); + + row = uiLayoutRow(col, FALSE); + uiItemR(row, &view_transform_ptr, "view_transform", UI_ITEM_R_EXPAND, IFACE_("View"), ICON_NONE); + + col = uiLayoutColumn(layout, FALSE); + uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE); + uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, FALSE); + uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE); + if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) + uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0); +} diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 026f02d1089..8a7f2d9ca47 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1874,7 +1874,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) int color_profile = but->block->color_profile; if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; radstep = 2.0f * (float)M_PI / (float)tot; centx = BLI_RCT_CENTER_X_FL(rect); @@ -1887,17 +1887,20 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) /* color */ ui_get_but_vectorf(but, rgb); - copy_v3_v3(hsv, ui_block_hsv_get(but->block)); + /* copy_v3_v3(hsv, ui_block_hsv_get(but->block)); */ /* UNUSED */ + + rgb_to_hsv_compat_v(rgb, hsvo); + + if (color_profile) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_compat_v(rgb, hsv); - copy_v3_v3(hsvo, hsv); /* exception: if 'lock' is set * lock the value of the color wheel to 1. * Useful for color correction tools where you're only interested in hue. */ if (but->flag & UI_BUT_COLOR_LOCK) hsv[2] = 1.f; - else if (color_profile) - hsv[2] = linearrgb_to_srgb(hsv[2]); hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2); @@ -2139,15 +2142,16 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) int color_profile = but->block->color_profile; if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; ui_get_but_vectorf(but, rgb); + + if (color_profile) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_v(rgb, hsv); v = hsv[2]; - if (color_profile) - v = linearrgb_to_srgb(v); - /* map v from property range to [0,1] */ range = but->softmax - but->softmin; v = (v - but->softmin) / range; @@ -2531,7 +2535,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) { col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3); @@ -2559,7 +2563,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat } if (color_profile) - linearrgb_to_srgb_v3_v3(col, col); + ui_block_to_display_space_v3(but->block, col); rgba_float_to_uchar((unsigned char *)wcol->inner, col); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index f9b73a56403..f03cb312e3e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -69,6 +69,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "GPU_draw.h" /* GPU_free_image */ @@ -685,7 +686,7 @@ static void apply_heights_data(void *bake_data) } } - ibuf->userflags = IB_RECT_INVALID; + ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID; } static void free_heights_data(void *bake_data) @@ -769,6 +770,8 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, char *rrgb = (char *)ibuf->rect + pixel * 4; rrgb[3] = 255; } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } /* MultiresBake callback for normals' baking @@ -826,6 +829,8 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, rgb_float_to_uchar(rrgb, vec); rrgb[3] = 255; } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } static void count_images(MultiresBakeRender *bkr) @@ -895,7 +900,7 @@ static void finish_images(MultiresBakeRender *bkr) RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter); - ibuf->userflags |= IB_BITMAPDIRTY; + ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;; if (ibuf->rect_float) ibuf->userflags |= IB_RECT_INVALID; @@ -1369,6 +1374,7 @@ static void finish_bake_internal(BakeRender *bkr) if (ima->ok == IMA_OK_LOADED) { if (ibuf) { if (ibuf->userflags & IB_BITMAPDIRTY) { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; GPU_free_image(ima); imb_freemipmapImBuf(ibuf); } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index b236b555850..ebacac917e8 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -61,6 +61,7 @@ #include "ED_object.h" #include "RE_pipeline.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -78,7 +79,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat { float *rectf = NULL; int ymin, ymax, xmin, xmax; - int rymin, rxmin, predivide, profile_from; + int rymin, rxmin; unsigned char *rectc; /* if renrect argument, we only refresh scanlines */ @@ -138,18 +139,9 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat rectf += 4 * (rr->rectx * ymin + xmin); rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin); - if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) { - profile_from = IB_PROFILE_LINEAR_RGB; - predivide = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); - } - else { - profile_from = IB_PROFILE_SRGB; - predivide = 0; - } - - IMB_buffer_byte_from_float(rectc, rectf, - 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, - xmax, ymax, ibuf->x, rr->rectx); + IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin, + &scene->view_settings, &scene->display_settings, + rxmin, rymin, rxmin + xmax, rymin + ymax); } /* ****************************** render invoking ***************** */ diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 55df1caf3eb..d9618e89b68 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -63,6 +63,7 @@ #include "RE_pipeline.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "RNA_access.h" #include "RNA_define.h" @@ -143,22 +144,30 @@ static void screen_opengl_render_apply(OGLRender *oglrender) ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown); if (ibuf) { + ImBuf *linear_ibuf; + BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); - if (ibuf->rect_float == NULL) { - /* internally sequencer working in sRGB space and stores both bytes and float - * buffers in sRGB space, but if byte->float onversion doesn't happen in sequencer - * (e.g. when adding image sequence/movie into sequencer) there'll be only - * byte buffer and profile will still indicate sRGB->linear space conversion is needed - * here we're ensure there'll be no conversion happen and float buffer would store - * linear frame (sergey) */ - ibuf->profile = IB_PROFILE_NONE; - IMB_float_from_rect(ibuf); + linear_ibuf = IMB_dupImBuf(ibuf); + IMB_freeImBuf(ibuf); + + if (linear_ibuf->rect_float == NULL) { + /* internally sequencer working in display space and stores both bytes and float buffers in that space. + * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie + * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear + */ + + IMB_float_from_rect(linear_ibuf); + } + else { + /* ensure float buffer is in linear space, not in display space */ + BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } - memcpy(rr->rectf, ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); - IMB_freeImBuf(ibuf); + memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); + + IMB_freeImBuf(linear_ibuf); } } else if (view_context) { @@ -181,7 +190,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } if ((scene->r.mode & R_OSA) == 0) { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf); } else { @@ -195,7 +204,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) BLI_jitter_init(jit_ofs[0], scene->r.osa); /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer); /* skip the first sample */ @@ -205,7 +214,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) (jit_ofs[j][0] * 2.0f) / sizex, (jit_ofs[j][1] * 2.0f) / sizey); - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_tmp); add_vn_vn(accum_buffer, accum_tmp, sizex * sizey * sizeof(float)); } @@ -221,7 +230,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) else { /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; - ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, TRUE, err_out); + ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, TRUE, FALSE, err_out); camera = scene->camera; if (ibuf_view) { @@ -233,27 +242,27 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } - /* rr->rectf is now filled with image data */ - - if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) - BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4); - /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be - * linear if color management is enabled. So we convert to linear here, so - * the conversion back to bytes using the color management flag can make it - * sRGB again, and so that e.g. openexr saving also saves the correct linear - * float buffer. */ + * linear So we convert to linear here, so the conversion back to bytes can make it + * sRGB (or other display space) again, and so that e.g. openexr saving also saves the + * correct linear float buffer. + */ - if (oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - int predivide = 0; /* no alpha */ + if (!oglrender->is_sequencer) { + /* sequencer has got tricker ocnversion happened above */ IMB_buffer_float_from_float(rr->rectf, rr->rectf, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, FALSE, oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } + /* rr->rectf is now filled with image data */ + + if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) + BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4); + RE_ReleaseResult(oglrender->re); /* update byte from float buffer */ @@ -536,12 +545,28 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { + int needs_free = FALSE; + + if (is_movie || !BKE_imtype_supports_float(scene->r.im_format.imtype)) { + ImBuf *colormanage_ibuf = IMB_dupImBuf(ibuf); + + IMB_display_buffer_to_imbuf_rect(colormanage_ibuf, &scene->view_settings, &scene->display_settings); + imb_freerectfloatImBuf(colormanage_ibuf); + + // IMB_freeImBuf(ibuf); /* owned by the image */ + ibuf = colormanage_ibuf; + needs_free = TRUE; + } + /* color -> grayscale */ /* editing directly would alter the render view */ if (scene->r.im_format.planes == R_IMF_PLANES_BW) { - ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); + ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); IMB_color_to_bw(ibuf_bw); - // IMB_freeImBuf(ibuf); /* owned by the image */ + + if (needs_free) + IMB_freeImBuf(ibuf); + ibuf = ibuf_bw; } else { @@ -551,6 +576,13 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) ibuf_cpy->rect = ibuf->rect; ibuf_cpy->rect_float = ibuf->rect_float; ibuf_cpy->zbuf_float = ibuf->zbuf_float; + + if (needs_free) { + ibuf_cpy->mall = ibuf->mall; + ibuf->mall = 0; + IMB_freeImBuf(ibuf); + } + ibuf = ibuf_cpy; } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 068a7aaa50a..a829ef57b85 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -64,6 +64,7 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" @@ -75,11 +76,13 @@ #include "BKE_material.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_world.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -115,7 +118,8 @@ ImBuf *get_brush_icon(Brush *brush) BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath)); BLI_path_abs(path, G.main->name); - brush->icon_imbuf = IMB_loadiffname(path, flags); + /* use default colorspaces for brushes */ + brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); // otherwise lets try to find it in other directories if (!(brush->icon_imbuf)) { @@ -123,8 +127,10 @@ ImBuf *get_brush_icon(Brush *brush) BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath); - if (path[0]) - brush->icon_imbuf = IMB_loadiffname(path, flags); + if (path[0]) { + /* use fefault color spaces */ + brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); + } } if (brush->icon_imbuf) @@ -254,6 +260,10 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre } sce->r.color_mgt_flag = scene->r.color_mgt_flag; + BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings); + + BKE_color_managed_view_settings_free(&sce->view_settings); + BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings); /* prevent overhead for small renders and icons (32) */ if (id && sp->sizex < 40) @@ -263,7 +273,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre /* exception: don't color manage texture previews or icons */ if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) - sce->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT; + BKE_scene_disable_color_management(sce); if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) sce->r.alphamode = R_ALPHAPREMUL; @@ -481,7 +491,7 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int if (id && GS(id->name) != ID_TE) { /* exception: don't color manage texture previews - show the raw values */ if (sce) { - do_gamma_correct = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT; + do_gamma_correct = TRUE; do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE; } } @@ -514,15 +524,25 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int /* temporary conversion to byte for drawing */ float fx = rect->xmin + offx; float fy = rect->ymin; - int profile_from = (do_gamma_correct) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB; int dither = 0; unsigned char *rect_byte; rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"); - IMB_buffer_byte_from_float(rect_byte, rres.rectf, - 4, dither, IB_PROFILE_SRGB, profile_from, do_predivide, - rres.rectx, rres.recty, rres.rectx, rres.rectx); + if (do_gamma_correct) { + IMB_display_buffer_transform_apply(rect_byte, rres.rectf, rres.rectx, rres.recty, 4, + &sce->view_settings, &sce->display_settings, do_predivide); + + } + else { + /* OCIO_TODO: currently seems an exception for textures (came fro mlegacish time), + * but is it indeed expected behavior, or textures should be + * color managed as well? + */ + IMB_buffer_byte_from_float(rect_byte, rres.rectf, + 4, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, do_predivide, + rres.rectx, rres.recty, rres.rectx, rres.rectx); + } glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 4e71c49465f..5e54119118a 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -245,7 +245,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op) /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr); - uiTemplateImageSettings(layout, &ptr); + uiTemplateImageSettings(layout, &ptr, TRUE); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 101235e9c99..64430a263f0 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -104,6 +104,8 @@ #include "GPU_draw.h" #include "GPU_extensions.h" +#include "IMB_colormanagement.h" + #include "paint_intern.h" /* Defines and Structs */ @@ -139,7 +141,7 @@ #define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) #define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS) -static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint); +static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint); typedef struct ImagePaintState { @@ -153,7 +155,6 @@ typedef struct ImagePaintState { Image *image; ImBuf *canvas; ImBuf *clonecanvas; - short clonefreefloat; char *warnpackedfile; char *warnmultifile; @@ -510,7 +511,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */ - + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } IMB_freeImBuf(tmpibuf); @@ -3615,7 +3616,7 @@ static int project_image_refresh_tagged(ProjPaintState *ps) pr = &(projIma->partRedrawRect[i]); if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ imapaintpartial = *pr; - imapaint_image_update(NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/ + imapaint_image_update(NULL, NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/ redraw = 1; } } @@ -3945,7 +3946,7 @@ static void *do_projectpaint_thread(void *ph_v) last_projIma->touch = 1; is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; - use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0; + use_color_correction = TRUE; } /* end copy */ @@ -4028,7 +4029,7 @@ static void *do_projectpaint_thread(void *ph_v) last_projIma->touch = 1; is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; - use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0; + use_color_correction = TRUE; } /* end copy */ @@ -4244,10 +4245,17 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, IMB_freeImBuf(tmpibuf); } -static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) +static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) { - if (ibuf->rect_float) - ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ + if (scene) { + IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, ibuf->x, 0, 0, + &scene->view_settings, &scene->display_settings, + imapaintpartial.x1, imapaintpartial.y1, + imapaintpartial.x2, imapaintpartial.y2); + } + else { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; @@ -4571,15 +4579,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) /* temporarily add float rect for cloning */ if (s->canvas->rect_float && !s->clonecanvas->rect_float) { - short profile = IB_PROFILE_NONE; - - /* Don't want to color manage, but don't disturb existing profiles */ - SWAP(short, s->clonecanvas->profile, profile); - IMB_float_from_rect(s->clonecanvas); - s->clonefreefloat = 1; - - SWAP(short, s->clonecanvas->profile, profile); } else if (!s->canvas->rect_float && !s->clonecanvas->rect) IMB_rect_from_float(s->clonecanvas); @@ -4588,10 +4588,8 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) return 1; } -static void imapaint_canvas_free(ImagePaintState *s) +static void imapaint_canvas_free(ImagePaintState *UNUSED(s)) { - if (s->clonefreefloat) - imb_freerectfloatImBuf(s->clonecanvas); } static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) @@ -4607,9 +4605,12 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0); - if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) { + /* OCIO_TODO: float buffers are now always linear, so always use color correction + * this should probably be changed when texture painting color space is supported + */ + if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, TRUE)) { if (update) - imapaint_image_update(s->sima, image, ibuf, texpaint); + imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); return 1; } else return 0; @@ -5884,7 +5885,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (w > maxsize) w = maxsize; if (h > maxsize) h = maxsize; - ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, err_out); + ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, FALSE, err_out); if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ /* but could be other reasons. Should be handled in the future. nazgul */ diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index e66faa88b93..0a1e1d75098 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -119,6 +119,8 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c uiTemplateID(layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL); if (clip) { + uiLayout *col; + row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); uiDefBut(block, LABEL, 0, "File Path:", 0, 19, 145, 19, NULL, 0, 0, 0, 0, ""); @@ -129,6 +131,9 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload"); + + col = uiLayoutColumn(layout, FALSE); + uiTemplateColorspaceSettings(col, &clipptr, "colorspace_settings"); } } diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 2353f8f8c12..d486caeacc2 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -42,6 +42,7 @@ #include "BKE_tracking.h" #include "BKE_mask.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -246,14 +247,7 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) ED_region_info_draw(ar, str, block, 0.6f); } -static void verify_buffer_float(ImBuf *ibuf) -{ - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) { - IMB_rect_from_float(ibuf); - } -} - -static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, +static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int width, int height, float zoomx, float zoomy) { int x, y; @@ -267,13 +261,16 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, glRectf(x, y, x + zoomx * width, y + zoomy * height); } else { - verify_buffer_float(ibuf); + unsigned char *display_buffer; + void *cache_handle; + + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - if (ibuf->rect) { + if (display_buffer) { int need_fallback = 1; if (ED_space_clip_texture_buffer_supported(sc)) { - if (ED_space_clip_load_movieclip_buffer(sc, ibuf)) { + if (ED_space_clip_load_movieclip_buffer(sc, ibuf, display_buffer)) { glPushMatrix(); glTranslatef(x, y, 0.0f); glScalef(zoomx, zoomy, 1.0f); @@ -299,12 +296,14 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, /* set zoom */ glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); /* reset zoom */ glPixelZoom(1.0f, 1.0f); } } + + IMB_display_buffer_release(cache_handle); } /* draw boundary border for frame if stabilization is enabled */ @@ -1461,7 +1460,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) } if (ibuf) { - draw_movieclip_buffer(sc, ar, ibuf, width, height, zoomx, zoomy); + draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy); IMB_freeImBuf(ibuf); } else { diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 08ad6aac970..f2a48f299cf 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -277,13 +277,7 @@ int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_ if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); - /* IB_PROFILE_NONE is default but infact its linear */ - if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) { - linearrgb_to_srgb_v3_v3(r_col, fp); - } - else { - copy_v3_v3(r_col, fp); - } + linearrgb_to_srgb_v3_v3(r_col, fp); ret = TRUE; } else if (ibuf->rect) { @@ -583,12 +577,15 @@ typedef struct SpaceClipDrawContext { GLuint texture; /* OGL texture ID */ short texture_allocated; /* flag if texture was allocated by glGenTextures */ struct ImBuf *texture_ibuf; /* image buffer for which texture was created */ + const unsigned char *display_buffer; /* display buffer for which texture was created */ int image_width, image_height; /* image width and height for which texture was created */ unsigned last_texture; /* ID of previously used texture, so it'll be restored after clip drawing */ /* fields to check if cache is still valid */ int framenr, start_frame, frame_offset; short render_size, render_flag; + + char colorspace[64]; } SpaceClipDrawContext; int ED_space_clip_texture_buffer_supported(SpaceClip *sc) @@ -613,7 +610,7 @@ int ED_space_clip_texture_buffer_supported(SpaceClip *sc) return context->buffers_supported; } -int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) +int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsigned char *display_buffer) { SpaceClipDrawContext *context = sc->draw_context; MovieClip *clip = ED_space_clip_get_clip(sc); @@ -625,12 +622,22 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) * assuming displaying happens of footage frames only on which painting doesn't heppen. * so not changed image buffer pointer means unchanged image content */ need_rebind |= context->texture_ibuf != ibuf; + need_rebind |= context->display_buffer != display_buffer; need_rebind |= context->framenr != sc->user.framenr; need_rebind |= context->render_size != sc->user.render_size; need_rebind |= context->render_flag != sc->user.render_flag; need_rebind |= context->start_frame != clip->start_frame; need_rebind |= context->frame_offset != clip->frame_offset; + if (!need_rebind) { + /* OCIO_TODO: not entirely nice, but currently it seems to be easiest way + * to deal with changing input color space settings + * pointer-based check could fail due to new buffers could be + * be allocated on on old memory + */ + need_rebind = strcmp(context->colorspace, clip->colorspace_settings.name) != 0; + } + if (need_rebind) { int width = ibuf->x, height = ibuf->y; int need_recreate = 0; @@ -670,16 +677,12 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) glBindTexture(GL_TEXTURE_2D, context->texture); } - if (ibuf->rect_float) { - if (ibuf->rect == NULL) - IMB_rect_from_float(ibuf); - } - - if (ibuf->rect) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + if (display_buffer) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); /* store settings */ context->texture_allocated = 1; + context->display_buffer = display_buffer; context->texture_ibuf = ibuf; context->image_width = ibuf->x; context->image_height = ibuf->y; @@ -688,6 +691,8 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) context->render_flag = sc->user.render_flag; context->start_frame = clip->start_frame; context->frame_offset = clip->frame_offset; + + strcpy(context->colorspace, clip->colorspace_settings.name); } else { /* displaying exactly the same image which was loaded t oa texture, diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 337e13f7785..d3b4df05aa9 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -389,7 +389,7 @@ void filelist_init_icons(void) #ifdef WITH_HEADLESS bbuf = NULL; #else - bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, "<splash>"); + bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, NULL, "<splash>"); #endif if (bbuf) { for (y = 0; y < SPECIAL_IMG_ROWS; y++) { diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 40f0683a852..c372973b7b0 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -169,47 +169,6 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree) /* ************ panel stuff ************* */ -/* is used for both read and write... */ - -static int image_panel_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceImage *sima = CTX_wm_space_image(C); - ImBuf *ibuf; - void *lock; - int result; - - ibuf = ED_space_image_acquire_buffer(sima, &lock); - result = ibuf && ibuf->rect_float; - ED_space_image_release_buffer(sima, lock); - - return result; -} - -static void image_panel_curves(const bContext *C, Panel *pa) -{ - bScreen *sc = CTX_wm_screen(C); - SpaceImage *sima = CTX_wm_space_image(C); - ImBuf *ibuf; - PointerRNA simaptr; - int levels; - void *lock; - - ibuf = ED_space_image_acquire_buffer(sima, &lock); - - if (ibuf) { - if (sima->cumap == NULL) - sima->cumap = curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); - - /* curvemap black/white levels only works for RGBA */ - levels = (ibuf->channels == 4); - - RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr); - uiTemplateCurveMapping(pa->layout, &simaptr, "curve", 'c', levels, 0); - } - - ED_space_image_release_buffer(sima, lock); -} - #if 0 /* 0: disable preview * otherwise refresh preview @@ -234,6 +193,7 @@ void image_preview_event(int event) } if (exec && G.scene->nodetree) { + Scene *scene = G.scene; /* should work when no node editor in screen..., so we execute right away */ ntreeCompositTagGenerators(G.scene->nodetree); @@ -244,7 +204,7 @@ void image_preview_event(int event) BIF_store_spare(); - ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1); /* 1 is do_previews */ + ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */ G.scene->nodetree->timecursor = NULL; G.scene->nodetree->test_break = NULL; @@ -611,6 +571,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiLayout *row, *split, *col; uiBlock *block; char str[128]; + void *lock; if (!ptr->data) @@ -728,7 +689,11 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiItemL(layout, str, ICON_NONE); } } - + + col = uiLayoutColumn(layout, FALSE); + uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); + uiItemR(col, &imaptr, "view_as_render", 0, NULL, ICON_NONE); + if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { /* background image view doesnt need these */ uiItemS(layout); @@ -794,15 +759,18 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char MEM_freeN(cb); } -void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) +void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management) { ImageFormatData *imf = imfptr->data; ID *id = imfptr->id.data; + PointerRNA display_settings_ptr; + PropertyRNA *prop; const int depth_ok = BKE_imtype_valid_depths(imf->imtype); /* some settings depend on this being a scene thats rendered */ const short is_render_out = (id && GS(id->name) == ID_SCE); uiLayout *col, *row, *split, *sub; + int show_preview = FALSE; col = uiLayoutColumn(layout, FALSE); @@ -843,6 +811,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) } if (is_render_out && (imf->imtype == R_IMF_IMTYPE_OPENEXR)) { + show_preview = TRUE; uiItemR(row, imfptr, "use_preview", 0, NULL, ICON_NONE); } @@ -864,6 +833,22 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE); #endif } + + /* color management */ + if (color_management && + (!BKE_imtype_supports_float(imf->imtype) || + (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG))) + { + prop = RNA_struct_find_property(imfptr, "display_settings"); + display_settings_ptr = RNA_property_pointer_get(imfptr, prop); + + col = uiLayoutColumn(layout, FALSE); + uiItemL(col, IFACE_("Color Management"), ICON_NONE); + + uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE); + + uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings"); + } } void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser) @@ -886,14 +871,6 @@ void image_buttons_register(ARegionType *art) { PanelType *pt; - pt = MEM_callocN(sizeof(PanelType), "spacetype image panel curves"); - strcpy(pt->idname, "IMAGE_PT_curves"); - strcpy(pt->label, "Curves"); - pt->draw = image_panel_curves; - pt->poll = image_panel_poll; - pt->flag |= PNL_DEFAULT_CLOSED; - BLI_addtail(&art->paneltypes, pt); - pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil"); strcpy(pt->idname, "IMAGE_PT_gpencil"); strcpy(pt->label, "Grease Pencil"); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index e293264c021..638a2ac6681 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -51,6 +51,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BKE_context.h" #include "BKE_global.h" @@ -70,6 +71,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "WM_api.h" +#include "WM_types.h" #include "RE_pipeline.h" @@ -77,27 +80,6 @@ #define HEADER_HEIGHT 18 -static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage) -{ - /* detect if we need to redo the curve map. - * ibuf->rect is zero for compositor and render results after change - * convert to 32 bits always... drawing float rects isn't supported well (atis) - * - * NOTE: if float buffer changes, we have to manually remove the rect - */ - - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID)) ) { - if (color_manage) { - if (ima && ima->source == IMA_SRC_VIEWER) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } - else - ibuf->profile = IB_PROFILE_NONE; - - IMB_rect_from_float(ibuf); - } -} - static void draw_render_info(Scene *scene, Image *ima, ARegion *ar) { RenderResult *rr; @@ -112,7 +94,7 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar) } /* used by node view too */ -void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int y, +void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf) { char str[256]; @@ -209,6 +191,20 @@ void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } + + if (color_manage && channels == 4) { + float pixel[4]; + + if (use_default_view) + IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, NULL, &scene->display_settings); + else + IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings); + + BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]); + BLF_position(blf_mono_font, dx, 6, 0); + BLF_draw_ascii(blf_mono_font, str, sizeof(str)); + dx += BLF_width(blf_mono_font, str); + } } /* color rectangle */ @@ -252,11 +248,15 @@ void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int } if (color_manage) { - linearrgb_to_srgb_v4(finalcol, col); + if (use_default_view) + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings); + else + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); } + glDisable(GL_BLEND); glColor3fv(finalcol); dx += 5; @@ -418,10 +418,9 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec MEM_freeN(rectf); } -static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) +static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { int x, y; - int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; /* set zoom */ glPixelZoom(zoomx, zoomy); @@ -445,6 +444,9 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float); } else { + unsigned char *display_buffer; + void *cache_handle; + if (sima->flag & SI_USE_ALPHA) { fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); @@ -452,17 +454,17 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - /* we don't draw floats buffers directly but - * convert them, and optionally apply curves */ - image_verify_buffer_float(ima, ibuf, color_manage); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - if (ibuf->rect) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + if (display_buffer) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); #if 0 else glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float); #endif - + + IMB_display_buffer_release(cache_handle); + if (sima->flag & SI_USE_ALPHA) glDisable(GL_BLEND); } @@ -471,14 +473,14 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image glPixelZoom(1.0f, 1.0f); } -static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy) +static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short startx, short starty, short endx, short endy) { unsigned int *rt, *rp, *rectmain; short y, heigth, len; /* the right offset in rectot */ - rt = ibuf->rect + (starty * ibuf->x + startx); + rt = buffer + (starty * width + startx); len = (endx - startx); heigth = (endy - starty); @@ -487,7 +489,7 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, for (y = 0; y < heigth; y++) { memcpy(rp, rt, len * 4); - rt += ibuf->x; + rt += width; rp += len; } return rectmain; @@ -495,28 +497,34 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { + unsigned char *display_buffer; unsigned int *rect; int dx, dy, sx, sy, x, y; - int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; + void *cache_handle; /* verify valid values, just leave this a while */ if (ima->xrep < 1) return; if (ima->yrep < 1) return; - + + if (ima->flag & IMA_VIEW_AS_RENDER) + display_buffer = IMB_display_buffer_acquire(ibuf, &scene->view_settings, &scene->display_settings, &cache_handle); + else + display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &scene->display_settings, &cache_handle); + + if (!display_buffer) + return; + glPixelZoom(zoomx, zoomy); if (sima->curtile >= ima->xrep * ima->yrep) sima->curtile = ima->xrep * ima->yrep - 1; - /* create char buffer from float if needed */ - image_verify_buffer_float(ima, ibuf, color_manage); - /* retrieve part of image buffer */ dx = ibuf->x / ima->xrep; dy = ibuf->y / ima->yrep; sx = (sima->curtile % ima->xrep) * dx; sy = (sima->curtile / ima->xrep) * dy; - rect = get_part_from_ibuf(ibuf, sx, sy, sx + dx, sy + dy); + rect = get_part_from_buffer((unsigned int*)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); /* draw repeated */ for (sy = 0; sy + dy <= ibuf->y; sy += dy) { @@ -529,10 +537,12 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, glPixelZoom(1.0f, 1.0f); + IMB_display_buffer_release(cache_handle); + MEM_freeN(rect); } -static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy) +static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy) { const double time_current = PIL_check_seconds_timer(); @@ -549,7 +559,7 @@ static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *sce if (ima && (ima->tpageflag & IMA_TILES)) draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); else - draw_image_buffer(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); + draw_image_buffer(C, sima, ar, scene, ibuf, x, y, zoomx, zoomy); /* only draw until running out of time */ if ((PIL_check_seconds_timer() - time_current) > 0.25) @@ -632,22 +642,35 @@ static void draw_image_view_tool(Scene *scene) } #endif -static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *height) +static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height) { Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint); ImBuf *ibuf; unsigned int size, alpha; + unsigned char *display_buffer; unsigned char *rect, *cp; + void *cache_handle; if (!brush || !brush->clone.image) return NULL; ibuf = BKE_image_get_ibuf(brush->clone.image, NULL); - if (!ibuf || !ibuf->rect) + if (!ibuf) return NULL; - rect = MEM_dupallocN(ibuf->rect); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + + if (!display_buffer) { + IMB_display_buffer_release(cache_handle); + + return NULL; + } + + rect = MEM_dupallocN(display_buffer); + + IMB_display_buffer_release(cache_handle); + if (!rect) return NULL; @@ -666,7 +689,7 @@ static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *heigh return rect; } -static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, float zoomy) +static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy) { Brush *brush; int x, y, w, h; @@ -677,7 +700,7 @@ static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, flo if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) { /* this is not very efficient, but glDrawPixels doesn't allow * drawing with alpha */ - clonerect = get_alpha_clone_image(scene, &w, &h); + clonerect = get_alpha_clone_image(C, scene, &w, &h); if (clonerect) { UI_view2d_to_region_no_clip(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); @@ -698,8 +721,10 @@ static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, flo /* draw main image area */ -void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene) +void draw_image_main(const bContext *C, ARegion *ar) { + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); Image *ima; ImBuf *ibuf; float zoomx, zoomy; @@ -748,15 +773,15 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene) if (ibuf == NULL) ED_region_grid_draw(ar, zoomx, zoomy); else if (sima->flag & SI_DRAW_TILE) - draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy); + draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy); else if (ima && (ima->tpageflag & IMA_TILES)) draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); else - draw_image_buffer(sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy); + draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); /* paint helpers */ if (sima->mode == SI_MODE_PAINT) - draw_image_paint_helpers(ar, scene, zoomx, zoomy); + draw_image_paint_helpers(C, ar, scene, zoomx, zoomy); /* XXX integrate this code */ diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 0d3a7614f10..f86e59c41a8 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -52,7 +52,7 @@ struct ARegion *image_has_scope_region(struct ScrArea *sa); extern const char *image_context_dir[]; /* doc access */ /* image_draw.c */ -void draw_image_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene); +void draw_image_main(const struct bContext *C, struct ARegion *ar); void draw_image_grease_pencil(struct bContext *C, short onlyv2d); void draw_image_sample_line(struct SpaceImage *sima); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 52a2bf22d4b..16804c5a1c6 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -55,6 +55,7 @@ #include "BKE_report.h" #include "BKE_screen.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -1168,6 +1169,10 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, } BLI_path_abs(simopts->filepath, G.main->name); } + + /* color management */ + BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings); + BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); } ED_space_image_release_buffer(sima, lock); @@ -1178,6 +1183,8 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op) { if (op->customdata) { + BKE_color_managed_view_settings_free(&simopts->im_format.view_settings); + simopts->im_format = *(ImageFormatData *)op->customdata; } @@ -1190,12 +1197,47 @@ static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) { if (op->customdata) { + BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings); + *(ImageFormatData *)op->customdata = simopts->im_format; } RNA_string_set(op->ptr, "filepath", simopts->filepath); } +static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, int save_as_render, void **cache_handle) +{ + ImageFormatData *imf = &simopts->im_format; + ImBuf *colormanaged_ibuf; + int do_colormanagement; + + *cache_handle = NULL; + do_colormanagement = save_as_render && !BKE_imtype_supports_float(imf->imtype); + + if (do_colormanagement) { + unsigned char *display_buffer; + + display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); + + if (*cache_handle) { + colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); + colormanaged_ibuf->rect = (unsigned int *) display_buffer; + } + else { + /* no cache handle means color management didn't run transformation + * or performed transformation to image's byte buffer which doesn't + * require allocating new image buffer + */ + colormanaged_ibuf = ibuf; + } + } + else { + colormanaged_ibuf = ibuf; + } + + return colormanaged_ibuf; +} + /* assumes name is FILE_MAX */ /* ima->name and ibuf->name should end up the same */ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, int do_newpath) @@ -1205,9 +1247,12 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); if (ibuf) { + void *cache_handle; + ImBuf *colormanaged_ibuf; const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id); const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")); + const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); short ok = FALSE; /* old global to ensure a 2nd save goes to same dir */ @@ -1231,7 +1276,9 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? 32 : 24; } } - + + colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, save_as_render, &cache_handle); + if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { Scene *scene = CTX_data_scene(C); RenderResult *rr = BKE_image_acquire_renderresult(scene, ima); @@ -1245,7 +1292,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI BKE_image_release_renderresult(scene, ima); } else { - if (BKE_imbuf_write_as(ibuf, simopts->filepath, &simopts->im_format, save_copy)) { + if (BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy)) + { ok = TRUE; } } @@ -1284,6 +1332,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI if (relative) { BLI_path_rel(ima->name, relbase); /* only after saving */ } + + IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf); } } else { @@ -1294,6 +1344,13 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image); WM_cursor_wait(0); + + if (cache_handle) { + colormanaged_ibuf->rect = NULL; + IMB_freeImBuf(colormanaged_ibuf); + + IMB_display_buffer_release(cache_handle); + } } ED_space_image_release_buffer(sima, lock); @@ -1302,6 +1359,9 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI static void image_save_as_free(wmOperator *op) { if (op->customdata) { + ImageFormatData *im_format = (ImageFormatData *)op->customdata; + BKE_color_managed_view_settings_free(&im_format->view_settings); + MEM_freeN(op->customdata); op->customdata = NULL; } @@ -1354,6 +1414,11 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve RNA_boolean_set(op->ptr, "copy", TRUE); } + if (ima->source == IMA_SRC_VIEWER) + RNA_boolean_set(op->ptr, "save_as_render", TRUE); + else + RNA_boolean_set(op->ptr, "save_as_render", FALSE); + op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__); memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format)); @@ -1389,7 +1454,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr); - uiTemplateImageSettings(layout, &ptr); + uiTemplateImageSettings(layout, &ptr, FALSE); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); @@ -1417,6 +1482,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ + RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image"); RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender"); WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE, @@ -1601,8 +1667,10 @@ static int image_new_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "color", color); alpha = RNA_boolean_get(op->ptr, "alpha"); - if (!floatbuf && scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + if (!floatbuf) { + /* OCIO_TODO: perhaps we need to convert to display space, not just to sRGB */ linearrgb_to_srgb_v3_v3(color, color); + } if (!alpha) color[3] = 1.0f; @@ -1938,14 +2006,18 @@ typedef struct ImageSampleInfo { float *zfp; int draw; + int color_manage; + int use_default_view; } ImageSampleInfo; -static void image_sample_draw(const bContext *UNUSED(C), ARegion *ar, void *arg_info) +static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) { ImageSampleInfo *info = arg_info; if (info->draw) { - /* no color management needed for images (color_manage=0) */ - ED_image_draw_info(ar, 0, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); + Scene *scene = CTX_data_scene(C); + + ED_image_draw_info(scene, ar, info->color_manage, info->use_default_view, info->channels, + info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); } } @@ -1975,13 +2047,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); - - if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) { - linearrgb_to_srgb_v3_v3(r_col, fp); - } - else { - copy_v3_v3(r_col, fp); - } + linearrgb_to_srgb_v3_v3(r_col, fp); ret = TRUE; } else if (ibuf->rect) { @@ -2003,7 +2069,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); ImageSampleInfo *info = op->customdata; float fx, fy; - + Scene *scene = CTX_data_scene(C); + CurveMapping *curve_mapping = scene->view_settings.curve_mapping; + if (ibuf == NULL) { ED_space_image_release_buffer(sima, lock); info->draw = 0; @@ -2016,6 +2084,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) float *fp; unsigned char *cp; int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y); + Image *image = ED_space_image(sima); CLAMP(x, 0, ibuf->x - 1); CLAMP(y, 0, ibuf->y - 1); @@ -2029,7 +2098,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colfp = NULL; info->zp = NULL; info->zfp = NULL; - + + info->use_default_view = (image->flag & IMA_VIEW_AS_RENDER) ? FALSE : TRUE; + if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); @@ -2044,6 +2115,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = (float)cp[2] / 255.0f; info->colf[3] = (float)cp[3] / 255.0f; info->colfp = info->colf; + + info->color_manage = FALSE; } if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); @@ -2053,6 +2126,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = fp[2]; info->colf[3] = fp[3]; info->colfp = info->colf; + + info->color_manage = TRUE; } if (ibuf->zbuf) { @@ -2063,25 +2138,21 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->zf = ibuf->zbuf_float[y * ibuf->x + x]; info->zfp = &info->zf; } - - if (sima->cumap && ibuf->channels == 4) { + + if (curve_mapping && ibuf->channels == 4) { /* we reuse this callback for set curves point operators */ if (RNA_struct_find_property(op->ptr, "point")) { int point = RNA_enum_get(op->ptr, "point"); if (point == 1) { - curvemapping_set_black_white(sima->cumap, NULL, info->colfp); - if (ibuf->rect_float) - curvemapping_do_ibuf(sima->cumap, ibuf); + curvemapping_set_black_white(curve_mapping, NULL, info->colfp); } else if (point == 0) { - curvemapping_set_black_white(sima->cumap, info->colfp, NULL); - if (ibuf->rect_float) - curvemapping_do_ibuf(sima->cumap, ibuf); + curvemapping_set_black_white(curve_mapping, info->colfp, NULL); } } } - + // XXX node curve integration .. #if 0 { @@ -2211,7 +2282,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) hist->co[1][0] = x2f; hist->co[1][1] = y2f; - BKE_histogram_update_sample_line(hist, ibuf, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0); + BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings); /* reset y zoom */ hist->ymax = 1.0f; @@ -2306,7 +2377,8 @@ static int image_record_composite_apply(bContext *C, wmOperator *op) BKE_image_all_free_anim_ibufs(scene->r.cfra); ntreeCompositTagAnimated(scene->nodetree); - ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra); /* 1 is no previews */ + ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra, + &scene->view_settings, &scene->display_settings); /* 1 is no previews */ ED_area_tag_redraw(CTX_wm_area(C)); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 91a0cba2555..5b288bd6149 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -195,9 +195,7 @@ static SpaceLink *image_new(const bContext *UNUSED(C)) static void image_free(SpaceLink *sl) { SpaceImage *simage = (SpaceImage *) sl; - - if (simage->cumap) - curvemapping_free(simage->cumap); + scopes_free(&simage->scopes); } @@ -217,8 +215,6 @@ static SpaceLink *image_duplicate(SpaceLink *sl) SpaceImage *simagen = MEM_dupallocN(sl); /* clear or remove stuff from old */ - if (simagen->cumap) - simagen->cumap = curvemapping_copy(simagen->cumap); scopes_new(&simagen->scopes); @@ -443,6 +439,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) break; case ND_MODE: case ND_RENDER_RESULT: + case ND_RENDER_OPTIONS: case ND_COMPO_RESULT: if (ED_space_image_show_render(sima)) image_scopes_tag_refresh(sa); @@ -652,7 +649,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) image_main_area_set_view2d(sima, ar); /* we draw image in pixelspace */ - draw_image_main(sima, ar, scene); + draw_image_main(C, ar); /* and uvs in 0.0-1.0 space */ UI_view2d_view_ortho(v2d); @@ -776,9 +773,9 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar) ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); if (ibuf) { if (!sima->scopes.ok) { - BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT); + BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings); } - scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT); + scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); } ED_space_image_release_buffer(sima, lock); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 4c46f5c4c62..1f266c98020 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -63,6 +63,7 @@ #include "UI_resources.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -2023,7 +2024,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER); node_composit_buts_file_output(layout, C, ptr); - uiTemplateImageSettings(layout, &imfptr); + uiTemplateImageSettings(layout, &imfptr, TRUE); uiItemS(layout); @@ -2082,7 +2083,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C col = uiLayoutColumn(layout, FALSE); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE); - uiTemplateImageSettings(col, &imfptr); + uiTemplateImageSettings(col, &imfptr, TRUE); } } } @@ -3051,7 +3052,7 @@ void ED_node_init_butfuncs(void) /* ************** Generic drawing ************** */ -void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) +void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) { if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) { @@ -3059,7 +3060,10 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { + SpaceNode *snode = CTX_wm_space_node(C); float x, y; + unsigned char *display_buffer; + void *cache_handle; glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -3078,15 +3082,10 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof; y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof; - if (!ibuf->rect) { - if (color_manage) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - else - ibuf->profile = IB_PROFILE_NONE; - IMB_rect_from_float(ibuf); - } - if (ibuf->rect) { + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + + if (display_buffer) { if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) { int ofs; @@ -3114,7 +3113,7 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) #ifdef __BIG_ENDIAN__ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); #endif - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, ibuf->rect); + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer); #ifdef __BIG_ENDIAN__ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); @@ -3126,7 +3125,7 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); @@ -3134,12 +3133,14 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) else { glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); glPixelZoom(1.0f, 1.0f); } } + IMB_display_buffer_release(cache_handle); + /** @note draw selected info on backdrop */ if (snode->edittree) { bNode *node = snode->edittree->nodes.first; diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index f1a91df6f53..7d35f566140 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1091,8 +1091,6 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) { View2DScrollers *scrollers; SpaceNode *snode = CTX_wm_space_node(C); - Scene *scene = CTX_data_scene(C); - int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; bNodeLinkDrag *nldrag; LinkData *linkdata; @@ -1118,7 +1116,7 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) UI_view2d_multi_grid_draw(v2d, 25.0f, 5, 2); /* backdrop */ - draw_nodespace_back_pix(ar, snode, color_manage); + draw_nodespace_back_pix(C, ar, snode); /* nodes */ snode_set_context(snode, CTX_data_scene(C)); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 9e04bd36a1f..cc386da2e93 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -148,8 +148,9 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog { CompoJob *cj = cjv; bNodeTree *ntree = cj->localtree; + Scene *scene = cj->scene; - if (cj->scene->use_nodes == FALSE) + if (scene->use_nodes == FALSE) return; cj->stop = stop; @@ -165,7 +166,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog // XXX BIF_store_spare(); - ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1); /* 1 is do_previews */ + ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */ ntree->test_break = NULL; ntree->stats_draw = NULL; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 2bb550d1a63..36ebddc8d22 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -125,7 +125,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link); void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3); int node_link_bezier_points(View2D * v2d, SpaceNode * snode, bNodeLink * link, float coord_array[][2], int resol); // void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 ); -void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage); +void draw_nodespace_back_pix(const struct bContext *C, ARegion *ar, SpaceNode *snode); /* node_add.c */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index e89e798a6fa..8e38247348f 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -327,12 +327,12 @@ typedef struct ImageSampleInfo { void *draw_handle; int x, y; int channels; - int color_manage; unsigned char col[4]; float colf[4]; int draw; + int color_manage; } ImageSampleInfo; static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) @@ -341,7 +341,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, + ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, info->x, info->y, info->col, info->colf, NULL, NULL /* zbuf - unused for nodes */ ); @@ -381,12 +381,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); /* IB_PROFILE_NONE is default but infact its linear */ - if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) { - linearrgb_to_srgb_v3_v3(r_col, fp); - } - else { - copy_v3_v3(r_col, fp); - } + linearrgb_to_srgb_v3_v3(r_col, fp); ret = TRUE; } else if (ibuf->rect) { @@ -419,10 +414,6 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) } if (!ibuf->rect) { - if (info->color_manage) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - else - ibuf->profile = IB_PROFILE_NONE; IMB_rect_from_float(ibuf); } @@ -457,6 +448,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[1] = (float)cp[1] / 255.0f; info->colf[2] = (float)cp[2] / 255.0f; info->colf[3] = (float)cp[3] / 255.0f; + + info->color_manage = FALSE; } if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); @@ -465,6 +458,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[1] = fp[1]; info->colf[2] = fp[2]; info->colf[3] = fp[3]; + + info->color_manage = TRUE; } ED_node_sample_set(info->colf); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 0c316450c29..7363bf2fbd8 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -52,6 +52,7 @@ #include "BKE_sound.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "BIF_gl.h" @@ -68,6 +69,9 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "WM_api.h" +#include "WM_types.h" + /* own include */ #include "sequencer_intern.h" @@ -846,6 +850,50 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int return ibuf; } +static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf) +{ + if (scopes->reference_ibuf != ibuf) { + if (scopes->zebra_ibuf) { + IMB_freeImBuf(scopes->zebra_ibuf); + scopes->zebra_ibuf = NULL; + } + + if (scopes->waveform_ibuf) { + IMB_freeImBuf(scopes->waveform_ibuf); + scopes->waveform_ibuf = NULL; + } + + if (scopes->sep_waveform_ibuf) { + IMB_freeImBuf(scopes->sep_waveform_ibuf); + scopes->sep_waveform_ibuf = NULL; + } + + if (scopes->vector_ibuf) { + IMB_freeImBuf(scopes->vector_ibuf); + scopes->vector_ibuf = NULL; + } + + if (scopes->histogram_ibuf) { + IMB_freeImBuf(scopes->histogram_ibuf); + scopes->histogram_ibuf = NULL; + } + } +} + +static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_cb) (ImBuf *ibuf)) +{ + ImBuf *display_ibuf = IMB_dupImBuf(ibuf); + ImBuf *scope; + + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + + scope = make_scope_cb(display_ibuf); + + IMB_freeImBuf(display_ibuf); + + return scope; +} + void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, int draw_overlay) { struct Main *bmain = CTX_data_main(C); @@ -859,6 +907,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq float col[3]; GLuint texid; GLuint last_texid; + unsigned char *display_buffer; + void *cache_handle = NULL; render_size = sseq->render_size; if (render_size == 0) { @@ -906,38 +956,64 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; - - switch (sseq->mainb) { - case SEQ_DRAW_IMG_IMBUF: - if (sseq->zebra != 0) { - scope = make_zebra_view_from_ibuf(ibuf, sseq->zebra); - } - break; - case SEQ_DRAW_IMG_WAVEFORM: - if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { - scope = make_sep_waveform_view_from_ibuf(ibuf); - } - else { - scope = make_waveform_view_from_ibuf(ibuf); - } - break; - case SEQ_DRAW_IMG_VECTORSCOPE: - scope = make_vectorscope_view_from_ibuf(ibuf); - break; - case SEQ_DRAW_IMG_HISTOGRAM: - scope = make_histogram_view_from_ibuf(ibuf); - break; + + if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) { + SequencerScopes *scopes = &sseq->scopes; + + sequencer_check_scopes(scopes, ibuf); + + switch (sseq->mainb) { + case SEQ_DRAW_IMG_IMBUF: + if (!scopes->zebra_ibuf) { + ImBuf *display_ibuf = IMB_dupImBuf(ibuf); + + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra); + IMB_freeImBuf(display_ibuf); + } + scope = scopes->zebra_ibuf; + break; + case SEQ_DRAW_IMG_WAVEFORM: + if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { + if (!scopes->sep_waveform_ibuf) + scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf); + scope = scopes->sep_waveform_ibuf; + } + else { + if (!scopes->waveform_ibuf) + scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf); + scope = scopes->waveform_ibuf; + } + break; + case SEQ_DRAW_IMG_VECTORSCOPE: + if (!scopes->vector_ibuf) + scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf); + scope = scopes->vector_ibuf; + break; + case SEQ_DRAW_IMG_HISTOGRAM: + if (!scopes->histogram_ibuf) + scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf); + scope = scopes->histogram_ibuf; + break; + } + + scopes->reference_ibuf = ibuf; } if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; - } - if (ibuf->rect_float && ibuf->rect == NULL) { - IMB_rect_from_float(ibuf); + if (ibuf->rect_float && ibuf->rect == NULL) { + IMB_rect_from_float(ibuf); + } + + display_buffer = (unsigned char *)ibuf->rect; } - + else { + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + } + /* setting up the view - actual drawing starts here */ UI_view2d_view_ortho(v2d); @@ -950,7 +1026,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); glBegin(GL_QUADS); if (draw_overlay) { @@ -1030,7 +1106,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* draw grease-pencil (image aligned) */ draw_gpencil_2dimage(C); - IMB_freeImBuf(ibuf); + if (!scope) + IMB_freeImBuf(ibuf); /* ortho at pixel level */ UI_view2d_view_restore(C); @@ -1065,6 +1142,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } + if (cache_handle) + IMB_display_buffer_release(cache_handle); } #if 0 diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 1655b3ec7bc..d09d6a29c10 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -460,12 +460,28 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) memset(bins, 0, sizeof(bins)); + #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256) for (y = 0; y < ibuf->y; y++) { + unsigned int cur_bins[3][512]; + + memset(cur_bins, 0, sizeof(cur_bins)); + for (x = 0; x < ibuf->x; x++) { - bins[0][*src++]++; - bins[1][*src++]++; - bins[2][*src++]++; - src++; + unsigned char *pixel = src + (y * ibuf->x + x) * 4; + + cur_bins[0][pixel[0]]++; + cur_bins[1][pixel[1]]++; + cur_bins[2][pixel[2]]++; + } + + #pragma omp critical + { + int i; + for (i = 0; i < 512; i++) { + bins[0][i] += cur_bins[0][i]; + bins[1][i] += cur_bins[1][i]; + bins[2][i] += cur_bins[2][i]; + } } } @@ -490,7 +506,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) return rval; } -static int get_bin_float(float f) +BLI_INLINE int get_bin_float(float f) { if (f < -0.25f) { return 0; @@ -512,12 +528,28 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) memset(bins, 0, sizeof(bins)); + #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256) for (y = 0; y < ibuf->y; y++) { + unsigned int cur_bins[3][512]; + + memset(cur_bins, 0, sizeof(cur_bins)); + for (x = 0; x < ibuf->x; x++) { - bins[0][get_bin_float(*src++)]++; - bins[1][get_bin_float(*src++)]++; - bins[2][get_bin_float(*src++)]++; - src++; + float *pixel = src + (y * ibuf->x + x) * 4; + + cur_bins[0][get_bin_float(pixel[0])]++; + cur_bins[1][get_bin_float(pixel[1])]++; + cur_bins[2][get_bin_float(pixel[2])]++; + } + + #pragma omp critical + { + int i; + for (i = 0; i < 512; i++) { + bins[0][i] += cur_bins[0][i]; + bins[1][i] += cur_bins[1][i]; + bins[2][i] += cur_bins[2][i]; + } } } diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index f5a13e4efb7..3c3489115a4 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -49,6 +49,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "UI_view2d.h" @@ -70,6 +71,7 @@ typedef struct ImageSampleInfo { float *colfp; int draw; +int color_manage; } ImageSampleInfo; static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) @@ -78,8 +80,8 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, - info->x, info->y, info->col, info->colf, NULL, NULL); + ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, + info->x, info->y, info->colp, info->colfp, NULL, NULL); } } @@ -131,6 +133,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = (float)cp[2] / 255.0f; info->colf[3] = (float)cp[3] / 255.0f; info->colfp = info->colf; + + info->color_manage = FALSE; } if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); @@ -140,6 +144,11 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = fp[2]; info->colf[3] = fp[3]; info->colfp = info->colf; + + /* sequencer's image buffers are in non-linear space, need to make them linear */ + BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->colf); + + info->color_manage = TRUE; } } else { diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index f7362aab7aa..8ac50a57b10 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -57,8 +57,19 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "IMB_imbuf.h" + #include "sequencer_intern.h" // own include +/**************************** common state *****************************/ + +static void sequencer_scopes_tag_refresh(ScrArea *sa) +{ + SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first; + + sseq->scopes.reference_ibuf = NULL; +} + /* ******************** manage regions ********************* */ ARegion *sequencer_has_buttons_region(ScrArea *sa) @@ -183,12 +194,27 @@ static SpaceLink *sequencer_new(const bContext *C) } /* not spacelink itself */ -static void sequencer_free(SpaceLink *UNUSED(sl)) +static void sequencer_free(SpaceLink *sl) { -// SpaceSeq *sseq= (SpaceSequencer*) sl; - + SpaceSeq *sseq= (SpaceSeq *) sl; + SequencerScopes *scopes = &sseq->scopes; + // XXX if (sseq->gpd) BKE_gpencil_free(sseq->gpd); + if (scopes->zebra_ibuf) + IMB_freeImBuf(scopes->zebra_ibuf); + + if (scopes->waveform_ibuf) + IMB_freeImBuf(scopes->waveform_ibuf); + + if (scopes->sep_waveform_ibuf) + IMB_freeImBuf(scopes->sep_waveform_ibuf); + + if (scopes->vector_ibuf) + IMB_freeImBuf(scopes->vector_ibuf); + + if (scopes->histogram_ibuf) + IMB_freeImBuf(scopes->histogram_ibuf); } @@ -290,7 +316,24 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) return (SpaceLink *)sseqn; } - +static void sequencer_listener(ScrArea *sa, wmNotifier *wmn) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + case ND_FRAME: + case ND_SEQUENCER: + sequencer_scopes_tag_refresh(sa); + break; + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_SEQUENCER) + sequencer_scopes_tag_refresh(sa); + break; + } +} /* *********************** sequencer (main) region ************************ */ /* add handlers, stuff you only do once or on area/region changes */ @@ -610,6 +653,7 @@ void ED_spacetype_sequencer(void) st->context = sequencer_context; st->dropboxes = sequencer_dropboxes; st->refresh = sequencer_refresh; + st->listener = sequencer_listener; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 895b256ab84..ca4f00be2d5 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -372,7 +372,15 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.ob = ob; Gtexdraw.is_tex = is_tex; - Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; + + /* OCIO_TODO: for now assume OpenGL is always doing color management and working in sRGB space + * supporting for real display conversion could be nice here, but it's a bit challenging + * since all the shaders should be aware of such a transform + * perhaps this flag could be completely removed before release in separated commit and + * be re-implemented if real display transform would be needed + */ + Gtexdraw.color_profile = TRUE; + memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); set_draw_settings_cached(1, NULL, NULL, Gtexdraw); glShadeModel(GL_SMOOTH); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 8a334423ab0..5fbf1971349 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -69,6 +69,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -2375,7 +2376,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); invert_m4_m4(rv3d.persinv, rv3d.viewinv); - ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE); + ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE, FALSE); GPU_lamp_shadow_buffer_unbind(shadow->lamp); v3d->drawtype = drawtype; @@ -2514,7 +2515,7 @@ static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4], - int do_bgpic) + int do_bgpic, int colormanage_background) { RegionView3D *rv3d = ar->regiondata; Base *base; @@ -2553,10 +2554,25 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, /* set background color, fallback on the view background color * (if active clip is set but frame is failed to load fallback to horizon color as background) */ if (scene->world) { - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + /* NOTE: currently OpenGL is supposed to always work in sRGB space and do not + * apply any tonemaps since it's really tricky to support for all features (GLSL, textures, etc) + * but due to compatibility issues background is being affected display transform, so we can + * emulate behavior of disabled colro management + * but this function is also used for sequencer's scene strips which shouldn't be affected by + * tonemaps now and should be purely sRGB, that's why we've got this colormanage_background + * we can drop this flag in cost of some compatibility loss -- background wouldn't be + * color managed in 3d viewport + * same goes to opengl rendering, where color profile should be applied as very final step + */ + + if (colormanage_background) { + IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings, + &scene->display_settings); + } + else { linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); - else - copy_v3_v3(backcol, &scene->world->horr); + } + glClearColor(backcol[0], backcol[1], backcol[2], 0.0); } else { @@ -2661,7 +2677,8 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, /* utility func for ED_view3d_draw_offscreen */ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, - int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256]) + int sizex, int sizey, unsigned int flag, int draw_background, + int colormanage_background, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; @@ -2686,10 +2703,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, colormanage_background); } else { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, colormanage_background); } /* read in pixels & stamp */ @@ -2714,7 +2731,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, /* creates own 3d views, used by the sequencer */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, - unsigned int flag, int drawtype, int draw_background, char err_out[256]) + unsigned int flag, int drawtype, int draw_background, + int colormanage_background, char err_out[256]) { View3D v3d = {NULL}; ARegion ar = {NULL}; @@ -2753,7 +2771,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); invert_m4_m4(rv3d.persinv, rv3d.viewinv); - return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, draw_background, err_out); + return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, + draw_background, colormanage_background, err_out); // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty); } @@ -2936,10 +2955,9 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const /* clear background */ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) { - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); - else - copy_v3_v3(backcol, &scene->world->horr); + IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings, + &scene->display_settings); + glClearColor(backcol[0], backcol[1], backcol[2], 0.0); } else @@ -3163,6 +3181,17 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) const char *grid_unit = NULL; int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER)); + /* --- until we get a clue and make viewport threadsafe (temp mango change for stability) */ + if (G.is_rendering) { + ED_region_pixelspace(ar); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + UI_ThemeClearColor(TH_BACK); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + BLF_draw_default(10,10,0, "do do da da.. da da.. da da.. can't touch this! it's render time", 512); + return; + } + /* --- end temp mango change */ + /* draw viewport using opengl */ if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); |