Merged changes in the trunk up to revision 54110.
[blender.git] / source / blender / render / intern / source / pipeline.c
index 4d227f9586d6c603db11de80ad9b90182a4da65f..866932632c27b06152feaaa82fa1208dcb758c5d 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "BLI_threads.h"
+#include "BLI_rand.h"
+#include "BLI_callbacks.h"
+
 #include "BKE_animsys.h"  /* <------ should this be here?, needed for sequencer update */
 #include "BKE_camera.h"
 #include "BKE_global.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_sequencer.h"
-#include "BKE_utildefines.h"
 #include "BKE_writeavi.h"  /* <------ should be replaced once with generic movie module */
 
-#include "BLI_math.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BLI_path_util.h"
-#include "BLI_fileops.h"
-#include "BLI_rand.h"
-#include "BLI_callbacks.h"
-
 #include "PIL_time.h"
 #include "IMB_colormanagement.h"
 #include "IMB_imbuf.h"
 #include "RE_engine.h"
 #include "RE_pipeline.h"
 
+#ifdef WITH_FREESTYLE
+#  include "BKE_library.h"
+#  include "FRS_freestyle.h"
+#endif
+
 /* internal */
 #include "render_result.h"
 #include "render_types.h"
@@ -139,7 +145,7 @@ static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr)) {}
 static void result_rcti_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) {}
 static void stats_nothing(void *UNUSED(arg), RenderStats *UNUSED(rs)) {}
 static void float_nothing(void *UNUSED(arg), float UNUSED(val)) {}
-static int default_break(void *UNUSED(arg)) {return G.afbreek == 1;}
+static int default_break(void *UNUSED(arg)) { return G.is_break == TRUE; }
 
 static void stats_background(void *UNUSED(arg), RenderStats *rs)
 {
@@ -167,9 +173,9 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
        }
        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);
@@ -195,19 +201,17 @@ float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype)
 
 RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
 {
-       RenderLayer *rl;
-       
-       if (rr == NULL) return NULL;
-       
-       for (rl = rr->layers.first; rl; rl = rl->next)
-               if (strncmp(rl->name, name, RE_MAXNAME) == 0)
-                       return rl;
-       return NULL;
+       if (rr == NULL) {
+               return NULL;
+       }
+       else {
+               return BLI_findstring(&rr->layers, name, offsetof(RenderLayer, name));
+       }
 }
 
-RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty)
+RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty)
 {
-       return render_result_new_from_exr(exrhandle, rectx, recty);
+       return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty);
 }
 
 RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
@@ -246,17 +250,6 @@ Render *RE_GetRender(const char *name)
        return re;
 }
 
-Render *RE_GetRender_FromData(const RenderData *rd)
-{
-       Render *re;
-
-       /* search for existing renders */
-       for (re = RenderGlobal.renderlist.first; re; re = re->next)
-               if (&re->r == rd)
-                       break;
-
-       return re;
-}
 
 /* if you want to know exactly what has been done */
 RenderResult *RE_AcquireResultRead(Render *re)
@@ -348,7 +341,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
        RenderResult rres;
        
        RE_AcquireResultImage(re, &rres);
-       render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty);
+       render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
        RE_ReleaseResultImage(re);
 }
 
@@ -401,6 +394,9 @@ void RE_InitRenderCB(Render *re)
 /* only call this while you know it will remove the link too */
 void RE_FreeRender(Render *re)
 {
+       if (re->engine)
+               RE_engine_free(re->engine);
+
        BLI_rw_mutex_end(&re->resultmutex);
        
        free_renderdata_tables(re);
@@ -435,6 +431,22 @@ void RE_FreeAllRenderResults(void)
        }
 }
 
+void RE_FreePersistentData(void)
+{
+       Render *re;
+
+       /* render engines can be kept around for quick re-render, this clears all */
+       for (re = RenderGlobal.renderlist.first; re; re = re->next) {
+               if (re->engine) {
+                       /* if engine is currently rendering, just tag it to be freed when render is finished */
+                       if (!(re->engine->flag & RE_ENGINE_RENDERING))
+                               RE_engine_free(re->engine);
+
+                       re->engine = NULL;
+               }
+       }
+}
+
 /* ********* initialize state ******** */
 
 
@@ -451,8 +463,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
        re->winy = winy;
        if (disprect) {
                re->disprect = *disprect;
-               re->rectx = disprect->xmax - disprect->xmin;
-               re->recty = disprect->ymax - disprect->ymin;
+               re->rectx = BLI_rcti_size_x(disprect);
+               re->recty = BLI_rcti_size_y(disprect);
        }
        else {
                re->disprect.xmin = re->disprect.ymin = 0;
@@ -462,7 +474,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
                re->recty = winy;
        }
        
-       if (re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
+       if (re->rectx < 1 || re->recty < 1 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
                                               (re->rectx < 16 || re->recty < 16) ))
        {
                BKE_report(re->reports, RPT_ERROR, "Image too small");
@@ -513,13 +525,15 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
        }
                
        /* always call, checks for gamma, gamma tables and jitter too */
-       make_sample_tables(re); 
+       make_sample_tables(re);
        
        /* if preview render, we try to keep old result */
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 
        if (re->r.scemode & R_PREVIEWBUTS) {
-               if (re->result && re->result->rectx == re->rectx && re->result->recty == re->recty) ;
+               if (re->result && re->result->rectx == re->rectx && re->result->recty == re->recty) {
+                       /* pass */
+               }
                else {
                        render_result_free(re->result);
                        re->result = NULL;
@@ -573,7 +587,7 @@ void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend)
                        re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend);
 }
 
-void RE_SetView(Render *re, float mat[][4])
+void RE_SetView(Render *re, float mat[4][4])
 {
        /* re->ok flag? */
        copy_m4_m4(re->viewmat, mat);
@@ -646,7 +660,9 @@ static int render_display_draw_enabled(Render *re)
 static void *do_part_thread(void *pa_v)
 {
        RenderPart *pa = pa_v;
-       
+
+       pa->status = PART_STATUS_IN_PROGRESS;
+
        /* need to return nicely all parts on esc */
        if (R.test_break(R.tbh) == 0) {
                
@@ -668,31 +684,36 @@ static void *do_part_thread(void *pa_v)
                }
                else if (render_display_draw_enabled(&R)) {
                        /* on break, don't merge in result for preview renders, looks nicer */
-                       if (R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS)) ;
-                       else render_result_merge(R.result, pa->result);
+                       if (R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS)) {
+                               /* pass */
+                       }
+                       else {
+                               render_result_merge(R.result, pa->result);
+                       }
                }
        }
        
-       pa->ready = 1;
+       pa->status = PART_STATUS_READY;
        
        return NULL;
 }
 
 /* calculus for how much 1 pixel rendered should rotate the 3d geometry */
 /* is not that simple, needs to be corrected for errors of larger viewplane sizes */
-/* called in initrender.c, initparts() and convertblender.c, for speedvectors */
+/* called in initrender.c, RE_parts_init() and convertblender.c, for speedvectors */
 float panorama_pixel_rot(Render *re)
 {
        float psize, phi, xfac;
-       float borderfac = (float)(re->disprect.xmax - re->disprect.xmin) / (float)re->winx;
+       float borderfac = (float)BLI_rcti_size_x(&re->disprect) / (float)re->winx;
+       int xparts = (re->rectx + re->partx - 1) / re->partx;
        
        /* size of 1 pixel mapped to viewplane coords */
-       psize = (re->viewplane.xmax - re->viewplane.xmin) / (float)(re->winx);
+       psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx;
        /* angle of a pixel */
        phi = atan(psize / re->clipsta);
        
        /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */
-       xfac = borderfac * ((re->viewplane.xmax - re->viewplane.xmin)) / (float)re->xparts;
+       xfac = borderfac * BLI_rctf_size_x(&re->viewplane) / (float)xparts;
        xfac = atan(0.5f * xfac / re->clipsta);
        /* and how much the same viewplane angle is wrapped */
        psize = 0.5f * phi * ((float)re->partx);
@@ -713,7 +734,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
        
        /* most left part of the non-rendering parts */
        for (pa = re->parts.first; pa; pa = pa->next) {
-               if (pa->ready == 0 && pa->nr == 0) {
+               if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
                        if (pa->disprect.xmin < *minx) {
                                best = pa;
                                *minx = pa->disprect.xmin;
@@ -725,7 +746,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
                float phi = panorama_pixel_rot(re);
 
                R.panodxp = (re->winx - (best->disprect.xmin + best->disprect.xmax) ) / 2;
-               R.panodxv = ((viewplane->xmax - viewplane->xmin) * R.panodxp) / (float)(re->winx);
+               R.panodxv = (BLI_rctf_size_x(viewplane) * R.panodxp) / (float)(re->winx);
 
                /* shift viewplane */
                R.viewplane.xmin = viewplane->xmin + R.panodxv;
@@ -751,9 +772,9 @@ static RenderPart *find_next_part(Render *re, int minx)
        
        /* find center of rendered parts, image center counts for 1 too */
        for (pa = re->parts.first; pa; pa = pa->next) {
-               if (pa->ready) {
-                       centx += (pa->disprect.xmin + pa->disprect.xmax) / 2;
-                       centy += (pa->disprect.ymin + pa->disprect.ymax) / 2;
+               if (pa->status == PART_STATUS_READY) {
+                       centx += BLI_rcti_cent_x(&pa->disprect);
+                       centy += BLI_rcti_cent_y(&pa->disprect);
                        tot++;
                }
        }
@@ -762,9 +783,9 @@ static RenderPart *find_next_part(Render *re, int minx)
        
        /* closest of the non-rendering parts */
        for (pa = re->parts.first; pa; pa = pa->next) {
-               if (pa->ready == 0 && pa->nr == 0) {
-                       long long int distx = centx - (pa->disprect.xmin + pa->disprect.xmax) / 2;
-                       long long int disty = centy - (pa->disprect.ymin + pa->disprect.ymax) / 2;
+               if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
+                       long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
+                       long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
                        distx = (long long int)sqrt(distx * distx + disty * disty);
                        if (distx < mindist) {
                                if (re->r.mode & R_PANORAMA) {
@@ -819,10 +840,10 @@ static void threaded_tile_processor(Render *re)
        
        if (re->result == NULL)
                return;
-       
+
        /* warning; no return here without closing exr file */
        
-       initparts(re, TRUE);
+       RE_parts_init(re, TRUE);
 
        if (re->result->do_exr_tile)
                render_result_exr_file_begin(re);
@@ -870,7 +891,7 @@ static void threaded_tile_processor(Render *re)
                rendering = 0;
                hasdrawn = 0;
                for (pa = re->parts.first; pa; pa = pa->next) {
-                       if (pa->ready) {
+                       if (pa->status == PART_STATUS_READY) {
                                
                                BLI_remove_thread(&threads, pa);
                                
@@ -914,7 +935,7 @@ static void threaded_tile_processor(Render *re)
        g_break = 0;
        
        BLI_end_threads(&threads);
-       freeparts(re);
+       RE_parts_free(re);
        re->viewplane = viewplane; /* restore viewplane, modified by pano render */
 }
 
@@ -926,17 +947,29 @@ void RE_TileProcessor(Render *re)
 
 /* ************  This part uses API, for rendering Blender scenes ********** */
 
+#ifdef WITH_FREESTYLE
+static void add_freestyle(Render *re);
+#endif
+
 static void do_render_3d(Render *re)
 {
+       float cfra;
+       int cfra_backup;
+
        /* try external */
        if (RE_engine_render(re, 0))
                return;
 
        /* internal */
+       RE_parts_clamp(re);
        
-//     re->cfra= cfra; /* <- unused! */
-       re->scene->r.subframe = re->mblur_offs + re->field_offs;
-       
+       /* add motion blur and fields offset to frames */
+       cfra_backup = re->scene->r.cfra;
+
+       cfra = re->scene->r.cfra + re->mblur_offs + re->field_offs;
+       re->scene->r.cfra = floorf(cfra);
+       re->scene->r.subframe = cfra - floorf(cfra);
+
        /* lock drawing in UI during data phase */
        if (re->draw_lock)
                re->draw_lock(re->dlh, 1);
@@ -958,9 +991,17 @@ static void do_render_3d(Render *re)
                if (!re->test_break(re->tbh))
                        add_halo_flare(re);
        
+#ifdef WITH_FREESTYLE
+       /* Freestyle  */
+       if( re->r.mode & R_EDGE_FRS)
+               if(!re->test_break(re->tbh))
+                       add_freestyle(re);
+#endif
+               
        /* free all render verts etc */
        RE_Database_Free(re);
        
+       re->scene->r.cfra = cfra_backup;
        re->scene->r.subframe = 0.f;
 }
 
@@ -992,7 +1033,7 @@ static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, floa
                                        rf[1] = mfac * rf[1] + blurfac * rf1[1];
                                        rf[2] = mfac * rf[2] + blurfac * rf1[2];
                                        rf[3] = mfac * rf[3] + blurfac * rf1[3];
-                               }                               
+                               }
                        }
                }
                rectf += stride;
@@ -1069,7 +1110,7 @@ static void do_render_blur_3d(Render *re)
                
                blurfac = 1.0f / (float)(re->r.mblur_samples - blur);
                
-               merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
+               merge_renderresult_blur(rres, re->result, blurfac, FALSE);
                if (re->test_break(re->tbh)) break;
        }
        
@@ -1084,7 +1125,7 @@ static void do_render_blur_3d(Render *re)
        
        /* weak... the display callback wants an active renderlayer pointer... */
        re->result->renlay = render_get_active_layer(re, re->result);
-       re->display_draw(re->ddh, re->result, NULL);    
+       re->display_draw(re->ddh, re->result, NULL);
 }
 
 
@@ -1121,7 +1162,10 @@ static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, Rende
                /* passes are allocated in sync */
                rpass1 = rl1->passes.first;
                rpass2 = rl2->passes.first;
-               for (rpass = rl->passes.first; rpass && rpass1 && rpass2; rpass = rpass->next, rpass1 = rpass1->next, rpass2 = rpass2->next) {
+               for (rpass = rl->passes.first;
+                    rpass && rpass1 && rpass2;
+                    rpass = rpass->next, rpass1 = rpass1->next, rpass2 = rpass2->next)
+               {
                        interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels);
                }
        }
@@ -1211,8 +1255,8 @@ static void do_render_fields_blur_3d(Render *re)
        Object *camera = RE_GetCamera(re);
        /* also check for camera here */
        if (camera == NULL) {
-               printf("ERROR: Cannot render, no camera\n");
-               G.afbreek = 1;
+               BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
+               G.is_break = TRUE;
                return;
        }
 
@@ -1393,12 +1437,80 @@ static void render_composit_stats(void *UNUSED(arg), char *str)
        R.i.infostr = NULL;
 }
 
+#ifdef WITH_FREESTYLE
+/* invokes Freestyle stroke rendering */
+static void add_freestyle(Render *re)
+{
+       SceneRenderLayer *srl, *actsrl;
+       LinkData *link;
+
+       actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+
+       FRS_init_stroke_rendering(re);
+
+       for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
+
+               link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+               BLI_addtail(&re->freestyle_renders, link);
+
+               if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+                       continue;
+               if (FRS_is_freestyle_enabled(srl)) {
+                       link->data = (void *)FRS_do_stroke_rendering(re, srl);
+               }
+       }
+
+       FRS_finish_stroke_rendering(re);
+}
+
+/* merges the results of Freestyle stroke rendering into a given render result */
+static void composite_freestyle_renders(Render *re, int sample)
+{
+       Render *freestyle_render;
+       SceneRenderLayer *srl, *actsrl;
+       LinkData *link;
+
+       actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+
+       link = (LinkData *)re->freestyle_renders.first;
+       for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
+               if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+                       continue;
+               if (FRS_is_freestyle_enabled(srl)) {
+                       freestyle_render = (Render *)link->data;
+                       render_result_exr_file_read(freestyle_render, sample);
+                       FRS_composite_result(re, srl, freestyle_render);
+                       RE_FreeRenderResult(freestyle_render->result);
+                       freestyle_render->result = NULL;
+               }
+               link = link->next;
+       }
+}
+
+/* releases temporary scenes and renders for Freestyle stroke rendering */
+static void free_all_freestyle_renders(Scene *scene)
+{
+       Render *re1, *freestyle_render;
+       LinkData *link;
+
+       for (re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
+               for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
+                       if (link->data) {
+                               freestyle_render = (Render *)link->data;
+                               BKE_scene_unlink(G.main, freestyle_render->scene, scene);
+                               RE_FreeRender(freestyle_render);
+                       }
+               }
+               BLI_freelistN( &re1->freestyle_renders );
+       }
+}
+#endif
 
 /* reads all buffers, calls optional composite, merges in first result->rectf */
 static void do_merge_fullsample(Render *re, bNodeTree *ntree)
 {
        float *rectf, filt[3][3];
-       int sample;
+       int x, y, sample;
        
        /* interaction callbacks */
        if (ntree) {
@@ -1419,7 +1531,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
        for (sample = 0; sample < re->r.osa; sample++) {
                Render *re1;
                RenderResult rres;
-               int x, y, mask;
+               int mask;
                
                /* enable full sample print */
                R.i.curfsa = sample + 1;
@@ -1434,6 +1546,10 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                                        if (sample) {
                                                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                                                render_result_exr_file_read(re1, sample);
+#ifdef WITH_FREESTYLE
+                                               if( re1->r.mode & R_EDGE_FRS)
+                                                       composite_freestyle_renders(re1, sample);
+#endif
                                                BLI_rw_mutex_unlock(&re->resultmutex);
                                        }
                                        ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */
@@ -1446,7 +1562,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                        ntreeCompositTagRender(re->scene);
                        ntreeCompositTagAnimated(ntree);
                        
-                       ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0);
+                       ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
                }
                
                /* ensure we get either composited result or the active layer */
@@ -1482,6 +1598,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                if (re->test_break(re->tbh))
                        break;
        }
+
+       /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+       for (y = 0; y < re->recty; y++) {
+               float *rf = rectf + 4 * y * re->rectx;
+                       
+               for (x = 0; x < re->rectx; x++, rf += 4) {
+                       rf[0] = MAX2(rf[0], 0.0f);
+                       rf[1] = MAX2(rf[1], 0.0f);
+                       rf[2] = MAX2(rf[2], 0.0f);
+                       CLAMP(rf[3], 0.0f, 1.0f);
+               }
+       }
        
        /* clear interaction callbacks */
        if (ntree) {
@@ -1508,10 +1636,11 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree)
        bNode *node;
 
        /* default start situation */
-       G.afbreek = 0;
+       G.is_break = FALSE;
        
        re->main = bmain;
        re->scene = sce;
+       re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
        
        /* first call RE_ReadRenderResult on every renderlayer scene. this creates Render structs */
        
@@ -1559,7 +1688,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
                ntreeFreeCache(ntree);
                
                do_render_fields_blur_3d(re);
-       } 
+       }
        else {
                /* ensure new result gets added, like for regular renders */
                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
@@ -1610,7 +1739,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
                                if (re->r.scemode & R_FULL_SAMPLE)
                                        do_merge_fullsample(re, ntree);
                                else {
-                                       ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0);
+                                       ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
                                }
                                
                                ntree->stats_draw = NULL;
@@ -1623,6 +1752,10 @@ static void do_render_composite_fields_blur_3d(Render *re)
                        do_merge_fullsample(re, NULL);
        }
 
+#ifdef WITH_FREESTYLE
+       free_all_freestyle_renders(re->scene);
+#endif
+
        /* weak... the display callback wants an active renderlayer pointer... */
        re->result->renlay = render_get_active_layer(re, re->result);
        re->display_draw(re->ddh, re->result, NULL);
@@ -1659,7 +1792,7 @@ int RE_seq_render_active(Scene *scene, RenderData *rd)
 static void do_render_seq(Render *re)
 {
        static int recurs_depth = 0;
-       struct ImBuf *ibuf;
+       struct ImBuf *ibuf, *out;
        RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
        int cfra = re->r.cfra;
        SeqRenderData context;
@@ -1676,17 +1809,26 @@ static void do_render_seq(Render *re)
        if ((re->r.mode & R_BORDER) && (re->r.mode & R_CROP) == 0) {
                /* if border rendering is used and cropping is disabled, final buffer should
                 * be as large as the whole frame */
-               context = seq_new_render_data(re->main, re->scene,
+               context = BKE_sequencer_new_render_data(re->main, re->scene,
                                              re->winx, re->winy,
                                              100);
        }
        else {
-               context = seq_new_render_data(re->main, re->scene,
+               context = BKE_sequencer_new_render_data(re->main, re->scene,
                                              re->result->rectx, re->result->recty,
                                              100);
        }
 
-       ibuf = give_ibuf_seq(context, cfra, 0);
+       out = BKE_sequencer_give_ibuf(context, cfra, 0);
+
+       if (out) {
+               ibuf = IMB_dupImBuf(out);
+               IMB_freeImBuf(out);
+               BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf);
+       }
+       else {
+               ibuf = NULL;
+       }
 
        recurs_depth--;
 
@@ -1701,7 +1843,7 @@ static void do_render_seq(Render *re)
                if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
                        Editing *ed = re->scene->ed;
                        if (ed)
-                               free_imbuf_seq(re->scene, &ed->seqbase, TRUE, TRUE);
+                               BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, TRUE);
                }
                IMB_freeImBuf(ibuf);
        }
@@ -1720,6 +1862,9 @@ static void do_render_seq(Render *re)
                re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra));
        else
                re->progress(re->prh, 1.0f);
+
+       /* would mark display buffers as invalid */
+       re->display_draw(re->ddh, re->result, NULL);
 }
 
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -1734,6 +1879,8 @@ static void do_render_all_options(Render *re)
        /* ensure no images are in memory from previous animated sequences */
        BKE_image_all_free_anim_ibufs(re->r.cfra);
 
+       re->pool = BKE_image_pool_new();
+
        if (RE_engine_render(re, 1)) {
                /* in this case external render overrides all */
        }
@@ -1758,6 +1905,9 @@ static void do_render_all_options(Render *re)
                renderresult_stampinfo(re);
                re->display_draw(re->ddh, re->result, NULL);
        }
+
+       BKE_image_pool_free(re->pool);
+       re->pool = NULL;
 }
 
 static int check_valid_camera(Scene *scene, Object *camera_override)
@@ -1828,8 +1978,11 @@ static int node_tree_has_composite_output(bNodeTree *ntree)
                        return TRUE;
                }
                else if (node->type == NODE_GROUP) {
-                       if (node_tree_has_composite_output((bNodeTree *)node->id))
-                               return TRUE;
+                       if (node->id) {
+                               if (node_tree_has_composite_output((bNodeTree *)node->id)) {
+                                       return TRUE;
+                               }
+                       }
                }
        }
 
@@ -1849,7 +2002,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
                if (scene->r.border.xmax <= scene->r.border.xmin ||
                    scene->r.border.ymax <= scene->r.border.ymin)
                {
-                       BKE_report(reports, RPT_ERROR, "No border area selected.");
+                       BKE_report(reports, RPT_ERROR, "No border area selected");
                        return 0;
                }
        }
@@ -1860,13 +2013,13 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
                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");
+                       BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path");
                        return 0;
                }
                
                /* no fullsample and edge */
                if ((scene->r.scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) {
-                       BKE_report(reports, RPT_ERROR, "Full Sample doesn't support Edge Enhance");
+                       BKE_report(reports, RPT_ERROR, "Full sample does not support edge enhance");
                        return 0;
                }
                
@@ -1877,18 +2030,18 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
        if (scene->r.scemode & R_DOCOMP) {
                if (scene->use_nodes) {
                        if (!scene->nodetree) {
-                               BKE_report(reports, RPT_ERROR, "No Nodetree in Scene");
+                               BKE_report(reports, RPT_ERROR, "No node tree in scene");
                                return 0;
                        }
                        
                        if (!check_composite_output(scene)) {
-                               BKE_report(reports, RPT_ERROR, "No Render Output Node in Scene");
+                               BKE_report(reports, RPT_ERROR, "No render output node in scene");
                                return 0;
                        }
                        
                        if (scene->r.scemode & R_FULL_SAMPLE) {
                                if (composite_needs_render(scene, 0) == 0) {
-                                       BKE_report(reports, RPT_ERROR, "Full Sample AA not supported without 3d rendering");
+                                       BKE_report(reports, RPT_ERROR, "Full sample AA not supported without 3D rendering");
                                        return 0;
                                }
                        }
@@ -1907,7 +2060,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
        /* forbidden combinations */
        if (scene->r.mode & R_PANORAMA) {
                if (scene->r.mode & R_ORTHO) {
-                       BKE_report(reports, RPT_ERROR, "No Ortho render possible for Panorama");
+                       BKE_report(reports, RPT_ERROR, "No ortho render possible for panorama");
                        return 0;
                }
        }
@@ -1923,7 +2076,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
                if (!(srl->layflag & SCE_LAY_DISABLE))
                        break;
        if (srl == NULL) {
-               BKE_report(reports, RPT_ERROR, "All RenderLayers are disabled");
+               BKE_report(reports, RPT_ERROR, "All render layers are disabled");
                return 0;
        }
 
@@ -1992,6 +2145,7 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc
        
        re->main = bmain;
        re->scene = scene;
+       re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
        re->camera_override = camera_override;
        re->lay = lay;
        
@@ -2044,7 +2198,7 @@ void RE_SetReports(Render *re, ReportList *reports)
 void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int frame, const short write_still)
 {
        /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
-       G.rendering = 1;
+       G.is_rendering = TRUE;
        
        scene->r.cfra = frame;
        
@@ -2055,14 +2209,14 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
 
                do_render_all_options(re);
 
-               if (write_still && !G.afbreek) {
+               if (write_still && !G.is_break) {
                        if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
                                /* operator checks this but in case its called from elsewhere */
                                printf("Error: cant write single images with a movie format!\n");
                        }
                        else {
                                char name[FILE_MAX];
-                               BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, FALSE);
+                               BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE);
 
                                /* reports only used for Movie */
                                do_write_image_or_movie(re, bmain, scene, NULL, name);
@@ -2072,20 +2226,22 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
                BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
        }
 
-       BLI_callback_exec(re->main, (ID *)scene, G.afbreek ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
+       BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
 
        /* UGLY WARNING */
-       G.rendering = 0;
+       G.is_rendering = FALSE;
 }
 
-static void colormanage_image_for_write(ImBuf *ibuf, Scene *scene)
+#ifdef WITH_FREESTYLE
+void RE_RenderFreestyleStrokes(Render *re, Main *bmain, 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);
+       re->result_ok= 0;
+       if(render_initialize_from_main(re, bmain, scene, NULL, NULL, scene->lay, 0, 0)) {
+               do_render_fields_blur_3d(re);
+       }
+       re->result_ok= 1;
 }
+#endif
 
 static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
 {
@@ -2099,26 +2255,38 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
        /* write movie or image */
        if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
                int do_free = FALSE;
-               unsigned int *rect32 = (unsigned int *)rres.rect32;
+               ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+
                /* note; the way it gets 32 bits rects is weak... */
-               if (rres.rect32 == NULL) {
-                       rect32 = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect");
-                       RE_ResultGet32(re, rect32);
+               if (ibuf->rect == NULL) {
+                       ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect");
+                       ibuf->mall |= IB_rect;
+                       RE_ResultGet32(re, ibuf->rect);
                        do_free = TRUE;
                }
 
-               ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *)rect32,
-                                     rres.rectx, rres.recty, re->reports);
+
+               IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
+                                                   &scene->display_settings, &scene->r.im_format);
+
+               ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect,
+                                     ibuf->x, ibuf->y, re->reports);
                if (do_free) {
-                       MEM_freeN(rect32);
+                       MEM_freeN(ibuf->rect);
+                       ibuf->rect = NULL;
+                       ibuf->mall &= ~IB_rect;
                }
+
+               /* imbuf knows which rects are not part of ibuf */
+               IMB_freeImBuf(ibuf);
+
                printf("Append frame %d", scene->r.cfra);
-       } 
+       }
        else {
                if (name_override)
                        BLI_strncpy(name, name_override, sizeof(name));
                else
-                       BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+                       BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
                
                if (re->r.im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
                        if (re->result) {
@@ -2128,12 +2296,9 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
                }
                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);
+                       IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
+                                                           &scene->display_settings, &scene->r.im_format);
 
                        ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format);
                        
@@ -2149,10 +2314,11 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
 
                                if (BLI_testextensie(name, ".exr"))
                                        name[strlen(name) - 4] = 0;
-                               BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90);
+                               BKE_add_image_extension(name, &imf);
                                ibuf->planes = 24;
 
-                               colormanage_image_for_write(ibuf, scene);
+                               IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
+                                                                   &scene->display_settings, &imf);
 
                                BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf);
                                printf("\nSaved: %s", name);
@@ -2189,16 +2355,16 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
        
        /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
        /* is also set by caller renderwin.c */
-       G.rendering = 1;
+       G.is_rendering = TRUE;
 
        re->flag |= R_ANIMATION;
 
        if (BKE_imtype_is_movie(scene->r.im_format.imtype))
                if (!mh->start_movie(scene, &re->r, re->rectx, re->recty, re->reports))
-                       G.afbreek = 1;
+                       G.is_break = TRUE;
 
        if (mh->get_next_frame) {
-               while (!(G.afbreek == 1)) {
+               while (!(G.is_break == 1)) {
                        int nf = mh->get_next_frame(&re->r, re->reports);
                        if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) {
                                scene->r.cfra = re->r.cfra = nf;
@@ -2210,16 +2376,17 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
 
                                if (re->test_break(re->tbh) == 0) {
                                        if (!do_write_image_or_movie(re, bmain, scene, mh, NULL))
-                                               G.afbreek = 1;
+                                               G.is_break = TRUE;
                                }
 
-                               if (G.afbreek == 0) {
+                               if (G.is_break == FALSE) {
                                        BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
                                }
                        }
                        else {
-                               if (re->test_break(re->tbh))
-                                       G.afbreek = 1;
+                               if (re->test_break(re->tbh)) {
+                                       G.is_break = TRUE;
+                               }
                        }
                }
        }
@@ -2252,7 +2419,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
                        /* Touch/NoOverwrite options are only valid for image's */
                        if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
                                if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
-                                       BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+                                       BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
 
                                if (scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) {
                                        printf("skipping existing frame \"%s\"\n", name);
@@ -2275,14 +2442,14 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
                        totrendered++;
                        
                        if (re->test_break(re->tbh) == 0) {
-                               if (!G.afbreek)
+                               if (!G.is_break)
                                        if (!do_write_image_or_movie(re, bmain, scene, mh, NULL))
-                                               G.afbreek = 1;
+                                               G.is_break = TRUE;
                        }
                        else
-                               G.afbreek = 1;
+                               G.is_break = TRUE;
                
-                       if (G.afbreek == 1) {
+                       if (G.is_break == TRUE) {
                                /* remove touched file */
                                if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
                                        if (scene->r.mode & R_TOUCH && BLI_exists(name) && BLI_file_size(name) == 0) {
@@ -2293,7 +2460,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
                                break;
                        }
 
-                       if (G.afbreek == 0) {
+                       if (G.is_break == FALSE) {
                                BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
                        }
                }
@@ -2310,10 +2477,10 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
 
        re->flag &= ~R_ANIMATION;
 
-       BLI_callback_exec(re->main, (ID *)scene, G.afbreek ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
+       BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
 
        /* UGLY WARNING */
-       G.rendering = 0;
+       G.is_rendering = FALSE;
 }
 
 void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
@@ -2326,14 +2493,20 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
 
        RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL);
 
+       re->pool = BKE_image_pool_new();
+
        re->main = bmain;
        re->scene = sce;
+       re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
        re->lay = sce->lay;
 
        camera = RE_GetCamera(re);
        RE_SetCamera(re, camera);
 
        do_render_3d(re);
+
+       BKE_image_pool_free(re->pool);
+       re->pool = NULL;
 }
 
 /* note; repeated win/disprect calc... solve that nicer, also in compo */
@@ -2372,6 +2545,7 @@ int RE_ReadRenderResult(Scene *scene, Scene *scenode)
                re = RE_NewRender(scene->id.name);
        RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
        re->scene = scene;
+       re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
        
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        success = render_result_exr_file_read(re, 0);
@@ -2407,7 +2581,8 @@ void RE_init_threadcount(Render *re)
  * x/y offsets are only used on a partial copy when dimensions don't match */
 void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y)
 {
-       ImBuf *ibuf = IMB_loadiffname(filename, IB_rect);
+       /* OCIO_TODO: assume layer was saved in defaule color space */
+       ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL);
 
        if (ibuf && (ibuf->rect || ibuf->rect_float)) {
                if (ibuf->x == layer->rectx && ibuf->y == layer->recty) {
@@ -2431,25 +2606,25 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
                                        IMB_freeImBuf(ibuf_clip);
                                }
                                else {
-                                       BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'\n", filename);
+                                       BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'", filename);
                                }
                        }
                        else {
-                               BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'\n", filename);
+                               BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'", filename);
                        }
                }
 
                IMB_freeImBuf(ibuf);
        }
        else {
-               BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
+               BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename);
        }
 }
 
 void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *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);
+               BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename);
                return;
        }
 }
@@ -2477,8 +2652,8 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
 
        if (env->type == ENV_CUBE) {
                for (i = 0; i < 12; i += 2) {
-                       maxX = MAX2(maxX, layout[i] + 1);
-                       maxY = MAX2(maxY, layout[i + 1] + 1);
+                       maxX = max_ii(maxX, (int)layout[i] + 1);
+                       maxY = max_ii(maxY, (int)layout[i + 1] + 1);
                }
 
                ibuf = IMB_allocImBuf(maxX * dx, maxY * dx, 24, IB_rectfloat);
@@ -2496,8 +2671,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
                return 0;
        }
 
-       if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
-               ibuf->profile = IB_PROFILE_LINEAR_RGB;
+       IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, &scene->display_settings, &imf);
 
        /* to save, we first get absolute path */
        BLI_strncpy(filepath, relpath, sizeof(filepath));
@@ -2511,7 +2685,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
                return TRUE;
        }
        else {
-               BKE_report(reports, RPT_ERROR, "Error writing environment map.");
+               BKE_report(reports, RPT_ERROR, "Error writing environment map");
                return FALSE;
        }
 }