Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / render / render_preview.c
index dc79d5d..b360122 100644 (file)
@@ -51,6 +51,7 @@
 
 #include "DNA_world_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_group_types.h"
 #include "DNA_material_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
@@ -69,6 +70,7 @@
 #include "BKE_image.h"
 #include "BKE_icons.h"
 #include "BKE_lamp.h"
+#include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_library_remap.h"
 #include "BKE_main.h"
 #include "BKE_texture.h"
 #include "BKE_world.h"
 
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+#include "DEG_depsgraph_build.h"
+
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 #include "IMB_thumbs.h"
@@ -85,6 +91,7 @@
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "GPU_shader.h"
 
 #include "RE_pipeline.h"
 #include "RE_engine.h"
 
 #include "ED_datafiles.h"
 #include "ED_render.h"
+#include "ED_screen.h"
 
 #ifndef NDEBUG
 /* Used for database init assert(). */
@@ -149,6 +157,7 @@ typedef struct ShaderPreview {
        short *stop, *do_update;
 
        Scene *scene;
+       Depsgraph *depsgraph;
        ID *id;
        ID *parent;
        MTex *slot;
@@ -178,6 +187,7 @@ typedef struct IconPreviewSize {
 typedef struct IconPreview {
        Main *bmain;
        Scene *scene;
+       Depsgraph *depsgraph;
        void *owner;
        ID *id;
        ListBase sizes;
@@ -236,52 +246,84 @@ void ED_preview_free_dbase(void)
                BKE_main_free(G_pr_main_cycles);
 }
 
-static int preview_mat_has_sss(Material *mat, bNodeTree *ntree)
+static Scene *preview_get_scene(Main *pr_main)
 {
-       if (mat) {
-               if (mat->sss_flag & MA_DIFF_SSS)
-                       return 1;
-               if (mat->nodetree)
-                       if (preview_mat_has_sss(NULL, mat->nodetree))
-                               return 1;
-       }
-       else if (ntree) {
-               bNode *node;
-               for (node = ntree->nodes.first; node; node = node->next) {
-                       if (node->type == NODE_GROUP && node->id) {
-                               if (preview_mat_has_sss(NULL, (bNodeTree *)node->id))
-                                       return 1;
-                       }
-                       else if (node->id && ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
-                               mat = (Material *)node->id;
-                               if (mat->sss_flag & MA_DIFF_SSS)
-                                       return 1;
-                       }
-               }
+       if (pr_main == NULL) return NULL;
+
+       return pr_main->scene.first;
+}
+
+static const char *preview_collection_name(const char pr_type)
+{
+       switch (pr_type) {
+               case MA_FLAT:
+                       return "Flat";
+               case MA_SPHERE:
+                       return "Sphere";
+               case MA_CUBE:
+                       return "Cube";
+               case MA_MONKEY:
+                       return "Monkey";
+               case MA_SPHERE_A:
+                       return "World Sphere";
+               case MA_TEXTURE:
+                       return "Texture";
+               case MA_LAMP:
+                       return "Lamp";
+               case MA_SKY:
+                       return "Sky";
+               case MA_HAIR:
+                       return "Hair";
+               case MA_ATMOS:
+                       return "Atmosphere";
+               default:
+                       BLI_assert(!"Unknown preview type");
+                       return "";
        }
-       return 0;
 }
 
-static Scene *preview_get_scene(Main *pr_main)
+static void set_preview_collection(Scene *scene, ViewLayer *view_layer, char pr_type)
 {
-       if (pr_main == NULL) return NULL;
+       LayerCollection *lc = view_layer->layer_collections.first;
+       const char *collection_name = preview_collection_name(pr_type);
 
-       return pr_main->scene.first;
+       for (lc = lc->layer_collections.first; lc; lc = lc->next) {
+               if (STREQ(lc->collection->id.name + 2, collection_name)) {
+                       lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
+               }
+               else {
+                       lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
+               }
+       }
+
+       BKE_layer_collection_sync(scene, view_layer);
 }
 
+static World *preview_get_localized_world(ShaderPreview *sp, World *world)
+{
+       if (world == NULL) {
+               return NULL;
+       }
+       if (sp->worldcopy != NULL) {
+               return sp->worldcopy;
+       }
+       sp->worldcopy = BKE_world_localize(world);
+       BLI_addtail(&sp->pr_main->world, sp->worldcopy);
+       return sp->worldcopy;
+}
 
 /* call this with a pointer to initialize preview scene */
 /* call this with NULL to restore assigned ID pointers in preview scene */
 static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
 {
        Scene *sce;
-       Base *base;
        Main *pr_main = sp->pr_main;
 
        memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));
 
        sce = preview_get_scene(pr_main);
        if (sce) {
+               ViewLayer *view_layer = sce->view_layers.first;
 
                /* this flag tells render to not execute depsgraph or ipos etc */
                sce->r.scemode |= R_BUTS_PREVIEW;
@@ -320,7 +362,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                         * seems commonly used render engines does not support
                         * such kind of rendering.
                         */
-                       BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine));
+                       BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
                }
                else {
                        BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
@@ -335,77 +377,26 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                                sp->matcopy = mat;
                                BLI_addtail(&pr_main->mat, mat);
 
-                               if (!BKE_scene_use_new_shading_nodes(scene)) {
-                                       init_render_material(bmain, mat, 0, NULL);     /* call that retrieves mode_l */
-                                       end_render_material(mat);
-
-                                       /* un-useful option */
-                                       if (sp->pr_method == PR_ICON_RENDER)
-                                               mat->shade_flag &= ~MA_OBCOLOR;
-
-                                       /* turn on raytracing if needed */
-                                       if (mat->mode_l & MA_RAYMIRROR)
-                                               sce->r.mode |= R_RAYTRACE;
-                                       if (mat->material_type == MA_TYPE_VOLUME)
-                                               sce->r.mode |= R_RAYTRACE;
-                                       if ((mat->mode_l & MA_RAYTRANSP) && (mat->mode_l & MA_TRANSP))
-                                               sce->r.mode |= R_RAYTRACE;
-                                       if (preview_mat_has_sss(mat, NULL))
-                                               sce->r.mode |= R_SSS;
-
-                                       /* turn off fake shadows if needed */
-                                       /* this only works in a specific case where the preview.blend contains
-                                        * an object starting with 'c' which has a material linked to it (not the obdata)
-                                        * and that material has a fake shadow texture in the active texture slot */
-                                       for (base = sce->base.first; base; base = base->next) {
-                                               if (base->object->id.name[2] == 'c') {
-                                                       Material *shadmat = give_current_material(base->object, base->object->actcol);
-                                                       if (shadmat) {
-                                                               if (mat->mode2 & MA_CASTSHADOW) shadmat->septex = 0;
-                                                               else shadmat->septex |= 1;
-                                                       }
-                                               }
-                                       }
-
-                                       /* turn off bounce lights for volume,
-                                        * doesn't make much visual difference and slows it down too */
-                                       for (base = sce->base.first; base; base = base->next) {
-                                               if (base->object->type == OB_LAMP) {
-                                                       /* if doesn't match 'Lamp.002' --> main key light */
-                                                       if (!STREQ(base->object->id.name + 2, "Lamp.002")) {
-                                                               if (mat->material_type == MA_TYPE_VOLUME)
-                                                                       base->object->restrictflag |= OB_RESTRICT_RENDER;
-                                                               else
-                                                                       base->object->restrictflag &= ~OB_RESTRICT_RENDER;
-                                                       }
-                                               }
-                                       }
+                               /* use current scene world to light sphere */
+                               if (mat->pr_type == MA_SPHERE_A && sp->pr_method == PR_BUTS_RENDER) {
+                                       /* Use current scene world to light sphere. */
+                                       sce->world = preview_get_localized_world(sp, scene->world);
                                }
-                               else {
-                                       if (mat->pr_type == MA_SPHERE_A && sp->pr_method == PR_BUTS_RENDER) {
-                                               /* Use current scene world to light sphere. */
-                                               sce->world = scene->world;
-                                       }
-                                       else if (sce->world) {
-                                               /* Use a default world color. Using the current
-                                                * scene world can be slow if it has big textures. */
-                                               sce->world->use_nodes = false;
-                                               sce->world->horr = 0.5f;
-                                               sce->world->horg = 0.5f;
-                                               sce->world->horb = 0.5f;
-                                       }
+                               else if (sce->world) {
+                                       /* Use a default world color. Using the current
+                                        * scene world can be slow if it has big textures. */
+                                       sce->world->use_nodes = false;
+                                       sce->world->horr = 0.5f;
+                                       sce->world->horg = 0.5f;
+                                       sce->world->horb = 0.5f;
                                }
 
                                if (sp->pr_method == PR_ICON_RENDER) {
-                                       if (mat->material_type == MA_TYPE_HALO) {
-                                               sce->lay = 1 << MA_FLAT;
-                                       }
-                                       else {
-                                               sce->lay = 1 << MA_SPHERE_A;
-                                       }
+                                       set_preview_collection(sce, view_layer, MA_SPHERE_A);
                                }
                                else {
-                                       sce->lay = 1 << mat->pr_type;
+                                       set_preview_collection(sce, view_layer, mat->pr_type);
+
                                        if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
                                                /* two previews, they get copied by wmJob */
                                                BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
@@ -414,11 +405,11 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                                }
                        }
                        else {
-                               sce->r.mode &= ~(R_OSA | R_RAYTRACE | R_SSS);
+                               sce->r.mode &= ~(R_OSA);
 
                        }
 
-                       for (base = sce->base.first; base; base = base->next) {
+                       for (Base *base = view_layer->object_bases.first; base; base = base->next) {
                                if (base->object->id.name[2] == 'p') {
                                        /* copy over object color, in case material uses it */
                                        copy_v4_v4(base->object->col, sp->col);
@@ -432,7 +423,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                                                        (*matar)[actcol] = mat;
                                        }
                                        else if (base->object->type == OB_LAMP) {
-                                               base->object->restrictflag &= ~OB_RESTRICT_RENDER;
+                                               base->flag |= BASE_VISIBLED;
                                        }
                                }
                        }
@@ -445,30 +436,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                                sp->texcopy = tex;
                                BLI_addtail(&pr_main->tex, tex);
                        }
-                       sce->lay = 1 << MA_TEXTURE;
-
-                       for (base = sce->base.first; base; base = base->next) {
-                               if (base->object->id.name[2] == 't') {
-                                       Material *mat = give_current_material(base->object, base->object->actcol);
-                                       if (mat && mat->mtex[0]) {
-                                               mat->mtex[0]->tex = tex;
-
-                                               if (tex && sp->slot)
-                                                       mat->mtex[0]->which_output = sp->slot->which_output;
-
-                                               mat->mtex[0]->mapto &= ~MAP_ALPHA;
-                                               mat->alpha = 1.0f;
-
-                                               /* show alpha in this case */
-                                               if (tex == NULL || (tex->flag & TEX_PRV_ALPHA)) {
-                                                       if (!(tex && tex->type == TEX_IMAGE && (tex->imaflag & (TEX_USEALPHA | TEX_CALCALPHA)) == 0)) {
-                                                               mat->mtex[0]->mapto |= MAP_ALPHA;
-                                                               mat->alpha = 0.0f;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
+                       set_preview_collection(sce, view_layer, MA_TEXTURE);
 
                        if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
                                /* two previews, they get copied by wmJob */
@@ -486,30 +454,17 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                                BLI_addtail(&pr_main->lamp, la);
                        }
 
-                       sce->lay = 1 << MA_LAMP;
+                       set_preview_collection(sce, view_layer, MA_LAMP);
 
-                       if (!BKE_scene_use_new_shading_nodes(scene)) {
-                               if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
-                                       sce->lay = 1 << MA_ATMOS;
-                                       sce->world = scene->world;
-                                       sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2);
-                               }
-                               else {
-                                       sce->world = NULL;
-                                       sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2);
-                               }
-                       }
-                       else {
-                               if (sce->world) {
-                                       /* Only use lighting from the lamp. */
-                                       sce->world->use_nodes = false;
-                                       sce->world->horr = 0.0f;
-                                       sce->world->horg = 0.0f;
-                                       sce->world->horb = 0.0f;
-                               }
+                       if (sce->world) {
+                               /* Only use lighting from the lamp. */
+                               sce->world->use_nodes = false;
+                               sce->world->horr = 0.0f;
+                               sce->world->horg = 0.0f;
+                               sce->world->horb = 0.0f;
                        }
 
-                       for (base = sce->base.first; base; base = base->next) {
+                       for (Base *base = view_layer->object_bases.first; base; base = base->next) {
                                if (base->object->id.name[2] == 'p') {
                                        if (base->object->type == OB_LAMP)
                                                base->object->data = la;
@@ -531,7 +486,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
                                BLI_addtail(&pr_main->world, wrld);
                        }
 
-                       sce->lay = 1 << MA_SKY;
+                       set_preview_collection(sce, view_layer, MA_SKY);
                        sce->world = wrld;
 
                        if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
@@ -607,7 +562,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
                                if (re)
                                        RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
 
-                               glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
+                               IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+                               immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte,
+                                                1.0f, 1.0f, NULL);
 
                                MEM_freeN(rect_byte);
 
@@ -728,6 +685,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
        char name[32];
        int sizex;
        Main *pr_main = sp->pr_main;
+       ID *id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
 
        /* in case of split preview, use border render */
        if (split) {
@@ -747,7 +705,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
        }
 
        /* get the stuff from the builtin preview dbase */
-       sce = preview_prepare_scene(sp->bmain, sp->scene, id, idtype, sp);
+       sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
        if (sce == NULL) return;
 
        if (!split || first) sprintf(name, "Preview %p", sp->owner);
@@ -1036,6 +994,12 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
 
                        *do_update = true;
                }
+               else if (idtype == ID_SCR) {
+                       bScreen *screen = (bScreen *)id;
+
+                       ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
+                       *do_update = true;
+               }
                else {
                        /* re-use shader job */
                        shader_preview_startjob(customdata, stop, do_update);
@@ -1045,12 +1009,6 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
                        if (idtype == ID_WO) {
                                set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
                        }
-                       else if (idtype == ID_MA) {
-                               Material *ma = (Material *)id;
-
-                               if (ma->material_type == MA_TYPE_HALO)
-                                       set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
-                       }
                }
        }
 }
@@ -1095,7 +1053,6 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
 {
        IconPreview *ip = (IconPreview *)customdata;
        IconPreviewSize *cur_size;
-       const bool use_new_shading = BKE_scene_use_new_shading_nodes(ip->scene);
 
        for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
                PreviewImage *prv = ip->owner;
@@ -1110,6 +1067,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
 
                /* construct shader preview from image size and previewcustomdata */
                sp->scene = ip->scene;
+               sp->depsgraph = ip->depsgraph;
                sp->owner = ip->owner;
                sp->sizex = cur_size->sizex;
                sp->sizey = cur_size->sizey;
@@ -1120,19 +1078,14 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
 
                if (is_render) {
                        BLI_assert(ip->id);
-                       if (use_new_shading) {
-                               /* texture icon rendering is hardcoded to use BI,
-                                * so don't even think of using cycle's bmain for
-                                * texture icons
-                                */
-                               if (GS(ip->id->name) != ID_TE)
-                                       sp->pr_main = G_pr_main_cycles;
-                               else
-                                       sp->pr_main = G_pr_main;
-                       }
-                       else {
+                       /* texture icon rendering is hardcoded to use the BI scene,
+                        * so don't even think of using cycle's bmain for
+                        * texture icons
+                        */
+                       if (GS(ip->id->name) != ID_TE)
+                               sp->pr_main = G_pr_main_cycles;
+                       else
                                sp->pr_main = G_pr_main;
-                       }
                }
 
                common_preview_startjob(sp, stop, do_update, progress);
@@ -1227,6 +1180,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
        /* customdata for preview thread */
        ip->bmain = CTX_data_main(C);
        ip->scene = CTX_data_scene(C);
+       ip->depsgraph = CTX_data_depsgraph(C);
        ip->owner = owner;
        ip->id = id;
 
@@ -1255,10 +1209,11 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
        ShaderPreview *sp;
        Scene *scene = CTX_data_scene(C);
        short id_type = GS(id->name);
-       bool use_new_shading = BKE_scene_use_new_shading_nodes(scene);
+
+       /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
 
        /* Only texture node preview is supported with Cycles. */
-       if (use_new_shading && method == PR_NODE_RENDER && id_type != ID_TE) {
+       if (method == PR_NODE_RENDER && id_type != ID_TE) {
                return;
        }
 
@@ -1270,6 +1225,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
 
        /* customdata for preview thread */
        sp->scene = scene;
+       sp->depsgraph = CTX_data_depsgraph(C);
        sp->owner = owner;
        sp->sizex = sizex;
        sp->sizey = sizey;
@@ -1279,9 +1235,9 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
        sp->slot = slot;
        sp->bmain = CTX_data_main(C);
 
-       /* hardcoded preview .blend for cycles/internal, this should be solved
+       /* hardcoded preview .blend for Eevee + Cycles, this should be solved
         * once with custom preview .blend path for external engines */
-       if ((method != PR_NODE_RENDER) && id_type != ID_TE && use_new_shading) {
+       if ((method != PR_NODE_RENDER) && id_type != ID_TE) {
                sp->pr_main = G_pr_main_cycles;
        }
        else {
@@ -1299,11 +1255,9 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
        WM_jobs_start(CTX_wm_manager(C), wm_job);
 }
 
-void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain)
+void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
 {
        if (wm)
                WM_jobs_kill(wm, NULL, common_preview_startjob);
-
-       ED_viewport_render_kill_jobs(wm, bmain, false);
 }