Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / render / render_preview.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/render/render_preview.c
29  *  \ingroup edrend
30  */
31
32
33 /* global includes */
34
35 #include <stdlib.h>
36 #include <math.h>
37 #include <string.h>
38
39 #ifndef WIN32
40 #include <unistd.h>
41 #else
42 #include <io.h>
43 #endif
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_math.h"
47 #include "BLI_blenlib.h"
48 #include "BLI_utildefines.h"
49
50 #include "BLO_readfile.h"
51
52 #include "DNA_world_types.h"
53 #include "DNA_camera_types.h"
54 #include "DNA_group_types.h"
55 #include "DNA_material_types.h"
56 #include "DNA_node_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_lamp_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_brush_types.h"
62 #include "DNA_screen_types.h"
63
64 #include "BKE_appdir.h"
65 #include "BKE_brush.h"
66 #include "BKE_context.h"
67 #include "BKE_colortools.h"
68 #include "BKE_global.h"
69 #include "BKE_idprop.h"
70 #include "BKE_image.h"
71 #include "BKE_icons.h"
72 #include "BKE_lamp.h"
73 #include "BKE_layer.h"
74 #include "BKE_library.h"
75 #include "BKE_library_remap.h"
76 #include "BKE_main.h"
77 #include "BKE_material.h"
78 #include "BKE_node.h"
79 #include "BKE_scene.h"
80 #include "BKE_texture.h"
81 #include "BKE_world.h"
82
83 #include "DEG_depsgraph.h"
84 #include "DEG_depsgraph_query.h"
85 #include "DEG_depsgraph_build.h"
86
87 #include "IMB_imbuf.h"
88 #include "IMB_imbuf_types.h"
89 #include "IMB_thumbs.h"
90
91 #include "BIF_gl.h"
92 #include "BIF_glutil.h"
93
94 #include "GPU_shader.h"
95
96 #include "RE_pipeline.h"
97 #include "RE_engine.h"
98
99 #include "WM_api.h"
100 #include "WM_types.h"
101
102 #include "ED_datafiles.h"
103 #include "ED_render.h"
104 #include "ED_screen.h"
105
106 #ifndef NDEBUG
107 /* Used for database init assert(). */
108 #  include "BLI_threads.h"
109 #endif
110
111 ImBuf *get_brush_icon(Brush *brush)
112 {
113         static const int flags = IB_rect | IB_multilayer | IB_metadata;
114
115         char path[FILE_MAX];
116         const char *folder;
117
118         if (!(brush->icon_imbuf)) {
119                 if (brush->flag & BRUSH_CUSTOM_ICON) {
120
121                         if (brush->icon_filepath[0]) {
122                                 // first use the path directly to try and load the file
123
124                                 BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
125                                 BLI_path_abs(path, G.main->name);
126
127                                 /* use default colorspaces for brushes */
128                                 brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
129
130                                 // otherwise lets try to find it in other directories
131                                 if (!(brush->icon_imbuf)) {
132                                         folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
133
134                                         BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath);
135
136                                         if (path[0]) {
137                                                 /* use fefault color spaces */
138                                                 brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
139                                         }
140                                 }
141
142                                 if (brush->icon_imbuf)
143                                         BKE_icon_changed(BKE_icon_id_ensure(&brush->id));
144                         }
145                 }
146         }
147
148         if (!(brush->icon_imbuf))
149                 brush->id.icon_id = 0;
150
151         return brush->icon_imbuf;
152 }
153
154 typedef struct ShaderPreview {
155         /* from wmJob */
156         void *owner;
157         short *stop, *do_update;
158
159         Scene *scene;
160         Depsgraph *depsgraph;
161         ID *id;
162         ID *parent;
163         MTex *slot;
164
165         /* datablocks with nodes need full copy during preview render, glsl uses it too */
166         Material *matcopy;
167         Tex *texcopy;
168         Lamp *lampcopy;
169         World *worldcopy;
170
171         float col[4];       /* active object color */
172
173         int sizex, sizey;
174         unsigned int *pr_rect;
175         int pr_method;
176
177         Main *bmain;
178         Main *pr_main;
179 } ShaderPreview;
180
181 typedef struct IconPreviewSize {
182         struct IconPreviewSize *next, *prev;
183         int sizex, sizey;
184         unsigned int *rect;
185 } IconPreviewSize;
186
187 typedef struct IconPreview {
188         Main *bmain;
189         Scene *scene;
190         Depsgraph *depsgraph;
191         void *owner;
192         ID *id;
193         ListBase sizes;
194 } IconPreview;
195
196 /* *************************** Preview for buttons *********************** */
197
198 static Main *G_pr_main = NULL;
199 static Main *G_pr_main_cycles = NULL;
200
201 #ifndef WITH_HEADLESS
202 static Main *load_main_from_memory(const void *blend, int blend_size)
203 {
204         const int fileflags = G.fileflags;
205         Main *bmain = NULL;
206         BlendFileData *bfd;
207
208         G.fileflags |= G_FILE_NO_UI;
209         bfd = BLO_read_from_memory(blend, blend_size, NULL, BLO_READ_SKIP_NONE);
210         if (bfd) {
211                 bmain = bfd->main;
212
213                 MEM_freeN(bfd);
214         }
215         G.fileflags = fileflags;
216
217         return bmain;
218 }
219 #endif
220
221 void ED_preview_ensure_dbase(void)
222 {
223 #ifndef WITH_HEADLESS
224         static bool base_initialized = false;
225         BLI_assert(BLI_thread_is_main());
226         if (!base_initialized) {
227                 G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
228                 G_pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size);
229                 base_initialized = true;
230         }
231 #endif
232 }
233
234 static bool check_engine_supports_textures(Scene *scene)
235 {
236         RenderEngineType *type = RE_engines_find(scene->r.engine);
237         return type->flag & RE_USE_TEXTURE_PREVIEW;
238 }
239
240 void ED_preview_free_dbase(void)
241 {
242         if (G_pr_main)
243                 BKE_main_free(G_pr_main);
244
245         if (G_pr_main_cycles)
246                 BKE_main_free(G_pr_main_cycles);
247 }
248
249 static Scene *preview_get_scene(Main *pr_main)
250 {
251         if (pr_main == NULL) return NULL;
252
253         return pr_main->scene.first;
254 }
255
256 static const char *preview_collection_name(const char pr_type)
257 {
258         switch (pr_type) {
259                 case MA_FLAT:
260                         return "Flat";
261                 case MA_SPHERE:
262                         return "Sphere";
263                 case MA_CUBE:
264                         return "Cube";
265                 case MA_MONKEY:
266                         return "Monkey";
267                 case MA_SPHERE_A:
268                         return "World Sphere";
269                 case MA_TEXTURE:
270                         return "Texture";
271                 case MA_LAMP:
272                         return "Lamp";
273                 case MA_SKY:
274                         return "Sky";
275                 case MA_HAIR:
276                         return "Hair";
277                 case MA_ATMOS:
278                         return "Atmosphere";
279                 default:
280                         BLI_assert(!"Unknown preview type");
281                         return "";
282         }
283 }
284
285 static void set_preview_collection(Scene *scene, ViewLayer *view_layer, char pr_type)
286 {
287         LayerCollection *lc = view_layer->layer_collections.first;
288         const char *collection_name = preview_collection_name(pr_type);
289
290         for (lc = lc->layer_collections.first; lc; lc = lc->next) {
291                 if (STREQ(lc->collection->id.name + 2, collection_name)) {
292                         lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
293                 }
294                 else {
295                         lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
296                 }
297         }
298
299         BKE_layer_collection_sync(scene, view_layer);
300 }
301
302 static World *preview_get_localized_world(ShaderPreview *sp, World *world)
303 {
304         if (world == NULL) {
305                 return NULL;
306         }
307         if (sp->worldcopy != NULL) {
308                 return sp->worldcopy;
309         }
310         sp->worldcopy = BKE_world_localize(world);
311         BLI_addtail(&sp->pr_main->world, sp->worldcopy);
312         return sp->worldcopy;
313 }
314
315 /* call this with a pointer to initialize preview scene */
316 /* call this with NULL to restore assigned ID pointers in preview scene */
317 static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
318 {
319         Scene *sce;
320         Main *pr_main = sp->pr_main;
321
322         memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));
323
324         sce = preview_get_scene(pr_main);
325         if (sce) {
326                 ViewLayer *view_layer = sce->view_layers.first;
327
328                 /* this flag tells render to not execute depsgraph or ipos etc */
329                 sce->r.scemode |= R_BUTS_PREVIEW;
330                 /* set world always back, is used now */
331                 sce->world = pr_main->world.first;
332                 /* now: exposure copy */
333                 if (scene->world) {
334                         sce->world->exp = scene->world->exp;
335                         sce->world->range = scene->world->range;
336                 }
337
338                 sce->r.color_mgt_flag = scene->r.color_mgt_flag;
339                 BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
340
341                 BKE_color_managed_view_settings_free(&sce->view_settings);
342                 BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
343
344                 /* prevent overhead for small renders and icons (32) */
345                 if (id && sp->sizex < 40) {
346                         sce->r.tilex = sce->r.tiley = 64;
347                 }
348                 else {
349                         sce->r.tilex = sce->r.xsch / 4;
350                         sce->r.tiley = sce->r.ysch / 4;
351                 }
352
353                 if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
354                         sce->r.alphamode = R_ALPHAPREMUL;
355                 else
356                         sce->r.alphamode = R_ADDSKY;
357
358                 sce->r.cfra = scene->r.cfra;
359
360                 if (id_type == ID_TE && !check_engine_supports_textures(scene)) {
361                         /* Force blender internal for texture icons and nodes render,
362                          * seems commonly used render engines does not support
363                          * such kind of rendering.
364                          */
365                         BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
366                 }
367                 else {
368                         BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
369                 }
370
371                 if (id_type == ID_MA) {
372                         Material *mat = NULL, *origmat = (Material *)id;
373
374                         if (origmat) {
375                                 /* work on a copy */
376                                 mat = BKE_material_localize(origmat);
377                                 sp->matcopy = mat;
378                                 BLI_addtail(&pr_main->mat, mat);
379
380                                 /* use current scene world to light sphere */
381                                 if (mat->pr_type == MA_SPHERE_A && sp->pr_method == PR_BUTS_RENDER) {
382                                         /* Use current scene world to light sphere. */
383                                         sce->world = preview_get_localized_world(sp, scene->world);
384                                 }
385                                 else if (sce->world) {
386                                         /* Use a default world color. Using the current
387                                          * scene world can be slow if it has big textures. */
388                                         sce->world->use_nodes = false;
389                                         sce->world->horr = 0.5f;
390                                         sce->world->horg = 0.5f;
391                                         sce->world->horb = 0.5f;
392                                 }
393
394                                 if (sp->pr_method == PR_ICON_RENDER) {
395                                         set_preview_collection(sce, view_layer, MA_SPHERE_A);
396                                 }
397                                 else {
398                                         set_preview_collection(sce, view_layer, mat->pr_type);
399
400                                         if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
401                                                 /* two previews, they get copied by wmJob */
402                                                 BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
403                                                 BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
404                                         }
405                                 }
406                         }
407                         else {
408                                 sce->r.mode &= ~(R_OSA);
409
410                         }
411
412                         for (Base *base = view_layer->object_bases.first; base; base = base->next) {
413                                 if (base->object->id.name[2] == 'p') {
414                                         /* copy over object color, in case material uses it */
415                                         copy_v4_v4(base->object->col, sp->col);
416
417                                         if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
418                                                 /* don't use assign_material, it changed mat->id.us, which shows in the UI */
419                                                 Material ***matar = give_matarar(base->object);
420                                                 int actcol = max_ii(base->object->actcol - 1, 0);
421
422                                                 if (matar && actcol < base->object->totcol)
423                                                         (*matar)[actcol] = mat;
424                                         }
425                                         else if (base->object->type == OB_LAMP) {
426                                                 base->flag |= BASE_VISIBLED;
427                                         }
428                                 }
429                         }
430                 }
431                 else if (id_type == ID_TE) {
432                         Tex *tex = NULL, *origtex = (Tex *)id;
433
434                         if (origtex) {
435                                 tex = BKE_texture_localize(origtex);
436                                 sp->texcopy = tex;
437                                 BLI_addtail(&pr_main->tex, tex);
438                         }
439                         set_preview_collection(sce, view_layer, MA_TEXTURE);
440
441                         if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
442                                 /* two previews, they get copied by wmJob */
443                                 BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
444                                 BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
445                         }
446                 }
447                 else if (id_type == ID_LA) {
448                         Lamp *la = NULL, *origla = (Lamp *)id;
449
450                         /* work on a copy */
451                         if (origla) {
452                                 la = BKE_lamp_localize(origla);
453                                 sp->lampcopy = la;
454                                 BLI_addtail(&pr_main->lamp, la);
455                         }
456
457                         set_preview_collection(sce, view_layer, MA_LAMP);
458
459                         if (sce->world) {
460                                 /* Only use lighting from the lamp. */
461                                 sce->world->use_nodes = false;
462                                 sce->world->horr = 0.0f;
463                                 sce->world->horg = 0.0f;
464                                 sce->world->horb = 0.0f;
465                         }
466
467                         for (Base *base = view_layer->object_bases.first; base; base = base->next) {
468                                 if (base->object->id.name[2] == 'p') {
469                                         if (base->object->type == OB_LAMP)
470                                                 base->object->data = la;
471                                 }
472                         }
473
474                         if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
475                                 /* two previews, they get copied by wmJob */
476                                 BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
477                                 BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
478                         }
479                 }
480                 else if (id_type == ID_WO) {
481                         World *wrld = NULL, *origwrld = (World *)id;
482
483                         if (origwrld) {
484                                 wrld = BKE_world_localize(origwrld);
485                                 sp->worldcopy = wrld;
486                                 BLI_addtail(&pr_main->world, wrld);
487                         }
488
489                         set_preview_collection(sce, view_layer, MA_SKY);
490                         sce->world = wrld;
491
492                         if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
493                                 /* two previews, they get copied by wmJob */
494                                 BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
495                                 BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
496                         }
497                 }
498
499                 return sce;
500         }
501
502         return NULL;
503 }
504
505 /* new UI convention: draw is in pixel space already. */
506 /* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
507 static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
508 {
509         Render *re;
510         RenderView *rv;
511         RenderResult rres;
512         char name[32];
513         int offx = 0;
514         int newx = BLI_rcti_size_x(rect);
515         int newy = BLI_rcti_size_y(rect);
516         bool ok = false;
517
518         if (!split || first) sprintf(name, "Preview %p", (void *)sa);
519         else sprintf(name, "SecondPreview %p", (void *)sa);
520
521         if (split) {
522                 if (first) {
523                         offx = 0;
524                         newx = newx / 2;
525                 }
526                 else {
527                         offx = newx / 2;
528                         newx = newx - newx / 2;
529                 }
530         }
531
532         /* test if something rendered ok */
533         re = RE_GetRender(name);
534
535         if (re == NULL)
536                 return false;
537
538         RE_AcquireResultImageViews(re, &rres);
539
540         if (!BLI_listbase_is_empty(&rres.views)) {
541                 /* material preview only needs monoscopy (view 0) */
542                 rv = RE_RenderViewGetById(&rres, 0);
543         }
544         else {
545                 /* possible the job clears the views but we're still drawing T45496 */
546                 rv = NULL;
547         }
548
549         if (rv && rv->rectf) {
550
551                 if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
552
553                         newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
554                         newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
555
556                         if (rres.rectx && rres.recty) {
557                                 unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
558                                 float fx = rect->xmin + offx;
559                                 float fy = rect->ymin;
560
561                                 /* material preview only needs monoscopy (view 0) */
562                                 if (re)
563                                         RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
564
565                                 IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
566                                 immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte,
567                                                  1.0f, 1.0f, NULL);
568
569                                 MEM_freeN(rect_byte);
570
571                                 ok = 1;
572                         }
573                 }
574         }
575
576         RE_ReleaseResultImageViews(re, &rres);
577
578         return ok;
579 }
580
581 void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
582 {
583         if (idp) {
584                 wmWindowManager *wm = CTX_wm_manager(C);
585                 ScrArea *sa = CTX_wm_area(C);
586                 ID *id = (ID *)idp;
587                 ID *parent = (ID *)parentp;
588                 MTex *slot = (MTex *)slotp;
589                 SpaceButs *sbuts = CTX_wm_space_buts(C);
590                 ShaderPreview *sp = WM_jobs_customdata(wm, sa);
591                 rcti newrect;
592                 int ok;
593                 int newx = BLI_rcti_size_x(rect);
594                 int newy = BLI_rcti_size_y(rect);
595
596                 newrect.xmin = rect->xmin;
597                 newrect.xmax = rect->xmin;
598                 newrect.ymin = rect->ymin;
599                 newrect.ymax = rect->ymin;
600
601                 if (parent) {
602                         ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
603                         ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
604                 }
605                 else
606                         ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
607
608                 if (ok)
609                         *rect = newrect;
610
611                 /* start a new preview render job if signaled through sbuts->preview,
612                  * if no render result was found and no preview render job is running,
613                  * or if the job is running and the size of preview changed */
614                 if ((sbuts != NULL && sbuts->preview) ||
615                     (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) ||
616                     (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2)))
617                 {
618                         if (sbuts != NULL) {
619                                 sbuts->preview = 0;
620                         }
621                         ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
622                 }
623         }
624 }
625
626 /* **************************** new shader preview system ****************** */
627
628 /* inside thread, called by renderer, sets job update value */
629 static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
630 {
631         ShaderPreview *sp = spv;
632
633         *(sp->do_update) = true;
634 }
635
636 /* called by renderer, checks job value */
637 static int shader_preview_break(void *spv)
638 {
639         ShaderPreview *sp = spv;
640
641         return *(sp->stop);
642 }
643
644 /* outside thread, called before redraw notifiers, it moves finished preview over */
645 static void shader_preview_updatejob(void *spv)
646 {
647         ShaderPreview *sp = spv;
648
649         if (sp->id) {
650                 if (sp->pr_method == PR_NODE_RENDER) {
651                         if (GS(sp->id->name) == ID_MA) {
652                                 Material *mat = (Material *)sp->id;
653
654                                 if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
655                                         ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
656                         }
657                         else if (GS(sp->id->name) == ID_TE) {
658                                 Tex *tex = (Tex *)sp->id;
659
660                                 if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
661                                         ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree);
662                         }
663                         else if (GS(sp->id->name) == ID_WO) {
664                                 World *wrld = (World *)sp->id;
665
666                                 if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
667                                         ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree);
668                         }
669                         else if (GS(sp->id->name) == ID_LA) {
670                                 Lamp *la = (Lamp *)sp->id;
671
672                                 if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
673                                         ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
674                         }
675                 }
676         }
677 }
678
679 static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
680 {
681         Render *re;
682         Scene *sce;
683         float oldlens;
684         short idtype = GS(id->name);
685         char name[32];
686         int sizex;
687         Main *pr_main = sp->pr_main;
688         ID *id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
689
690         /* in case of split preview, use border render */
691         if (split) {
692                 if (first) sizex = sp->sizex / 2;
693                 else sizex = sp->sizex - sp->sizex / 2;
694         }
695         else {
696                 sizex = sp->sizex;
697         }
698
699         /* we have to set preview variables first */
700         sce = preview_get_scene(pr_main);
701         if (sce) {
702                 sce->r.xsch = sizex;
703                 sce->r.ysch = sp->sizey;
704                 sce->r.size = 100;
705         }
706
707         /* get the stuff from the builtin preview dbase */
708         sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
709         if (sce == NULL) return;
710
711         if (!split || first) sprintf(name, "Preview %p", sp->owner);
712         else sprintf(name, "SecondPreview %p", sp->owner);
713         re = RE_GetRender(name);
714
715         /* full refreshed render from first tile */
716         if (re == NULL)
717                 re = RE_NewRender(name);
718
719         /* sce->r gets copied in RE_InitState! */
720         sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW);
721         sce->r.scemode &= ~R_NO_IMAGE_LOAD;
722
723         if (sp->pr_method == PR_ICON_RENDER) {
724                 sce->r.scemode |= R_NO_IMAGE_LOAD;
725                 sce->r.mode |= R_OSA;
726         }
727         else if (sp->pr_method == PR_NODE_RENDER) {
728                 if (idtype == ID_MA) sce->r.scemode |= R_MATNODE_PREVIEW;
729                 else if (idtype == ID_TE) sce->r.scemode |= R_TEXNODE_PREVIEW;
730                 sce->r.mode &= ~R_OSA;
731         }
732         else {  /* PR_BUTS_RENDER */
733                 sce->r.mode |= R_OSA;
734         }
735
736
737         /* callbacs are cleared on GetRender() */
738         if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
739                 RE_display_update_cb(re, sp, shader_preview_update);
740         }
741         /* set this for all previews, default is react to G.is_break still */
742         RE_test_break_cb(re, sp, shader_preview_break);
743
744         /* lens adjust */
745         oldlens = ((Camera *)sce->camera->data)->lens;
746         if (sizex > sp->sizey)
747                 ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
748
749         /* entire cycle for render engine */
750         RE_PreviewRender(re, pr_main, sce);
751
752         ((Camera *)sce->camera->data)->lens = oldlens;
753
754         /* handle results */
755         if (sp->pr_method == PR_ICON_RENDER) {
756                 // char *rct= (char *)(sp->pr_rect + 32*16 + 16);
757
758                 if (sp->pr_rect)
759                         RE_ResultGet32(re, sp->pr_rect);
760         }
761
762         /* unassign the pointers, reset vars */
763         preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
764
765         /* XXX bad exception, end-exec is not being called in render, because it uses local main */
766 //      if (idtype == ID_TE) {
767 //              Tex *tex= (Tex *)id;
768 //              if (tex->use_nodes && tex->nodetree)
769 //                      ntreeEndExecTree(tex->nodetree);
770 //      }
771
772 }
773
774 /* runs inside thread for material and icons */
775 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
776 {
777         ShaderPreview *sp = customdata;
778
779         sp->stop = stop;
780         sp->do_update = do_update;
781
782         if (sp->parent) {
783                 shader_preview_render(sp, sp->id, 1, 1);
784                 shader_preview_render(sp, sp->parent, 1, 0);
785         }
786         else
787                 shader_preview_render(sp, sp->id, 0, 0);
788
789         *do_update = true;
790 }
791
792 static void shader_preview_free(void *customdata)
793 {
794         ShaderPreview *sp = customdata;
795         Main *pr_main = sp->pr_main;
796
797         if (sp->matcopy) {
798                 struct IDProperty *properties;
799
800                 /* node previews */
801                 shader_preview_updatejob(sp);
802
803                 /* get rid of copied material */
804                 BLI_remlink(&pr_main->mat, sp->matcopy);
805
806                 BKE_material_free(sp->matcopy);
807
808                 properties = IDP_GetProperties((ID *)sp->matcopy, false);
809                 if (properties) {
810                         IDP_FreeProperty(properties);
811                         MEM_freeN(properties);
812                 }
813                 MEM_freeN(sp->matcopy);
814         }
815         if (sp->texcopy) {
816                 struct IDProperty *properties;
817                 /* node previews */
818                 shader_preview_updatejob(sp);
819
820                 /* get rid of copied texture */
821                 BLI_remlink(&pr_main->tex, sp->texcopy);
822                 BKE_texture_free(sp->texcopy);
823
824                 properties = IDP_GetProperties((ID *)sp->texcopy, false);
825                 if (properties) {
826                         IDP_FreeProperty(properties);
827                         MEM_freeN(properties);
828                 }
829                 MEM_freeN(sp->texcopy);
830         }
831         if (sp->worldcopy) {
832                 struct IDProperty *properties;
833                 /* node previews */
834                 shader_preview_updatejob(sp);
835
836                 /* get rid of copied world */
837                 BLI_remlink(&pr_main->world, sp->worldcopy);
838                 BKE_world_free(sp->worldcopy);
839
840                 properties = IDP_GetProperties((ID *)sp->worldcopy, false);
841                 if (properties) {
842                         IDP_FreeProperty(properties);
843                         MEM_freeN(properties);
844                 }
845                 MEM_freeN(sp->worldcopy);
846         }
847         if (sp->lampcopy) {
848                 struct IDProperty *properties;
849                 /* node previews */
850                 shader_preview_updatejob(sp);
851
852                 /* get rid of copied lamp */
853                 BLI_remlink(&pr_main->lamp, sp->lampcopy);
854                 BKE_lamp_free(sp->lampcopy);
855
856                 properties = IDP_GetProperties((ID *)sp->lampcopy, false);
857                 if (properties) {
858                         IDP_FreeProperty(properties);
859                         MEM_freeN(properties);
860                 }
861                 MEM_freeN(sp->lampcopy);
862         }
863
864         MEM_freeN(sp);
865 }
866
867 /* ************************* icon preview ********************** */
868
869 static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
870 {
871         struct ImBuf *ima;
872         unsigned int *drect, *srect;
873         float scaledx, scaledy;
874         short ex, ey, dx, dy;
875
876         /* paranoia test */
877         if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL))
878                 return;
879
880         /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
881         ima = IMB_dupImBuf(ibuf);
882
883         if (!ima)
884                 return;
885
886         if (ima->x > ima->y) {
887                 scaledx = (float)w;
888                 scaledy =  ( (float)ima->y / (float)ima->x) * (float)w;
889         }
890         else {
891                 scaledx =  ( (float)ima->x / (float)ima->y) * (float)h;
892                 scaledy = (float)h;
893         }
894
895         ex = (short)scaledx;
896         ey = (short)scaledy;
897
898         dx = (w - ex) / 2;
899         dy = (h - ey) / 2;
900
901         IMB_scalefastImBuf(ima, ex, ey);
902
903         /* if needed, convert to 32 bits */
904         if (ima->rect == NULL)
905                 IMB_rect_from_float(ima);
906
907         srect = ima->rect;
908         drect = rect;
909
910         drect += dy * w + dx;
911         for (; ey > 0; ey--) {
912                 memcpy(drect, srect, ex * sizeof(int));
913                 drect += w;
914                 srect += ima->x;
915         }
916
917         IMB_freeImBuf(ima);
918 }
919
920 static void set_alpha(char *cp, int sizex, int sizey, char alpha)
921 {
922         int a, size = sizex * sizey;
923
924         for (a = 0; a < size; a++, cp += 4)
925                 cp[3] = alpha;
926 }
927
928 static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
929 {
930         ShaderPreview *sp = customdata;
931
932         if (sp->pr_method == PR_ICON_DEFERRED) {
933                 PreviewImage *prv = sp->owner;
934                 ImBuf *thumb;
935                 char *deferred_data = PRV_DEFERRED_DATA(prv);
936                 int source =  deferred_data[0];
937                 char *path = &deferred_data[1];
938
939 //              printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
940
941                 thumb = IMB_thumb_manage(path, THB_LARGE, source);
942
943                 if (thumb) {
944                         /* PreviewImage assumes premultiplied alhpa... */
945                         IMB_premultiply_alpha(thumb);
946
947                         icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
948                         IMB_freeImBuf(thumb);
949                 }
950         }
951         else {
952                 ID *id = sp->id;
953                 short idtype = GS(id->name);
954
955                 if (idtype == ID_IM) {
956                         Image *ima = (Image *)id;
957                         ImBuf *ibuf = NULL;
958                         ImageUser iuser = {NULL};
959
960                         /* ima->ok is zero when Image cannot load */
961                         if (ima == NULL || ima->ok == 0)
962                                 return;
963
964                         /* setup dummy image user */
965                         iuser.ok = iuser.framenr = 1;
966                         iuser.scene = sp->scene;
967
968                         /* elubie: this needs to be changed: here image is always loaded if not
969                          * already there. Very expensive for large images. Need to find a way to
970                          * only get existing ibuf */
971                         ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
972                         if (ibuf == NULL || ibuf->rect == NULL) {
973                                 BKE_image_release_ibuf(ima, ibuf, NULL);
974                                 return;
975                         }
976
977                         icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
978
979                         *do_update = true;
980
981                         BKE_image_release_ibuf(ima, ibuf, NULL);
982                 }
983                 else if (idtype == ID_BR) {
984                         Brush *br = (Brush *)id;
985
986                         br->icon_imbuf = get_brush_icon(br);
987
988                         memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
989
990                         if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
991                                 return;
992
993                         icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
994
995                         *do_update = true;
996                 }
997                 else if (idtype == ID_SCR) {
998                         bScreen *screen = (bScreen *)id;
999
1000                         ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
1001                         *do_update = true;
1002                 }
1003                 else {
1004                         /* re-use shader job */
1005                         shader_preview_startjob(customdata, stop, do_update);
1006
1007                         /* world is rendered with alpha=0, so it wasn't displayed
1008                          * this could be render option for sky to, for later */
1009                         if (idtype == ID_WO) {
1010                                 set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
1011                         }
1012                 }
1013         }
1014 }
1015
1016 /* use same function for icon & shader, so the job manager
1017  * does not run two of them at the same time. */
1018
1019 static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
1020 {
1021         ShaderPreview *sp = customdata;
1022
1023         if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED))
1024                 icon_preview_startjob(customdata, stop, do_update);
1025         else
1026                 shader_preview_startjob(customdata, stop, do_update);
1027 }
1028
1029 /* exported functions */
1030
1031 static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex, int sizey)
1032 {
1033         IconPreviewSize *cur_size = ip->sizes.first, *new_size;
1034
1035         while (cur_size) {
1036                 if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
1037                         /* requested size is already in list, no need to add it again */
1038                         return;
1039                 }
1040
1041                 cur_size = cur_size->next;
1042         }
1043
1044         new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
1045         new_size->sizex = sizex;
1046         new_size->sizey = sizey;
1047         new_size->rect = rect;
1048
1049         BLI_addtail(&ip->sizes, new_size);
1050 }
1051
1052 static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress)
1053 {
1054         IconPreview *ip = (IconPreview *)customdata;
1055         IconPreviewSize *cur_size;
1056
1057         for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
1058                 PreviewImage *prv = ip->owner;
1059
1060                 if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
1061                         /* Non-thread-protected reading is not an issue here. */
1062                         continue;
1063                 }
1064
1065                 ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
1066                 const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
1067
1068                 /* construct shader preview from image size and previewcustomdata */
1069                 sp->scene = ip->scene;
1070                 sp->depsgraph = ip->depsgraph;
1071                 sp->owner = ip->owner;
1072                 sp->sizex = cur_size->sizex;
1073                 sp->sizey = cur_size->sizey;
1074                 sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
1075                 sp->pr_rect = cur_size->rect;
1076                 sp->id = ip->id;
1077                 sp->bmain = ip->bmain;
1078
1079                 if (is_render) {
1080                         BLI_assert(ip->id);
1081                         /* texture icon rendering is hardcoded to use the BI scene,
1082                          * so don't even think of using cycle's bmain for
1083                          * texture icons
1084                          */
1085                         if (GS(ip->id->name) != ID_TE)
1086                                 sp->pr_main = G_pr_main_cycles;
1087                         else
1088                                 sp->pr_main = G_pr_main;
1089                 }
1090
1091                 common_preview_startjob(sp, stop, do_update, progress);
1092                 shader_preview_free(sp);
1093         }
1094 }
1095
1096 static void icon_preview_endjob(void *customdata)
1097 {
1098         IconPreview *ip = customdata;
1099
1100         if (ip->id) {
1101
1102                 if (GS(ip->id->name) == ID_BR)
1103                         WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
1104 #if 0
1105                 if (GS(ip->id->name) == ID_MA) {
1106                         Material *ma = (Material *)ip->id;
1107                         PreviewImage *prv_img = ma->preview;
1108                         int i;
1109
1110                         /* signal to gpu texture */
1111                         for (i = 0; i < NUM_ICON_SIZES; ++i) {
1112                                 if (prv_img->gputexture[i]) {
1113                                         GPU_texture_free(prv_img->gputexture[i]);
1114                                         prv_img->gputexture[i] = NULL;
1115                                         WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
1116                                 }
1117                         }
1118                 }
1119 #endif
1120         }
1121
1122         if (ip->owner) {
1123                 PreviewImage *prv_img = ip->owner;
1124                 prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
1125                 if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
1126                         BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
1127                         BKE_previewimg_cached_release_pointer(prv_img);
1128                 }
1129         }
1130 }
1131
1132 static void icon_preview_free(void *customdata)
1133 {
1134         IconPreview *ip = (IconPreview *)customdata;
1135
1136         BLI_freelistN(&ip->sizes);
1137         MEM_freeN(ip);
1138 }
1139
1140 void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
1141 {
1142         IconPreview ip = {NULL};
1143         short stop = false, update = false;
1144         float progress = 0.0f;
1145
1146         ED_preview_ensure_dbase();
1147
1148         ip.bmain = bmain;
1149         ip.scene = scene;
1150         ip.owner = BKE_previewimg_id_ensure(id);
1151         ip.id = id;
1152
1153         icon_preview_add_size(&ip, rect, sizex, sizey);
1154
1155         icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
1156
1157         icon_preview_endjob(&ip);
1158
1159         BLI_freelistN(&ip.sizes);
1160 }
1161
1162 void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
1163 {
1164         wmJob *wm_job;
1165         IconPreview *ip, *old_ip;
1166
1167         ED_preview_ensure_dbase();
1168
1169         /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
1170         wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview",
1171                              WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, WM_JOB_TYPE_RENDER_PREVIEW);
1172
1173         ip = MEM_callocN(sizeof(IconPreview), "icon preview");
1174
1175         /* render all resolutions from suspended job too */
1176         old_ip = WM_jobs_customdata_get(wm_job);
1177         if (old_ip)
1178                 BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
1179
1180         /* customdata for preview thread */
1181         ip->bmain = CTX_data_main(C);
1182         ip->scene = CTX_data_scene(C);
1183         ip->depsgraph = CTX_data_depsgraph(C);
1184         ip->owner = owner;
1185         ip->id = id;
1186
1187         icon_preview_add_size(ip, rect, sizex, sizey);
1188
1189         /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */
1190         {
1191                 PreviewImage *prv_img = owner;
1192                 if (prv_img->tag & PRV_TAG_DEFFERED) {
1193                         prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
1194                 }
1195         }
1196
1197         /* setup job */
1198         WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
1199         WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
1200         WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
1201
1202         WM_jobs_start(CTX_wm_manager(C), wm_job);
1203 }
1204
1205 void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method)
1206 {
1207         Object *ob = CTX_data_active_object(C);
1208         wmJob *wm_job;
1209         ShaderPreview *sp;
1210         Scene *scene = CTX_data_scene(C);
1211         short id_type = GS(id->name);
1212
1213         /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
1214
1215         /* Only texture node preview is supported with Cycles. */
1216         if (method == PR_NODE_RENDER && id_type != ID_TE) {
1217                 return;
1218         }
1219
1220         ED_preview_ensure_dbase();
1221
1222         wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview",
1223                             WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
1224         sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
1225
1226         /* customdata for preview thread */
1227         sp->scene = scene;
1228         sp->depsgraph = CTX_data_depsgraph(C);
1229         sp->owner = owner;
1230         sp->sizex = sizex;
1231         sp->sizey = sizey;
1232         sp->pr_method = method;
1233         sp->id = id;
1234         sp->parent = parent;
1235         sp->slot = slot;
1236         sp->bmain = CTX_data_main(C);
1237
1238         /* hardcoded preview .blend for Eevee + Cycles, this should be solved
1239          * once with custom preview .blend path for external engines */
1240         if ((method != PR_NODE_RENDER) && id_type != ID_TE) {
1241                 sp->pr_main = G_pr_main_cycles;
1242         }
1243         else {
1244                 sp->pr_main = G_pr_main;
1245         }
1246
1247         if (ob && ob->totcol) copy_v4_v4(sp->col, ob->col);
1248         else sp->col[0] = sp->col[1] = sp->col[2] = sp->col[3] = 1.0f;
1249
1250         /* setup job */
1251         WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
1252         WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
1253         WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
1254
1255         WM_jobs_start(CTX_wm_manager(C), wm_job);
1256 }
1257
1258 void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
1259 {
1260         if (wm)
1261                 WM_jobs_kill(wm, NULL, common_preview_startjob);
1262 }
1263