Blender  V2.93
render_preview.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) Blender Foundation.
17  * All rights reserved.
18  */
19 
24 /* global includes */
25 
26 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #ifndef WIN32
31 # include <unistd.h>
32 #else
33 # include <io.h>
34 #endif
35 #include "MEM_guardedalloc.h"
36 
37 #include "BLI_blenlib.h"
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40 
41 #include "PIL_time.h"
42 
43 #include "BLO_readfile.h"
44 
45 #include "DNA_brush_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_collection_types.h"
48 #include "DNA_light_types.h"
49 #include "DNA_material_types.h"
50 #include "DNA_node_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_screen_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_world_types.h"
56 
57 #include "BKE_appdir.h"
58 #include "BKE_brush.h"
59 #include "BKE_colortools.h"
60 #include "BKE_context.h"
61 #include "BKE_global.h"
62 #include "BKE_icons.h"
63 #include "BKE_idprop.h"
64 #include "BKE_image.h"
65 #include "BKE_layer.h"
66 #include "BKE_lib_id.h"
67 #include "BKE_light.h"
68 #include "BKE_main.h"
69 #include "BKE_material.h"
70 #include "BKE_node.h"
71 #include "BKE_object.h"
72 #include "BKE_scene.h"
73 #include "BKE_texture.h"
74 #include "BKE_world.h"
75 
76 #include "DEG_depsgraph.h"
77 #include "DEG_depsgraph_build.h"
78 #include "DEG_depsgraph_query.h"
79 
80 #include "IMB_imbuf.h"
81 #include "IMB_imbuf_types.h"
82 #include "IMB_thumbs.h"
83 
84 #include "BIF_glutil.h"
85 
86 #include "GPU_shader.h"
87 
88 #include "RE_engine.h"
89 #include "RE_pipeline.h"
90 #include "RE_texture.h"
91 
92 #include "WM_api.h"
93 #include "WM_types.h"
94 
95 #include "ED_datafiles.h"
96 #include "ED_render.h"
97 #include "ED_screen.h"
98 #include "ED_view3d.h"
99 #include "ED_view3d_offscreen.h"
100 
101 #ifndef NDEBUG
102 /* Used for database init assert(). */
103 # include "BLI_threads.h"
104 #endif
105 
106 static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect);
107 
108 /* -------------------------------------------------------------------- */
112 typedef struct ShaderPreview {
113  /* from wmJob */
114  void *owner;
115  short *stop, *do_update;
116 
121 
122  /* datablocks with nodes need full copy during preview render, glsl uses it too */
127 
129  float color[4];
130 
131  int sizex, sizey;
135 
139 
140 typedef struct IconPreviewSize {
142  int sizex, sizey;
145 
146 typedef struct IconPreview {
148  Depsgraph *depsgraph; /* May be NULL (see #WM_OT_previews_ensure). */
150  void *owner;
151  ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */
154 
157 /* -------------------------------------------------------------------- */
161 static Main *G_pr_main = NULL;
163 
164 #ifndef WITH_HEADLESS
165 static Main *load_main_from_memory(const void *blend, int blend_size)
166 {
167  const int fileflags = G.fileflags;
168  Main *bmain = NULL;
169  BlendFileData *bfd;
170 
171  G.fileflags |= G_FILE_NO_UI;
172  bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL);
173  if (bfd) {
174  bmain = bfd->main;
175 
176  MEM_freeN(bfd);
177  }
178  G.fileflags = fileflags;
179 
180  return bmain;
181 }
182 #endif
183 
185 {
186 #ifndef WITH_HEADLESS
187  static bool base_initialized = false;
189  if (!base_initialized) {
193  base_initialized = true;
194  }
195 #endif
196 }
197 
199 {
201  return (type->flag & RE_USE_PREVIEW) != 0;
202 }
203 
204 static bool preview_method_is_render(int pr_method)
205 {
206  return ELEM(pr_method, PR_ICON_RENDER, PR_BUTS_RENDER, PR_NODE_RENDER);
207 }
208 
210 {
211  if (G_pr_main) {
213  }
214 
217  }
218 }
219 
220 static Scene *preview_get_scene(Main *pr_main)
221 {
222  if (pr_main == NULL) {
223  return NULL;
224  }
225 
226  return pr_main->scenes.first;
227 }
228 
229 static const char *preview_collection_name(const char pr_type)
230 {
231  switch (pr_type) {
232  case MA_FLAT:
233  return "Flat";
234  case MA_SPHERE:
235  return "Sphere";
236  case MA_CUBE:
237  return "Cube";
238  case MA_SHADERBALL:
239  return "Shader Ball";
240  case MA_CLOTH:
241  return "Cloth";
242  case MA_FLUID:
243  return "Fluid";
244  case MA_SPHERE_A:
245  return "World Sphere";
246  case MA_LAMP:
247  return "Lamp";
248  case MA_SKY:
249  return "Sky";
250  case MA_HAIR:
251  return "Hair";
252  case MA_ATMOS:
253  return "Atmosphere";
254  default:
255  BLI_assert(!"Unknown preview type");
256  return "";
257  }
258 }
259 
261  ViewLayer *view_layer,
262  char pr_type,
263  int pr_method)
264 {
265  /* Set appropriate layer as visible. */
266  LayerCollection *lc = view_layer->layer_collections.first;
267  const char *collection_name = preview_collection_name(pr_type);
268 
269  for (lc = lc->layer_collections.first; lc; lc = lc->next) {
270  if (STREQ(lc->collection->id.name + 2, collection_name)) {
272  }
273  else {
275  }
276  }
277 
278  /* Hide floor for icon renders. */
279  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
280  if (STREQ(base->object->id.name + 2, "Floor")) {
281  if (pr_method == PR_ICON_RENDER) {
282  base->object->restrictflag |= OB_RESTRICT_RENDER;
283  }
284  else {
285  base->object->restrictflag &= ~OB_RESTRICT_RENDER;
286  }
287  }
288  }
289 
290  BKE_layer_collection_sync(scene, view_layer);
291 }
292 
294 {
295  if (world == NULL) {
296  return NULL;
297  }
298  if (sp->worldcopy != NULL) {
299  return sp->worldcopy;
300  }
301 
302  ID *id_copy = BKE_id_copy_ex(NULL,
303  &world->id,
304  NULL,
307  sp->worldcopy = (World *)id_copy;
308  BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
309  return sp->worldcopy;
310 }
311 
312 static ID *duplicate_ids(ID *id, const bool allow_failure)
313 {
314  if (id == NULL) {
315  /* Non-ID preview render. */
316  return NULL;
317  }
318 
319  switch (GS(id->name)) {
320  case ID_OB:
321  case ID_MA:
322  case ID_TE:
323  case ID_LA:
324  case ID_WO: {
326  ID *id_copy = BKE_id_copy_ex(
328  return id_copy;
329  }
330  /* These support threading, but don't need duplicating. */
331  case ID_IM:
332  case ID_BR:
334  return NULL;
335  default:
336  if (!allow_failure) {
337  BLI_assert(!"ID type preview not supported.");
338  }
339  return NULL;
340  }
341 }
342 
343 /* call this with a pointer to initialize preview scene */
344 /* call this with NULL to restore assigned ID pointers in preview scene */
346  Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
347 {
348  Scene *sce;
349  Main *pr_main = sp->pr_main;
350 
351  memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));
352 
353  sce = preview_get_scene(pr_main);
354  if (sce) {
355  ViewLayer *view_layer = sce->view_layers.first;
356 
357  /* Only enable the combined renderpass */
358  view_layer->passflag = SCE_PASS_COMBINED;
359  view_layer->eevee.render_passes = 0;
360 
361  /* this flag tells render to not execute depsgraph or ipos etc */
362  sce->r.scemode |= R_BUTS_PREVIEW;
363  /* set world always back, is used now */
364  sce->world = pr_main->worlds.first;
365  /* now: exposure copy */
366  if (scene->world) {
367  sce->world->exp = scene->world->exp;
368  sce->world->range = scene->world->range;
369  }
370 
373 
376 
377  /* prevent overhead for small renders and icons (32) */
378  if (id && sp->sizex < 40) {
379  sce->r.tilex = sce->r.tiley = 64;
380  }
381  else {
382  sce->r.tilex = sce->r.xsch / 4;
383  sce->r.tiley = sce->r.ysch / 4;
384  }
385 
386  if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) {
387  sce->r.alphamode = R_ALPHAPREMUL;
388  }
389  else {
390  sce->r.alphamode = R_ADDSKY;
391  }
392 
393  sce->r.cfra = scene->r.cfra;
394 
395  if (id_type == ID_TE) {
396  /* Texture is not actually rendered with engine, just set dummy value. */
397  BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
398  }
399  else {
400  BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
401  }
402 
403  if (id_type == ID_MA) {
404  Material *mat = NULL, *origmat = (Material *)id;
405 
406  if (origmat) {
407  /* work on a copy */
408  BLI_assert(sp->id_copy != NULL);
409  mat = sp->matcopy = (Material *)sp->id_copy;
410  sp->id_copy = NULL;
411  BLI_addtail(&pr_main->materials, mat);
412 
413  /* Use current scene world for lighting. */
414  if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
415  /* Use current scene world to light sphere. */
417  }
418  else if (sce->world) {
419  /* Use a default world color. Using the current
420  * scene world can be slow if it has big textures. */
421  sce->world->use_nodes = false;
422  sce->world->horr = 0.05f;
423  sce->world->horg = 0.05f;
424  sce->world->horb = 0.05f;
425  }
426 
428  /* For grease pencil, always use sphere for icon renders. */
429  set_preview_visibility(sce, view_layer, MA_SPHERE_A, sp->pr_method);
430  }
431  else {
432  /* Use specified preview shape for both preview panel and icon previews. */
433  set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
434  }
435 
436  if (sp->pr_method != PR_ICON_RENDER) {
437  if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
438  /* two previews, they get copied by wmJob */
439  BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
440  /* WATCH: Accessing origmat is not safe! */
441  BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
442  }
443  }
444  }
445  else {
447  }
448 
449  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
450  if (base->object->id.name[2] == 'p') {
451  /* copy over object color, in case material uses it */
452  copy_v4_v4(base->object->color, sp->color);
453 
454  if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
455  /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI
456  */
457  Material ***matar = BKE_object_material_array_p(base->object);
458  int actcol = max_ii(base->object->actcol - 1, 0);
459 
460  if (matar && actcol < base->object->totcol) {
461  (*matar)[actcol] = mat;
462  }
463  }
464  else if (base->object->type == OB_LAMP) {
465  base->flag |= BASE_VISIBLE_DEPSGRAPH;
466  }
467  }
468  }
469  }
470  else if (id_type == ID_TE) {
471  Tex *tex = NULL, *origtex = (Tex *)id;
472 
473  if (origtex) {
474  BLI_assert(sp->id_copy != NULL);
475  tex = sp->texcopy = (Tex *)sp->id_copy;
476  sp->id_copy = NULL;
477  BLI_addtail(&pr_main->textures, tex);
478  }
479 
480  if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
481  /* two previews, they get copied by wmJob */
483  /* WATCH: Accessing origtex is not safe! */
484  BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
485  }
486  }
487  else if (id_type == ID_LA) {
488  Light *la = NULL, *origla = (Light *)id;
489 
490  /* work on a copy */
491  if (origla) {
492  BLI_assert(sp->id_copy != NULL);
493  la = sp->lampcopy = (Light *)sp->id_copy;
494  sp->id_copy = NULL;
495  BLI_addtail(&pr_main->lights, la);
496  }
497 
498  set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
499 
500  if (sce->world) {
501  /* Only use lighting from the light. */
502  sce->world->use_nodes = false;
503  sce->world->horr = 0.0f;
504  sce->world->horg = 0.0f;
505  sce->world->horb = 0.0f;
506  }
507 
508  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
509  if (base->object->id.name[2] == 'p') {
510  if (base->object->type == OB_LAMP) {
511  base->object->data = la;
512  }
513  }
514  }
515 
516  if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
517  /* two previews, they get copied by wmJob */
518  BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
519  /* WATCH: Accessing origla is not safe! */
520  BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
521  }
522  }
523  else if (id_type == ID_WO) {
524  World *wrld = NULL, *origwrld = (World *)id;
525 
526  if (origwrld) {
527  BLI_assert(sp->id_copy != NULL);
528  wrld = sp->worldcopy = (World *)sp->id_copy;
529  sp->id_copy = NULL;
530  BLI_addtail(&pr_main->worlds, wrld);
531  }
532 
533  set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
534  sce->world = wrld;
535 
536  if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
537  /* two previews, they get copied by wmJob */
538  BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
539  /* WATCH: Accessing origwrld is not safe! */
540  BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
541  }
542  }
543 
544  return sce;
545  }
546 
547  return NULL;
548 }
549 
550 /* new UI convention: draw is in pixel space already. */
551 /* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
552 static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
553 {
554  Render *re;
555  RenderView *rv;
556  RenderResult rres;
557  char name[32];
558  int offx = 0;
559  int newx = BLI_rcti_size_x(rect);
560  int newy = BLI_rcti_size_y(rect);
561  bool ok = false;
562 
563  if (!split || first) {
564  sprintf(name, "Preview %p", (void *)area);
565  }
566  else {
567  sprintf(name, "SecondPreview %p", (void *)area);
568  }
569 
570  if (split) {
571  if (first) {
572  offx = 0;
573  newx = newx / 2;
574  }
575  else {
576  offx = newx / 2;
577  newx = newx - newx / 2;
578  }
579  }
580 
581  /* test if something rendered ok */
582  re = RE_GetRender(name);
583 
584  if (re == NULL) {
585  return false;
586  }
587 
588  RE_AcquireResultImageViews(re, &rres);
589 
590  if (!BLI_listbase_is_empty(&rres.views)) {
591  /* material preview only needs monoscopy (view 0) */
592  rv = RE_RenderViewGetById(&rres, 0);
593  }
594  else {
595  /* possible the job clears the views but we're still drawing T45496 */
596  rv = NULL;
597  }
598 
599  if (rv && rv->rectf) {
600 
601  if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
602 
603  newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
604  newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
605 
606  if (rres.rectx && rres.recty) {
607  uchar *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int),
608  "ed_preview_draw_rect");
609  float fx = rect->xmin + offx;
610  float fy = rect->ymin;
611 
612  /* material preview only needs monoscopy (view 0) */
613  if (re) {
614  RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0);
615  }
616 
619  &state, fx, fy, rres.rectx, rres.recty, GPU_RGBA8, false, rect_byte, 1.0f, 1.0f, NULL);
620 
621  MEM_freeN(rect_byte);
622 
623  ok = 1;
624  }
625  }
626  }
627 
628  RE_ReleaseResultImageViews(re, &rres);
629 
630  return ok;
631 }
632 
633 void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
634 {
635  if (idp) {
638  ID *id = (ID *)idp;
639  ID *parent = (ID *)parentp;
640  MTex *slot = (MTex *)slotp;
643  rcti newrect;
644  int ok;
645  int newx = BLI_rcti_size_x(rect);
646  int newy = BLI_rcti_size_y(rect);
647 
648  newrect.xmin = rect->xmin;
649  newrect.xmax = rect->xmin;
650  newrect.ymin = rect->ymin;
651  newrect.ymax = rect->ymin;
652 
653  if (parent) {
654  ok = ed_preview_draw_rect(area, 1, 1, rect, &newrect);
655  ok &= ed_preview_draw_rect(area, 1, 0, rect, &newrect);
656  }
657  else {
658  ok = ed_preview_draw_rect(area, 0, 0, rect, &newrect);
659  }
660 
661  if (ok) {
662  *rect = newrect;
663  }
664 
665  /* start a new preview render job if signaled through sbuts->preview,
666  * if no render result was found and no preview render job is running,
667  * or if the job is running and the size of preview changed */
668  if ((sbuts != NULL && sbuts->preview) ||
669  (!ok && !WM_jobs_test(wm, area, WM_JOB_TYPE_RENDER_PREVIEW)) ||
670  (sp && (abs(sp->sizex - newx) >= 2 || abs(sp->sizey - newy) > 2))) {
671  if (sbuts != NULL) {
672  sbuts->preview = 0;
673  }
674  ED_preview_shader_job(C, area, id, parent, slot, newx, newy, PR_BUTS_RENDER);
675  }
676  }
677 }
678 
681 /* -------------------------------------------------------------------- */
686  /* The main for the preview, not of the current file. */
688  /* Copy of the object to create the preview for. The copy is for thread safety (and to insert it
689  * into an own main). */
691  int sizex;
692  int sizey;
693 };
694 
696  Main *preview_main, ViewLayer *view_layer, Object *preview_object, int sizex, int sizey)
697 {
698  Object *camera = BKE_object_add(preview_main, view_layer, OB_CAMERA, "Preview Camera");
699 
700  float rotmat[3][3];
701  float dummyscale[3];
702  mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat);
703 
704  /* Camera is Y up, so needs additional 90deg rotation around X to match object's Z up. */
705  float drotmat[3][3];
706  axis_angle_to_mat3_single(drotmat, 'X', M_PI_2);
707  mul_m3_m3_post(rotmat, drotmat);
708 
709  camera->rotmode = ROT_MODE_QUAT;
710  mat3_to_quat(camera->quat, rotmat);
711 
712  /* shader_preview_render() does this too. */
713  if (sizex > sizey) {
714  ((Camera *)camera->data)->lens *= (float)sizey / (float)sizex;
715  }
716 
717  return camera;
718 }
719 
720 static Scene *object_preview_scene_create(const struct ObjectPreviewData *preview_data,
721  Depsgraph **r_depsgraph)
722 {
723  Scene *scene = BKE_scene_add(preview_data->pr_main, "Object preview scene");
724  ViewLayer *view_layer = scene->view_layers.first;
726  preview_data->pr_main, scene, view_layer, DAG_EVAL_VIEWPORT);
727 
728  BLI_assert(preview_data->object != NULL);
729  BLI_addtail(&preview_data->pr_main->objects, preview_data->object);
730 
731  BKE_collection_object_add(preview_data->pr_main, scene->master_collection, preview_data->object);
732 
733  Object *camera_object = object_preview_camera_create(preview_data->pr_main,
734  view_layer,
735  preview_data->object,
736  preview_data->sizex,
737  preview_data->sizey);
738 
739  scene->camera = camera_object;
740  scene->r.xsch = preview_data->sizex;
741  scene->r.ysch = preview_data->sizey;
742  scene->r.size = 100;
743 
744  Base *preview_base = BKE_view_layer_base_find(view_layer, preview_data->object);
745  /* For 'view selected' below. */
746  preview_base->flag |= BASE_SELECTED;
747 
750 
751  ED_view3d_camera_to_view_selected(preview_data->pr_main, depsgraph, scene, camera_object);
752 
754 
755  *r_depsgraph = depsgraph;
756  return scene;
757 }
758 
759 static void object_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
760 {
761  Main *preview_main = BKE_main_new();
762  const float pixelsize_old = U.pixelsize;
763  char err_out[256] = "unknown";
764 
765  BLI_assert(preview->id_copy && (preview->id_copy != preview->id));
766 
767  struct ObjectPreviewData preview_data = {
768  .pr_main = preview_main,
769  /* Act on a copy. */
770  .object = (Object *)preview->id_copy,
771  .sizex = preview_sized->sizex,
772  .sizey = preview_sized->sizey,
773  };
775  Scene *scene = object_preview_scene_create(&preview_data, &depsgraph);
776 
777  /* Ownership is now ours. */
778  preview->id_copy = NULL;
779 
780  U.pixelsize = 2.0f;
781 
783  depsgraph,
785  NULL,
786  OB_SOLID,
788  preview_sized->sizex,
789  preview_sized->sizey,
790  IB_rect,
793  NULL,
794  NULL,
795  err_out);
796  /* TODO color-management? */
797 
798  U.pixelsize = pixelsize_old;
799 
800  if (ibuf) {
801  icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect);
802  IMB_freeImBuf(ibuf);
803  }
804 
806  BKE_main_free(preview_main);
807 }
808 
811 /* -------------------------------------------------------------------- */
815 /* Render a pose. It is assumed that the pose has already been applied and that the scene camera is
816  * capturing the pose. In other words, this function just renders from the scene camera without
817  * evaluating the Action stored in preview->id. */
818 static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
819 {
820  char err_out[256] = "";
821 
822  Depsgraph *depsgraph = preview->depsgraph;
823  /* Not all code paths that lead to this function actually provide a depsgraph.
824  * The "Refresh Asset Preview" button (ED_OT_lib_id_generate_preview) does,
825  * but WM_OT_previews_ensure does not. */
828 
829  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
830  Object *camera_eval = scene_eval->camera;
831  if (camera_eval == NULL) {
832  printf("Scene has no camera, unable to render preview of %s without it.\n",
833  preview->id->name + 2);
834  return;
835  }
836 
837  /* This renders with the Workbench engine settings stored on the Scene. */
839  scene_eval,
840  NULL,
841  OB_SOLID,
842  camera_eval,
843  preview_sized->sizex,
844  preview_sized->sizey,
845  IB_rect,
848  NULL,
849  NULL,
850  err_out);
851 
852  if (err_out[0] != '\0') {
853  printf("Error rendering Action %s preview: %s\n", preview->id->name + 2, err_out);
854  }
855 
856  if (ibuf) {
857  icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect);
858  IMB_freeImBuf(ibuf);
859  }
860 }
861 
864 /* -------------------------------------------------------------------- */
868 /* inside thread, called by renderer, sets job update value */
869 static void shader_preview_update(void *spv,
870  RenderResult *UNUSED(rr),
871  volatile struct rcti *UNUSED(rect))
872 {
873  ShaderPreview *sp = spv;
874 
875  *(sp->do_update) = true;
876 }
877 
878 /* called by renderer, checks job value */
879 static int shader_preview_break(void *spv)
880 {
881  ShaderPreview *sp = spv;
882 
883  return *(sp->stop);
884 }
885 
886 /* outside thread, called before redraw notifiers, it moves finished preview over */
887 static void shader_preview_updatejob(void *spv)
888 {
889  ShaderPreview *sp = spv;
890 
891  if (sp->pr_method == PR_NODE_RENDER) {
892  if (GS(sp->id->name) == ID_MA) {
893  Material *mat = (Material *)sp->id;
894 
895  if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree) {
897  }
898  }
899  else if (GS(sp->id->name) == ID_TE) {
900  Tex *tex = (Tex *)sp->id;
901 
902  if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree) {
904  }
905  }
906  else if (GS(sp->id->name) == ID_WO) {
907  World *wrld = (World *)sp->id;
908 
909  if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree) {
911  }
912  }
913  else if (GS(sp->id->name) == ID_LA) {
914  Light *la = (Light *)sp->id;
915 
916  if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree) {
918  }
919  }
920  }
921 }
922 
923 /* Renders texture directly to render buffer. */
925 {
926  /* Setup output buffer. */
927  int width = sp->sizex;
928  int height = sp->sizey;
929 
930  /* This is needed otherwise no RenderResult is created. */
931  sce->r.scemode &= ~R_BUTS_PREVIEW;
932  RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL);
933  RE_SetScene(re, sce);
934 
935  /* Create buffer in empty RenderView created in the init step. */
937  RenderView *rv = (RenderView *)rr->views.first;
938  rv->rectf = MEM_callocN(sizeof(float[4]) * width * height, "texture render result");
939  RE_ReleaseResult(re);
940 
941  /* Get texture image pool (if any) */
942  struct ImagePool *img_pool = BKE_image_pool_new();
944 
945  /* Fill in image buffer. */
946  float *rect_float = rv->rectf;
947  float tex_coord[3] = {0.0f, 0.0f, 0.0f};
948  bool color_manage = true;
949 
950  for (int y = 0; y < height; y++) {
951  /* Tex coords between -1.0f and 1.0f. */
952  tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f;
953 
954  for (int x = 0; x < width; x++) {
955  tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f;
956 
957  /* Evaluate texture at tex_coord .*/
958  TexResult texres = {0};
959  BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
960 
961  rect_float[0] = texres.tr;
962  rect_float[1] = texres.tg;
963  rect_float[2] = texres.tb;
964  rect_float[3] = texres.talpha ? texres.ta : 1.0f;
965 
966  rect_float += 4;
967  }
968 
969  /* Check if we should cancel texture preview. */
970  if (shader_preview_break(sp)) {
971  break;
972  }
973  }
974 
975  BKE_image_pool_free(img_pool);
976 }
977 
978 static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
979 {
980  Render *re;
981  Scene *sce;
982  float oldlens;
983  short idtype = GS(id->name);
984  char name[32];
985  int sizex;
986  Main *pr_main = sp->pr_main;
987 
988  /* in case of split preview, use border render */
989  if (split) {
990  if (first) {
991  sizex = sp->sizex / 2;
992  }
993  else {
994  sizex = sp->sizex - sp->sizex / 2;
995  }
996  }
997  else {
998  sizex = sp->sizex;
999  }
1000 
1001  /* we have to set preview variables first */
1002  sce = preview_get_scene(pr_main);
1003  if (sce) {
1004  sce->r.xsch = sizex;
1005  sce->r.ysch = sp->sizey;
1006  sce->r.size = 100;
1007  }
1008 
1009  /* get the stuff from the builtin preview dbase */
1010  sce = preview_prepare_scene(sp->bmain, sp->scene, id, idtype, sp);
1011  if (sce == NULL) {
1012  return;
1013  }
1014 
1015  if (!split || first) {
1016  sprintf(name, "Preview %p", sp->owner);
1017  }
1018  else {
1019  sprintf(name, "SecondPreview %p", sp->owner);
1020  }
1021  re = RE_GetRender(name);
1022 
1023  /* full refreshed render from first tile */
1024  if (re == NULL) {
1025  re = RE_NewRender(name);
1026  }
1027 
1028  /* sce->r gets copied in RE_InitState! */
1030  sce->r.scemode &= ~R_NO_IMAGE_LOAD;
1031 
1032  if (sp->pr_method == PR_ICON_RENDER) {
1033  sce->r.scemode |= R_NO_IMAGE_LOAD;
1035  }
1036  else if (sp->pr_method == PR_NODE_RENDER) {
1037  if (idtype == ID_MA) {
1038  sce->r.scemode |= R_MATNODE_PREVIEW;
1039  }
1040  else if (idtype == ID_TE) {
1041  sce->r.scemode |= R_TEXNODE_PREVIEW;
1042  }
1044  }
1045  else { /* PR_BUTS_RENDER */
1047  }
1048 
1049  /* Callbacks are cleared on GetRender(). */
1052  }
1053  /* set this for all previews, default is react to G.is_break still */
1055 
1056  /* lens adjust */
1057  oldlens = ((Camera *)sce->camera->data)->lens;
1058  if (sizex > sp->sizey) {
1059  ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
1060  }
1061 
1062  /* entire cycle for render engine */
1063  if (idtype == ID_TE) {
1064  shader_preview_texture(sp, (Tex *)id, sce, re);
1065  }
1066  else {
1067  /* Render preview scene */
1068  RE_PreviewRender(re, pr_main, sce);
1069  }
1070 
1071  ((Camera *)sce->camera->data)->lens = oldlens;
1072 
1073  /* handle results */
1074  if (sp->pr_method == PR_ICON_RENDER) {
1075  // char *rct = (char *)(sp->pr_rect + 32 * 16 + 16);
1076 
1077  if (sp->pr_rect) {
1078  RE_ResultGet32(re, sp->pr_rect);
1079  }
1080  }
1081 
1082  /* unassign the pointers, reset vars */
1083  preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
1084 
1085  /* XXX bad exception, end-exec is not being called in render, because it uses local main. */
1086 #if 0
1087  if (idtype == ID_TE) {
1088  Tex *tex = (Tex *)id;
1089  if (tex->use_nodes && tex->nodetree)
1090  ntreeEndExecTree(tex->nodetree);
1091  }
1092 #endif
1093 }
1094 
1095 /* runs inside thread for material and icons */
1096 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
1097 {
1098  ShaderPreview *sp = customdata;
1099 
1100  sp->stop = stop;
1101  sp->do_update = do_update;
1102 
1103  if (sp->parent) {
1104  shader_preview_render(sp, sp->id, 1, 1);
1105  shader_preview_render(sp, sp->parent, 1, 0);
1106  }
1107  else {
1108  shader_preview_render(sp, sp->id, 0, 0);
1109  }
1110 
1111  *do_update = true;
1112 }
1113 
1114 static void preview_id_copy_free(ID *id)
1115 {
1116  struct IDProperty *properties;
1117  /* get rid of copied ID */
1118  properties = IDP_GetProperties(id, false);
1119  if (properties) {
1120  IDP_FreePropertyContent_ex(properties, false);
1121  MEM_freeN(properties);
1122  }
1124  MEM_freeN(id);
1125 }
1126 
1127 static void shader_preview_free(void *customdata)
1128 {
1129  ShaderPreview *sp = customdata;
1130  Main *pr_main = sp->pr_main;
1131  ID *main_id_copy = NULL;
1132  ID *sub_id_copy = NULL;
1133 
1134  if (sp->matcopy) {
1135  main_id_copy = (ID *)sp->matcopy;
1136  BLI_remlink(&pr_main->materials, sp->matcopy);
1137  }
1138  if (sp->texcopy) {
1139  BLI_assert(main_id_copy == NULL);
1140  main_id_copy = (ID *)sp->texcopy;
1141  BLI_remlink(&pr_main->textures, sp->texcopy);
1142  }
1143  if (sp->worldcopy) {
1144  /* worldcopy is also created for material with `Preview World` enabled */
1145  if (main_id_copy) {
1146  sub_id_copy = (ID *)sp->worldcopy;
1147  }
1148  else {
1149  main_id_copy = (ID *)sp->worldcopy;
1150  }
1151  BLI_remlink(&pr_main->worlds, sp->worldcopy);
1152  }
1153  if (sp->lampcopy) {
1154  BLI_assert(main_id_copy == NULL);
1155  main_id_copy = (ID *)sp->lampcopy;
1156  BLI_remlink(&pr_main->lights, sp->lampcopy);
1157  }
1158  if (main_id_copy || sp->id_copy) {
1159  /* node previews */
1161  }
1162  if (sp->own_id_copy) {
1163  if (sp->id_copy) {
1165  }
1166  if (main_id_copy) {
1167  preview_id_copy_free(main_id_copy);
1168  }
1169  if (sub_id_copy) {
1170  preview_id_copy_free(sub_id_copy);
1171  }
1172  }
1173 
1174  MEM_freeN(sp);
1175 }
1176 
1179 /* -------------------------------------------------------------------- */
1184 {
1185  static const int flags = IB_rect | IB_multilayer | IB_metadata;
1186 
1187  char path[FILE_MAX];
1188  const char *folder;
1189 
1190  if (!(brush->icon_imbuf)) {
1191  if (brush->flag & BRUSH_CUSTOM_ICON) {
1192 
1193  if (brush->icon_filepath[0]) {
1194  /* First use the path directly to try and load the file. */
1195 
1196  BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
1197  BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&brush->id));
1198 
1199  /* use default colorspaces for brushes */
1200  brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
1201 
1202  /* otherwise lets try to find it in other directories */
1203  if (!(brush->icon_imbuf)) {
1204  folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
1205 
1207  BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath);
1208 
1209  if (path[0]) {
1210  /* Use default color spaces. */
1211  brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
1212  }
1213  }
1214 
1215  if (brush->icon_imbuf) {
1217  }
1218  }
1219  }
1220  }
1221 
1222  if (!(brush->icon_imbuf)) {
1223  brush->id.icon_id = 0;
1224  }
1225 
1226  return brush->icon_imbuf;
1227 }
1228 
1229 static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
1230 {
1231  struct ImBuf *ima;
1232  uint *drect, *srect;
1233  float scaledx, scaledy;
1234  short ex, ey, dx, dy;
1235 
1236  /* paranoia test */
1237  if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
1238  return;
1239  }
1240 
1241  /* Waste of cpu cycles... but the imbuf API has no other way to scale fast (ton). */
1242  ima = IMB_dupImBuf(ibuf);
1243 
1244  if (!ima) {
1245  return;
1246  }
1247 
1248  if (ima->x > ima->y) {
1249  scaledx = (float)w;
1250  scaledy = ((float)ima->y / (float)ima->x) * (float)w;
1251  }
1252  else {
1253  scaledx = ((float)ima->x / (float)ima->y) * (float)h;
1254  scaledy = (float)h;
1255  }
1256 
1257  /* Scaling down must never assign zero width/height, see: T89868. */
1258  ex = MAX2(1, (short)scaledx);
1259  ey = MAX2(1, (short)scaledy);
1260 
1261  dx = (w - ex) / 2;
1262  dy = (h - ey) / 2;
1263 
1264  IMB_scalefastImBuf(ima, ex, ey);
1265 
1266  /* if needed, convert to 32 bits */
1267  if (ima->rect == NULL) {
1268  IMB_rect_from_float(ima);
1269  }
1270 
1271  srect = ima->rect;
1272  drect = rect;
1273 
1274  drect += dy * w + dx;
1275  for (; ey > 0; ey--) {
1276  memcpy(drect, srect, ex * sizeof(int));
1277  drect += w;
1278  srect += ima->x;
1279  }
1280 
1281  IMB_freeImBuf(ima);
1282 }
1283 
1284 static void set_alpha(char *cp, int sizex, int sizey, char alpha)
1285 {
1286  int a, size = sizex * sizey;
1287 
1288  for (a = 0; a < size; a++, cp += 4) {
1289  cp[3] = alpha;
1290  }
1291 }
1292 
1293 static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
1294 {
1295  ShaderPreview *sp = customdata;
1296 
1297  if (sp->pr_method == PR_ICON_DEFERRED) {
1298  PreviewImage *prv = sp->owner;
1299  ImBuf *thumb;
1300  char *deferred_data = PRV_DEFERRED_DATA(prv);
1301  int source = deferred_data[0];
1302  char *path = &deferred_data[1];
1303 
1304  // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
1305 
1306  thumb = IMB_thumb_manage(path, THB_LARGE, source);
1307 
1308  if (thumb) {
1309  /* PreviewImage assumes premultiplied alhpa... */
1310  IMB_premultiply_alpha(thumb);
1311 
1312  icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
1313  IMB_freeImBuf(thumb);
1314  }
1315  }
1316  else {
1317  ID *id = sp->id;
1318  short idtype = GS(id->name);
1319 
1320  BLI_assert(id != NULL);
1321 
1322  if (idtype == ID_IM) {
1323  Image *ima = (Image *)id;
1324  ImBuf *ibuf = NULL;
1325  ImageUser iuser;
1326  BKE_imageuser_default(&iuser);
1327 
1328  if (ima == NULL) {
1329  return;
1330  }
1331 
1332  ImageTile *tile = BKE_image_get_tile(ima, 0);
1333  /* tile->ok is zero when Image cannot load */
1334  if (tile->ok == 0) {
1335  return;
1336  }
1337 
1338  /* setup dummy image user */
1339  iuser.ok = iuser.framenr = 1;
1340  iuser.scene = sp->scene;
1341 
1342  /* elubie: this needs to be changed: here image is always loaded if not
1343  * already there. Very expensive for large images. Need to find a way to
1344  * only get existing ibuf */
1345  ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
1346  if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
1347  BKE_image_release_ibuf(ima, ibuf, NULL);
1348  return;
1349  }
1350 
1351  icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
1352 
1353  *do_update = true;
1354 
1355  BKE_image_release_ibuf(ima, ibuf, NULL);
1356  }
1357  else if (idtype == ID_BR) {
1358  Brush *br = (Brush *)id;
1359 
1361 
1362  memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(uint));
1363 
1364  if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) {
1365  return;
1366  }
1367 
1368  icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
1369 
1370  *do_update = true;
1371  }
1372  else if (idtype == ID_SCR) {
1373  bScreen *screen = (bScreen *)id;
1374 
1375  ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
1376  *do_update = true;
1377  }
1378  else {
1379  /* re-use shader job */
1380  shader_preview_startjob(customdata, stop, do_update);
1381 
1382  /* world is rendered with alpha=0, so it wasn't displayed
1383  * this could be render option for sky to, for later */
1384  if (idtype == ID_WO) {
1385  set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
1386  }
1387  }
1388  }
1389 }
1390 
1391 /* use same function for icon & shader, so the job manager
1392  * does not run two of them at the same time. */
1393 
1394 static void common_preview_startjob(void *customdata,
1395  short *stop,
1396  short *do_update,
1397  float *UNUSED(progress))
1398 {
1399  ShaderPreview *sp = customdata;
1400 
1402  icon_preview_startjob(customdata, stop, do_update);
1403  }
1404  else {
1405  shader_preview_startjob(customdata, stop, do_update);
1406  }
1407 }
1408 
1414  IconPreviewSize *cur_size,
1415  const int pr_method,
1416  short *stop,
1417  short *do_update,
1418  float *progress)
1419 {
1420  ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
1421 
1422  /* These types don't use the ShaderPreview mess, they have their own types and functions. */
1423  BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB));
1424 
1425  /* construct shader preview from image size and previewcustomdata */
1426  sp->scene = ip->scene;
1427  sp->owner = ip->owner;
1428  sp->sizex = cur_size->sizex;
1429  sp->sizey = cur_size->sizey;
1430  sp->pr_method = pr_method;
1431  sp->pr_rect = cur_size->rect;
1432  sp->id = ip->id;
1433  sp->id_copy = ip->id_copy;
1434  sp->bmain = ip->bmain;
1435  sp->own_id_copy = false;
1436  Material *ma = NULL;
1437 
1438  if (sp->pr_method == PR_ICON_RENDER) {
1439  BLI_assert(ip->id);
1440 
1441  /* grease pencil use its own preview file */
1442  if (GS(ip->id->name) == ID_MA) {
1443  ma = (Material *)ip->id;
1444  }
1445 
1446  if ((ma == NULL) || (ma->gp_style == NULL)) {
1447  sp->pr_main = G_pr_main;
1448  }
1449  else {
1451  }
1452  }
1453 
1454  common_preview_startjob(sp, stop, do_update, progress);
1455  shader_preview_free(sp);
1456 }
1457 
1458 /* exported functions */
1459 
1464  const PreviewImage *preview_image)
1465 {
1466  for (int i = 0; i < NUM_ICON_SIZES; i++) {
1467  if ((preview_image->w[i] == icon_size->sizex) && (preview_image->h[i] == icon_size->sizey)) {
1468  return i;
1469  }
1470  }
1471 
1472  BLI_assert(!"The searched icon size does not match any in the preview image");
1473  return -1;
1474 }
1475 
1476 static void icon_preview_startjob_all_sizes(void *customdata,
1477  short *stop,
1478  short *do_update,
1479  float *progress)
1480 {
1481  IconPreview *ip = (IconPreview *)customdata;
1482  IconPreviewSize *cur_size;
1483 
1484  for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
1485  PreviewImage *prv = ip->owner;
1486  /* Is this a render job or a deferred loading job? */
1487  const int pr_method = (prv->tag & PRV_TAG_DEFFERED) ? PR_ICON_DEFERRED : PR_ICON_RENDER;
1488 
1489  if (*stop) {
1490  break;
1491  }
1492 
1493  if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
1494  /* Non-thread-protected reading is not an issue here. */
1495  continue;
1496  }
1497 
1498  /* check_engine_supports_preview() checks whether the engine supports "preview mode" (think:
1499  * Material Preview). This check is only relevant when the render function called below is
1500  * going to use such a mode. Object and Action render functions use Solid mode, though, so they
1501  * can skip this test. */
1502  /* TODO: Decouple the ID-type-specific render functions from this function, so that it's not
1503  * necessary to know here what happens inside lower-level functions. */
1504  const bool use_solid_render_mode = (ip->id != NULL) && ELEM(GS(ip->id->name), ID_OB, ID_AC);
1505  if (!use_solid_render_mode && preview_method_is_render(pr_method) &&
1507  continue;
1508  }
1509 
1510 #ifndef NDEBUG
1511  {
1512  int size_index = icon_previewimg_size_index_get(cur_size, prv);
1513  BLI_assert(!BKE_previewimg_is_finished(prv, size_index));
1514  }
1515 #endif
1516 
1517  if (ip->id != NULL) {
1518  switch (GS(ip->id->name)) {
1519  case ID_OB:
1520  /* Much simpler than the ShaderPreview mess used for other ID types. */
1521  object_preview_render(ip, cur_size);
1522  continue;
1523  case ID_AC:
1524  action_preview_render(ip, cur_size);
1525  continue;
1526  default:
1527  /* Fall through to the same code as the `ip->id == NULL` case. */
1528  break;
1529  }
1530  }
1531  other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress);
1532  }
1533 }
1534 
1535 static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
1536 {
1537  IconPreviewSize *cur_size = ip->sizes.first, *new_size;
1538 
1539  while (cur_size) {
1540  if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
1541  /* requested size is already in list, no need to add it again */
1542  return;
1543  }
1544 
1545  cur_size = cur_size->next;
1546  }
1547 
1548  new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
1549  new_size->sizex = sizex;
1550  new_size->sizey = sizey;
1551  new_size->rect = rect;
1552 
1553  BLI_addtail(&ip->sizes, new_size);
1554 }
1555 
1556 static void icon_preview_endjob(void *customdata)
1557 {
1558  IconPreview *ip = customdata;
1559 
1560  if (ip->id) {
1561 
1562  if (GS(ip->id->name) == ID_BR) {
1564  }
1565 #if 0
1566  if (GS(ip->id->name) == ID_MA) {
1567  Material *ma = (Material *)ip->id;
1568  PreviewImage *prv_img = ma->preview;
1569  int i;
1570 
1571  /* signal to gpu texture */
1572  for (i = 0; i < NUM_ICON_SIZES; i++) {
1573  if (prv_img->gputexture[i]) {
1574  GPU_texture_free(prv_img->gputexture[i]);
1575  prv_img->gputexture[i] = NULL;
1577  }
1578  }
1579  }
1580 #endif
1581  }
1582 
1583  if (ip->owner) {
1584  PreviewImage *prv_img = ip->owner;
1585  prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
1586 
1587  LISTBASE_FOREACH (IconPreviewSize *, icon_size, &ip->sizes) {
1588  int size_index = icon_previewimg_size_index_get(icon_size, prv_img);
1589  BKE_previewimg_finish(prv_img, size_index);
1590  }
1591 
1592  if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
1593  BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
1595  }
1596  }
1597 }
1598 
1599 static void icon_preview_free(void *customdata)
1600 {
1601  IconPreview *ip = (IconPreview *)customdata;
1602 
1603  if (ip->id_copy) {
1605  }
1606 
1607  BLI_freelistN(&ip->sizes);
1608  MEM_freeN(ip);
1609 }
1610 
1612  const bContext *C, Scene *scene, ID *id, uint *rect, int sizex, int sizey)
1613 {
1614  IconPreview ip = {NULL};
1615  short stop = false, update = false;
1616  float progress = 0.0f;
1617 
1619 
1620  ip.bmain = CTX_data_main(C);
1621  ip.scene = scene;
1624  ip.id = id;
1625  /* Control isn't given back to the caller until the preview is done. So we don't need to copy
1626  * the ID to avoid thread races. */
1627  ip.id_copy = duplicate_ids(id, true);
1628 
1629  icon_preview_add_size(&ip, rect, sizex, sizey);
1630 
1631  icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
1632 
1633  icon_preview_endjob(&ip);
1634 
1635  BLI_freelistN(&ip.sizes);
1636  if (ip.id_copy != NULL) {
1638  }
1639 }
1640 
1642  const bContext *C, void *owner, ID *id, uint *rect, int sizex, int sizey, const bool delay)
1643 {
1644  wmJob *wm_job;
1645  IconPreview *ip, *old_ip;
1646 
1648 
1649  /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
1650  wm_job = WM_jobs_get(CTX_wm_manager(C),
1651  CTX_wm_window(C),
1652  owner,
1653  "Icon Preview",
1656 
1657  ip = MEM_callocN(sizeof(IconPreview), "icon preview");
1658 
1659  /* render all resolutions from suspended job too */
1660  old_ip = WM_jobs_customdata_get(wm_job);
1661  if (old_ip) {
1662  BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
1663  }
1664 
1665  /* customdata for preview thread */
1666  ip->bmain = CTX_data_main(C);
1668  ip->scene = DEG_get_input_scene(ip->depsgraph);
1669  ip->owner = owner;
1670  ip->id = id;
1671  ip->id_copy = duplicate_ids(id, false);
1672 
1673  icon_preview_add_size(ip, rect, sizex, sizey);
1674 
1675  /* Special threading hack:
1676  * warn main code that this preview is being rendered and cannot be freed... */
1677  {
1678  PreviewImage *prv_img = owner;
1679  if (prv_img->tag & PRV_TAG_DEFFERED) {
1680  prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
1681  }
1682  }
1683 
1684  /* setup job */
1686  WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
1687  /* Wait 2s to start rendering icon previews, to not bog down user interaction.
1688  * Particularly important for heavy scenes and Eevee using OpenGL that blocks
1689  * the user interface drawing. */
1690  WM_jobs_delay_start(wm_job, (delay) ? 2.0 : 0.0);
1692 
1693  WM_jobs_start(CTX_wm_manager(C), wm_job);
1694 }
1695 
1697  void *owner,
1698  ID *id,
1699  ID *parent,
1700  MTex *slot,
1701  int sizex,
1702  int sizey,
1703  int method)
1704 {
1706  wmJob *wm_job;
1707  ShaderPreview *sp;
1709  short id_type = GS(id->name);
1710 
1712 
1713  /* Use workspace render only for buttons Window,
1714  * since the other previews are related to the datablock. */
1715 
1717  return;
1718  }
1719 
1720  /* Only texture node preview is supported with Cycles. */
1721  if (method == PR_NODE_RENDER && id_type != ID_TE) {
1722  return;
1723  }
1724 
1726 
1727  wm_job = WM_jobs_get(CTX_wm_manager(C),
1728  CTX_wm_window(C),
1729  owner,
1730  "Shader Preview",
1733  sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
1734 
1735  /* customdata for preview thread */
1736  sp->scene = scene;
1737  sp->owner = owner;
1738  sp->sizex = sizex;
1739  sp->sizey = sizey;
1740  sp->pr_method = method;
1741  sp->id = id;
1742  sp->id_copy = duplicate_ids(id, false);
1743  sp->own_id_copy = true;
1744  sp->parent = parent;
1745  sp->slot = slot;
1746  sp->bmain = CTX_data_main(C);
1747  Material *ma = NULL;
1748 
1749  /* hardcoded preview .blend for Eevee + Cycles, this should be solved
1750  * once with custom preview .blend path for external engines */
1751 
1752  /* grease pencil use its own preview file */
1753  if (GS(id->name) == ID_MA) {
1754  ma = (Material *)id;
1755  }
1756 
1757  if ((ma == NULL) || (ma->gp_style == NULL)) {
1758  sp->pr_main = G_pr_main;
1759  }
1760  else {
1762  }
1763 
1764  if (ob && ob->totcol) {
1765  copy_v4_v4(sp->color, ob->color);
1766  }
1767  else {
1768  ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
1769  }
1770 
1771  /* setup job */
1773  WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
1775 
1776  WM_jobs_start(CTX_wm_manager(C), wm_job);
1777 }
1778 
1780 {
1781  if (wm) {
1782  /* This is called to stop all preview jobs before scene data changes, to
1783  * avoid invalid memory access. */
1786  }
1787 }
1788 
typedef float(TangentPoint)[2]
void immDrawPixelsTex(IMMDrawPixelsTexState *state, float x, float y, int img_w, int img_h, eGPUTextureFormat gpu_format, bool use_filter, void *rect, float xzoom, float yzoom, const float color[4])
Definition: glutil.c:298
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
Definition: glutil.c:66
@ BLENDER_DATAFILES
Definition: BKE_appdir.h:78
const char * BKE_appdir_folder_id(const int folder_id, const char *subfolder)
Definition: appdir.c:674
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
Definition: collection.c:1134
void BKE_color_managed_display_settings_copy(struct ColorManagedDisplaySettings *new_settings, const struct ColorManagedDisplaySettings *settings)
void BKE_color_managed_view_settings_free(struct ColorManagedViewSettings *settings)
Definition: colortools.c:1820
void BKE_color_managed_view_settings_copy(struct ColorManagedViewSettings *new_settings, const struct ColorManagedViewSettings *settings)
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct SpaceProperties * CTX_wm_space_properties(const bContext *C)
Definition: context.c:809
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
@ G_FILE_NO_UI
Definition: BKE_global.h:170
struct PreviewImage * BKE_previewimg_id_ensure(struct ID *id)
Definition: icons.cc:400
bool BKE_previewimg_id_supports_jobs(const struct ID *id)
void BKE_icon_changed(const int icon_id)
Definition: icons.cc:678
bool BKE_previewimg_is_finished(const struct PreviewImage *prv, const int size)
void BKE_previewimg_finish(struct PreviewImage *prv, const int size)
Definition: icons.cc:614
void BKE_previewimg_deferred_release(struct PreviewImage *prv)
Definition: icons.cc:440
int BKE_icon_id_ensure(struct ID *id)
Definition: icons.cc:740
struct IDProperty * IDP_GetProperties(struct ID *id, const bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:769
void IDP_FreePropertyContent_ex(struct IDProperty *prop, const bool do_id_user)
Definition: idprop.c:1006
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
Definition: image.c:5113
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
Definition: image.c:5100
struct ImagePool * BKE_image_pool_new(void)
Definition: image.c:5173
void BKE_imageuser_default(struct ImageUser *iuser)
Definition: image.c:3451
void BKE_image_pool_free(struct ImagePool *pool)
Definition: image.c:5181
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:394
void BKE_layer_collection_sync(const struct Scene *scene, struct ViewLayer *view_layer)
@ LIB_ID_CREATE_LOCAL
Definition: BKE_lib_id.h:105
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:145
@ LIB_ID_COPY_NO_ANIMDATA
Definition: BKE_lib_id.h:120
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag)
void BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL()
General operations, lookup, etc. for blender lights.
struct Main * BKE_main_new(void)
Definition: main.c:45
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_main_free(struct Main *mainvar)
Definition: main.c:53
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:439
General operations, lookup, etc. for materials.
struct Material *** BKE_object_material_array_p(struct Object *ob)
Definition: material.c:323
void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree)
Definition: node.cc:3227
void BKE_node_preview_init_tree(struct bNodeTree *ntree, int xsize, int ysize, bool create_previews)
Definition: node.cc:2659
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_add(struct Main *bmain, struct ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.c:2713
struct Scene * BKE_scene_add(struct Main *bmain, const char *name)
Definition: scene.c:2078
void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool)
Definition: texture.c:771
void BKE_texture_get_value_ex(const struct Scene *scene, struct Tex *texture, const float *tex_co, struct TexResult *texres, struct ImagePool *pool, bool use_color_management)
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
MINLINE int max_ii(int a, int b)
#define M_PI_2
Definition: BLI_math_base.h:41
void mul_m3_m3_post(float R[3][3], const float B[3][3])
Definition: math_matrix.c:412
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
Definition: math_matrix.c:2236
void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle)
void mat3_to_quat(float q[4], const float mat[3][3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
#define FILE_MAX
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
Definition: path_util.c:1365
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:1016
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
int BLI_thread_is_main(void)
Definition: threads.cc:234
#define ARRAY_SET_ITEMS(...)
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
#define STREQ(a, b)
external readfile function prototypes.
@ BLO_READ_SKIP_NONE
Definition: BLO_readfile.h:94
BlendFileData * BLO_read_from_memory(const void *mem, int memsize, eBLOReadSkip skip_flags, struct ReportList *reports)
void DEG_evaluate_on_refresh(Depsgraph *graph)
Depsgraph * DEG_graph_new(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, eEvaluationMode mode)
Definition: depsgraph.cc:281
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ DAG_EVAL_VIEWPORT
Definition: DEG_depsgraph.h:61
void DEG_graph_free(Depsgraph *graph)
Definition: depsgraph.cc:314
void DEG_graph_build_from_view_layer(struct Depsgraph *graph)
struct Scene * DEG_get_input_scene(const Depsgraph *graph)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition: DNA_ID.h:421
#define PRV_DEFERRED_DATA(prv)
Definition: DNA_ID.h:407
@ PRV_TAG_DEFFERED_DELETE
Definition: DNA_ID.h:386
@ PRV_TAG_DEFFERED
Definition: DNA_ID.h:384
@ PRV_TAG_DEFFERED_RENDERING
Definition: DNA_ID.h:385
@ NUM_ICON_SIZES
Definition: DNA_ID_enums.h:32
@ ID_TE
Definition: DNA_ID_enums.h:64
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_BR
Definition: DNA_ID_enums.h:81
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_AC
Definition: DNA_ID_enums.h:79
@ ID_SCR
Definition: DNA_ID_enums.h:72
@ ID_OB
Definition: DNA_ID_enums.h:59
@ ROT_MODE_QUAT
@ BRUSH_CUSTOM_ICON
Object groups, one object can be in many groups at once.
@ COLLECTION_RESTRICT_RENDER
@ BASE_VISIBLE_DEPSGRAPH
@ BASE_SELECTED
#define MA_FLAT
#define MA_SKY
#define MA_CLOTH
#define MA_ATMOS
#define MA_SHADERBALL
#define MA_HAIR
#define MA_LAMP
#define MA_SPHERE
#define MA_PREVIEW_WORLD
#define MA_FLUID
#define MA_SPHERE_A
#define MA_CUBE
@ OB_SOLID
Object is a sort of wrapper for general info.
#define OB_TYPE_SUPPORT_MATERIAL(_type)
@ OB_CAMERA
@ OB_LAMP
@ OB_RESTRICT_RENDER
#define R_NO_IMAGE_LOAD
#define R_TEXNODE_PREVIEW
@ R_ADDSKY
@ R_ALPHAPREMUL
@ SCE_DISPLAY_AA_OFF
@ SCE_DISPLAY_AA_SAMPLES_8
#define R_BUTS_PREVIEW
#define R_MATNODE_PREVIEW
@ SCE_PASS_COMBINED
@ V3D_OFSDRAW_NONE
char datatoc_preview_blend[]
int datatoc_preview_grease_pencil_blend_size
char datatoc_preview_grease_pencil_blend[]
int datatoc_preview_blend_size
@ PR_NODE_RENDER
Definition: ED_render.h:79
@ PR_ICON_RENDER
Definition: ED_render.h:78
@ PR_ICON_DEFERRED
Definition: ED_render.h:80
@ PR_BUTS_RENDER
Definition: ED_render.h:77
void ED_screen_preview_render(const struct bScreen *screen, int size_x, int size_y, unsigned int *r_rect) ATTR_NONNULL()
bool ED_view3d_camera_to_view_selected(struct Main *bmain, struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *camera_ob)
struct ImBuf * ED_view3d_draw_offscreen_imbuf_simple(struct Depsgraph *depsgraph, struct Scene *scene, struct View3DShading *shading_override, eDrawType drawtype, struct Object *camera, int width, int height, eImBufFlags imbuf_flags, eV3DOffscreenDrawFlag draw_flags, int alpha_mode, const char *viewname, struct GPUOffScreen *ofs, char err_out[256])
Definition: view3d_draw.c:1991
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
@ GPU_SHADER_2D_IMAGE_COLOR
Definition: GPU_shader.h:187
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:508
@ GPU_RGBA8
Definition: GPU_texture.h:88
struct ImBuf * IMB_dupImBuf(const struct ImBuf *ibuf1)
void IMB_rect_from_float(struct ImBuf *ibuf)
Definition: divers.c:720
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
struct ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
Definition: readimage.c:224
void IMB_premultiply_alpha(struct ImBuf *ibuf)
Definition: filter.c:687
bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
Definition: scaling.c:1715
Contains defines and structs used throughout the imbuf module.
@ IB_metadata
@ IB_multilayer
@ IB_rect
struct ImBuf * IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source)
Definition: thumbs.c:563
@ THB_LARGE
Definition: IMB_thumbs.h:40
Read Guarded memory(de)allocation.
Platform independent time functions.
#define RE_USE_PREVIEW
Definition: RE_engine.h:59
#define C
Definition: RandGen.cpp:39
@ WM_JOB_TYPE_RENDER_PREVIEW
Definition: WM_api.h:737
@ WM_JOB_EXCL_RENDER
Definition: WM_api.h:725
#define NC_WINDOW
Definition: WM_types.h:277
#define NC_BRUSH
Definition: WM_types.h:286
#define NA_EDITED
Definition: WM_types.h:462
#define NC_MATERIAL
Definition: WM_types.h:281
#define ND_SHADING_DRAW
Definition: WM_types.h:378
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
Scene scene
World world
const Depsgraph * depsgraph
static CCL_NAMESPACE_BEGIN const double alpha
RenderEngineType * RE_engines_find(const char *idname)
Definition: engine.c:108
uint tex_coord
Definition: gpu_viewport.c:81
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong state[N]
static unsigned a[3]
Definition: RandGen.cpp:92
static void area(int d1, int d2, int e1, int e2, float weights[2])
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition: abc_util.cc:115
static void update(bNodeTree *ntree)
void RE_ReleaseResultImageViews(Render *re, RenderResult *rr)
Definition: pipeline.c:453
Render * RE_GetRender(const char *name)
Definition: pipeline.c:328
void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
Definition: pipeline.c:2583
Render * RE_NewRender(const char *name)
Definition: pipeline.c:557
void RE_InitState(Render *re, Render *source, RenderData *rd, ListBase *render_layers, ViewLayer *single_layer, int winx, int winy, rcti *disprect)
Definition: pipeline.c:788
void RE_ReleaseResult(Render *re)
Definition: pipeline.c:379
RenderResult * RE_AcquireResultWrite(Render *re)
Definition: pipeline.c:353
void RE_test_break_cb(Render *re, void *handle, int(*f)(void *handle))
Definition: pipeline.c:959
void RE_display_update_cb(Render *re, void *handle, void(*f)(void *handle, RenderResult *rr, volatile rcti *rect))
Definition: pipeline.c:930
void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect, const int view_id)
Definition: pipeline.c:538
void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
Definition: pipeline.c:407
void RE_SetScene(Render *re, Scene *sce)
Definition: pipeline.c:395
void RE_ResultGet32(Render *re, unsigned int *rect)
Definition: pipeline.c:520
static Scene * preview_get_scene(Main *pr_main)
static Object * object_preview_camera_create(Main *preview_main, ViewLayer *view_layer, Object *preview_object, int sizex, int sizey)
static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Render *re)
static void icon_preview_endjob(void *customdata)
static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress)
static bool check_engine_supports_preview(Scene *scene)
static Main * G_pr_main
static const char * preview_collection_name(const char pr_type)
static void shader_preview_free(void *customdata)
static Main * load_main_from_memory(const void *blend, int blend_size)
static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
void ED_preview_ensure_dbase(void)
static Scene * object_preview_scene_create(const struct ObjectPreviewData *preview_data, Depsgraph **r_depsgraph)
void ED_preview_free_dbase(void)
void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
static void icon_preview_free(void *customdata)
struct IconPreviewSize IconPreviewSize
struct ShaderPreview ShaderPreview
static World * preview_get_localized_world(ShaderPreview *sp, World *world)
static void set_preview_visibility(Scene *scene, ViewLayer *view_layer, char pr_type, int pr_method)
static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
void ED_preview_icon_job(const bContext *C, void *owner, ID *id, uint *rect, int sizex, int sizey, const bool delay)
static Scene * preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
static void object_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size, const PreviewImage *preview_image)
static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
static bool preview_method_is_render(int pr_method)
void ED_preview_icon_render(const bContext *C, Scene *scene, ID *id, uint *rect, int sizex, int sizey)
static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
static Main * G_pr_main_grease_pencil
void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
static void set_alpha(char *cp, int sizex, int sizey, char alpha)
static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
static void preview_id_copy_free(ID *id)
static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
static ImBuf * icon_preview_imbuf_from_brush(Brush *brush)
static int shader_preview_break(void *spv)
static void shader_preview_updatejob(void *spv)
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
static ID * duplicate_ids(ID *id, const bool allow_failure)
struct IconPreview IconPreview
void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method)
static void other_id_types_preview_render(IconPreview *ip, IconPreviewSize *cur_size, const int pr_method, short *stop, short *do_update, float *progress)
RenderView * RE_RenderViewGetById(RenderResult *rr, const int view_id)
const char * RE_engine_id_BLENDER_EEVEE
Definition: scene.c:1742
short flag
struct Main * main
Definition: BLO_readfile.h:70
struct ImBuf * icon_imbuf
char icon_filepath[1024]
Definition: DNA_ID.h:273
int icon_id
Definition: DNA_ID.h:294
char name[66]
Definition: DNA_ID.h:283
struct IconPreviewSize * next
struct IconPreviewSize * prev
ListBase sizes
Depsgraph * depsgraph
unsigned int * rect
float * rect_float
struct Scene * scene
struct LayerCollection * next
ListBase layer_collections
struct Collection * collection
struct bNodeTree * nodetree
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase scenes
Definition: BKE_main.h:146
ListBase textures
Definition: BKE_main.h:153
ListBase lights
Definition: BKE_main.h:156
ListBase materials
Definition: BKE_main.h:152
char name[1024]
Definition: BKE_main.h:118
ListBase worlds
Definition: BKE_main.h:160
ListBase objects
Definition: BKE_main.h:148
struct bNodeTree * nodetree
struct PreviewImage * preview
struct MaterialGPencilStyle * gp_style
float loc[3]
float obmat[4][4]
float quat[4]
short rotmode
float color[4]
void * data
unsigned int h[2]
Definition: DNA_ID.h:392
short tag
Definition: DNA_ID.h:403
unsigned int w[2]
Definition: DNA_ID.h:391
char engine[32]
ListBase views
Definition: RE_pipeline.h:138
float * rectf
Definition: RE_pipeline.h:69
struct Collection * master_collection
struct SceneDisplay display
ColorManagedViewSettings view_settings
struct RenderData r
ListBase view_layers
struct Object * camera
struct World * world
ColorManagedDisplaySettings display_settings
Material * matcopy
int talpha
Definition: RE_texture.h:85
float tb
Definition: RE_texture.h:84
float ta
Definition: RE_texture.h:84
float tr
Definition: RE_texture.h:84
float tg
Definition: RE_texture.h:84
char use_nodes
struct bNodeTree * nodetree
struct ViewLayerEEVEE eevee
ListBase layer_collections
ListBase object_bases
struct bNodeTree * nodetree
float horg
float range
short use_nodes
float exp
float horb
float horr
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79
Definition: wm_jobs.c:73
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
#define G(x, y, z)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_jobs_kill(wmWindowManager *wm, void *owner, void(*startjob)(void *, short int *, short int *, float *))
Definition: wm_jobs.c:596
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:450
void * WM_jobs_customdata(wmWindowManager *wm, void *owner)
Definition: wm_jobs.c:303
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:196
bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type)
Definition: wm_jobs.c:223
void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
Definition: wm_jobs.c:367
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition: wm_jobs.c:372
void * WM_jobs_customdata_get(wmJob *wm_job)
Definition: wm_jobs.c:336
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:344
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:360