Merged changes in the trunk up to revision 55357.
[blender.git] / source / blender / render / intern / source / render_result.c
index 603e49766b1b9903a7591c4a49d215265ab63156..21e7b6986100826b7679b7c8a38ecfb725ee8124 100644 (file)
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
 
-#include "BKE_image.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_report.h"
-
+#include "BLI_utildefines.h"
 #include "BLI_fileops.h"
 #include "BLI_listbase.h"
 #include "BLI_path_util.h"
 #include "BLI_rect.h"
 #include "BLI_string.h"
 #include "BLI_threads.h"
-#include "BLI_utildefines.h"
+
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
 
 #include "intern/openexr/openexr_multi.h"
 
 #include "render_result.h"
 #include "render_types.h"
 
+#ifdef WITH_FREESTYLE
+#  include "FRS_freestyle_config.h"
+#endif
+
 /********************************** Free *************************************/
 
 void render_result_free(RenderResult *res)
@@ -420,8 +426,8 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
        SceneRenderLayer *srl;
        int rectx, recty, nr;
        
-       rectx = BLI_RCT_SIZE_X(partrct);
-       recty = BLI_RCT_SIZE_Y(partrct);
+       rectx = BLI_rcti_size_x(partrct);
+       recty = BLI_rcti_size_y(partrct);
        
        if (rectx <= 0 || recty <= 0)
                return NULL;
@@ -432,7 +438,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
        rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop;
        /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
        rr->crop = crop;
-       
+
        /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
        rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
        rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
@@ -554,20 +560,24 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
                        IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
                        IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
                }
-               else
+               else {
                        rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
+               }
                
                /* note, this has to be in sync with scene.c */
                rl->lay = (1 << 20) - 1;
                rl->layflag = 0x7FFF;    /* solid ztra halo strand */
                rl->passflag = SCE_PASS_COMBINED;
+#ifdef WITH_FREESTYLE
+               FRS_init_freestyle_config(&srl->freestyleConfig);
+#endif
                
                re->r.actlay = 0;
        }
        
        /* border render; calculate offset for use in compositor. compo is centralized coords */
-       rr->xof = re->disprect.xmin + BLI_RCT_CENTER_X(&re->disprect) - (re->winx / 2);
-       rr->yof = re->disprect.ymin + BLI_RCT_CENTER_Y(&re->disprect) - (re->winy / 2);
+       rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
+       rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
        
        return rr;
 }
@@ -624,12 +634,13 @@ static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float
 }
 
 /* from imbuf, if a handle was returned we convert this to render result */
-RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
+RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty)
 {
        RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
        RenderLayer *rl;
        RenderPass *rpass;
-       
+       const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
        rr->rectx = rectx;
        rr->recty = recty;
        
@@ -642,6 +653,11 @@ RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
                for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
                        rpass->rectx = rectx;
                        rpass->recty = recty;
+
+                       if (rpass->channels >= 3) {
+                               IMB_colormanagement_transform(rpass->rect, rpass->rectx, rpass->recty, rpass->channels,
+                                                             colorspace, to_colorspace, predivide);
+                       }
                }
        }
        
@@ -691,16 +707,18 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
        RenderPass *rpass, *rpassp;
        
        for (rl = rr->layers.first; rl; rl = rl->next) {
-               for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
-                       if (strcmp(rlp->name, rl->name) == 0) {
-                               /* combined */
-                               if (rl->rectf && rlp->rectf)
-                                       do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
-                               
-                               /* passes are allocated in sync */
-                               for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp; rpass = rpass->next, rpassp = rpassp->next) {
-                                       do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
-                               }
+               rlp = RE_GetRenderLayer(rrpart, rl->name);
+               if (rlp) {
+                       /* combined */
+                       if (rl->rectf && rlp->rectf)
+                               do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
+
+                       /* passes are allocated in sync */
+                       for (rpass = rl->passes.first, rpassp = rlp->passes.first;
+                            rpass && rpassp;
+                            rpass = rpass->next, rpassp = rpassp->next)
+                       {
+                               do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
                        }
                }
        }
@@ -746,21 +764,24 @@ int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *file
                /* combined */
                if (rl->rectf) {
                        int a, xstride = 4;
-                       for (a = 0; a < xstride; a++)
-                               IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
+                       for (a = 0; a < xstride; a++) {
+                               IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a),
                                                    xstride, xstride * rr->rectx, rl->rectf + a);
+                       }
                }
                
                /* passes are allocated in sync */
                for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
                        int a, xstride = rpass->channels;
                        for (a = 0; a < xstride; a++) {
-                               if (rpass->passtype)
-                                       IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
+                               if (rpass->passtype) {
+                                       IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a),
                                                            xstride, xstride * rr->rectx, rpass->rect + a);
-                               else
-                                       IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 
+                               }
+                               else {
+                                       IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a),
                                                            xstride, xstride * rr->rectx, rpass->rect + a);
+                               }
                        }
                }
        }
@@ -772,7 +793,7 @@ int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *file
        }
        else {
                /* TODO, get the error from openexr's exception */
-               BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console");
+               BKE_report(reports, RPT_ERROR, "Error writing render result (see console)");
                success = FALSE;
        }
        IMB_exr_close(exrhandle);
@@ -818,8 +839,9 @@ void render_result_single_layer_end(Render *re)
                
                /* reconstruct render result layers */
                for (nr = 0, srl = re->scene->r.layers.first; srl; srl = srl->next, nr++) {
-                       if (nr == re->r.actlay)
+                       if (nr == re->r.actlay) {
                                BLI_addtail(&re->result->layers, rl);
+                       }
                        else {
                                rlpush = RE_GetRenderLayer(re->pushedresult, srl->name);
                                if (rlpush) {
@@ -845,10 +867,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
        BLI_lock_thread(LOCK_IMAGE);
        
        for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
-               for (rl = rr->layers.first; rl; rl = rl->next)
-                       if (strcmp(rl->name, rlp->name) == 0)
-                               break;
-               
+               rl = RE_GetRenderLayer(rr, rlp->name);
+
+               /* should never happen but prevents crash if it does */
+               BLI_assert(rl);
+               if (UNLIKELY(rl == NULL)) {
+                       continue;
+               }
+
                if (rrpart->crop) { /* filters add pixel extra */
                        offs = (rrpart->crop + rrpart->crop * rrpart->rectx);
                }
@@ -859,17 +885,19 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
                /* combined */
                if (rlp->rectf) {
                        int a, xstride = 4;
-                       for (a = 0; a < xstride; a++)
+                       for (a = 0; a < xstride; a++) {
                                IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 
                                                    xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs);
+                       }
                }
                
                /* passes are allocated in sync */
                for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
                        int a, xstride = rpassp->channels;
-                       for (a = 0; a < xstride; a++)
+                       for (a = 0; a < xstride; a++) {
                                IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
                                                    xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
+                       }
                }
                
        }
@@ -878,10 +906,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
        partx = rrpart->tilerect.xmin + rrpart->crop;
 
        for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
-               for (rl = rr->layers.first; rl; rl = rl->next)
-                       if (strcmp(rl->name, rlp->name) == 0)
-                               break;
-       
+               rl = RE_GetRenderLayer(rr, rlp->name);
+
+               /* should never happen but prevents crash if it does */
+               BLI_assert(rl);
+               if (UNLIKELY(rl == NULL)) {
+                       continue;
+               }
+
                IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
        }
 
@@ -899,7 +931,7 @@ static void save_empty_result_tiles(Render *re)
                        IMB_exrtile_clear_channels(rl->exrhandle);
                
                        for (pa = re->parts.first; pa; pa = pa->next) {
-                               if (pa->ready == 0) {
+                               if (pa->status != PART_STATUS_READY) {
                                        int party = pa->disprect.ymin - re->disprect.ymin + pa->crop;
                                        int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop;
                                        IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
@@ -958,11 +990,9 @@ void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
 /* path to temporary exr file */
 void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath)
 {
-       char di[FILE_MAX], name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE];
-       
-       BLI_strncpy(di, G.main->name, FILE_MAX);
-       BLI_splitdirstring(di, fi);
+       char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE];
        
+       BLI_split_file_part(G.main->name, fi, sizeof(fi));
        if (sample == 0)
                BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
        else
@@ -1052,8 +1082,7 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
 
 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
 {
-       int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) ? IB_cm_predivide : 0;
-       ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
+       ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
        
        /* if not exists, BKE_imbuf_write makes one */
        ibuf->rect = (unsigned int *)rr->rect32;
@@ -1063,16 +1092,16 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
        /* float factor for random dither, imbuf takes care of it */
        ibuf->dither = rd->dither_intensity;
        
-       /* prepare to gamma correct to sRGB color space */
-       if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
-               /* sequence editor can generate 8bpc render buffers */
-               if (ibuf->rect) {
-                       ibuf->profile = IB_PROFILE_SRGB;
-                       if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32))
-                               IMB_float_from_rect(ibuf);
+       /* prepare to gamma correct to sRGB color space
+        * note that sequence editor can generate 8bpc render buffers
+        */
+       if (ibuf->rect) {
+               if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
+                       IMB_float_from_rect(ibuf);
                }
-               else {
-                       ibuf->profile = IB_PROFILE_LINEAR_RGB;
+               else  {
+                       /* ensure no float buffer remained from previous frame */
+                       ibuf->rect_float = NULL;
                }
        }
 
@@ -1127,19 +1156,15 @@ void render_result_rect_fill_zero(RenderResult *rr)
                rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
 }
 
-void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty)
+void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty,
+                                   const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
 {
        if (rr->rect32) {
                memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
        }
        else if (rr->rectf) {
-               int profile_from = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
-               int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-               int dither = 0;
-
-               IMB_buffer_byte_from_float((unsigned char *)rect, rr->rectf,
-                                          4, dither, IB_PROFILE_SRGB, profile_from, predivide,
-                                          rr->rectx, rr->recty, rr->rectx, rr->rectx);
+               IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
+                                                  view_settings, display_settings, TRUE);
        }
        else
                /* else fill with black */