Fix T52653: Render output of linked scenes conflicts with other scenes with the same...
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 12 Sep 2017 06:27:22 +0000 (11:27 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 14 Sep 2017 11:50:19 +0000 (16:50 +0500)
The issue was caused by render result identifier only consist of scene name,
which could indeed cause conflicts.

On the one hand, there are quite some areas in Blender where we need identifier
to be unique to properly address things. Usually this is required for sub-data
of IDs, like bones. On another hand, it's not that hard to support this
particular case and avoid possible frustration.

The idea is, we add library name to render identifier for linked scenes. We use
library name and not pointer so we preserve render results through undo stack.

Reviewers: campbellbarton, mont29, brecht

Reviewed By: mont29

Differential Revision: https://developer.blender.org/D2836

18 files changed:
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/sequencer.c
source/blender/compositor/nodes/COM_CompositorNode.cpp
source/blender/compositor/nodes/COM_RenderLayersNode.cpp
source/blender/compositor/operations/COM_CompositorOperation.cpp
source/blender/compositor/operations/COM_CompositorOperation.h
source/blender/compositor/operations/COM_RenderLayersProg.cpp
source/blender/editors/object/object_bake_api.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_opengl.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_node/node_edit.c
source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/source/pipeline.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/creator_args.c

index 902076c2d14dc96a75eb0e65ceb1a01c29a0c137..f8ed4843a99de8ef195a7a1a9bbcde4b9d6f1f7d 100644 (file)
@@ -1735,7 +1735,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
        }
 
        {
-               Render *re = RE_GetRender(scene->id.name);
+               Render *re = RE_GetSceneRender(scene);
                RenderStats *stats = re ? RE_GetStats(re) : NULL;
 
                if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
@@ -2929,7 +2929,7 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
        }
        else if (ima->type == IMA_TYPE_R_RESULT) {
                if (ima->render_slot == ima->last_render_slot)
-                       rr = RE_AcquireResultRead(RE_GetRender(scene->id.name));
+                       rr = RE_AcquireResultRead(RE_GetSceneRender(scene));
                else
                        rr = ima->renders[ima->render_slot];
 
@@ -2947,7 +2947,7 @@ void BKE_image_release_renderresult(Scene *scene, Image *ima)
        }
        else if (ima->type == IMA_TYPE_R_RESULT) {
                if (ima->render_slot == ima->last_render_slot)
-                       RE_ReleaseResult(RE_GetRender(scene->id.name));
+                       RE_ReleaseResult(RE_GetSceneRender(scene));
        }
 }
 
@@ -2967,7 +2967,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
 {
        /* called right before rendering, ima->renders contains render
         * result pointers for everything but the current render */
-       Render *re = RE_GetRender(scene->id.name);
+       Render *re = RE_GetSceneRender(scene);
        int slot = ima->render_slot, last = ima->last_render_slot;
 
        if (slot != last) {
@@ -3692,7 +3692,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
        if (!r_lock)
                return NULL;
 
-       re = RE_GetRender(iuser->scene->id.name);
+       re = RE_GetSceneRender(iuser->scene);
 
        channels = 4;
        layer = iuser->layer;
index 05ce9c4bbb691c5e8047482faf9e05d1c79cf5cb..9b0db300e6d326e2df8be31431c56336d3784905 100644 (file)
@@ -3320,7 +3320,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
                }
        }
        else {
-               Render *re = RE_GetRender(scene->id.name);
+               Render *re = RE_GetSceneRender(scene);
                const int totviews = BKE_scene_multiview_num_views_get(&scene->r);
                int i;
                ImBuf **ibufs_arr;
@@ -3337,7 +3337,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
                 */
                if (!is_thread_main || is_rendering == false || is_background || context->eval_ctx->mode == DAG_EVAL_RENDER) {
                        if (re == NULL)
-                               re = RE_NewRender(scene->id.name);
+                               re = RE_NewSceneRender(scene);
 
                        BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
                        RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false);
index 9e8b40d8af41e1da406e84d6f9e7bf2322b7c775..4754f23a1671f8a6836b5bbeb62aacf86d6e8c83 100644 (file)
@@ -41,6 +41,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi
        NodeInput *depthSocket = this->getInputSocket(2);
 
        CompositorOperation *compositorOperation = new CompositorOperation();
+       compositorOperation->setScene(context.getScene());
        compositorOperation->setSceneName(context.getScene()->id.name);
        compositorOperation->setRenderData(context.getRenderData());
        compositorOperation->setViewName(context.getViewName());
index 9a11ddbbceb40942887d4c874d49d48820cc2460..2286db81860274f2bc7bc7a987d87f2a93ac3871 100644 (file)
@@ -176,7 +176,7 @@ void RenderLayersNode::convertToOperations(NodeConverter &converter,
                                            const CompositorContext &context) const
 {
        Scene *scene = (Scene *)this->getbNode()->id;
-       Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
+       Render *re = (scene) ? RE_GetSceneRender(scene) : NULL;
 
        if (re != NULL) {
                testRenderLink(converter, context, re);
index 76f74c144f6bc88dbb40b976f4feebc75eb8efdf..15ffff2fc9096ee07283308b3b22a5f1fbaebeba 100644 (file)
@@ -51,6 +51,7 @@ CompositorOperation::CompositorOperation() : NodeOperation()
        this->m_useAlphaInput = false;
        this->m_active = false;
 
+       this->m_scene = NULL;
        this->m_sceneName[0] = '\0';
        this->m_viewName = NULL;
 }
@@ -78,7 +79,7 @@ void CompositorOperation::deinitExecution()
                return;
 
        if (!isBreaked()) {
-               Render *re = RE_GetRender(this->m_sceneName);
+               Render *re = RE_GetSceneRender(this->m_scene);
                RenderResult *rr = RE_AcquireResultWrite(re);
 
                if (rr) {
@@ -217,7 +218,7 @@ void CompositorOperation::determineResolution(unsigned int resolution[2], unsign
 
        // check actual render resolution with cropping it may differ with cropped border.rendering
        // FIX for: [31777] Border Crop gives black (easy)
-       Render *re = RE_GetRender(this->m_sceneName);
+       Render *re = RE_GetSceneRender(this->m_scene);
        if (re) {
                RenderResult *rr = RE_AcquireResultRead(re);
                if (rr) {
index e81ba520695f11bdca5ae0925b8cbd57e4a3c1de..269a065a7931f387b35f082c2523c5d64872b535 100644 (file)
 #include "BLI_rect.h"
 #include "BLI_string.h"
 
+struct Scene;
+
 /**
  * @brief Compositor output operation
  */
 class CompositorOperation : public NodeOperation {
 private:
+       const struct Scene *m_scene;
        /**
         * @brief Scene name, used for getting the render output, includes 'SC' prefix.
         */
@@ -84,6 +87,7 @@ public:
        CompositorOperation();
        const bool isActiveCompositorOutput() const { return this->m_active; }
        void executeRegion(rcti *rect, unsigned int tileNumber);
+       void setScene(const struct Scene *scene) { m_scene = scene; }
        void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); }
        void setViewName(const char *viewName) { this->m_viewName = viewName; }
        void setRenderData(const RenderData *rd) { this->m_rd = rd; }
index 26654b31e163e38c8b2739013f41159af7c67f3f..d1c654ddb6c9b53648301c060f4b9f315079b4ac 100644 (file)
@@ -48,7 +48,7 @@ RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elem
 void RenderLayersProg::initExecution()
 {
        Scene *scene = this->getScene();
-       Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
+       Render *re = (scene) ? RE_GetSceneRender(scene) : NULL;
        RenderResult *rr = NULL;
        
        if (re)
@@ -179,7 +179,7 @@ void RenderLayersProg::deinitExecution()
 void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
 {
        Scene *sce = this->getScene();
-       Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
+       Render *re = (sce) ? RE_GetSceneRender(sce) : NULL;
        RenderResult *rr = NULL;
        
        resolution[0] = 0;
index d25730d7c109bf8a2ddc07a5f6b2de8dc96a0229..122330f7ede37fa4a601f5a99eda31179bc809b5 100644 (file)
@@ -1161,7 +1161,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
 
        bkr->result = OPERATOR_CANCELLED;
 
-       bkr->render = RE_NewRender(bkr->scene->id.name);
+       bkr->render = RE_NewSceneRender(bkr->scene);
 
        /* XXX hack to force saving to always be internal. Whether (and how) to support
         * external saving will be addressed later */
index da14e72f887ef370dace58907bda16fd691999b1..26c863d8514cfb6fb3d241562b5ba03602f8afbf 100644 (file)
@@ -305,7 +305,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
 
-       re = RE_NewRender(scene->id.name);
+       re = RE_NewSceneRender(scene);
        lay_override = (v3d && v3d->lay != scene->lay) ? v3d->lay : 0;
 
        G.is_break = false;
@@ -964,7 +964,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
        rj->image = ima;
 
        /* setup new render */
-       re = RE_NewRender(scene->id.name);
+       re = RE_NewSceneRender(scene);
        RE_test_break_cb(re, rj, render_breakjob);
        RE_draw_lock_cb(re, rj, render_drawlock);
        RE_display_update_cb(re, rj, image_rect_update);
index 01050eda70ba5d777bc82d096b3de566188bc490..a27026878e1cc23539efdf45f02ce2f56a6f8e24 100644 (file)
@@ -681,7 +681,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
        }
 
        /* create render */
-       oglrender->re = RE_NewRender(scene->id.name);
+       oglrender->re = RE_NewSceneRender(scene);
 
        /* create image and image user */
        oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
index e810f4db7dd9f1f244fd34bf126526335e093978..8cb23c9e021ff592fa2e2f765227b5c8d2b0ed09 100644 (file)
@@ -88,7 +88,7 @@ static void draw_render_info(const bContext *C,
                              float zoomy)
 {
        RenderResult *rr;
-       Render *re = RE_GetRender(scene->id.name);
+       Render *re = RE_GetSceneRender(scene);
        RenderData *rd = RE_engine_get_render_data(re);
        Scene *stats_scene = ED_render_job_get_scene(C);
        if (stats_scene == NULL) {
index 3c64d1ebb7154607ef75992f5208dea66c133b9c..eb01b1856e47e988123c206f0515ee604c343c6f 100644 (file)
@@ -3632,7 +3632,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
 {
        ARegion *ar = CTX_wm_region(C);
        Scene *scene = CTX_data_scene(C);
-       Render *re = RE_GetRender(scene->id.name);
+       Render *re = RE_GetSceneRender(scene);
        RenderData *rd;
        rctf border;
 
index 5f8f839025f4fb3e56cea798c68e1d99bf4ae064..e91fd1ee575e1168b2892f1a6f049cfced03b14d 100644 (file)
@@ -1321,7 +1321,7 @@ static int node_read_fullsamplelayers_exec(bContext *C, wmOperator *UNUSED(op))
        Main *bmain = CTX_data_main(C);
        SpaceNode *snode = CTX_wm_space_node(C);
        Scene *curscene = CTX_data_scene(C);
-       Render *re = RE_NewRender(curscene->id.name);
+       Render *re = RE_NewSceneRender(curscene);
 
        WM_cursor_wait(1);
        RE_MergeFullSample(re, bmain, curscene, snode->nodetree);
index 1dbac1848b7e282ce404c68c3f5c2090f7f89157..9c478c203e745b956416d61740e0bed9299a2a62 100644 (file)
@@ -957,7 +957,7 @@ Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render)
        }
 #endif
 
-       Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
+       Render *freestyle_render = RE_NewSceneRender(freestyle_scene);
 
        RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene,
                                  render && get_stroke_count() > 0);
index 0d2e29ba4c8189947a878a646e424bbf04a8726c..cf9298bdb9e5c40fdf01fedf18127bb44ca64c83 100644 (file)
@@ -194,6 +194,10 @@ typedef struct RenderStats {
 struct Render *RE_NewRender(const char *name);
 struct Render *RE_GetRender(const char *name);
 
+struct Scene;
+struct Render *RE_NewSceneRender(const struct Scene *scene);
+struct Render *RE_GetSceneRender(const struct Scene *scene);
+
 /* assign default dummy callbacks */
 void RE_InitRenderCB(struct Render *re);
 
index e078365e1edf74aac1d24d0c78690211852f2c70..a0ebe24156944198d77ed761a1a22fc3fc24359a 100644 (file)
@@ -307,7 +307,6 @@ Render *RE_GetRender(const char *name)
        return re;
 }
 
-
 /* if you want to know exactly what has been done */
 RenderResult *RE_AcquireResultRead(Render *re)
 {
@@ -514,6 +513,36 @@ Render *RE_NewRender(const char *name)
        return re;
 }
 
+/* MAX_ID_NAME + sizeof(Library->name) + space + null-terminator. */
+#define MAX_SCENE_RENDER_NAME (MAX_ID_NAME + 1024 + 2)
+
+static void scene_render_name_get(const Scene *scene,
+                                  const size_t max_size,
+                                  char *render_name)
+{
+       if (ID_IS_LINKED_DATABLOCK(scene)) {
+               BLI_snprintf(render_name, max_size, "%s %s",
+                            scene->id.lib->id.name, scene->id.name);
+       }
+       else {
+               BLI_snprintf(render_name, max_size, "%s", scene->id.name);
+       }
+}
+
+Render *RE_GetSceneRender(const Scene *scene)
+{
+       char render_name[MAX_SCENE_RENDER_NAME];
+       scene_render_name_get(scene, sizeof(render_name), render_name);
+       return RE_GetRender(render_name);
+}
+
+Render *RE_NewSceneRender(const Scene *scene)
+{
+       char render_name[MAX_SCENE_RENDER_NAME];
+       scene_render_name_get(scene, sizeof(render_name), render_name);
+       return RE_NewRender(render_name);
+}
+
 /* called for new renders and when finishing rendering so
  * we always have valid callbacks on a render */
 void RE_InitRenderCB(Render *re)
@@ -1913,7 +1942,7 @@ static void do_render_fields_blur_3d(Render *re)
  */
 static void render_scene(Render *re, Scene *sce, int cfra)
 {
-       Render *resc = RE_NewRender(sce->id.name);
+       Render *resc = RE_NewSceneRender(sce);
        int winx = re->winx, winy = re->winy;
        
        sce->r.cfra = cfra;
@@ -2348,7 +2377,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                tag_scenes_for_render(re);
                for (sce = re->main->scene.first; sce; sce = sce->id.next) {
                        if (sce->id.tag & LIB_TAG_DOIT) {
-                               re1 = RE_GetRender(sce->id.name);
+                               re1 = RE_GetSceneRender(sce);
 
                                if (re1 && (re1->r.scemode & R_FULL_SAMPLE)) {
                                        if (sample) {
@@ -3858,9 +3887,9 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
                scene = scenode;
        
        /* get render: it can be called from UI with draw callbacks */
-       re = RE_GetRender(scene->id.name);
+       re = RE_GetSceneRender(scene);
        if (re == NULL)
-               re = RE_NewRender(scene->id.name);
+               re = RE_NewSceneRender(scene);
        RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
        re->scene = scene;
        re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
index 8bc3f709551b52df929ec268f3be4f49503eb2b3..6afb6c103e07f333dae39529e5d5d4448679f55e 100644 (file)
@@ -271,6 +271,7 @@ void RE_sample_material_color(
         int tri_index, struct DerivedMesh *orcoDm, struct Object *ob) RET_NONE
 /* nodes */
 struct Render *RE_GetRender(const char *name) RET_NULL
+struct Render *RE_GetSceneRender(const struct Scene *scene) RET_NULL
 struct Object *RE_GetCamera(struct Render *re) RET_NULL
 float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO
 const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL
@@ -296,6 +297,7 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
 void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype) RET_NONE
 double elbeemEstimateMemreq(int res, float sx, float sy, float sz, int refine, char *retstr) RET_ZERO
 struct Render *RE_NewRender(const char *name) RET_NULL
+struct Render *RE_NewSceneRender(const struct Scene *scene) RET_NULL
 void RE_SwapResult(struct Render *re, struct RenderResult **rr) RET_NONE
 void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay_override, int frame, const bool write_still) RET_NONE
 bool RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]) RET_ZERO
index 658a0b2db080f5f90fe1e98f7d6b5cddfe2bb647..74ae97bfcb8ac4e67f8dfe476f21600bfa56d8f4 100644 (file)
@@ -1362,7 +1362,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
                                return 1;
                        }
 
-                       re = RE_NewRender(scene->id.name);
+                       re = RE_NewSceneRender(scene);
                        BLI_begin_threaded_malloc();
                        BKE_reports_init(&reports, RPT_STORE);
 
@@ -1404,7 +1404,7 @@ static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(arg
        Scene *scene = CTX_data_scene(C);
        if (scene) {
                Main *bmain = CTX_data_main(C);
-               Render *re = RE_NewRender(scene->id.name);
+               Render *re = RE_NewSceneRender(scene);
                ReportList reports;
                BLI_begin_threaded_malloc();
                BKE_reports_init(&reports, RPT_STORE);