svn merge ^/trunk/blender -r48691:48729
authorCampbell Barton <ideasman42@gmail.com>
Sun, 8 Jul 2012 15:55:58 +0000 (15:55 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 8 Jul 2012 15:55:58 +0000 (15:55 +0000)
13 files changed:
1  2 
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/image.c
source/blender/editors/interface/resources.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_ops.c
source/blender/imbuf/intern/allocimbuf.c
source/blender/makesdna/DNA_space_types.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/render_result.c
source/blender/windowmanager/intern/wm_init_exit.c
source/creator/creator.c

index a2bf42a39e17c88e3cd53163c5f85d6638ff93c8,9e222307aa99836244872972518903b5b45723cc..e89b82138e32cfbfd7b84dc0a1999920d6ccfd31
@@@ -91,8 -91,6 +91,8 @@@
  
  #include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie
  
 +#include "IMB_colormanagement.h"
 +
  #ifdef WITH_PYTHON
  #include "BPY_extern.h"
  #endif
@@@ -303,8 -301,8 +303,8 @@@ static void setup_app_data(bContext *C
                //setscreen(G.curscreen);
        }
        
-       // FIXME: this version patching should really be part of the file-reading code, 
-       // but we still get too many unrelated data-corruption crashes otherwise...
+       /* FIXME: this version patching should really be part of the file-reading code,
+        * but we still get too many unrelated data-corruption crashes otherwise... */
        if (G.main->versionfile < 250)
                do_versions_ipos_to_animato(G.main);
        
  
        /* baseflags, groups, make depsgraph, etc */
        BKE_scene_set_background(G.main, CTX_data_scene(C));
 -      
 +
 +      if (mode != 'u') {
 +              IMB_colormanagement_check_file_config(G.main);
 +      }
 +
        MEM_freeN(bfd);
  
        (void)curscene; /* quiet warning */
index a5e424edbf9d4b70b5c5a17e01fabd5fa6afc5ce,61cfc8e747bbb1e218079e0f4f939a96889fa048..24269c287bbc5160a62c56f1bab43608ff850be4
@@@ -1011,20 -1011,6 +1011,20 @@@ int BKE_imtype_supports_quality(const c
        return 0;
  }
  
 +int BKE_imtype_supports_float(const char imtype)
 +{
 +      switch (imtype) {
 +              case R_IMF_IMTYPE_CINEON:
 +              case R_IMF_IMTYPE_DPX:
 +              case R_IMF_IMTYPE_RADHDR:
 +              case R_IMF_IMTYPE_OPENEXR:
 +              case R_IMF_IMTYPE_MULTILAYER:
 +              case R_IMF_IMTYPE_JP2:
 +                      return TRUE;
 +      }
 +      return 0;
 +}
 +
  char BKE_imtype_valid_channels(const char imtype)
  {
        char chan_flag = IMA_CHAN_FLAG_RGB; /* assume all support rgb */
@@@ -1230,7 -1216,7 +1230,7 @@@ void BKE_imbuf_to_image_format(struct I
  {
        BKE_imformat_defaults(im_format);
  
-       // file type
+       /* file type */
  
        if (imbuf->ftype == IMAGIC)
                im_format->imtype = R_IMF_IMTYPE_IRIS;
                im_format->quality = imbuf->ftype & ~JPG_MSK;
        }
  
-       // planes
+       /* planes */
        switch (imbuf->channels) {
                case 0:
                case 4: im_format->planes = R_IMF_PLANES_RGBA;
@@@ -2556,11 -2542,7 +2556,11 @@@ static ImBuf *image_get_render_result(I
        /* free rect buffer if float buffer changes, so it can be recreated with
         * the updated result, and also in case we got byte buffer from sequencer,
         * so we don't keep reference to freed buffer */
 -      if (ibuf->rect_float != rectf || rect || !rectf)
 +      
 +      /* todo: this fix breaks save buffers render progress 
 +         if (ibuf->rect_float != rectf || rect || !rectf) */
 +
 +      if (ibuf->rect_float != rectf || rect)
                imb_freerectImBuf(ibuf);
  
        if (rect)
index 9a965fa8f7fb4dbb4f1f170978013c67cfe31558,1d7a423a15a86959b95c704bfa14a677f73531a9..f3acd970a57cf68947898aec57d21aace84dafc6
@@@ -91,7 -91,7 +91,7 @@@ const unsigned char *UI_ThemeGetColorPt
        
        if (btheme) {
        
-               // first check for ui buttons theme
+               /* first check for ui buttons theme */
                if (colorid < TH_THEMEUI) {
                
                        switch (colorid) {
@@@ -936,7 -936,7 +936,7 @@@ void UI_SetTheme(int spacetype, int reg
                theme_regionid = RGN_TYPE_WINDOW;
        }
        else {
-               // later on, a local theme can be found too
+               /* later on, a local theme can be found too */
                theme_active = U.themes.first;
                theme_spacetype = spacetype;
                theme_regionid = regionid;
@@@ -1295,8 -1295,8 +1295,8 @@@ void init_userdef_do_versions(void
        /* transform widget settings */
        if (U.tw_hotspot == 0) {
                U.tw_hotspot = 14;
-               U.tw_size = 20;          // percentage of window size
-               U.tw_handlesize = 16;    // percentage of widget radius
+               U.tw_size = 20;          /* percentage of window size */
+               U.tw_handlesize = 16;    /* percentage of widget radius */
        }
        if (U.pad_rot_angle == 0)
                U.pad_rot_angle = 15;
                for (btheme = U.themes.first; btheme; btheme = btheme->next) {
                        /* check for (alpha == 0) is safe, then color was never set */
                        if (btheme->ttime.back[3] == 0) {
-                               // copied from ui_theme_init_default
+                               /* copied from ui_theme_init_default */
                                btheme->ttime = btheme->tv3d;
                                rgba_char_args_set_fl(btheme->ttime.back,   0.45, 0.45, 0.45, 1.0);
                                rgba_char_args_set_fl(btheme->ttime.grid,   0.36, 0.36, 0.36, 1.0);
        if (U.dbl_click_time == 0) {
                U.dbl_click_time = 350;
        }
 -      if (U.anim_player_preset == 0) {
 -              U.anim_player_preset = 1;
 -      }
        if (U.scrcastfps == 0) {
                U.scrcastfps = 10;
                U.scrcastwait = 50;
index b92f4829cd32de72e0335f997589c5edc00e6013,116e155f50151817bcc2cce7566e08a69494d5cc..1f4fc9398186764dd052d292c792479d9e797454
@@@ -372,7 -372,7 +372,7 @@@ static char *slot_menu(void
  static char *layer_menu(RenderResult *rr, short *UNUSED(curlay))
  {
        RenderLayer *rl;
-       int len = 64 + 32 * BLI_countlist(&rr->layers);
+       int len = 64 + RE_MAXNAME * BLI_countlist(&rr->layers);
        short a, nr = 0;
        char *str = MEM_callocN(len, "menu layers");
        
@@@ -798,14 -798,11 +798,14 @@@ void uiTemplateImageSettings(uiLayout *
  {
        ImageFormatData *imf = imfptr->data;
        ID *id = imfptr->id.data;
 +      PointerRNA display_settings_ptr, view_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);
  
        }
  
        if (is_render_out && (imf->imtype == R_IMF_IMTYPE_OPENEXR)) {
 +              show_preview = TRUE;
                uiItemR(row, imfptr, "use_preview", 0, NULL, ICON_NONE);
        }
  
                uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
  #endif
        }
 +
 +      /* color management */
 +      if (!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);
 +
 +              prop = RNA_struct_find_property(imfptr, "view_settings");
 +              view_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);
 +
 +              uiItemR(col, &view_settings_ptr, "view_transform", 0, NULL, ICON_NONE);
 +              uiItemR(col, &view_settings_ptr, "exposure", 0, NULL, ICON_NONE);
 +              uiItemR(col, &view_settings_ptr, "gamma", 0, NULL, ICON_NONE);
 +      }
  }
  
  void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
index 28fe1459239db19c83ac204d8617aaf6df05fa0a,ca16558f3a6dad68c36a1c515d1678fc186a5c38..dba943589ba59857f802e3ae0d57d06153274951
@@@ -55,7 -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"
  
@@@ -1083,14 -1082,12 +1083,14 @@@ static char imtype_best_depth(ImBuf *ib
        }
  }
  
 -static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, Scene *scene, const short guess_path)
 +static int save_image_options_init(bContext *C, SaveImageOptions *simopts, SpaceImage *sima, Scene *scene, const short guess_path)
  {
        void *lock;
        ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
  
        if (ibuf) {
 +              wmWindow *win = CTX_wm_window(C);
 +              const ColorManagedViewSettings *view_settings;
                Image *ima = sima->image;
                short is_depth_set = FALSE;
  
                        }
                        BLI_path_abs(simopts->filepath, G.main->name);
                }
 +
 +              /* color management */
 +              view_settings = IMB_view_settings_get_effective(win, &sima->view_settings);
 +
 +              BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &win->display_settings);
 +              BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, view_settings);
        }
  
        ED_space_image_release_buffer(sima, lock);
@@@ -1173,29 -1164,6 +1173,29 @@@ static void save_image_options_to_op(Sa
        RNA_string_set(op->ptr, "filepath", simopts->filepath);
  }
  
 +static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, void **cache_handle)
 +{
 +      ImageFormatData *imf = &simopts->im_format;
 +      ImBuf *colormanaged_ibuf;
 +      int do_colormanagement;
 +
 +      *cache_handle = NULL;
 +      do_colormanagement = !BKE_imtype_supports_float(imf->imtype);
 +
 +      if (do_colormanagement) {
 +              unsigned char *display_buffer =
 +                      IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle);
 +
 +              colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0);
 +              colormanaged_ibuf->rect = (unsigned int *) display_buffer;
 +      }
 +      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)
        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"));
                                ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? 32 : 24;
                        }
                }
 -              
 +
 +              colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, &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);
                        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;
                        }
                }
                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);
@@@ -1327,7 -1284,7 +1327,7 @@@ static int image_save_as_exec(bContext 
  
        /* just in case to initialize values,
         * these should be set on invoke or by the caller. */
 -      save_image_options_init(&simopts, sima, CTX_data_scene(C), 0);
 +      save_image_options_init(C, &simopts, sima, CTX_data_scene(C), 0);
  
        save_image_options_from_op(&simopts, op);
  
@@@ -1356,7 -1313,7 +1356,7 @@@ static int image_save_as_invoke(bContex
  
        save_image_options_defaults(&simopts);
  
 -      if (save_image_options_init(&simopts, sima, scene, TRUE) == 0)
 +      if (save_image_options_init(C, &simopts, sima, scene, TRUE) == 0)
                return OPERATOR_CANCELLED;
        save_image_options_to_op(&simopts, op);
  
@@@ -1441,7 -1398,7 +1441,7 @@@ static int image_save_exec(bContext *C
        Scene *scene = CTX_data_scene(C);
        SaveImageOptions simopts;
  
 -      if (save_image_options_init(&simopts, sima, scene, FALSE) == 0)
 +      if (save_image_options_init(C, &simopts, sima, scene, FALSE) == 0)
                return OPERATOR_CANCELLED;
        save_image_options_from_op(&simopts, op);
  
@@@ -1695,7 -1652,7 +1695,7 @@@ static int image_invert_exec(bContext *
        Image *ima = CTX_data_edit_image(C);
        ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
  
-       // flags indicate if this channel should be inverted
+       /* flags indicate if this channel should be inverted */
        const short r = RNA_boolean_get(op->ptr, "invert_r");
        const short g = RNA_boolean_get(op->ptr, "invert_g");
        const short b = RNA_boolean_get(op->ptr, "invert_b");
  
        int i;
  
-       if (ibuf == NULL)  // TODO: this should actually never happen, but does for render-results -> cleanup
+       if (ibuf == NULL)  /* TODO: this should actually never happen, but does for render-results -> cleanup */
                return OPERATOR_CANCELLED;
  
        /* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */
index 0c36ecdda7e3447c21b76fe2de70f340ae181d8f,c717d8eee5a7b0141f7c6322f64f329ed4ef24a5..41e78422f4bcace249dc79b20dcc3ad6d84c4550
@@@ -41,7 -41,6 +41,7 @@@
  #include "IMB_allocimbuf.h"
  #include "IMB_filetype.h"
  #include "IMB_metadata.h"
 +#include "IMB_colormanagement.h"
  
  #include "imbuf.h"
  
@@@ -163,11 -162,8 +163,11 @@@ void IMB_freeImBuf(ImBuf *ibuf
                        IMB_freezbuffloatImBuf(ibuf);
                        freeencodedbufferImBuf(ibuf);
                        IMB_metadata_free(ibuf);
 -                      if (ibuf->dds_data.data != NULL)
 +                      IMB_colormanage_cache_free(ibuf);
 +
 +                      if (ibuf->dds_data.data != NULL) {
                                free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
 +                      }
                        MEM_freeN(ibuf);
                }
        }
@@@ -428,7 -424,7 +428,7 @@@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1
        /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
        tbuf = *ibuf1;
        
-       // fix pointers 
+       /* fix pointers */
        tbuf.rect          = ibuf2->rect;
        tbuf.rect_float    = ibuf2->rect_float;
        tbuf.encodedbuffer = ibuf2->encodedbuffer;
        for (a = 0; a < IB_MIPMAP_LEVELS; a++)
                tbuf.mipmap[a] = NULL;
        
-       // set malloc flag
+       /* set malloc flag */
        tbuf.mall               = ibuf2->mall;
        tbuf.c_handle           = NULL;
        tbuf.refcounter         = 0;
  
-       // for now don't duplicate metadata
+       /* for now don't duplicate metadata */
        tbuf.metadata = NULL;
  
        *ibuf2 = tbuf;
 -      
 +
 +      IMB_colormanage_cache_free(ibuf2);
 +
        return(ibuf2);
  }
  
index 816187ad61d315bc6e94e47032fee03c8b0153fa,71b59131f0b41b9e849f200915bac147346d4b94..0d47f7073beec1d552238144d1a97b10440c4633
@@@ -35,7 -35,7 +35,7 @@@
  
  #include "DNA_defs.h"
  #include "DNA_listBase.h"
 -#include "DNA_color_types.h"        /* for Histogram */
 +#include "DNA_color_types.h"        /* for Histogram and color management */
  #include "DNA_vec_types.h"
  #include "DNA_outliner_types.h"     /* for TreeStoreElem */
  #include "DNA_image_types.h"        /* ImageUser */
@@@ -518,7 -518,7 +518,7 @@@ typedef enum eSpaceSeq_Proxy_RenderSiz
  
  /* Config and Input for File Selector */
  typedef struct FileSelectParams {
-       char title[32]; /* title, also used for the text of the execute button */
+       char title[96]; /* title, also used for the text of the execute button */
        char dir[1056]; /* directory, FILE_MAX_LIBEXTRA, 1024 + 32, this is for extreme case when 1023 length path
                         * needs to be linked in, where foo.blend/Armature need adding  */
        char file[256]; /* file */
@@@ -689,8 -689,6 +689,8 @@@ typedef struct SpaceImage 
        char sticky; /* sticky selection type */
        char dt_uvstretch;
        char around;
 +
 +      ColorManagedViewSettings view_settings;
  } SpaceImage;
  
  
@@@ -873,8 -871,6 +873,8 @@@ typedef struct SpaceNode 
        ListBase linkdrag;  /* temporary data for modal linking operator */
        
        struct bGPdata *gpd;        /* grease-pencil data */
 +
 +      ColorManagedViewSettings view_settings;
  } SpaceNode;
  
  /* snode->flag */
@@@ -1022,9 -1018,6 +1022,9 @@@ typedef struct SpaceClip 
        char mask_draw_flag;
        char mask_draw_type;
        char pad3[6];
 +
 +      /* **** color management **** */
 +      ColorManagedViewSettings view_settings;
  } SpaceClip;
  
  /* SpaceClip->flag */
index c276d3796ddaed7f2326e108448fb2d94a421581,8ca229c1a1b2edecd538c93499a576789be5c4af..f9c55a3dc031b64dd1d2a35269c91a41a55968ec
@@@ -51,8 -51,8 +51,8 @@@ struct EnvMap
  /* this include is what is exposed of render to outside world */
  /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  
- #define RE_MAXNAME    32
+ /* length of the scene name + passname */
+ #define RE_MAXNAME    ((MAX_ID_NAME - 2) + 10)
  
  /* only used as handle */
  typedef struct Render Render;
@@@ -81,7 -81,7 +81,7 @@@ typedef struct RenderLayer 
        struct RenderLayer *next, *prev;
        
        /* copy of RenderData */
-       char name[RE_MAXNAME];          
+       char name[RE_MAXNAME];
        unsigned int lay, lay_zmask, lay_exclude;
        int layflag, passflag, pass_xor;                
        
@@@ -92,9 -92,6 +92,9 @@@
        float *acolrect;        /* 4 float, optional transparent buffer, needs storage for display updates */
        float *scolrect;        /* 4 float, optional strand buffer, needs storage for display updates */
        int rectx, recty;
 +
 +      /* optional saved endresult on disk */
 +      void *exrhandle;
        
        ListBase passes;
        
@@@ -127,7 -124,7 +127,7 @@@ typedef struct RenderResult 
        volatile RenderLayer *renlay;
        
        /* optional saved endresult on disk */
 -      void *exrhandle;
 +      int do_exr_tile;
        
        /* for render results in Image, verify validity for sequences */
        int framenr;
@@@ -147,8 -144,7 +147,7 @@@ typedef struct RenderStats 
        short curfield, curblur, curpart, partsdone, convertdone, curfsa;
        double starttime, lastframetime;
        const char *infostr, *statstr;
-       char scenename[32];
-       
+       char scene_name[MAX_ID_NAME - 2];
  } RenderStats;
  
  /* *********************** API ******************** */
index 2b5ccae7df715415fb6be4d72a4d562acba6b112,1180e74d39184974709a4145ffa82fc72952b477..ab66a3c770f75220ae77ddaa0abf93a11061cadd
@@@ -55,7 -55,6 +55,7 @@@
  #include "RE_engine.h"
  #include "RE_pipeline.h"
  
 +#include "initrender.h"
  #include "render_types.h"
  #include "render_result.h"
  
@@@ -150,7 -149,7 +150,7 @@@ void RE_engine_free(RenderEngine *engin
  
  /* Render Results */
  
 -RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
 +RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
  {
        Render *re = engine->re;
        RenderResult *result;
        disprect.ymin = y;
        disprect.ymax = y + h;
  
 -      result = render_result_new(re, &disprect, 0, RR_USE_MEM);
 +      result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername);
 +
 +      /* todo: make this thread safe */
  
        /* can be NULL if we CLAMP the width or height to 0 */
        if (result) {
@@@ -195,41 -192,26 +195,41 @@@ void RE_engine_update_result(RenderEngi
        Render *re = engine->re;
  
        if (result) {
-               result->renlay = result->layers.first; // weak, draws first layer always
+               result->renlay = result->layers.first; /* weak, draws first layer always */
                re->display_draw(re->ddh, result, NULL);
        }
  }
  
 -void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
 +void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel)
  {
        Render *re = engine->re;
 +      RenderPart *pa;
  
        if (!result)
                return;
  
        /* merge. on break, don't merge in result for preview renders, looks nicer */
 -      if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
 -              render_result_merge(re->result, result);
 +      if (!cancel) {
 +              /* for exr tile render, detect tiles that are done */
 +              for (pa = re->parts.first; pa; pa = pa->next) {
 +                      if (result->tilerect.xmin == pa->disprect.xmin &&
 +                         result->tilerect.ymin == pa->disprect.ymin &&
 +                         result->tilerect.xmax == pa->disprect.xmax &&
 +                         result->tilerect.ymax == pa->disprect.ymax) {
 +                              pa->ready = 1;
 +                      }
 +              }
  
 -      /* draw */
 -      if (!re->test_break(re->tbh)) {
 -              result->renlay = result->layers.first; /* weak, draws first layer always */
 -              re->display_draw(re->ddh, result, NULL);
 +              if (re->result->do_exr_tile)
 +                      render_result_exr_file_merge(re->result, result);
 +              else if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
 +                      render_result_merge(re->result, result);
 +
 +              /* draw */
 +              if (!re->test_break(re->tbh)) {
-                       result->renlay = result->layers.first; // weak, draws first layer always
++                      result->renlay = result->layers.first; /* weak, draws first layer always */
 +                      re->display_draw(re->ddh, result, NULL);
 +              }
        }
  
        /* free */
@@@ -312,22 -294,18 +312,22 @@@ int RE_engine_render(Render *re, int do
        /* create render result */
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        if (re->result == NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
 +              int savebuffers;
 +
                if (re->result)
                        render_result_free(re->result);
 -              re->result = render_result_new(re, &re->disprect, 0, 0);
 +
 +              savebuffers = (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM;
 +              re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
        }
        BLI_rw_mutex_unlock(&re->resultmutex);
 -      
 +
        if (re->result == NULL)
                return 1;
  
        /* set render info */
        re->i.cfra = re->scene->r.cfra;
-       BLI_strncpy(re->i.scenename, re->scene->id.name + 2, sizeof(re->i.scenename));
+       BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
        re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
  
        /* render */
        if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0)
                BKE_scene_update_for_newframe(re->main, re->scene, re->lay);
  
 +      initparts(re, FALSE);
 +      engine->tile_x = re->partx;
 +      engine->tile_y = re->party;
 +
 +      if (re->result->do_exr_tile)
 +              render_result_exr_file_begin(re);
 +
        if (type->update)
                type->update(engine, re->main, re->scene);
 +      
        if (type->render)
                type->render(engine, re->scene);
  
 +      if (re->result->do_exr_tile) {
 +              BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 +              render_result_exr_file_end(re);
 +              BLI_rw_mutex_unlock(&re->resultmutex);
 +      }
 +
 +      engine->tile_x = 0;
 +      engine->tile_y = 0;
 +      freeparts(re);
 +
        render_result_free_list(&engine->fullresult, engine->fullresult.first);
  
        RE_engine_free(engine);
index 4d227f9586d6c603db11de80ad9b90182a4da65f,77f75caa36a91725b1299fad6aeef15be5d9b8d3..a665d1a4bc20aa42f4c69930b28f366825a3f6dc
@@@ -67,7 -67,6 +67,7 @@@
  #include "BLI_callbacks.h"
  
  #include "PIL_time.h"
 +#include "IMB_colormanagement.h"
  #include "IMB_imbuf.h"
  #include "IMB_imbuf_types.h"
  
@@@ -167,9 -166,9 +167,9 @@@ static void stats_background(void *UNUS
        }
        else {
                if (rs->tothalo)
-                       fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
+                       fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scene_name, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
                else
-                       fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->totlamp);
+                       fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scene_name, rs->totvert, rs->totface, rs->totlamp);
        }
  
        BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
@@@ -653,7 -652,7 +653,7 @@@ static void *do_part_thread(void *pa_v
                if (!R.sss_points && (R.r.scemode & R_FULL_SAMPLE))
                        pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM);
                else
 -                      pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM);
 +                      pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS);
  
                if (R.sss_points)
                        zbufshade_sss_tile(pa);
                        zbufshade_tile(pa);
                
                /* merge too on break! */
 -              if (R.result->exrhandle) {
 +              if (R.result->do_exr_tile) {
                        render_result_exr_file_merge(R.result, pa->result);
                }
                else if (render_display_draw_enabled(&R)) {
@@@ -807,12 -806,12 +807,12 @@@ static void threaded_tile_processor(Ren
                render_result_free(re->result);
        
                if (re->sss_points && render_display_draw_enabled(re))
 -                      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 +                      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
                else if (re->r.scemode & R_FULL_SAMPLE)
                        re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR);
                else
                        re->result = render_result_new(re, &re->disprect, 0,
 -                                                     (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM);
 +                                                     (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS);
        }
  
        BLI_rw_mutex_unlock(&re->resultmutex);
        
        /* warning; no return here without closing exr file */
        
 -      initparts(re);
 +      initparts(re, TRUE);
  
 -      if (re->result->exrhandle)
 +      if (re->result->do_exr_tile)
                render_result_exr_file_begin(re);
        
        BLI_init_threads(&threads, do_part_thread, re->r.threads);
                
        }
        
 -      if (re->result->exrhandle) {
 +      if (re->result->do_exr_tile) {
                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                render_result_exr_file_end(re);
                BLI_rw_mutex_unlock(&re->resultmutex);
@@@ -1057,7 -1056,7 +1057,7 @@@ static void do_render_blur_3d(Render *r
        int blur = re->r.mblur_samples;
        
        /* create accumulation render result */
 -      rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 +      rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
        
        /* do the blur steps */
        while (blur--) {
@@@ -1182,7 -1181,7 +1182,7 @@@ static void do_render_fields_3d(Render 
        re->disprect.ymax *= 2;
  
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 +      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
  
        if (rr2) {
                if (re->r.mode & R_ODDFIELD)
@@@ -1245,7 -1244,7 +1245,7 @@@ static void do_render_fields_blur_3d(Re
                                re->rectx = re->winx;
                                re->recty = re->winy;
                                
 -                              rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 +                              rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
                                
                                render_result_merge(rres, re->result);
                                render_result_free(re->result);
@@@ -1565,7 -1564,7 +1565,7 @@@ static void do_render_composite_fields_
                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                
                render_result_free(re->result);
 -              re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 +              re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
  
                BLI_rw_mutex_unlock(&re->resultmutex);
                
@@@ -1857,7 -1856,7 +1857,7 @@@ int RE_is_rendering_allowed(Scene *scen
        if (scene->r.scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE)) {
                char str[FILE_MAX];
                
 -              render_result_exr_file_path(scene, 0, str);
 +              render_result_exr_file_path(scene, "", 0, str);
                
                if (BLI_file_is_writable(str) == 0) {
                        BKE_report(reports, RPT_ERROR, "Can not save render buffers, check the temp default path");
@@@ -1941,7 -1940,7 +1941,7 @@@ static void validate_render_settings(Re
  
        if (RE_engine_is_external(re)) {
                /* not supported yet */
 -              re->r.scemode &= ~(R_EXR_TILE_FILE | R_FULL_SAMPLE);
 +              re->r.scemode &= ~(R_FULL_SAMPLE);
                re->r.mode &= ~(R_FIELDS | R_MBLUR);
        }
  }
@@@ -2078,15 -2077,6 +2078,15 @@@ void RE_BlenderFrame(Render *re, Main *
        G.rendering = 0;
  }
  
 +static void colormanage_image_for_write(ImBuf *ibuf, Scene *scene)
 +{
 +      IMB_display_buffer_to_imbuf_rect(ibuf, &scene->r.im_format.view_settings,
 +                                       &scene->r.im_format.display_settings);
 +
 +      if (ibuf)
 +              imb_freerectfloatImBuf(ibuf);
 +}
 +
  static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
  {
        char name[FILE_MAX];
                }
                else {
                        ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
 +                      int do_colormanagement;
 +
 +                      do_colormanagement = !BKE_imtype_supports_float(scene->r.im_format.imtype);
 +
 +                      if (do_colormanagement)
 +                              colormanage_image_for_write(ibuf, scene);
  
                        ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format);
                        
                                        name[strlen(name) - 4] = 0;
                                BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90);
                                ibuf->planes = 24;
 +
 +                              colormanage_image_for_write(ibuf, scene);
 +
                                BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf);
                                printf("\nSaved: %s", name);
                        }
@@@ -2448,7 -2429,7 +2448,7 @@@ void RE_layer_load_from_file(RenderLaye
  
  void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename)
  {
 -      if (!render_result_exr_file_read_path(result, filename)) {
 +      if (!render_result_exr_file_read_path(result, NULL, filename)) {
                BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
                return;
        }
index 8a9b483a540b3fe620bbf0a78bb3a08d5e17f602,5da661e718263cc4d6b9caba6a1977fe04c754f8..f1c4c0b15afd5d418a42436b972211af86e3bf57
@@@ -384,10 -384,10 +384,10 @@@ static void render_layer_add_pass(Rende
        rpass->recty = rl->recty;
        BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
        
 -      if (rr->exrhandle) {
 +      if (rl->exrhandle) {
                int a;
                for (a = 0; a < channels; a++)
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
 +                      IMB_exr_add_channel(rl->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
        }
        else {
                float *rect;
  /* will read info from Render *re to define layers */
  /* called in threads */
  /* re->winx,winy is coordinate space of entire image, partrct the part within */
 -RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers)
 +RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers, const char *layername)
  {
        RenderResult *rr;
        RenderLayer *rl;
        
        /* 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.xmax;
 +      rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
        rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
 -      rr->tilerect.ymax = partrct->ymax - re->disprect.ymax;
 +      rr->tilerect.ymax = partrct->ymax - re->disprect.ymin;
        
        if (savebuffers) {
 -              rr->exrhandle = IMB_exr_get_handle();
 +              rr->do_exr_tile = TRUE;
        }
 -      
 +
        /* check renderdata for amount of layers */
        for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
 -              
 +
 +              if (layername && layername[0])
 +                      if (strcmp(srl->name, layername) != 0)
 +                              continue;
 +
                if ((re->r.scemode & R_SINGLE_LAYER) && nr != re->r.actlay)
                        continue;
                if (srl->layflag & SCE_LAY_DISABLE)
                rl->lay_zmask = srl->lay_zmask;
                rl->lay_exclude = srl->lay_exclude;
                rl->layflag = srl->layflag;
-               rl->passflag = srl->passflag; // for debugging: srl->passflag|SCE_PASS_RAYHITS;
+               rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */
                rl->pass_xor = srl->pass_xor;
                rl->light_override = srl->light_override;
                rl->mat_override = srl->mat_override;
                rl->rectx = rectx;
                rl->recty = recty;
                
 -              if (rr->exrhandle) {
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
 +              if (rr->do_exr_tile) {
 +                      rl->exrhandle = IMB_exr_get_handle();
 +
 +                      IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
 +                      IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
 +                      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
                        rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
                
        }
        /* sss, previewrender and envmap don't do layers, so we make a default one */
 -      if (rr->layers.first == NULL) {
 +      if (rr->layers.first == NULL && !(layername && layername[0])) {
                rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
                BLI_addtail(&rr->layers, rl);
                
                rl->recty = recty;
  
                /* duplicate code... */
 -              if (rr->exrhandle) {
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
 -                      IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
 +              if (rr->do_exr_tile) {
 +                      rl->exrhandle = IMB_exr_get_handle();
 +
 +                      IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
 +                      IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
 +                      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
                        rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
@@@ -578,10 -570,10 +578,10 @@@ RenderResult *render_result_new_full_sa
        int a;
        
        if (re->osa == 0)
 -              return render_result_new(re, partrct, crop, savebuffers);
 +              return render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS);
        
        for (a = 0; a < re->osa; a++) {
 -              RenderResult *rr = render_result_new(re, partrct, crop, savebuffers);
 +              RenderResult *rr = render_result_new(re, partrct, crop, savebuffers, RR_ALL_LAYERS);
                BLI_addtail(lb, rr);
                rr->sample_nr = a;
        }
  }
  
  /* callbacks for render_result_new_from_exr */
- static void *ml_addlayer_cb(void *base, char *str)
+ static void *ml_addlayer_cb(void *base, const char *str)
  {
        RenderResult *rr = base;
        RenderLayer *rl;
        return rl;
  }
  
- static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id)
+ static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float *rect, int totchan, const char *chan_id)
  {
        RenderLayer *rl = lay;
        RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
  /* 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 *rr = MEM_callocN(sizeof(RenderResult), "loaded render result");
+       RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
        RenderLayer *rl;
        RenderPass *rpass;
        
@@@ -690,18 -682,15 +690,18 @@@ void render_result_merge(RenderResult *
        RenderLayer *rl, *rlp;
        RenderPass *rpass, *rpassp;
        
 -      for (rl = rr->layers.first, rlp = rrpart->layers.first; rl && rlp; rl = rl->next, rlp = rlp->next) {
 -              
 -              /* 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);
 +      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);
 +                              }
 +                      }
                }
        }
  }
@@@ -838,16 -827,13 +838,16 @@@ void render_result_single_layer_end(Ren
  
  static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
  {
 -      RenderLayer *rlp;
 +      RenderLayer *rlp, *rl;
        RenderPass *rpassp;
        int offs, partx, party;
        
        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;
                
                if (rrpart->crop) { /* filters add pixel extra */
                        offs = (rrpart->crop + rrpart->crop * rrpart->rectx);
                if (rlp->rectf) {
                        int a, xstride = 4;
                        for (a = 0; a < xstride; a++)
 -                              IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, 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);
                }
                
                for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
                        int a, xstride = rpassp->channels;
                        for (a = 0; a < xstride; a++)
 -                              IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
 +                              IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
                                                    xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
                }
                
  
        party = rrpart->tilerect.ymin + rrpart->crop;
        partx = rrpart->tilerect.xmin + rrpart->crop;
 -      IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
 +
 +      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;
 +      
 +              IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0);
 +      }
  
        BLI_unlock_thread(LOCK_IMAGE);
  }
@@@ -892,18 -871,15 +892,18 @@@ static void save_empty_result_tiles(Ren
  {
        RenderPart *pa;
        RenderResult *rr;
 +      RenderLayer *rl;
        
        for (rr = re->result; rr; rr = rr->next) {
 -              IMB_exrtile_clear_channels(rr->exrhandle);
 +              for (rl = rr->layers.first; rl; rl = rl->next) {
 +                      IMB_exrtile_clear_channels(rl->exrhandle);
                
 -              for (pa = re->parts.first; pa; pa = pa->next) {
 -                      if (pa->ready == 0) {
 -                              int party = pa->disprect.ymin - re->disprect.ymin + pa->crop;
 -                              int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop;
 -                              IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
 +                      for (pa = re->parts.first; pa; pa = pa->next) {
 +                              if (pa->ready == 0) {
 +                                      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);
 +                              }
                        }
                }
        }
  void render_result_exr_file_begin(Render *re)
  {
        RenderResult *rr;
 +      RenderLayer *rl;
        char str[FILE_MAX];
 -      
 +
        for (rr = re->result; rr; rr = rr->next) {
 -              render_result_exr_file_path(re->scene, rr->sample_nr, str);
 -      
 -              printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
 -              IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
 +              for (rl = rr->layers.first; rl; rl = rl->next) {
 +                      render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str);
 +                      printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
 +                      IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
 +              }
        }
  }
  
  void render_result_exr_file_end(Render *re)
  {
        RenderResult *rr;
 +      RenderLayer *rl;
  
        save_empty_result_tiles(re);
        
        for (rr = re->result; rr; rr = rr->next) {
 -              IMB_exr_close(rr->exrhandle);
 -              rr->exrhandle = NULL;
 +              for (rl = rr->layers.first; rl; rl = rl->next) {
 +                      IMB_exr_close(rl->exrhandle);
 +                      rl->exrhandle = NULL;
 +              }
 +
 +              rr->do_exr_tile = FALSE;
        }
        
        render_result_free_list(&re->fullresult, re->result);
@@@ -956,17 -925,17 +956,17 @@@ void render_result_exr_file_merge(Rende
  }
  
  /* path to temporary exr file */
 -void render_result_exr_file_path(Scene *scene, int sample, char *filepath)
 +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 + 100], fi[FILE_MAXFILE];
 +      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);
        
        if (sample == 0)
 -              BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name + 2);
 +              BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
        else
 -              BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name + 2, sample);
 +              BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
  
        BLI_make_file_string("/", filepath, BLI_temporary_dir(), name);
  }
  /* only for temp buffer files, makes exact copy of render result */
  int render_result_exr_file_read(Render *re, int sample)
  {
 +      RenderLayer *rl;
        char str[FILE_MAX];
 -      int success;
 +      int success = TRUE;
  
        RE_FreeRenderResult(re->result);
 -      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 +      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
  
 -      render_result_exr_file_path(re->scene, sample, str);
 -      printf("read exr tmp file: %s\n", str);
 +      for (rl = re->result->layers.first; rl; rl = rl->next) {
  
 -      if (render_result_exr_file_read_path(re->result, str)) {
 -              success = TRUE;
 -      }
 -      else {
 -              printf("cannot read: %s\n", str);
 -              success = FALSE;
 +              render_result_exr_file_path(re->scene, rl->name, sample, str);
 +              printf("read exr tmp file: %s\n", str);
  
 +              if (!render_result_exr_file_read_path(re->result, rl, str)) {
 +                      printf("cannot read: %s\n", str);
 +                      success = FALSE;
 +
 +              }
        }
  
        return success;
  }
  
  /* called for reading temp files, and for external engines */
 -int render_result_exr_file_read_path(RenderResult *rr, const char *filepath)
 +int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath)
  {
        RenderLayer *rl;
        RenderPass *rpass;
        }
  
        for (rl = rr->layers.first; rl; rl = rl->next) {
 +              if (rl_single && rl_single != rl)
 +                      continue;
 +
                /* combined */
                if (rl->rectf) {
                        int a, xstride = 4;
index cabc51a6e5bb2f03bdd5c0c8d194a69fe41fe50e,3dbb3b7ef667159a5980f579a761b660486cc489..0a9d865800051e471c5679c0c47debf700967d81
  #include "BKE_depsgraph.h"
  #include "BKE_sound.h"
  
 +#include "IMB_colormanagement.h"
 +
  static void wm_init_reports(bContext *C)
  {
        BKE_reports_init(CTX_wm_reports(C), RPT_STORE);
@@@ -145,10 -143,6 +145,10 @@@ void WM_init(bContext *C, int argc, con
        
        BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
        BLF_lang_init();
 +
 +      /* initialize color management stuff */
 +      IMB_colormanagement_init();
 +
        /* get the default database, plus a wm */
        WM_read_homefile(C, NULL, G.factory_startup);
  
@@@ -232,21 -226,21 +232,21 @@@ int WM_init_game(bContext *C
        Scene *scene = CTX_data_scene(C);
  
        if (!scene) {
-               // XXX, this should not be needed.
+               /* XXX, this should not be needed. */
                Main *bmain = CTX_data_main(C);
                scene = bmain->scene.first;
        }
  
        win = wm->windows.first;
  
-       //first to get a valid window
+       /* first to get a valid window */
        if (win)
                CTX_wm_window_set(C, win);
  
        sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0);
        ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
  
-       // if we have a valid 3D view
+       /* if we have a valid 3D view */
        if (sa && ar) {
                ARegion *arhide;
  
@@@ -338,7 -332,6 +338,7 @@@ void WM_exit_ext(bContext *C, const sho
  
        sound_exit();
  
 +      IMB_colormanagement_exit();
  
        /* first wrap up running stuff, we assume only the active WM is running */
        /* modal handlers are on window level freed, others too? */
diff --combined source/creator/creator.c
index b2f05120732429df18883bfa4dd3f401179c1354,01c850412de9e4075479860daa62cc5bac635466..c9f2892bcceaa2dafcced5bec8b53e917b9cbd58
@@@ -453,14 -453,16 +453,14 @@@ static int set_env(int argc, const cha
        return 1;
  }
  
 -static int playback_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
 +static int playback_mode(int argc, const char **argv, void *UNUSED(data))
  {
 +      extern void playanim(int argc, const char **argv);
 +
        /* not if -b was given first */
        if (G.background == 0) {
 -#if 0   /* TODO, bring player back? */
                playanim(argc, argv); /* not the same argc and argv as before */
 -#else
 -              fprintf(stderr, "Playback mode not supported in blender 2.6x\n");
 -              exit(0);
 -#endif
 +              exit(0); /* 2.4x didn't do this */
        }
  
        return -2;
@@@ -1344,7 -1346,7 +1344,7 @@@ int main(int argc, const char **argv
         * WM_init() before #BPY_python_start() crashes Blender at startup.
         */
  
-       // TODO - U.pythondir
+       /* TODO - U.pythondir */
  #else
        printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
  #endif