Merged changes in the trunk up to revision 54110.
[blender.git] / source / blender / render / intern / source / pipeline.c
index 1b237d61e8147aaa33ec50f97ead3029238fde50..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_sequencer.h"
 #include "BKE_writeavi.h"  /* <------ should be replaced once with generic movie module */
 
-#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 "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"
@@ -336,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, &re->scene->view_settings, &re->scene->display_settings);
+       render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
        RE_ReleaseResultImage(re);
 }
 
@@ -469,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");
@@ -582,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);
@@ -655,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) {
                
@@ -686,14 +693,14 @@ static void *do_part_thread(void *pa_v)
                }
        }
        
-       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;
@@ -727,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;
@@ -765,7 +772,7 @@ 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) {
+               if (pa->status == PART_STATUS_READY) {
                        centx += BLI_rcti_cent_x(&pa->disprect);
                        centy += BLI_rcti_cent_y(&pa->disprect);
                        tot++;
@@ -776,7 +783,7 @@ 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) {
+               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);
@@ -833,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);
@@ -884,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);
                                
@@ -928,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 */
 }
 
@@ -940,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);
@@ -972,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;
 }
 
@@ -1083,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;
        }
        
@@ -1228,7 +1255,7 @@ 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");
+               BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
                G.is_break = TRUE;
                return;
        }
@@ -1410,6 +1437,74 @@ 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)
@@ -1451,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 */
@@ -1653,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);
@@ -1776,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 */
        }
@@ -1800,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)
@@ -2108,7 +2216,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
                        }
                        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);
@@ -2124,6 +2232,17 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
        G.is_rendering = FALSE;
 }
 
+#ifdef WITH_FREESTYLE
+void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene)
+{
+       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)
 {
        char name[FILE_MAX];
@@ -2167,7 +2286,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
                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) {
@@ -2195,7 +2314,7 @@ 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;
 
                                IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
@@ -2300,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);
@@ -2374,6 +2493,8 @@ 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);
@@ -2383,6 +2504,9 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
        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 */