code cleanup: favor braces when blocks have mixed brace use.
[blender.git] / source / blender / editors / render / render_preview.c
index f0ef7c6..5caa874 100644 (file)
@@ -1,5 +1,4 @@
-/* 
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -65,6 +64,7 @@
 
 #include "BKE_brush.h"
 #include "BKE_context.h"
+#include "BKE_colortools.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_idprop.h"
 #include "BKE_material.h"
 #include "BKE_node.h"
 #include "BKE_object.h"
+#include "BKE_scene.h"
 #include "BKE_texture.h"
 #include "BKE_world.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
+
+#include "GPU_extensions.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
@@ -93,6 +97,7 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "ED_datafiles.h"
 #include "ED_render.h"
 #include "ED_view3d.h"
 
 
 #include "render_intern.h"
 
-ImBufget_brush_icon(Brush *brush)
+ImBuf *get_brush_icon(Brush *brush)
 {
-       static const int flags = IB_rect|IB_multilayer|IB_metadata;
+       static const int flags = IB_rect | IB_multilayer | IB_metadata;
 
        char path[FILE_MAX];
-       char *folder;
+       const char *folder;
 
        if (!(brush->icon_imbuf)) {
                if (brush->flag & BRUSH_CUSTOM_ICON) {
@@ -116,16 +121,19 @@ ImBuf* get_brush_icon(Brush *brush)
                                BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
                                BLI_path_abs(path, G.main->name);
 
-                               brush->icon_imbuf= IMB_loadiffname(path, flags);
+                               /* use default colorspaces for brushes */
+                               brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
 
                                // otherwise lets try to find it in other directories
                                if (!(brush->icon_imbuf)) {
-                                       folder= BLI_get_folder(BLENDER_DATAFILES, "brushicons");
+                                       folder = BLI_get_folder(BLENDER_DATAFILES, "brushicons");
 
                                        BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath);
 
-                                       if (path[0])
-                                               brush->icon_imbuf= IMB_loadiffname(path, flags);
+                                       if (path[0]) {
+                                               /* use fefault color spaces */
+                                               brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
+                                       }
                                }
 
                                if (brush->icon_imbuf)
@@ -156,12 +164,13 @@ typedef struct ShaderPreview {
        Lamp *lampcopy;
        World *worldcopy;
        
-       float col[4];           /* active object color */
+       float col[4];       /* active object color */
        
        int sizex, sizey;
        unsigned int *pr_rect;
        int pr_method;
-       
+
+       Main *pr_main;
 } ShaderPreview;
 
 typedef struct IconPreviewSize {
@@ -179,52 +188,65 @@ typedef struct IconPreview {
 
 /* *************************** Preview for buttons *********************** */
 
-static Main *pr_main= NULL;
+static Main *pr_main = NULL;
+static Main *pr_main_cycles = NULL;
 
-void ED_preview_init_dbase(void)
-{
 #ifndef WITH_HEADLESS
+static Main *load_main_from_memory(char *blend, int blend_size)
+{
+       const int fileflags = G.fileflags;
+       Main *bmain = NULL;
        BlendFileData *bfd;
-       extern int datatoc_preview_blend_size;
-       extern char datatoc_preview_blend[];
-       const int fileflags= G.fileflags;
-       
+
        G.fileflags |= G_FILE_NO_UI;
-       bfd= BLO_read_from_memory(datatoc_preview_blend, datatoc_preview_blend_size, NULL);
+       bfd = BLO_read_from_memory(blend, blend_size, NULL);
        if (bfd) {
-               pr_main= bfd->main;
-               
+               bmain = bfd->main;
+
                MEM_freeN(bfd);
        }
-       G.fileflags= fileflags;
+       G.fileflags = fileflags;
+
+       return bmain;
+}
+#endif
+
+void ED_preview_init_dbase(void)
+{
+#ifndef WITH_HEADLESS
+       pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
+       pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size);
 #endif
 }
 
 void ED_preview_free_dbase(void)
 {
-       if(pr_main)
+       if (pr_main)
                free_main(pr_main);
+
+       if (pr_main_cycles)
+               free_main(pr_main_cycles);
 }
 
 static int preview_mat_has_sss(Material *mat, bNodeTree *ntree)
 {
-       if(mat) {
-               if(mat->sss_flag & MA_DIFF_SSS)
+       if (mat) {
+               if (mat->sss_flag & MA_DIFF_SSS)
                        return 1;
-               if(mat->nodetree)
-                       ifpreview_mat_has_sss(NULL, mat->nodetree))
+               if (mat->nodetree)
+                       if (preview_mat_has_sss(NULL, mat->nodetree))
                                return 1;
        }
-       else if(ntree) {
+       else if (ntree) {
                bNode *node;
-               for(node= ntree->nodes.first; node; node= node->next) {
-                       if(node->type==NODE_GROUP && node->id) {
-                               ifpreview_mat_has_sss(NULL, (bNodeTree *)node->id))
+               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)
+                       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;
                        }
                }
@@ -232,113 +254,129 @@ static int preview_mat_has_sss(Material *mat, bNodeTree *ntree)
        return 0;
 }
 
+static Scene *preview_get_scene(Main *pr_main)
+{
+       if (pr_main == NULL) return NULL;
+       
+       return pr_main->scene.first;
+}
+
+
 /* 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(Scene *scene, ID *id, int id_type, ShaderPreview *sp)
 {
        Scene *sce;
        Base *base;
+       Main *pr_main = sp->pr_main;
        
-       if(pr_main==NULL) return NULL;
-       
-       sce= pr_main->scene.first;
-       if(sce) {
+       sce = preview_get_scene(pr_main);
+       if (sce) {
                
                /* this flag tells render to not execute depsgraph or ipos etc */
                sce->r.scemode |= R_PREVIEWBUTS;
                /* set world always back, is used now */
-               sce->world= pr_main->world.first;
+               sce->world = pr_main->world.first;
                /* now: exposure copy */
-               if(scene->world) {
-                       sce->world->exp= scene->world->exp;
-                       sce->world->range= scene->world->range;
+               if (scene->world) {
+                       sce->world->exp = scene->world->exp;
+                       sce->world->range = scene->world->range;
                }
                
                sce->r.color_mgt_flag = scene->r.color_mgt_flag;
+               BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
+
+               BKE_color_managed_view_settings_free(&sce->view_settings);
+               BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
                
                /* prevent overhead for small renders and icons (32) */
-               if(id && sp->sizex < 40)
-                       sce->r.xparts= sce->r.yparts= 1;
-               else
-                       sce->r.xparts= sce->r.yparts= 4;
-               
-               /* exception: don't color manage texture previews or icons */
-               if((id && sp->pr_method==PR_ICON_RENDER) || id_type == ID_TE)
-                       sce->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT;
+               if (id && sp->sizex < 40) {
+                       sce->r.tilex = sce->r.tiley = 64;
+               }
+               else {
+                       sce->r.tilex = sce->r.xsch / 4;
+                       sce->r.tiley = sce->r.ysch / 4;
+               }
                
-               if((id && sp->pr_method==PR_ICON_RENDER) && id_type != ID_WO)
-                       sce->r.alphamode= R_ALPHAPREMUL;
+               if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
+                       sce->r.alphamode = R_ALPHAPREMUL;
                else
-                       sce->r.alphamode= R_ADDSKY;
+                       sce->r.alphamode = R_ADDSKY;
 
-               sce->r.cfra= scene->r.cfra;
+               sce->r.cfra = scene->r.cfra;
                BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
                
-               if(id_type==ID_MA) {
-                       Material *mat= NULL, *origmat= (Material *)id;
+               if (id_type == ID_MA) {
+                       Material *mat = NULL, *origmat = (Material *)id;
                        
-                       if(origmat) {
+                       if (origmat) {
                                /* work on a copy */
-                               mat= localize_material(origmat);
-                               sp->matcopy= mat;
+                               mat = localize_material(origmat);
+                               sp->matcopy = mat;
                                BLI_addtail(&pr_main->mat, mat);
                                
-                               init_render_material(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->mode & MA_SHADBUF) shadmat->septex = 0;
-                                                       else shadmat->septex |= 1;
+                               if (!BKE_scene_use_new_shading_nodes(scene)) {
+                                       init_render_material(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->mode & MA_SHADBUF) shadmat->septex = 0;
+                                                               else shadmat->septex |= 1;
+                                                       }
                                                }
                                        }
-                               }
-                               
-                               /* turn off bounce lights for volume, 
-                                * doesn't make much visual difference and slows it down too */
-                               if(mat->material_type == MA_TYPE_VOLUME) {
-                                       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( strcmp(base->object->id.name+2, "Lamp.002") != 0 ) {
-                                                               base->object->restrictflag |= OB_RESTRICT_RENDER;
+                                       
+                                       /* turn off bounce lights for volume, 
+                                        * doesn't make much visual difference and slows it down too */
+                                       if (mat->material_type == MA_TYPE_VOLUME) {
+                                               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 (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
+                                                                       base->object->restrictflag |= OB_RESTRICT_RENDER;
+                                                               }
                                                        }
                                                }
                                        }
                                }
-
+                               else {
+                                       /* use current scene world to light sphere */
+                                       if (mat->pr_type == MA_SPHERE_A)
+                                               sce->world = scene->world;
+                               }
                                
-                               if(sp->pr_method==PR_ICON_RENDER) {
+                               if (sp->pr_method == PR_ICON_RENDER) {
                                        if (mat->material_type == MA_TYPE_HALO) {
-                                               sce->lay= 1<<MA_FLAT;
-                                       } 
+                                               sce->lay = 1 << MA_FLAT;
+                                       }
                                        else {
-                                               sce->lay= 1<<MA_SPHERE_A;
+                                               sce->lay = 1 << MA_SPHERE_A;
                                        }
                                }
                                else {
-                                       sce->lay= 1<<mat->pr_type;
-                                       if(mat->nodetree && sp->pr_method==PR_NODE_RENDER) {
+                                       sce->lay = 1 << mat->pr_type;
+                                       if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
                                                /* two previews, they get copied by wmJob */
                                                ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
                                                ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
@@ -346,114 +384,118 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                                }
                        }
                        else {
-                               sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
+                               sce->r.mode &= ~(R_OSA | R_RAYTRACE | R_SSS);
                                
                        }
                        
-                       for(base= sce->base.first; base; base= base->next) {
-                               if(base->object->id.name[2]=='p') {
+                       for (base = sce->base.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);
                                        
-                                       if(OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
+                                       if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
                                                /* don't use assign_material, it changed mat->id.us, which shows in the UI */
-                                               Material ***matar= give_matarar(base->object);
-                                               int actcol= MAX2(base->object->actcol > 0, 1) - 1;
+                                               Material ***matar = give_matarar(base->object);
+                                               int actcol = max_ii(base->object->actcol - 1, 0);
 
-                                               if(matar && actcol < base->object->totcol)
-                                                       (*matar)[actcol]= mat;
-                                       } else if (base->object->type == OB_LAMP) {
+                                               if (matar && actcol < base->object->totcol)
+                                                       (*matar)[actcol] = mat;
+                                       }
+                                       else if (base->object->type == OB_LAMP) {
                                                base->object->restrictflag &= ~OB_RESTRICT_RENDER;
                                        }
                                }
                        }
                }
-               else if(id_type==ID_TE) {
-                       Tex *tex= NULL, *origtex= (Tex *)id;
+               else if (id_type == ID_TE) {
+                       Tex *tex = NULL, *origtex = (Tex *)id;
                        
-                       if(origtex) {
-                               tex= localize_texture(origtex);
-                               sp->texcopy= tex;
+                       if (origtex) {
+                               tex = localize_texture(origtex);
+                               sp->texcopy = tex;
                                BLI_addtail(&pr_main->tex, tex);
-                       }                       
-                       sce->lay= 1<<MA_TEXTURE;
+                       }
+                       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;
+                       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)
+                                               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)) {
-                                                       mat->mtex[0]->mapto |= MAP_ALPHA;
-                                                       mat->alpha= 0.0f;
-                                               }
-                                               else {
-                                                       mat->mtex[0]->mapto &= ~MAP_ALPHA;
-                                                       mat->alpha= 1.0f;
+                                               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;
+                                                       }
                                                }
                                        }
                                }
                        }
 
-                       if(tex && tex->nodetree && sp->pr_method==PR_NODE_RENDER) {
+                       if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
                                /* two previews, they get copied by wmJob */
                                ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey);
                                ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
                        }
                }
-               else if(id_type==ID_LA) {
-                       Lamp *la= NULL, *origla= (Lamp *)id;
+               else if (id_type == ID_LA) {
+                       Lamp *la = NULL, *origla = (Lamp *)id;
 
                        /* work on a copy */
-                       if(origla) {
-                               la= localize_lamp(origla);
-                               sp->lampcopy= la;
+                       if (origla) {
+                               la = localize_lamp(origla);
+                               sp->lampcopy = la;
                                BLI_addtail(&pr_main->lamp, la);
                        }
-                       
-                       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->lay= 1<<MA_LAMP;
-                               sce->world= NULL;
-                               sce->camera= (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name)+2);
+
+                       sce->lay = 1 << 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);
+                               }
                        }
-                       sce->r.mode &= ~R_SHADOW;
-                       
-                       for(base= sce->base.first; base; base= base->next) {
-                               if(base->object->id.name[2]=='p') {
-                                       if(base->object->type==OB_LAMP)
-                                               base->object->data= la;
+                               
+                       for (base = sce->base.first; base; base = base->next) {
+                               if (base->object->id.name[2] == 'p') {
+                                       if (base->object->type == OB_LAMP)
+                                               base->object->data = la;
                                }
                        }
 
-                       if(la && la->nodetree && sp->pr_method==PR_NODE_RENDER) {
+                       if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
                                /* two previews, they get copied by wmJob */
                                ntreeInitPreview(origla->nodetree, sp->sizex, sp->sizey);
                                ntreeInitPreview(la->nodetree, sp->sizex, sp->sizey);
                        }
                }
-               else if(id_type==ID_WO) {
-                       World *wrld= NULL, *origwrld= (World *)id;
+               else if (id_type == ID_WO) {
+                       World *wrld = NULL, *origwrld = (World *)id;
 
-                       if(origwrld) {
-                               wrld= localize_world(origwrld);
-                               sp->worldcopy= wrld;
+                       if (origwrld) {
+                               wrld = localize_world(origwrld);
+                               sp->worldcopy = wrld;
                                BLI_addtail(&pr_main->world, wrld);
                        }
 
-                       sce->lay= 1<<MA_SKY;
-                       sce->world= wrld;
+                       sce->lay = 1 << MA_SKY;
+                       sce->world = wrld;
 
-                       if(wrld && wrld->nodetree && sp->pr_method==PR_NODE_RENDER) {
+                       if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
                                /* two previews, they get copied by wmJob */
                                ntreeInitPreview(wrld->nodetree, sp->sizex, sp->sizey);
                                ntreeInitPreview(origwrld->nodetree, sp->sizex, sp->sizey);
@@ -468,112 +510,97 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
 
 /* new UI convention: draw is in pixel space already. */
 /* uses ROUNDBOX button in block to get the rect */
-static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int first, rcti *rect, rcti *newrect)
+static int ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
 {
        Render *re;
        RenderResult rres;
        char name[32];
-       int do_gamma_correct=0, do_predivide=0;
-       int offx=0, newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin;
-
-       if (id && GS(id->name) != ID_TE) {
-               /* exception: don't color manage texture previews - show the raw values */
-               if (sce) {
-                       do_gamma_correct = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT;
-                       do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
-               }
-       }
+       int offx = 0;
+       int newx = BLI_rcti_size_x(rect);
+       int newy = BLI_rcti_size_y(rect);
 
-       if(!split || first) sprintf(name, "Preview %p", (void *)sa);
+       if (!split || first) sprintf(name, "Preview %p", (void *)sa);
        else sprintf(name, "SecondPreview %p", (void *)sa);
 
-       if(split) {
-               if(first) {
-                       offx= 0;
-                       newx= newx/2;
+       if (split) {
+               if (first) {
+                       offx = 0;
+                       newx = newx / 2;
                }
                else {
-                       offx= newx/2;
-                       newx= newx - newx/2;
+                       offx = newx / 2;
+                       newx = newx - newx / 2;
                }
        }
 
-       re= RE_GetRender(name);
+       /* test if something rendered ok */
+       re = RE_GetRender(name);
        RE_AcquireResultImage(re, &rres);
+       RE_ReleaseResultImage(re);
 
-       if(rres.rectf) {
+       if (rres.rectf) {
                
-               if(ABS(rres.rectx-newx)<2 && ABS(rres.recty-newy)<2) {
-
-                       newrect->xmax= MAX2(newrect->xmax, rect->xmin + rres.rectx + offx);
-                       newrect->ymax= MAX2(newrect->ymax, rect->ymin + rres.recty);
-
-                       if(rres.rectx && rres.recty) {
-                               /* temporary conversion to byte for drawing */
-                               float fx= rect->xmin + offx;
-                               float fy= rect->ymin;
-                               int profile_from= (do_gamma_correct)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
-                               int dither= 0;
-                               unsigned char *rect_byte;
-
-                               rect_byte= MEM_mallocN(rres.rectx*rres.recty*sizeof(int), "ed_preview_draw_rect");
+               if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
 
-                               IMB_buffer_byte_from_float(rect_byte, rres.rectf,
-                                       4, dither, IB_PROFILE_SRGB, profile_from, do_predivide, 
-                                       rres.rectx, rres.recty, rres.rectx, rres.rectx);
+                       newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
+                       newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
 
+                       if (rres.rectx && rres.recty) {
+                               unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
+                               float fx = rect->xmin + offx;
+                               float fy = rect->ymin;
+                               
+                               RE_ResultGet32(re, (unsigned int *)rect_byte);
                                glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
-
+                               
                                MEM_freeN(rect_byte);
+                               
+                               return 1;
                        }
-
-                       RE_ReleaseResultImage(re);
-                       return 1;
                }
        }
 
-       RE_ReleaseResultImage(re);
        return 0;
 }
 
 void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
 {
-       if(idp) {
-               ScrArea *sa= CTX_wm_area(C);
-               Scene *sce = CTX_data_scene(C);
+       if (idp) {
+               ScrArea *sa = CTX_wm_area(C);
                ID *id = (ID *)idp;
-               ID *parent= (ID *)parentp;
-               MTex *slot= (MTex *)slotp;
-               SpaceButs *sbuts= sa->spacedata.first;
+               ID *parent = (ID *)parentp;
+               MTex *slot = (MTex *)slotp;
+               SpaceButs *sbuts = sa->spacedata.first;
                rcti newrect;
                int ok;
-               int newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin;
+               int newx = BLI_rcti_size_x(rect);
+               int newy = BLI_rcti_size_y(rect);
 
-               newrect.xmin= rect->xmin;
-               newrect.xmax= rect->xmin;
-               newrect.ymin= rect->ymin;
-               newrect.ymax= rect->ymin;
+               newrect.xmin = rect->xmin;
+               newrect.xmax = rect->xmin;
+               newrect.ymin = rect->ymin;
+               newrect.ymax = rect->ymin;
 
-               if(parent) {
-                       ok = ed_preview_draw_rect(sa, sce, id, 1, 1, rect, &newrect);
-                       ok &= ed_preview_draw_rect(sa, sce, parent, 1, 0, rect, &newrect);
+               if (parent) {
+                       ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
+                       ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
                }
                else
-                       ok = ed_preview_draw_rect(sa, sce, id, 0, 0, rect, &newrect);
+                       ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
 
-               if(ok)
-                       *rect= newrect;
+               if (ok)
+                       *rect = newrect;
 
                /* check for spacetype... */
-               if(sbuts->spacetype==SPACE_BUTS && sbuts->preview) {
-                       sbuts->preview= 0;
-                       ok= 0;
+               if (sbuts->spacetype == SPACE_BUTS && sbuts->preview) {
+                       sbuts->preview = 0;
+                       ok = 0;
                }
        
-               if(ok==0) {
+               if (ok == 0) {
                        ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
                }
-       }       
+       }
 }
 
 /* **************************** new shader preview system ****************** */
@@ -581,15 +608,15 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
 /* inside thread, called by renderer, sets job update value */
 static void shader_preview_draw(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
 {
-       ShaderPreview *sp= spv;
+       ShaderPreview *sp = spv;
        
-       *(sp->do_update)= 1;
+       *(sp->do_update) = TRUE;
 }
 
 /* called by renderer, checks job value */
 static int shader_preview_break(void *spv)
 {
-       ShaderPreview *sp= spv;
+       ShaderPreview *sp = spv;
 
        return *(sp->stop);
 }
@@ -597,35 +624,35 @@ static int shader_preview_break(void *spv)
 /* outside thread, called before redraw notifiers, it moves finished preview over */
 static void shader_preview_updatejob(void *spv)
 {
-       ShaderPreview *sp= spv;
+       ShaderPreview *sp = spv;
        
-       if(sp->id) {
-               if(sp->pr_method==PR_NODE_RENDER) {
-                       ifGS(sp->id->name) == ID_MA) {
-                               Material *mat= (Material *)sp->id;
+       if (sp->id) {
+               if (sp->pr_method == PR_NODE_RENDER) {
+                       if (GS(sp->id->name) == ID_MA) {
+                               Material *mat = (Material *)sp->id;
                                
-                               if(sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
+                               if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
                                        ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
                        }
-                       else ifGS(sp->id->name) == ID_TE) {
-                               Tex *tex= (Tex *)sp->id;
+                       else if (GS(sp->id->name) == ID_TE) {
+                               Tex *tex = (Tex *)sp->id;
                                
-                               if(sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
+                               if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
                                        ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree);
                        }
-                       else ifGS(sp->id->name) == ID_WO) {
-                               World *wrld= (World *)sp->id;
+                       else if (GS(sp->id->name) == ID_WO) {
+                               World *wrld = (World *)sp->id;
                                
-                               if(sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
+                               if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
                                        ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree);
                        }
-                       else ifGS(sp->id->name) == ID_LA) {
-                               Lamp *la= (Lamp *)sp->id;
+                       else if (GS(sp->id->name) == ID_LA) {
+                               Lamp *la = (Lamp *)sp->id;
                                
-                               if(sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
+                               if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
                                        ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
                        }
-               }               
+               }
        }
 }
 
@@ -634,79 +661,86 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
        Render *re;
        Scene *sce;
        float oldlens;
-       short idtype= GS(id->name);
+       short idtype = GS(id->name);
        char name[32];
        int sizex;
+       Main *pr_main = sp->pr_main;
+       
+       /* in case of split preview, use border render */
+       if (split) {
+               if (first) sizex = sp->sizex / 2;
+               else sizex = sp->sizex - sp->sizex / 2;
+       }
+       else {
+               sizex = sp->sizex;
+       }
+
+       /* we have to set preview variables first */
+       sce = preview_get_scene(pr_main);
+       if (sce) {
+               sce->r.xsch = sizex;
+               sce->r.ysch = sp->sizey;
+               sce->r.size = 100;
+       }
        
        /* get the stuff from the builtin preview dbase */
-       sce= preview_prepare_scene(sp->scene, id, idtype, sp); // XXX sizex
-       if(sce==NULL) return;
+       sce = preview_prepare_scene(sp->scene, id, idtype, sp);
+       if (sce == NULL) return;
        
-       if(!split || first) sprintf(name, "Preview %p", sp->owner);
+       if (!split || first) sprintf(name, "Preview %p", sp->owner);
        else sprintf(name, "SecondPreview %p", sp->owner);
-       re= RE_GetRender(name);
+       re = RE_GetRender(name);
        
        /* full refreshed render from first tile */
-       if(re==NULL)
-               re= RE_NewRender(name);
+       if (re == NULL)
+               re = RE_NewRender(name);
                
        /* sce->r gets copied in RE_InitState! */
-       sce->r.scemode &= ~(R_MATNODE_PREVIEW|R_TEXNODE_PREVIEW);
+       sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW);
        sce->r.scemode &= ~R_NO_IMAGE_LOAD;
 
-       if(sp->pr_method==PR_ICON_RENDER) {
+       if (sp->pr_method == PR_ICON_RENDER) {
                sce->r.scemode |= R_NO_IMAGE_LOAD;
                sce->r.mode |= R_OSA;
        }
-       else if(sp->pr_method==PR_NODE_RENDER) {
-               if(idtype == ID_MA) sce->r.scemode |= R_MATNODE_PREVIEW;
-               else if(idtype == ID_TE) sce->r.scemode |= R_TEXNODE_PREVIEW;
+       else if (sp->pr_method == PR_NODE_RENDER) {
+               if (idtype == ID_MA) sce->r.scemode |= R_MATNODE_PREVIEW;
+               else if (idtype == ID_TE) sce->r.scemode |= R_TEXNODE_PREVIEW;
                sce->r.mode &= ~R_OSA;
        }
-       else {  /* PR_BUTS_RENDER */
+       else {  /* PR_BUTS_RENDER */
                sce->r.mode |= R_OSA;
        }
 
-       /* in case of split preview, use border render */
-       if(split) {
-               if(first) sizex= sp->sizex/2;
-               else sizex= sp->sizex - sp->sizex/2;
-       }
-       else sizex= sp->sizex;
-
-       /* allocates or re-uses render result */
-       sce->r.xsch= sizex;
-       sce->r.ysch= sp->sizey;
-       sce->r.size= 100;
 
        /* callbacs are cleared on GetRender() */
-       if(ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
+       if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
                RE_display_draw_cb(re, sp, shader_preview_draw);
        }
-       /* set this for all previews, default is react to G.afbreek still */
+       /* set this for all previews, default is react to G.is_break still */
        RE_test_break_cb(re, sp, shader_preview_break);
        
        /* lens adjust */
-       oldlens= ((Camera *)sce->camera->data)->lens;
-       if(sizex > sp->sizey)
-               ((Camera *)sce->camera->data)->lens *= (float)sp->sizey/(float)sizex;
+       oldlens = ((Camera *)sce->camera->data)->lens;
+       if (sizex > sp->sizey)
+               ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
 
        /* entire cycle for render engine */
        RE_PreviewRender(re, pr_main, sce);
 
-       ((Camera *)sce->camera->data)->lens= oldlens;
+       ((Camera *)sce->camera->data)->lens = oldlens;
 
        /* handle results */
-       if(sp->pr_method==PR_ICON_RENDER) {
+       if (sp->pr_method == PR_ICON_RENDER) {
                // char *rct= (char *)(sp->pr_rect + 32*16 + 16);
                
-               if(sp->pr_rect)
+               if (sp->pr_rect)
                        RE_ResultGet32(re, sp->pr_rect);
        }
        else {
                /* validate owner */
-               //if(ri->rect==NULL)
-               //      ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+               //if (ri->rect == NULL)
+               //      ri->rect= MEM_mallocN(sizeof(int) * ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
                //RE_ResultGet32(re, ri->rect);
        }
 
@@ -714,9 +748,9 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
        preview_prepare_scene(sp->scene, NULL, GS(id->name), sp);
        
        /* XXX bad exception, end-exec is not being called in render, because it uses local main */
-//     if(idtype == ID_TE) {
+//     if (idtype == ID_TE) {
 //             Tex *tex= (Tex *)id;
-//             if(tex->use_nodes && tex->nodetree)
+//             if (tex->use_nodes && tex->nodetree)
 //                     ntreeEndExecTree(tex->nodetree);
 //     }
 
@@ -725,28 +759,28 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
 /* runs inside thread for material and icons */
 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
 {
-       ShaderPreview *sp= customdata;
+       ShaderPreview *sp = customdata;
 
-       sp->stop= stop;
-       sp->do_update= do_update;
+       sp->stop = stop;
+       sp->do_update = do_update;
 
-       if(sp->parent) {
+       if (sp->parent) {
                shader_preview_render(sp, sp->id, 1, 1);
                shader_preview_render(sp, sp->parent, 1, 0);
        }
        else
                shader_preview_render(sp, sp->id, 0, 0);
 
-       *do_update= 1;
+       *do_update = TRUE;
 }
 
 static void shader_preview_free(void *customdata)
 {
-       ShaderPreview *sp= customdata;
+       ShaderPreview *sp = customdata;
+       Main *pr_main = sp->pr_main;
        
-       if(sp->matcopy) {
+       if (sp->matcopy) {
                struct IDProperty *properties;
-               int a;
                
                /* node previews */
                shader_preview_updatejob(sp);
@@ -754,63 +788,57 @@ static void shader_preview_free(void *customdata)
                /* get rid of copied material */
                BLI_remlink(&pr_main->mat, sp->matcopy);
                
-               /* free_material decrements texture, prevent this. hack alert! */
-               for(a=0; a<MAX_MTEX; a++) {
-                       MTex *mtex= sp->matcopy->mtex[a];
-                       if(mtex && mtex->tex) mtex->tex= NULL;
-               }
-               
-               free_material(sp->matcopy);
+               BKE_material_free_ex(sp->matcopy, FALSE);
 
-               properties= IDP_GetProperties((ID *)sp->matcopy, FALSE);
+               properties = IDP_GetProperties((ID *)sp->matcopy, FALSE);
                if (properties) {
                        IDP_FreeProperty(properties);
                        MEM_freeN(properties);
                }
                MEM_freeN(sp->matcopy);
        }
-       if(sp->texcopy) {
+       if (sp->texcopy) {
                struct IDProperty *properties;
                /* node previews */
                shader_preview_updatejob(sp);
                
                /* get rid of copied texture */
                BLI_remlink(&pr_main->tex, sp->texcopy);
-               free_texture(sp->texcopy);
+               BKE_texture_free(sp->texcopy);
                
-               properties= IDP_GetProperties((ID *)sp->texcopy, FALSE);
+               properties = IDP_GetProperties((ID *)sp->texcopy, FALSE);
                if (properties) {
                        IDP_FreeProperty(properties);
                        MEM_freeN(properties);
                }
                MEM_freeN(sp->texcopy);
        }
-       if(sp->worldcopy) {
+       if (sp->worldcopy) {
                struct IDProperty *properties;
                /* node previews */
                shader_preview_updatejob(sp);
                
                /* get rid of copied world */
                BLI_remlink(&pr_main->world, sp->worldcopy);
-               free_world(sp->worldcopy);
+               BKE_world_free_ex(sp->worldcopy, TRUE); /* [#32865] - we need to unlink the texture copies, unlike for materials */
                
-               properties= IDP_GetProperties((ID *)sp->worldcopy, FALSE);
+               properties = IDP_GetProperties((ID *)sp->worldcopy, FALSE);
                if (properties) {
                        IDP_FreeProperty(properties);
                        MEM_freeN(properties);
                }
                MEM_freeN(sp->worldcopy);
        }
-       if(sp->lampcopy) {
+       if (sp->lampcopy) {
                struct IDProperty *properties;
                /* node previews */
                shader_preview_updatejob(sp);
                
                /* get rid of copied lamp */
                BLI_remlink(&pr_main->lamp, sp->lampcopy);
-               free_lamp(sp->lampcopy);
+               BKE_lamp_free(sp->lampcopy);
                
-               properties= IDP_GetProperties((ID *)sp->lampcopy, FALSE);
+               properties = IDP_GetProperties((ID *)sp->lampcopy, FALSE);
                if (properties) {
                        IDP_FreeProperty(properties);
                        MEM_freeN(properties);
@@ -831,7 +859,7 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
        short ex, ey, dx, dy;
 
        /* paranoia test */
-       if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
+       if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL))
                return;
        
        /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
@@ -842,10 +870,10 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
        
        if (ima->x > ima->y) {
                scaledx = (float)w;
-               scaledy =  ( (float)ima->y/(float)ima->x )*(float)w;
+               scaledy =  ( (float)ima->y / (float)ima->x) * (float)w;
        }
-       else {                  
-               scaledx =  ( (float)ima->x/(float)ima->y )*(float)h;
+       else {
+               scaledx =  ( (float)ima->x / (float)ima->y) * (float)h;
                scaledy = (float)h;
        }
        
@@ -858,15 +886,15 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
        IMB_scalefastImBuf(ima, ex, ey);
        
        /* if needed, convert to 32 bits */
-       if(ima->rect==NULL)
+       if (ima->rect == NULL)
                IMB_rect_from_float(ima);
 
        srect = ima->rect;
        drect = rect;
 
-       drect+= dy*w+dx;
-       for (;ey > 0; ey--){            
-               memcpy(drect,srect, ex * sizeof(int));
+       drect += dy * w + dx;
+       for (; ey > 0; ey--) {
+               memcpy(drect, srect, ex * sizeof(int));
                drect += w;
                srect += ima->x;
        }
@@ -876,55 +904,59 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned
 
 static void set_alpha(char *cp, int sizex, int sizey, char alpha) 
 {
-       int a, size= sizex*sizey;
+       int a, size = sizex * sizey;
 
-       for(a=0; a<size; a++, cp+=4)
-               cp[3]= alpha;
+       for (a = 0; a < size; a++, cp += 4)
+               cp[3] = alpha;
 }
 
 static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
 {
-       ShaderPreview *sp= customdata;
-       ID *id= sp->id;
-       short idtype= GS(id->name);
-
-       if(idtype == ID_IM) {
-               Image *ima= (Image*)id;
-               ImBuf *ibuf= NULL;
-               ImageUser iuser= {NULL};
+       ShaderPreview *sp = customdata;
+       ID *id = sp->id;
+       short idtype = GS(id->name);
+       
+       if (idtype == ID_IM) {
+               Image *ima = (Image *)id;
+               ImBuf *ibuf = NULL;
+               ImageUser iuser = {NULL};
 
                /* ima->ok is zero when Image cannot load */
-               if(ima==NULL || ima->ok==0)
+               if (ima == NULL || ima->ok == 0)
                        return;
 
                /* setup dummy image user */
-               iuser.ok= iuser.framenr= 1;
-               iuser.scene= sp->scene;
+               iuser.ok = iuser.framenr = 1;
+               iuser.scene = sp->scene;
                
                /* elubie: this needs to be changed: here image is always loaded if not
                 * already there. Very expensive for large images. Need to find a way to 
                 * only get existing ibuf */
-               ibuf = BKE_image_get_ibuf(ima, &iuser);
-               if(ibuf==NULL || ibuf->rect==NULL)
+               ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+               if (ibuf == NULL || ibuf->rect == NULL) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                        return;
+               }
                
                icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
 
-               *do_update= 1;
+               *do_update = TRUE;
+
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
-       else if(idtype == ID_BR) {
-               Brush *br= (Brush*)id;
+       else if (idtype == ID_BR) {
+               Brush *br = (Brush *)id;
 
-               br->icon_imbuf= get_brush_icon(br);
+               br->icon_imbuf = get_brush_icon(br);
 
-               memset(sp->pr_rect, 0x888888, sp->sizex*sp->sizey*sizeof(unsigned int));
+               memset(sp->pr_rect, 0x888888, sp->sizex * sp->sizey * sizeof(unsigned int));
 
-               if(!(br->icon_imbuf) || !(br->icon_imbuf->rect))
+               if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
                        return;
 
                icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
 
-               *do_update= 1;
+               *do_update = TRUE;
        }
        else {
                /* re-use shader job */
@@ -932,14 +964,14 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
 
                /* world is rendered with alpha=0, so it wasn't displayed 
                 * this could be render option for sky to, for later */
-               if(idtype == ID_WO) {
-                       set_alpha((char*)sp->pr_rect, sp->sizex, sp->sizey, 255);
+               if (idtype == ID_WO) {
+                       set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
                }
-               else if(idtype == ID_MA) {
-                       Material* ma = (Material*)id;
+               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);
+                       if (ma->material_type == MA_TYPE_HALO)
+                               set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
                }
        }
 }
@@ -949,9 +981,9 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
 
 static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
 {
-       ShaderPreview *sp= customdata;
+       ShaderPreview *sp = customdata;
 
-       if(sp->pr_method == PR_ICON_RENDER)
+       if (sp->pr_method == PR_ICON_RENDER)
                icon_preview_startjob(customdata, stop, do_update);
        else
                shader_preview_startjob(customdata, stop, do_update);
@@ -986,20 +1018,20 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
        IconPreviewSize *cur_size = ip->sizes.first;
 
        while (cur_size) {
-               ShaderPreview sp;
-
-               memset(&sp, 0, sizeof(ShaderPreview));
+               ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
 
                /* construct shader preview from image size and previewcustomdata */
-               sp.scene= ip->scene;
-               sp.owner= ip->owner;
-               sp.sizex= cur_size->sizex;
-               sp.sizey= cur_size->sizey;
-               sp.pr_method= PR_ICON_RENDER;
-               sp.pr_rect= cur_size->rect;
-               sp.id = ip->id;
-
-               common_preview_startjob(&sp, stop, do_update, progress);
+               sp->scene = ip->scene;
+               sp->owner = ip->owner;
+               sp->sizex = cur_size->sizex;
+               sp->sizey = cur_size->sizey;
+               sp->pr_method = PR_ICON_RENDER;
+               sp->pr_rect = cur_size->rect;
+               sp->id = ip->id;
+               sp->pr_main = pr_main;
+
+               common_preview_startjob(sp, stop, do_update, progress);
+               shader_preview_free(sp);
 
                cur_size = cur_size->next;
        }
@@ -1009,8 +1041,27 @@ static void icon_preview_endjob(void *customdata)
 {
        IconPreview *ip = customdata;
 
-       if (ip->id && GS(ip->id->name) == ID_BR)
-               WM_main_add_notifier(NC_BRUSH|NA_EDITED, ip->id);
+       if (ip->id) {
+
+               if (GS(ip->id->name) == ID_BR)
+                       WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
+#if 0          
+               if (GS(ip->id->name) == ID_MA) {
+                       Material *ma = (Material *)ip->id;
+                       PreviewImage *prv_img = ma->preview;
+                       int i;
+
+                       /* signal to gpu texture */
+                       for (i = 0; i < NUM_ICON_SIZES; ++i) {
+                               if (prv_img->gputexture[i]) {
+                                       GPU_texture_free(prv_img->gputexture[i]);
+                                       prv_img->gputexture[i] = NULL;
+                                       WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
+                               }
+                       }
+               }
+#endif
+       }
 }
 
 static void icon_preview_free(void *customdata)
@@ -1023,67 +1074,82 @@ static void icon_preview_free(void *customdata)
 
 void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
 {
-       wmJob *steve;
+       wmJob *wm_job;
        IconPreview *ip, *old_ip;
        
        /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
-       steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview", WM_JOB_EXCL_RENDER|WM_JOB_SUSPEND);
+       wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview",
+                            WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, WM_JOB_TYPE_RENDER_PREVIEW);
 
-       ip= MEM_callocN(sizeof(IconPreview), "icon preview");
+       ip = MEM_callocN(sizeof(IconPreview), "icon preview");
 
        /* render all resolutions from suspended job too */
-       old_ip= WM_jobs_get_customdata(steve);
+       old_ip = WM_jobs_customdata_get(wm_job);
        if (old_ip)
                BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
 
        /* customdata for preview thread */
-       ip->scene= CTX_data_scene(C);
-       ip->owner= id;
-       ip->id= id;
+       ip->scene = CTX_data_scene(C);
+       ip->owner = id;
+       ip->id = id;
 
        icon_preview_add_size(ip, rect, sizex, sizey);
 
        /* setup job */
-       WM_jobs_customdata(steve, ip, icon_preview_free);
-       WM_jobs_timer(steve, 0.25, NC_MATERIAL, NC_MATERIAL);
-       WM_jobs_callbacks(steve, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
+       WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
+       WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
+       WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
 
-       WM_jobs_start(CTX_wm_manager(C), steve);
+       WM_jobs_start(CTX_wm_manager(C), wm_job);
 }
 
 void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method)
 {
-       Object *ob= CTX_data_active_object(C);
-       wmJob *steve;
+       Object *ob = CTX_data_active_object(C);
+       wmJob *wm_job;
        ShaderPreview *sp;
+       Scene *scene = CTX_data_scene(C);
+
+       /* node previews not supported for cycles */
+       if (BKE_scene_use_new_shading_nodes(scene) && method == PR_NODE_RENDER)
+               return;
 
-       steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview", WM_JOB_EXCL_RENDER);
-       sp= MEM_callocN(sizeof(ShaderPreview), "shader preview");
+       wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview",
+                           WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
+       sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
 
        /* customdata for preview thread */
-       sp->scene= CTX_data_scene(C);
-       sp->owner= owner;
-       sp->sizex= sizex;
-       sp->sizey= sizey;
-       sp->pr_method= method;
+       sp->scene = scene;
+       sp->owner = owner;
+       sp->sizex = sizex;
+       sp->sizey = sizey;
+       sp->pr_method = method;
        sp->id = id;
-       sp->parent= parent;
-       sp->slot= slot;
-       if(ob && ob->totcol) copy_v4_v4(sp->col, ob->col);
-       else sp->col[0]= sp->col[1]= sp->col[2]= sp->col[3]= 1.0f;
+       sp->parent = parent;
+       sp->slot = slot;
+
+       /* hardcoded preview .blend for cycles/internal, this should be solved
+        * once with custom preview .blend path for external engines */
+       if (BKE_scene_use_new_shading_nodes(scene))
+               sp->pr_main = pr_main_cycles;
+       else
+               sp->pr_main = pr_main;
+
+       if (ob && ob->totcol) copy_v4_v4(sp->col, ob->col);
+       else sp->col[0] = sp->col[1] = sp->col[2] = sp->col[3] = 1.0f;
        
        /* setup job */
-       WM_jobs_customdata(steve, sp, shader_preview_free);
-       WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL);
-       WM_jobs_callbacks(steve, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
+       WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
+       WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
+       WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
        
-       WM_jobs_start(CTX_wm_manager(C), steve);
+       WM_jobs_start(CTX_wm_manager(C), wm_job);
 }
 
 void ED_preview_kill_jobs(const struct bContext *C)
 {
-       wmWindowManager *wm= CTX_wm_manager(C);
-       if(wm)
+       wmWindowManager *wm = CTX_wm_manager(C);
+       if (wm)
                WM_jobs_kill(wm, NULL, common_preview_startjob);
 }