Blender  V3.3
render_preview.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. All rights reserved. */
3 
8 /* global includes */
9 
10 #include <cmath>
11 #include <cstdlib>
12 #include <cstring>
13 #include <list>
14 
15 #ifndef WIN32
16 # include <unistd.h>
17 #else
18 # include <io.h>
19 #endif
20 #include "MEM_guardedalloc.h"
21 
22 #include "BLI_blenlib.h"
23 #include "BLI_math.h"
24 #include "BLI_utildefines.h"
25 
26 #include "PIL_time.h"
27 
28 #include "BLO_readfile.h"
29 
30 #include "DNA_brush_types.h"
31 #include "DNA_camera_types.h"
32 #include "DNA_collection_types.h"
33 #include "DNA_light_types.h"
34 #include "DNA_material_types.h"
35 #include "DNA_mesh_types.h"
36 #include "DNA_node_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_space_types.h"
41 #include "DNA_world_types.h"
42 
43 #include "BKE_animsys.h"
44 #include "BKE_appdir.h"
45 #include "BKE_armature.h"
46 #include "BKE_brush.h"
47 #include "BKE_colortools.h"
48 #include "BKE_context.h"
49 #include "BKE_global.h"
50 #include "BKE_icons.h"
51 #include "BKE_idprop.h"
52 #include "BKE_image.h"
53 #include "BKE_layer.h"
54 #include "BKE_lib_id.h"
55 #include "BKE_light.h"
56 #include "BKE_main.h"
57 #include "BKE_material.h"
58 #include "BKE_node.h"
59 #include "BKE_object.h"
60 #include "BKE_scene.h"
61 #include "BKE_screen.h"
62 #include "BKE_texture.h"
63 #include "BKE_world.h"
64 
65 #include "DEG_depsgraph.h"
66 #include "DEG_depsgraph_build.h"
67 #include "DEG_depsgraph_query.h"
68 
69 #include "IMB_imbuf.h"
70 #include "IMB_imbuf_types.h"
71 #include "IMB_thumbs.h"
72 
73 #include "BIF_glutil.h"
74 
75 #include "GPU_shader.h"
76 
77 #include "RE_engine.h"
78 #include "RE_pipeline.h"
79 #include "RE_texture.h"
80 
81 #include "WM_api.h"
82 #include "WM_types.h"
83 
84 #include "ED_armature.h"
85 #include "ED_datafiles.h"
86 #include "ED_render.h"
87 #include "ED_screen.h"
88 #include "ED_view3d.h"
89 #include "ED_view3d_offscreen.h"
90 
91 #include "UI_interface_icons.h"
92 
93 #ifndef NDEBUG
94 /* Used for database init assert(). */
95 # include "BLI_threads.h"
96 #endif
97 
98 static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect);
99 
100 /* -------------------------------------------------------------------- */
105  /* from wmJob */
106  void *owner;
107  short *stop, *do_update;
108 
113 
114  /* datablocks with nodes need full copy during preview render, glsl uses it too */
119 
121  float color[4];
122 
123  int sizex, sizey;
127 
130 };
131 
134  int sizex, sizey;
136 };
137 
138 struct IconPreview {
140  Depsgraph *depsgraph; /* May be nullptr (see #WM_OT_previews_ensure). */
142  void *owner;
143  ID *id,
144  *id_copy; /* May be nullptr! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */
146 
147  /* May be nullptr, is used for rendering IDs that require some other object for it to be applied
148  * on before the ID can be represented as an image, for example when rendering an Action. */
150 };
151 
154 /* -------------------------------------------------------------------- */
158 static Main *G_pr_main = nullptr;
159 static Main *G_pr_main_grease_pencil = nullptr;
160 
161 #ifndef WITH_HEADLESS
162 static Main *load_main_from_memory(const void *blend, int blend_size)
163 {
164  const int fileflags = G.fileflags;
165  Main *bmain = nullptr;
166  BlendFileData *bfd;
167 
168  G.fileflags |= G_FILE_NO_UI;
169  bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, nullptr);
170  if (bfd) {
171  bmain = bfd->main;
172 
173  MEM_freeN(bfd);
174  }
175  G.fileflags = fileflags;
176 
177  return bmain;
178 }
179 #endif
180 
182 {
183 #ifndef WITH_HEADLESS
184  static bool base_initialized = false;
186  if (!base_initialized) {
190  base_initialized = true;
191  }
192 #endif
193 }
194 
196 {
198  return (type->flag & RE_USE_PREVIEW) != 0;
199 }
200 
201 static bool preview_method_is_render(const ePreviewRenderMethod pr_method)
202 {
203  return ELEM(pr_method, PR_ICON_RENDER, PR_BUTS_RENDER);
204 }
205 
207 {
208  if (G_pr_main) {
210  }
211 
214  }
215 }
216 
217 static Scene *preview_get_scene(Main *pr_main)
218 {
219  if (pr_main == nullptr) {
220  return nullptr;
221  }
222 
223  return static_cast<Scene *>(pr_main->scenes.first);
224 }
225 
226 static const char *preview_collection_name(const ePreviewType pr_type)
227 {
228  switch (pr_type) {
229  case MA_FLAT:
230  return "Flat";
231  case MA_SPHERE:
232  return "Sphere";
233  case MA_CUBE:
234  return "Cube";
235  case MA_SHADERBALL:
236  return "Shader Ball";
237  case MA_CLOTH:
238  return "Cloth";
239  case MA_FLUID:
240  return "Fluid";
241  case MA_SPHERE_A:
242  return "World Sphere";
243  case MA_LAMP:
244  return "Lamp";
245  case MA_SKY:
246  return "Sky";
247  case MA_HAIR:
248  return "Hair";
249  case MA_ATMOS:
250  return "Atmosphere";
251  default:
252  BLI_assert_msg(0, "Unknown preview type");
253  return "";
254  }
255 }
256 
258 {
259  return !STREQ(sce->r.engine, RE_engine_id_BLENDER_EEVEE);
260 }
261 
262 static void switch_preview_collection_visibility(ViewLayer *view_layer, const ePreviewType pr_type)
263 {
264  /* Set appropriate layer as visible. */
265  LayerCollection *lc = static_cast<LayerCollection *>(view_layer->layer_collections.first);
266  const char *collection_name = preview_collection_name(pr_type);
267 
268  for (lc = static_cast<LayerCollection *>(lc->layer_collections.first); lc; lc = lc->next) {
269  if (STREQ(lc->collection->id.name + 2, collection_name)) {
271  }
272  else {
274  }
275  }
276 }
277 
278 static const char *preview_floor_material_name(const Scene *scene,
279  const ePreviewRenderMethod pr_method)
280 {
282  return "FloorHidden";
283  }
284  return "Floor";
285 }
286 
287 static void switch_preview_floor_material(Main *pr_main,
288  Mesh *me,
289  const Scene *scene,
290  const ePreviewRenderMethod pr_method)
291 {
292  if (me->totcol == 0) {
293  return;
294  }
295 
296  const char *material_name = preview_floor_material_name(scene, pr_method);
297  Material *mat = static_cast<Material *>(
298  BLI_findstring(&pr_main->materials, material_name, offsetof(ID, name) + 2));
299  if (mat) {
300  me->mat[0] = mat;
301  }
302 }
303 
305  const Scene *scene,
306  ViewLayer *view_layer,
307  const ePreviewRenderMethod pr_method)
308 {
309  /* Hide floor for icon renders. */
310  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
311  if (STREQ(base->object->id.name + 2, "Floor")) {
312  base->object->visibility_flag &= ~OB_HIDE_RENDER;
313  if (pr_method == PR_ICON_RENDER) {
315  base->object->visibility_flag |= OB_HIDE_RENDER;
316  }
317  }
318  if (base->object->type == OB_MESH) {
320  pr_main, static_cast<Mesh *>(base->object->data), scene, pr_method);
321  }
322  }
323  }
324 }
325 
326 static void set_preview_visibility(Main *pr_main,
327  Scene *scene,
328  ViewLayer *view_layer,
329  const ePreviewType pr_type,
330  const ePreviewRenderMethod pr_method)
331 {
332  switch_preview_collection_visibility(view_layer, pr_type);
333  switch_preview_floor_visibility(pr_main, scene, view_layer, pr_method);
334  BKE_layer_collection_sync(scene, view_layer);
335 }
336 
338 {
339  if (world == nullptr) {
340  return nullptr;
341  }
342  if (sp->worldcopy != nullptr) {
343  return sp->worldcopy;
344  }
345 
346  ID *id_copy = BKE_id_copy_ex(nullptr,
347  &world->id,
348  nullptr,
351  sp->worldcopy = (World *)id_copy;
352  BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
353  return sp->worldcopy;
354 }
355 
356 static ID *duplicate_ids(ID *id, const bool allow_failure)
357 {
358  if (id == nullptr) {
359  /* Non-ID preview render. */
360  return nullptr;
361  }
362 
363  switch (GS(id->name)) {
364  case ID_OB:
365  case ID_MA:
366  case ID_TE:
367  case ID_LA:
368  case ID_WO: {
370  ID *id_copy = BKE_id_copy_ex(nullptr,
371  id,
372  nullptr,
375  return id_copy;
376  }
377  case ID_GR: {
378  /* Doesn't really duplicate the collection. Just creates a collection instance empty. */
380  Object *instance_empty = BKE_object_add_only_object(nullptr, OB_EMPTY, nullptr);
381  instance_empty->instance_collection = (Collection *)id;
382  instance_empty->transflag |= OB_DUPLICOLLECTION;
383  return &instance_empty->id;
384  }
385  /* These support threading, but don't need duplicating. */
386  case ID_IM:
387  case ID_BR:
389  return nullptr;
390  default:
391  if (!allow_failure) {
392  BLI_assert_msg(0, "ID type preview not supported.");
393  }
394  return nullptr;
395  }
396 }
397 
398 static const char *preview_world_name(const Scene *sce,
399  const ID_Type id_type,
400  const ePreviewRenderMethod pr_method)
401 {
402  /* When rendering material icons the floor will not be shown in the output. Cycles will use a
403  * material trick to show the floor in the reflections, but hide the floor for camera rays. For
404  * Eevee we use a transparent world that has a projected grid.
405  *
406  * In the future when Eevee supports VULKAN ray-tracing we can re-evaluate and perhaps remove
407  * this approximation.
408  */
409  if (id_type == ID_MA && pr_method == PR_ICON_RENDER &&
411  return "WorldFloor";
412  }
413  return "World";
414 }
415 
416 static World *preview_get_world(Main *pr_main,
417  const Scene *sce,
418  const ID_Type id_type,
419  const ePreviewRenderMethod pr_method)
420 {
421  World *result = nullptr;
422  const char *world_name = preview_world_name(sce, id_type, pr_method);
423  result = static_cast<World *>(
424  BLI_findstring(&pr_main->worlds, world_name, offsetof(ID, name) + 2));
425 
426  /* No world found return first world. */
427  if (result == nullptr) {
428  result = static_cast<World *>(pr_main->worlds.first);
429  }
430 
431  BLI_assert_msg(result, "Preview file has no world.");
432  return result;
433 }
434 
435 static void preview_sync_exposure(World *dst, const World *src)
436 {
437  BLI_assert(dst);
438  BLI_assert(src);
439  dst->exp = src->exp;
440  dst->range = src->range;
441 }
442 
444  const Scene *sce,
445  const World *world,
446  const ID_Type id_type,
447  const ePreviewRenderMethod pr_method)
448 {
449  World *result = preview_get_world(pr_main, sce, id_type, pr_method);
450  if (world) {
452  }
453  return result;
454 }
455 
456 /* call this with a pointer to initialize preview scene */
457 /* call this with nullptr to restore assigned ID pointers in preview scene */
459  Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
460 {
461  Scene *sce;
462  Main *pr_main = sp->pr_main;
463 
464  memcpy(pr_main->filepath, BKE_main_blendfile_path(bmain), sizeof(pr_main->filepath));
465 
466  sce = preview_get_scene(pr_main);
467  if (sce) {
468  ViewLayer *view_layer = static_cast<ViewLayer *>(sce->view_layers.first);
469 
470  /* Only enable the combined render-pass. */
471  view_layer->passflag = SCE_PASS_COMBINED;
472  view_layer->eevee.render_passes = 0;
473 
474  /* This flag tells render to not execute depsgraph or F-Curves etc. */
475  sce->r.scemode |= R_BUTS_PREVIEW;
476  BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
477 
480 
483 
484  if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) {
485  sce->r.alphamode = R_ALPHAPREMUL;
486  }
487  else {
488  sce->r.alphamode = R_ADDSKY;
489  }
490 
491  sce->r.cfra = scene->r.cfra;
492 
493  /* Setup the world. */
495  pr_main, sce, scene->world, static_cast<ID_Type>(id_type), sp->pr_method);
496 
497  if (id_type == ID_TE) {
498  /* Texture is not actually rendered with engine, just set dummy value. */
499  BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
500  }
501 
502  if (id_type == ID_MA) {
503  Material *mat = nullptr, *origmat = (Material *)id;
504 
505  if (origmat) {
506  /* work on a copy */
507  BLI_assert(sp->id_copy != nullptr);
508  mat = sp->matcopy = (Material *)sp->id_copy;
509  sp->id_copy = nullptr;
510  BLI_addtail(&pr_main->materials, mat);
511 
512  /* Use current scene world for lighting. */
514  /* Use current scene world to light sphere. */
516  }
517  else if (sce->world && sp->pr_method != PR_ICON_RENDER) {
518  /* Use a default world color. Using the current
519  * scene world can be slow if it has big textures. */
520  sce->world->use_nodes = false;
521  sce->world->horr = 0.05f;
522  sce->world->horg = 0.05f;
523  sce->world->horb = 0.05f;
524  }
525 
526  /* For grease pencil, always use sphere for icon renders. */
527  const ePreviewType preview_type = static_cast<ePreviewType>(
529  MA_SPHERE_A :
531  set_preview_visibility(pr_main, sce, view_layer, preview_type, sp->pr_method);
532  }
533  else {
535  }
536 
537  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
538  if (base->object->id.name[2] == 'p') {
539  /* copy over object color, in case material uses it */
540  copy_v4_v4(base->object->color, sp->color);
541 
542  if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
543  /* don't use BKE_object_material_assign, it changed mat->id.us, which shows in the UI
544  */
545  Material ***matar = BKE_object_material_array_p(base->object);
546  int actcol = max_ii(base->object->actcol - 1, 0);
547 
548  if (matar && actcol < base->object->totcol) {
549  (*matar)[actcol] = mat;
550  }
551  }
552  else if (base->object->type == OB_LAMP) {
553  base->flag |= BASE_VISIBLE_DEPSGRAPH;
554  }
555  }
556  }
557  }
558  else if (id_type == ID_TE) {
559  Tex *tex = nullptr, *origtex = (Tex *)id;
560 
561  if (origtex) {
562  BLI_assert(sp->id_copy != nullptr);
563  tex = sp->texcopy = (Tex *)sp->id_copy;
564  sp->id_copy = nullptr;
565  BLI_addtail(&pr_main->textures, tex);
566  }
567  }
568  else if (id_type == ID_LA) {
569  Light *la = nullptr, *origla = (Light *)id;
570 
571  /* work on a copy */
572  if (origla) {
573  BLI_assert(sp->id_copy != nullptr);
574  la = sp->lampcopy = (Light *)sp->id_copy;
575  sp->id_copy = nullptr;
576  BLI_addtail(&pr_main->lights, la);
577  }
578 
579  set_preview_visibility(pr_main, sce, view_layer, MA_LAMP, sp->pr_method);
580 
581  if (sce->world) {
582  /* Only use lighting from the light. */
583  sce->world->use_nodes = false;
584  sce->world->horr = 0.0f;
585  sce->world->horg = 0.0f;
586  sce->world->horb = 0.0f;
587  }
588 
589  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
590  if (base->object->id.name[2] == 'p') {
591  if (base->object->type == OB_LAMP) {
592  base->object->data = la;
593  }
594  }
595  }
596  }
597  else if (id_type == ID_WO) {
598  World *wrld = nullptr, *origwrld = (World *)id;
599 
600  if (origwrld) {
601  BLI_assert(sp->id_copy != nullptr);
602  wrld = sp->worldcopy = (World *)sp->id_copy;
603  sp->id_copy = nullptr;
604  BLI_addtail(&pr_main->worlds, wrld);
605  }
606 
607  set_preview_visibility(pr_main, sce, view_layer, MA_SKY, sp->pr_method);
608  sce->world = wrld;
609  }
610 
611  return sce;
612  }
613 
614  return nullptr;
615 }
616 
617 /* new UI convention: draw is in pixel space already. */
618 /* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
619 static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
620 {
621  Render *re;
622  RenderView *rv;
623  RenderResult rres;
624  char name[32];
625  int offx = 0;
626  int newx = BLI_rcti_size_x(rect);
627  int newy = BLI_rcti_size_y(rect);
628  bool ok = false;
629 
630  if (!split || first) {
631  sprintf(name, "Preview %p", (void *)area);
632  }
633  else {
634  sprintf(name, "SecondPreview %p", (void *)area);
635  }
636 
637  if (split) {
638  if (first) {
639  offx = 0;
640  newx = newx / 2;
641  }
642  else {
643  offx = newx / 2;
644  newx = newx - newx / 2;
645  }
646  }
647 
648  /* test if something rendered ok */
649  re = RE_GetRender(name);
650 
651  if (re == nullptr) {
652  return false;
653  }
654 
655  RE_AcquireResultImageViews(re, &rres);
656 
657  if (!BLI_listbase_is_empty(&rres.views)) {
658  /* material preview only needs monoscopy (view 0) */
659  rv = RE_RenderViewGetById(&rres, 0);
660  }
661  else {
662  /* possible the job clears the views but we're still drawing T45496 */
663  rv = nullptr;
664  }
665 
666  if (rv && rv->rectf) {
667 
668  if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
669 
670  newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
671  newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
672 
673  if (rres.rectx && rres.recty) {
674  uchar *rect_byte = static_cast<uchar *>(
675  MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"));
676  float fx = rect->xmin + offx;
677  float fy = rect->ymin;
678 
679  /* material preview only needs monoscopy (view 0) */
680  RE_AcquiredResultGet32(re, &rres, (uint *)rect_byte, 0);
681 
684  fx,
685  fy,
686  rres.rectx,
687  rres.recty,
688  GPU_RGBA8,
689  false,
690  rect_byte,
691  1.0f,
692  1.0f,
693  nullptr);
694 
695  MEM_freeN(rect_byte);
696 
697  ok = true;
698  }
699  }
700  }
701 
702  RE_ReleaseResultImageViews(re, &rres);
703 
704  return ok;
705 }
706 
707 void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
708 {
709  if (idp) {
712  ID *id = (ID *)idp;
713  ID *parent = (ID *)parentp;
714  MTex *slot = (MTex *)slotp;
716  ShaderPreview *sp = static_cast<ShaderPreview *>(
718  rcti newrect;
719  bool ok;
720  int newx = BLI_rcti_size_x(rect);
721  int newy = BLI_rcti_size_y(rect);
722 
723  newrect.xmin = rect->xmin;
724  newrect.xmax = rect->xmin;
725  newrect.ymin = rect->ymin;
726  newrect.ymax = rect->ymin;
727 
728  if (parent) {
729  ok = ed_preview_draw_rect(area, 1, 1, rect, &newrect);
730  ok &= ed_preview_draw_rect(area, 1, 0, rect, &newrect);
731  }
732  else {
733  ok = ed_preview_draw_rect(area, 0, 0, rect, &newrect);
734  }
735 
736  if (ok) {
737  *rect = newrect;
738  }
739 
740  /* start a new preview render job if signaled through sbuts->preview,
741  * if no render result was found and no preview render job is running,
742  * or if the job is running and the size of preview changed */
743  if ((sbuts != nullptr && sbuts->preview) ||
744  (!ok && !WM_jobs_test(wm, area, WM_JOB_TYPE_RENDER_PREVIEW)) ||
745  (sp && (abs(sp->sizex - newx) >= 2 || abs(sp->sizey - newy) > 2))) {
746  if (sbuts != nullptr) {
747  sbuts->preview = 0;
748  }
749  ED_preview_shader_job(C, area, id, parent, slot, newx, newy, PR_BUTS_RENDER);
750  }
751  }
752 }
753 
756 /* -------------------------------------------------------------------- */
761  /* The main for the preview, not of the current file. */
763  /* Copy of the object to create the preview for. The copy is for thread safety (and to insert
764  * it into its own main). */
766  /* Current frame. */
767  int cfra;
768  int sizex;
769  int sizey;
770 };
771 
773 {
774  return OB_TYPE_IS_GEOMETRY(ob->type);
775 }
776 
778  ViewLayer *view_layer,
779  Object *preview_object)
780 {
781  Object *camera = BKE_object_add(preview_main, view_layer, OB_CAMERA, "Preview Camera");
782 
783  float rotmat[3][3];
784  float dummyscale[3];
785  mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat);
786 
787  /* Camera is Y up, so needs additional rotations to obliquely face the front. */
788  float drotmat[3][3];
789  const float eul[3] = {M_PI * 0.4f, 0.0f, M_PI * 0.1f};
790  eul_to_mat3(drotmat, eul);
791  mul_m3_m3_post(rotmat, drotmat);
792 
793  camera->rotmode = ROT_MODE_QUAT;
794  mat3_to_quat(camera->quat, rotmat);
795 
796  /* Nice focal length for close portraiture. */
797  ((Camera *)camera->data)->lens = 85;
798 
799  return camera;
800 }
801 
802 static Scene *object_preview_scene_create(const struct ObjectPreviewData *preview_data,
803  Depsgraph **r_depsgraph)
804 {
805  Scene *scene = BKE_scene_add(preview_data->pr_main, "Object preview scene");
806  /* Preview need to be in the current frame to get a thumbnail similar of what
807  * viewport displays. */
808  scene->r.cfra = preview_data->cfra;
809 
810  ViewLayer *view_layer = static_cast<ViewLayer *>(scene->view_layers.first);
812  preview_data->pr_main, scene, view_layer, DAG_EVAL_VIEWPORT);
813 
814  BLI_assert(preview_data->object != nullptr);
815  BLI_addtail(&preview_data->pr_main->objects, preview_data->object);
816 
817  BKE_collection_object_add(preview_data->pr_main, scene->master_collection, preview_data->object);
818 
819  Object *camera_object = object_preview_camera_create(
820  preview_data->pr_main, view_layer, preview_data->object);
821 
822  scene->camera = camera_object;
823  scene->r.xsch = preview_data->sizex;
824  scene->r.ysch = preview_data->sizey;
825  scene->r.size = 100;
826 
827  Base *preview_base = BKE_view_layer_base_find(view_layer, preview_data->object);
828  /* For 'view selected' below. */
829  preview_base->flag |= BASE_SELECTED;
830 
833 
835  preview_data->pr_main, depsgraph, scene, camera_object);
836 
838 
839  *r_depsgraph = depsgraph;
840  return scene;
841 }
842 
844 {
845  Main *preview_main = BKE_main_new();
846  char err_out[256] = "unknown";
847 
848  BLI_assert(preview->id_copy && (preview->id_copy != preview->id));
849 
850  struct ObjectPreviewData preview_data = {};
851  preview_data.pr_main = preview_main;
852  /* Act on a copy. */
853  preview_data.object = (Object *)preview->id_copy;
854  preview_data.cfra = preview->scene->r.cfra;
855  preview_data.sizex = preview_sized->sizex;
856  preview_data.sizey = preview_sized->sizey;
857 
859  Scene *scene = object_preview_scene_create(&preview_data, &depsgraph);
860 
861  /* Ownership is now ours. */
862  preview->id_copy = nullptr;
863 
864  View3DShading shading;
866  /* Enable shadows, makes it a bit easier to see the shape. */
867  shading.flag |= V3D_SHADING_SHADOW;
868 
870  depsgraph,
872  &shading,
873  OB_TEXTURE,
875  preview_sized->sizex,
876  preview_sized->sizey,
877  IB_rect,
880  nullptr,
881  nullptr,
882  err_out);
883  /* TODO: color-management? */
884 
885  if (ibuf) {
886  icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect);
887  IMB_freeImBuf(ibuf);
888  }
889 
891  BKE_main_free(preview_main);
892 }
893 
896 /* -------------------------------------------------------------------- */
910 {
911  LISTBASE_FOREACH (CollectionObject *, col_ob, &collection->gobject) {
912  if (col_ob->ob->visibility_flag & OB_HIDE_RENDER) {
913  continue;
914  }
915  if (OB_TYPE_IS_GEOMETRY(col_ob->ob->type)) {
916  return true;
917  }
918  }
919 
920  LISTBASE_FOREACH (CollectionChild *, child_col, &collection->children) {
921  if (child_col->collection->flag & COLLECTION_HIDE_RENDER) {
922  continue;
923  }
924  if (collection_preview_contains_geometry_recursive(child_col->collection)) {
925  return true;
926  }
927  }
928 
929  return false;
930 }
931 
934 /* -------------------------------------------------------------------- */
939 {
940  Object *object = preview->active_object;
941  if (object == nullptr) {
942  WM_report(RPT_WARNING, "No active object, unable to apply the Action before rendering");
943  return nullptr;
944  }
945  if (object->pose == nullptr) {
947  "Object %s has no pose, unable to apply the Action before rendering",
948  object->id.name + 2);
949  return nullptr;
950  }
951 
952  /* Create a backup of the current pose. */
953  struct bAction *action = (struct bAction *)preview->id;
954  struct PoseBackup *pose_backup = ED_pose_backup_create_all_bones(object, action);
955 
956  /* Apply the Action as pose, so that it can be rendered. This assumes the Action represents a
957  * single pose, and that thus the evaluation time doesn't matter. */
958  AnimationEvalContext anim_eval_context = {preview->depsgraph, 0.0f};
959  BKE_pose_apply_action_all_bones(object, action, &anim_eval_context);
960 
961  /* Force evaluation of the new pose, before the preview is rendered. */
963  DEG_evaluate_on_refresh(preview->depsgraph);
964 
965  return pose_backup;
966 }
967 
969 {
970  if (pose_backup == nullptr) {
971  return;
972  }
973  ED_pose_backup_restore(pose_backup);
974  ED_pose_backup_free(pose_backup);
975 
976  DEG_id_tag_update(&preview->active_object->id, ID_RECALC_GEOMETRY);
977 }
978 
979 /* Render a pose from the scene camera. It is assumed that the scene camera is
980  * capturing the pose. The pose is applied temporarily to the current object
981  * before rendering. */
983 {
984  char err_out[256] = "";
985 
986  Depsgraph *depsgraph = preview->depsgraph;
987  /* Not all code paths that lead to this function actually provide a depsgraph.
988  * The "Refresh Asset Preview" button (ED_OT_lib_id_generate_preview) does,
989  * but WM_OT_previews_ensure does not. */
990  BLI_assert(depsgraph != nullptr);
992 
993  /* Apply the pose before getting the evaluated scene, so that the new pose is evaluated. */
994  struct PoseBackup *pose_backup = action_preview_render_prepare(preview);
995 
996  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
997  Object *camera_eval = scene_eval->camera;
998  if (camera_eval == nullptr) {
999  printf("Scene has no camera, unable to render preview of %s without it.\n",
1000  preview->id->name + 2);
1001  return;
1002  }
1003 
1004  /* This renders with the Workbench engine settings stored on the Scene. */
1006  scene_eval,
1007  nullptr,
1008  OB_SOLID,
1009  camera_eval,
1010  preview_sized->sizex,
1011  preview_sized->sizey,
1012  IB_rect,
1014  R_ADDSKY,
1015  nullptr,
1016  nullptr,
1017  err_out);
1018 
1019  action_preview_render_cleanup(preview, pose_backup);
1020 
1021  if (err_out[0] != '\0') {
1022  printf("Error rendering Action %s preview: %s\n", preview->id->name + 2, err_out);
1023  }
1024 
1025  if (ibuf) {
1026  icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect);
1027  IMB_freeImBuf(ibuf);
1028  }
1029 }
1030 
1033 /* -------------------------------------------------------------------- */
1037 /* inside thread, called by renderer, sets job update value */
1038 static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), struct rcti *UNUSED(rect))
1039 {
1040  ShaderPreview *sp = static_cast<ShaderPreview *>(spv);
1041 
1042  *(sp->do_update) = true;
1043 }
1044 
1045 /* called by renderer, checks job value */
1046 static int shader_preview_break(void *spv)
1047 {
1048  ShaderPreview *sp = static_cast<ShaderPreview *>(spv);
1049 
1050  return *(sp->stop);
1051 }
1052 
1053 static void shader_preview_updatejob(void *UNUSED(spv))
1054 {
1055 }
1056 
1057 /* Renders texture directly to render buffer. */
1059 {
1060  /* Setup output buffer. */
1061  int width = sp->sizex;
1062  int height = sp->sizey;
1063 
1064  /* This is needed otherwise no RenderResult is created. */
1065  sce->r.scemode &= ~R_BUTS_PREVIEW;
1066  RE_InitState(re, nullptr, &sce->r, &sce->view_layers, nullptr, width, height, nullptr);
1067  RE_SetScene(re, sce);
1068 
1069  /* Create buffer in empty RenderView created in the init step. */
1071  RenderView *rv = (RenderView *)rr->views.first;
1072  rv->rectf = static_cast<float *>(
1073  MEM_callocN(sizeof(float[4]) * width * height, "texture render result"));
1074  RE_ReleaseResult(re);
1075 
1076  /* Get texture image pool (if any) */
1077  struct ImagePool *img_pool = BKE_image_pool_new();
1079 
1080  /* Fill in image buffer. */
1081  float *rect_float = rv->rectf;
1082  float tex_coord[3] = {0.0f, 0.0f, 0.0f};
1083  bool color_manage = true;
1084 
1085  for (int y = 0; y < height; y++) {
1086  /* Tex coords between -1.0f and 1.0f. */
1087  tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f;
1088 
1089  for (int x = 0; x < width; x++) {
1090  tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f;
1091 
1092  /* Evaluate texture at tex_coord. */
1093  TexResult texres = {0};
1094  BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
1095  copy_v4_fl4(rect_float,
1096  texres.trgba[0],
1097  texres.trgba[1],
1098  texres.trgba[2],
1099  texres.talpha ? texres.trgba[3] : 1.0f);
1100 
1101  rect_float += 4;
1102  }
1103 
1104  /* Check if we should cancel texture preview. */
1105  if (shader_preview_break(sp)) {
1106  break;
1107  }
1108  }
1109 
1110  BKE_image_pool_free(img_pool);
1111 }
1112 
1113 static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
1114 {
1115  Render *re;
1116  Scene *sce;
1117  float oldlens;
1118  short idtype = GS(id->name);
1119  char name[32];
1120  int sizex;
1121  Main *pr_main = sp->pr_main;
1122 
1123  /* in case of split preview, use border render */
1124  if (split) {
1125  if (first) {
1126  sizex = sp->sizex / 2;
1127  }
1128  else {
1129  sizex = sp->sizex - sp->sizex / 2;
1130  }
1131  }
1132  else {
1133  sizex = sp->sizex;
1134  }
1135 
1136  /* we have to set preview variables first */
1137  sce = preview_get_scene(pr_main);
1138  if (sce) {
1139  sce->r.xsch = sizex;
1140  sce->r.ysch = sp->sizey;
1141  sce->r.size = 100;
1142  }
1143 
1144  /* get the stuff from the builtin preview dbase */
1145  sce = preview_prepare_scene(sp->bmain, sp->scene, id, idtype, sp);
1146  if (sce == nullptr) {
1147  return;
1148  }
1149 
1150  if (!split || first) {
1151  sprintf(name, "Preview %p", sp->owner);
1152  }
1153  else {
1154  sprintf(name, "SecondPreview %p", sp->owner);
1155  }
1156  re = RE_GetRender(name);
1157 
1158  /* full refreshed render from first tile */
1159  if (re == nullptr) {
1160  re = RE_NewRender(name);
1161  }
1162 
1163  /* sce->r gets copied in RE_InitState! */
1165  sce->r.scemode &= ~R_NO_IMAGE_LOAD;
1166 
1167  if (sp->pr_method == PR_ICON_RENDER) {
1168  sce->r.scemode |= R_NO_IMAGE_LOAD;
1170  }
1171  else { /* PR_BUTS_RENDER */
1173  }
1174 
1175  /* Callbacks are cleared on GetRender(). */
1176  if (sp->pr_method == PR_BUTS_RENDER) {
1178  }
1179  /* set this for all previews, default is react to G.is_break still */
1181 
1182  /* lens adjust */
1183  oldlens = ((Camera *)sce->camera->data)->lens;
1184  if (sizex > sp->sizey) {
1185  ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
1186  }
1187 
1188  /* entire cycle for render engine */
1189  if (idtype == ID_TE) {
1190  shader_preview_texture(sp, (Tex *)id, sce, re);
1191  }
1192  else {
1193  /* Render preview scene */
1194  RE_PreviewRender(re, pr_main, sce);
1195  }
1196 
1197  ((Camera *)sce->camera->data)->lens = oldlens;
1198 
1199  /* handle results */
1200  if (sp->pr_method == PR_ICON_RENDER) {
1201  // char *rct = (char *)(sp->pr_rect + 32 * 16 + 16);
1202 
1203  if (sp->pr_rect) {
1204  RE_ResultGet32(re, sp->pr_rect);
1205  }
1206  }
1207 
1208  /* unassign the pointers, reset vars */
1209  preview_prepare_scene(sp->bmain, sp->scene, nullptr, GS(id->name), sp);
1210 
1211  /* XXX bad exception, end-exec is not being called in render, because it uses local main. */
1212 #if 0
1213  if (idtype == ID_TE) {
1214  Tex *tex = (Tex *)id;
1215  if (tex->use_nodes && tex->nodetree)
1216  ntreeEndExecTree(tex->nodetree);
1217  }
1218 #endif
1219 }
1220 
1221 /* runs inside thread for material and icons */
1222 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
1223 {
1224  ShaderPreview *sp = static_cast<ShaderPreview *>(customdata);
1225 
1226  sp->stop = stop;
1227  sp->do_update = do_update;
1228 
1229  if (sp->parent) {
1230  shader_preview_render(sp, sp->id, 1, 1);
1231  shader_preview_render(sp, sp->parent, 1, 0);
1232  }
1233  else {
1234  shader_preview_render(sp, sp->id, 0, 0);
1235  }
1236 
1237  *do_update = true;
1238 }
1239 
1240 static void preview_id_copy_free(ID *id)
1241 {
1242  struct IDProperty *properties;
1243  /* get rid of copied ID */
1244  properties = IDP_GetProperties(id, false);
1245  if (properties) {
1246  IDP_FreePropertyContent_ex(properties, false);
1247  MEM_freeN(properties);
1248  }
1250  MEM_freeN(id);
1251 }
1252 
1253 static void shader_preview_free(void *customdata)
1254 {
1255  ShaderPreview *sp = static_cast<ShaderPreview *>(customdata);
1256  Main *pr_main = sp->pr_main;
1257  ID *main_id_copy = nullptr;
1258  ID *sub_id_copy = nullptr;
1259 
1260  if (sp->matcopy) {
1261  main_id_copy = (ID *)sp->matcopy;
1262  BLI_remlink(&pr_main->materials, sp->matcopy);
1263  }
1264  if (sp->texcopy) {
1265  BLI_assert(main_id_copy == nullptr);
1266  main_id_copy = (ID *)sp->texcopy;
1267  BLI_remlink(&pr_main->textures, sp->texcopy);
1268  }
1269  if (sp->worldcopy) {
1270  /* worldcopy is also created for material with `Preview World` enabled */
1271  if (main_id_copy) {
1272  sub_id_copy = (ID *)sp->worldcopy;
1273  }
1274  else {
1275  main_id_copy = (ID *)sp->worldcopy;
1276  }
1277  BLI_remlink(&pr_main->worlds, sp->worldcopy);
1278  }
1279  if (sp->lampcopy) {
1280  BLI_assert(main_id_copy == nullptr);
1281  main_id_copy = (ID *)sp->lampcopy;
1282  BLI_remlink(&pr_main->lights, sp->lampcopy);
1283  }
1284  if (sp->own_id_copy) {
1285  if (sp->id_copy) {
1287  }
1288  if (main_id_copy) {
1289  preview_id_copy_free(main_id_copy);
1290  }
1291  if (sub_id_copy) {
1292  preview_id_copy_free(sub_id_copy);
1293  }
1294  }
1295 
1296  MEM_freeN(sp);
1297 }
1298 
1301 /* -------------------------------------------------------------------- */
1306 {
1307  static const int flags = IB_rect | IB_multilayer | IB_metadata;
1308 
1309  char filepath[FILE_MAX];
1310  const char *folder;
1311 
1312  if (!(brush->icon_imbuf)) {
1313  if (brush->flag & BRUSH_CUSTOM_ICON) {
1314 
1315  if (brush->icon_filepath[0]) {
1316  /* First use the path directly to try and load the file. */
1317 
1318  BLI_strncpy(filepath, brush->icon_filepath, sizeof(brush->icon_filepath));
1319  BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&brush->id));
1320 
1321  /* Use default color-spaces for brushes. */
1322  brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr);
1323 
1324  /* otherwise lets try to find it in other directories */
1325  if (!(brush->icon_imbuf)) {
1326  folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
1327 
1329  BKE_main_blendfile_path_from_global(), filepath, folder, brush->icon_filepath);
1330 
1331  if (filepath[0]) {
1332  /* Use default color spaces. */
1333  brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr);
1334  }
1335  }
1336 
1337  if (brush->icon_imbuf) {
1339  }
1340  }
1341  }
1342  }
1343 
1344  if (!(brush->icon_imbuf)) {
1345  brush->id.icon_id = 0;
1346  }
1347 
1348  return brush->icon_imbuf;
1349 }
1350 
1351 static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
1352 {
1353  struct ImBuf *ima;
1354  uint *drect, *srect;
1355  float scaledx, scaledy;
1356  short ex, ey, dx, dy;
1357 
1358  /* paranoia test */
1359  if (ibuf == nullptr || (ibuf->rect == nullptr && ibuf->rect_float == nullptr)) {
1360  return;
1361  }
1362 
1363  /* Waste of cpu cycles... but the imbuf API has no other way to scale fast (ton). */
1364  ima = IMB_dupImBuf(ibuf);
1365 
1366  if (!ima) {
1367  return;
1368  }
1369 
1370  if (ima->x > ima->y) {
1371  scaledx = (float)w;
1372  scaledy = ((float)ima->y / (float)ima->x) * (float)w;
1373  }
1374  else {
1375  scaledx = ((float)ima->x / (float)ima->y) * (float)h;
1376  scaledy = (float)h;
1377  }
1378 
1379  /* Scaling down must never assign zero width/height, see: T89868. */
1380  ex = MAX2(1, (short)scaledx);
1381  ey = MAX2(1, (short)scaledy);
1382 
1383  dx = (w - ex) / 2;
1384  dy = (h - ey) / 2;
1385 
1386  IMB_scalefastImBuf(ima, ex, ey);
1387 
1388  /* if needed, convert to 32 bits */
1389  if (ima->rect == nullptr) {
1390  IMB_rect_from_float(ima);
1391  }
1392 
1393  srect = ima->rect;
1394  drect = rect;
1395 
1396  drect += dy * w + dx;
1397  for (; ey > 0; ey--) {
1398  memcpy(drect, srect, ex * sizeof(int));
1399  drect += w;
1400  srect += ima->x;
1401  }
1402 
1403  IMB_freeImBuf(ima);
1404 }
1405 
1406 static void set_alpha(char *cp, int sizex, int sizey, char alpha)
1407 {
1408  int a, size = sizex * sizey;
1409 
1410  for (a = 0; a < size; a++, cp += 4) {
1411  cp[3] = alpha;
1412  }
1413 }
1414 
1415 static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
1416 {
1417  ShaderPreview *sp = static_cast<ShaderPreview *>(customdata);
1418 
1419  if (sp->pr_method == PR_ICON_DEFERRED) {
1421  return;
1422  }
1423 
1424  ID *id = sp->id;
1425  short idtype = GS(id->name);
1426 
1427  BLI_assert(id != nullptr);
1428 
1429  if (idtype == ID_IM) {
1430  Image *ima = (Image *)id;
1431  ImBuf *ibuf = nullptr;
1432  ImageUser iuser;
1433  BKE_imageuser_default(&iuser);
1434 
1435  if (ima == nullptr) {
1436  return;
1437  }
1438 
1439  /* setup dummy image user */
1440  iuser.framenr = 1;
1441  iuser.scene = sp->scene;
1442 
1443  /* NOTE(@elubie): this needs to be changed: here image is always loaded if not
1444  * already there. Very expensive for large images. Need to find a way to
1445  * only get existing `ibuf`. */
1446  ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr);
1447  if (ibuf == nullptr || (ibuf->rect == nullptr && ibuf->rect_float == nullptr)) {
1448  BKE_image_release_ibuf(ima, ibuf, nullptr);
1449  return;
1450  }
1451 
1452  icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
1453 
1454  *do_update = true;
1455 
1456  BKE_image_release_ibuf(ima, ibuf, nullptr);
1457  }
1458  else if (idtype == ID_BR) {
1459  Brush *br = (Brush *)id;
1460 
1462 
1463  memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(uint));
1464 
1465  if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) {
1466  return;
1467  }
1468 
1469  icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
1470 
1471  *do_update = true;
1472  }
1473  else if (idtype == ID_SCR) {
1474  bScreen *screen = (bScreen *)id;
1475 
1476  ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
1477  *do_update = true;
1478  }
1479  else {
1480  /* re-use shader job */
1481  shader_preview_startjob(customdata, stop, do_update);
1482 
1483  /* world is rendered with alpha=0, so it wasn't displayed
1484  * this could be render option for sky to, for later */
1485  if (idtype == ID_WO) {
1486  set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
1487  }
1488  }
1489 }
1490 
1491 /* use same function for icon & shader, so the job manager
1492  * does not run two of them at the same time. */
1493 
1494 static void common_preview_startjob(void *customdata,
1495  short *stop,
1496  short *do_update,
1497  float *UNUSED(progress))
1498 {
1499  ShaderPreview *sp = static_cast<ShaderPreview *>(customdata);
1500 
1502  icon_preview_startjob(customdata, stop, do_update);
1503  }
1504  else {
1505  shader_preview_startjob(customdata, stop, do_update);
1506  }
1507 }
1508 
1514  IconPreviewSize *cur_size,
1515  const ePreviewRenderMethod pr_method,
1516  short *stop,
1517  short *do_update,
1518  float *progress)
1519 {
1520  ShaderPreview *sp = MEM_cnew<ShaderPreview>("Icon ShaderPreview");
1521 
1522  /* These types don't use the ShaderPreview mess, they have their own types and functions. */
1523  BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB));
1524 
1525  /* Construct shader preview from image size and preview custom-data. */
1526  sp->scene = ip->scene;
1527  sp->owner = ip->owner;
1528  sp->sizex = cur_size->sizex;
1529  sp->sizey = cur_size->sizey;
1530  sp->pr_method = pr_method;
1531  sp->pr_rect = cur_size->rect;
1532  sp->id = ip->id;
1533  sp->id_copy = ip->id_copy;
1534  sp->bmain = ip->bmain;
1535  sp->own_id_copy = false;
1536  Material *ma = nullptr;
1537 
1538  if (sp->pr_method == PR_ICON_RENDER) {
1539  BLI_assert(ip->id);
1540 
1541  /* grease pencil use its own preview file */
1542  if (GS(ip->id->name) == ID_MA) {
1543  ma = (Material *)ip->id;
1544  }
1545 
1546  if ((ma == nullptr) || (ma->gp_style == nullptr)) {
1547  sp->pr_main = G_pr_main;
1548  }
1549  else {
1551  }
1552  }
1553 
1554  common_preview_startjob(sp, stop, do_update, progress);
1555  shader_preview_free(sp);
1556 }
1557 
1558 /* exported functions */
1559 
1564  const PreviewImage *preview_image)
1565 {
1566  for (int i = 0; i < NUM_ICON_SIZES; i++) {
1567  if ((preview_image->w[i] == icon_size->sizex) && (preview_image->h[i] == icon_size->sizey)) {
1568  return i;
1569  }
1570  }
1571 
1572  BLI_assert_msg(0, "The searched icon size does not match any in the preview image");
1573  return -1;
1574 }
1575 
1576 static void icon_preview_startjob_all_sizes(void *customdata,
1577  short *stop,
1578  short *do_update,
1579  float *progress)
1580 {
1581  IconPreview *ip = (IconPreview *)customdata;
1582  IconPreviewSize *cur_size;
1583 
1584  for (cur_size = static_cast<IconPreviewSize *>(ip->sizes.first); cur_size;
1585  cur_size = cur_size->next) {
1586  PreviewImage *prv = static_cast<PreviewImage *>(ip->owner);
1587  /* Is this a render job or a deferred loading job? */
1588  const ePreviewRenderMethod pr_method = (prv->tag & PRV_TAG_DEFFERED) ? PR_ICON_DEFERRED :
1590 
1591  if (*stop) {
1592  break;
1593  }
1594 
1595  if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
1596  /* Non-thread-protected reading is not an issue here. */
1597  continue;
1598  }
1599 
1600  /* check_engine_supports_preview() checks whether the engine supports "preview mode" (think:
1601  * Material Preview). This check is only relevant when the render function called below is
1602  * going to use such a mode. Object and Action render functions use Solid mode, though, so
1603  * they can skip this test. */
1604  /* TODO: Decouple the ID-type-specific render functions from this function, so that it's not
1605  * necessary to know here what happens inside lower-level functions. */
1606  const bool use_solid_render_mode = (ip->id != nullptr) && ELEM(GS(ip->id->name), ID_OB, ID_AC);
1607  if (!use_solid_render_mode && preview_method_is_render(pr_method) &&
1609  continue;
1610  }
1611 
1612 #ifndef NDEBUG
1613  {
1614  int size_index = icon_previewimg_size_index_get(cur_size, prv);
1615  BLI_assert(!BKE_previewimg_is_finished(prv, size_index));
1616  }
1617 #endif
1618 
1619  if (ip->id != nullptr) {
1620  switch (GS(ip->id->name)) {
1621  case ID_OB:
1623  /* Much simpler than the ShaderPreview mess used for other ID types. */
1624  object_preview_render(ip, cur_size);
1625  continue;
1626  }
1627  break;
1628  case ID_GR:
1630  /* A collection instance empty was created, so this can just reuse the object preview
1631  * rendering. */
1632  object_preview_render(ip, cur_size);
1633  continue;
1634  case ID_AC:
1635  action_preview_render(ip, cur_size);
1636  continue;
1637  default:
1638  /* Fall through to the same code as the `ip->id == nullptr` case. */
1639  break;
1640  }
1641  }
1642  other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress);
1643  }
1644 }
1645 
1646 static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
1647 {
1648  IconPreviewSize *cur_size = static_cast<IconPreviewSize *>(ip->sizes.first);
1649 
1650  while (cur_size) {
1651  if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
1652  /* requested size is already in list, no need to add it again */
1653  return;
1654  }
1655 
1656  cur_size = cur_size->next;
1657  }
1658 
1659  IconPreviewSize *new_size = MEM_cnew<IconPreviewSize>("IconPreviewSize");
1660  new_size->sizex = sizex;
1661  new_size->sizey = sizey;
1662  new_size->rect = rect;
1663 
1664  BLI_addtail(&ip->sizes, new_size);
1665 }
1666 
1667 static void icon_preview_endjob(void *customdata)
1668 {
1669  IconPreview *ip = static_cast<IconPreview *>(customdata);
1670 
1671  if (ip->id) {
1672 
1673  if (GS(ip->id->name) == ID_BR) {
1675  }
1676 #if 0
1677  if (GS(ip->id->name) == ID_MA) {
1678  Material *ma = (Material *)ip->id;
1679  PreviewImage *prv_img = ma->preview;
1680  int i;
1681 
1682  /* signal to gpu texture */
1683  for (i = 0; i < NUM_ICON_SIZES; i++) {
1684  if (prv_img->gputexture[i]) {
1685  GPU_texture_free(prv_img->gputexture[i]);
1686  prv_img->gputexture[i] = nullptr;
1688  }
1689  }
1690  }
1691 #endif
1692  }
1693 
1694  if (ip->owner) {
1695  PreviewImage *prv_img = static_cast<PreviewImage *>(ip->owner);
1696  prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
1697 
1698  LISTBASE_FOREACH (IconPreviewSize *, icon_size, &ip->sizes) {
1699  int size_index = icon_previewimg_size_index_get(icon_size, prv_img);
1700  BKE_previewimg_finish(prv_img, size_index);
1701  }
1702 
1703  if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
1704  BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
1706  }
1707  }
1708 }
1709 
1720  struct RequestedPreview {
1723  eIconSizes icon_size;
1724  };
1725 
1727  ThreadQueue *todo_queue_; /* RequestedPreview * */
1730  std::list<struct RequestedPreview> requested_previews_;
1731 
1732  public:
1733  PreviewLoadJob();
1734  ~PreviewLoadJob();
1735 
1737  static void load_jobless(PreviewImage *preview, eIconSizes icon_size);
1738 
1740 
1741  private:
1742  static void run_fn(void *customdata, short *stop, short *do_update, float *progress);
1743  static void update_fn(void *customdata);
1744  static void end_fn(void *customdata);
1745  static void free_fn(void *customdata);
1746 
1748  static void finish_request(RequestedPreview &request);
1749 };
1750 
1752 {
1753 }
1754 
1756 {
1757  BLI_thread_queue_free(todo_queue_);
1758 }
1759 
1761 {
1762  wmJob *wm_job = WM_jobs_get(wm, win, nullptr, "Load Previews", 0, WM_JOB_TYPE_LOAD_PREVIEW);
1763 
1764  if (!WM_jobs_is_running(wm_job)) {
1765  PreviewLoadJob *job_data = MEM_new<PreviewLoadJob>("PreviewLoadJobData");
1766 
1767  WM_jobs_customdata_set(wm_job, job_data, free_fn);
1768  WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
1769  WM_jobs_callbacks(wm_job, run_fn, nullptr, update_fn, end_fn);
1770 
1771  WM_jobs_start(wm, wm_job);
1772  }
1773 
1774  return *reinterpret_cast<PreviewLoadJob *>(WM_jobs_customdata_get(wm_job));
1775 }
1776 
1778 {
1779  PreviewLoadJob job_data{};
1780 
1781  job_data.push_load_request(preview, icon_size);
1782 
1783  short stop = 0, do_update = 0;
1784  float progress = 0;
1785  run_fn(&job_data, &stop, &do_update, &progress);
1786  update_fn(&job_data);
1787  end_fn(&job_data);
1788 }
1789 
1791 {
1793  RequestedPreview requested_preview{};
1794  requested_preview.preview = preview;
1795  requested_preview.icon_size = icon_size;
1796 
1797  preview->flag[icon_size] |= PRV_RENDERING;
1798  /* Warn main thread code that this preview is being rendered and cannot be freed. */
1800 
1801  requested_previews_.push_back(requested_preview);
1802  BLI_thread_queue_push(todo_queue_, &requested_previews_.back());
1803 }
1804 
1805 void PreviewLoadJob::run_fn(void *customdata,
1806  short *stop,
1807  short *do_update,
1808  float *UNUSED(progress))
1809 {
1810  PreviewLoadJob *job_data = reinterpret_cast<PreviewLoadJob *>(customdata);
1811 
1813 
1814  while (RequestedPreview *request = reinterpret_cast<RequestedPreview *>(
1815  BLI_thread_queue_pop_timeout(job_data->todo_queue_, 100))) {
1816  if (*stop) {
1817  break;
1818  }
1819 
1820  PreviewImage *preview = request->preview;
1821 
1822  const char *deferred_data = static_cast<char *>(PRV_DEFERRED_DATA(preview));
1823  const ThumbSource source = static_cast<ThumbSource>(deferred_data[0]);
1824  const char *filepath = &deferred_data[1];
1825 
1826  // printf("loading deferred %d×%d preview for %s\n", request->sizex, request->sizey, filepath);
1827 
1828  IMB_thumb_path_lock(filepath);
1829  ImBuf *thumb = IMB_thumb_manage(filepath, THB_LARGE, source);
1830  IMB_thumb_path_unlock(filepath);
1831 
1832  if (thumb) {
1833  /* PreviewImage assumes premultiplied alpha... */
1834  IMB_premultiply_alpha(thumb);
1835 
1836  icon_copy_rect(thumb,
1837  preview->w[request->icon_size],
1838  preview->h[request->icon_size],
1839  preview->rect[request->icon_size]);
1840  IMB_freeImBuf(thumb);
1841  }
1842 
1843  *do_update = true;
1844  }
1845 
1847 }
1848 
1849 /* Only execute on the main thread! */
1850 void PreviewLoadJob::finish_request(RequestedPreview &request)
1851 {
1852  PreviewImage *preview = request.preview;
1853 
1855  BKE_previewimg_finish(preview, request.icon_size);
1856 
1858  "Deferred releasing of preview images should only run on the main thread");
1859  if (preview->tag & PRV_TAG_DEFFERED_DELETE) {
1862  }
1863 }
1864 
1865 void PreviewLoadJob::update_fn(void *customdata)
1866 {
1867  PreviewLoadJob *job_data = reinterpret_cast<PreviewLoadJob *>(customdata);
1868 
1869  for (auto request_it = job_data->requested_previews_.begin();
1870  request_it != job_data->requested_previews_.end();) {
1871  RequestedPreview &requested = *request_it;
1872  /* Skip items that are not done loading yet. */
1873  if (requested.preview->tag & PRV_TAG_DEFFERED_RENDERING) {
1874  ++request_it;
1875  continue;
1876  }
1877  finish_request(requested);
1878 
1879  /* Remove properly finished previews from the job data. */
1880  auto next_it = job_data->requested_previews_.erase(request_it);
1881  request_it = next_it;
1882  }
1883 }
1884 
1885 void PreviewLoadJob::end_fn(void *customdata)
1886 {
1887  PreviewLoadJob *job_data = reinterpret_cast<PreviewLoadJob *>(customdata);
1888 
1889  /* Finish any possibly remaining queued previews. */
1890  for (RequestedPreview &request : job_data->requested_previews_) {
1891  finish_request(request);
1892  }
1893  job_data->requested_previews_.clear();
1894 }
1895 
1896 void PreviewLoadJob::free_fn(void *customdata)
1897 {
1898  MEM_delete(reinterpret_cast<PreviewLoadJob *>(customdata));
1899 }
1900 
1901 static void icon_preview_free(void *customdata)
1902 {
1903  IconPreview *ip = (IconPreview *)customdata;
1904 
1905  if (ip->id_copy) {
1907  }
1908 
1909  BLI_freelistN(&ip->sizes);
1910  MEM_freeN(ip);
1911 }
1912 
1914 {
1915  if (id == nullptr) {
1916  return false;
1917  }
1918  if (GS(id->name) == ID_NT) {
1919  /* Node groups don't support standard preview generation. */
1920  return false;
1921  }
1922  if (GS(id->name) == ID_OB) {
1923  return object_preview_is_type_supported((const Object *)id);
1924  }
1925  if (GS(id->name) == ID_GR) {
1927  }
1928  return BKE_previewimg_id_get_p(id) != nullptr;
1929 }
1930 
1932  const bContext *C, Scene *scene, PreviewImage *prv_img, ID *id, eIconSizes icon_size)
1933 {
1934  /* Deferred loading of previews from the file system. */
1935  if (prv_img->tag & PRV_TAG_DEFFERED) {
1936  if (prv_img->flag[icon_size] & PRV_RENDERING) {
1937  /* Already in the queue, don't add it again. */
1938  return;
1939  }
1940 
1941  PreviewLoadJob::load_jobless(prv_img, icon_size);
1942  return;
1943  }
1944 
1945  IconPreview ip = {nullptr};
1946  short stop = false, update = false;
1947  float progress = 0.0f;
1948 
1950 
1951  ip.bmain = CTX_data_main(C);
1952  ip.scene = scene;
1955  ip.id = id;
1956  /* Control isn't given back to the caller until the preview is done. So we don't need to copy
1957  * the ID to avoid thread races. */
1958  ip.id_copy = duplicate_ids(id, true);
1960 
1961  prv_img->flag[icon_size] |= PRV_RENDERING;
1962 
1964  &ip, prv_img->rect[icon_size], prv_img->w[icon_size], prv_img->h[icon_size]);
1965 
1966  icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
1967 
1968  icon_preview_endjob(&ip);
1969 
1970  BLI_freelistN(&ip.sizes);
1971  if (ip.id_copy != nullptr) {
1973  }
1974 }
1975 
1977  const bContext *C, PreviewImage *prv_img, ID *id, eIconSizes icon_size, const bool delay)
1978 {
1979  /* Deferred loading of previews from the file system. */
1980  if (prv_img->tag & PRV_TAG_DEFFERED) {
1981  if (prv_img->flag[icon_size] & PRV_RENDERING) {
1982  /* Already in the queue, don't add it again. */
1983  return;
1984  }
1986  load_job.push_load_request(prv_img, icon_size);
1987 
1988  return;
1989  }
1990 
1991  IconPreview *ip, *old_ip;
1992 
1994 
1995  /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
1996  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
1997  CTX_wm_window(C),
1998  prv_img,
1999  "Icon Preview",
2002 
2003  ip = MEM_cnew<IconPreview>("icon preview");
2004 
2005  /* render all resolutions from suspended job too */
2006  old_ip = static_cast<IconPreview *>(WM_jobs_customdata_get(wm_job));
2007  if (old_ip) {
2008  BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
2009  }
2010 
2011  /* customdata for preview thread */
2012  ip->bmain = CTX_data_main(C);
2014  ip->scene = DEG_get_input_scene(ip->depsgraph);
2016  ip->owner = prv_img;
2017  ip->id = id;
2018  ip->id_copy = duplicate_ids(id, false);
2019 
2020  prv_img->flag[icon_size] |= PRV_RENDERING;
2021 
2023  ip, prv_img->rect[icon_size], prv_img->w[icon_size], prv_img->h[icon_size]);
2024 
2025  /* setup job */
2027  WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
2028  /* Wait 2s to start rendering icon previews, to not bog down user interaction.
2029  * Particularly important for heavy scenes and Eevee using OpenGL that blocks
2030  * the user interface drawing. */
2031  WM_jobs_delay_start(wm_job, (delay) ? 2.0 : 0.0);
2033  wm_job, icon_preview_startjob_all_sizes, nullptr, nullptr, icon_preview_endjob);
2034 
2035  WM_jobs_start(CTX_wm_manager(C), wm_job);
2036 }
2037 
2039  void *owner,
2040  ID *id,
2041  ID *parent,
2042  MTex *slot,
2043  int sizex,
2044  int sizey,
2045  ePreviewRenderMethod method)
2046 {
2048  wmJob *wm_job;
2049  ShaderPreview *sp;
2051  const ID_Type id_type = GS(id->name);
2052 
2054 
2055  /* Use workspace render only for buttons Window,
2056  * since the other previews are related to the datablock. */
2057 
2059  return;
2060  }
2061 
2063 
2064  wm_job = WM_jobs_get(CTX_wm_manager(C),
2065  CTX_wm_window(C),
2066  owner,
2067  "Shader Preview",
2070  sp = MEM_cnew<ShaderPreview>("shader preview");
2071 
2072  /* customdata for preview thread */
2073  sp->scene = scene;
2074  sp->owner = owner;
2075  sp->sizex = sizex;
2076  sp->sizey = sizey;
2077  sp->pr_method = method;
2078  sp->id = id;
2079  sp->id_copy = duplicate_ids(id, false);
2080  sp->own_id_copy = true;
2081  sp->parent = parent;
2082  sp->slot = slot;
2083  sp->bmain = CTX_data_main(C);
2084  Material *ma = nullptr;
2085 
2086  /* hardcoded preview .blend for Eevee + Cycles, this should be solved
2087  * once with custom preview .blend path for external engines */
2088 
2089  /* grease pencil use its own preview file */
2090  if (id_type == ID_MA) {
2091  ma = (Material *)id;
2092  }
2093 
2094  if ((ma == nullptr) || (ma->gp_style == nullptr)) {
2095  sp->pr_main = G_pr_main;
2096  }
2097  else {
2099  }
2100 
2101  if (ob && ob->totcol) {
2102  copy_v4_v4(sp->color, ob->color);
2103  }
2104  else {
2105  ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
2106  }
2107 
2108  /* setup job */
2110  WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
2112 
2113  WM_jobs_start(CTX_wm_manager(C), wm_job);
2114 }
2115 
2117 {
2118  if (wm) {
2119  /* This is called to stop all preview jobs before scene data changes, to
2120  * avoid invalid memory access. */
2121  WM_jobs_kill(wm, nullptr, common_preview_startjob);
2123  }
2124 }
2125 
2128 
2129  enum eIconSizes size;
2130  ID *id;
2131 };
2132 
2133 static ListBase /* #PreviewRestartQueueEntry */ G_restart_previews_queue;
2134 
2136 {
2138 }
2139 
2141 {
2142  PreviewRestartQueueEntry *queue_entry = MEM_new<PreviewRestartQueueEntry>(__func__);
2143  queue_entry->size = size;
2144  queue_entry->id = id;
2145  BLI_addtail(&G_restart_previews_queue, queue_entry);
2146 }
2147 
2149 {
2151  PreviewImage *preview = BKE_previewimg_id_get(queue_entry->id);
2152  if (!preview) {
2153  continue;
2154  }
2155  if (preview->flag[queue_entry->size] & PRV_USER_EDITED) {
2156  /* Don't touch custom previews. */
2157  continue;
2158  }
2159 
2160  BKE_previewimg_clear_single(preview, queue_entry->size);
2161  UI_icon_render_id(C, nullptr, queue_entry->id, queue_entry->size, true);
2162 
2163  BLI_freelinkN(&G_restart_previews_queue, queue_entry);
2164  }
2165 }
2166 
typedef float(TangentPoint)[2]
void immDrawPixelsTexTiled(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:333
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
Definition: glutil.c:44
const char * BKE_appdir_folder_id(int folder_id, const char *subfolder)
Definition: appdir.c:672
@ BLENDER_DATAFILES
Definition: BKE_appdir.h:154
void BKE_pose_apply_action_all_bones(struct Object *ob, struct bAction *action, struct AnimationEvalContext *anim_eval_context)
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
Definition: collection.c:1125
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:1856
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:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct SpaceProperties * CTX_wm_space_properties(const bContext *C)
Definition: context.c:833
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
@ G_FILE_NO_UI
Definition: BKE_global.h:213
struct PreviewImage * BKE_previewimg_id_ensure(struct ID *id)
Definition: icons.cc:385
bool BKE_previewimg_id_supports_jobs(const struct ID *id)
void BKE_icon_changed(int icon_id)
Definition: icons.cc:637
struct PreviewImage ** BKE_previewimg_id_get_p(const struct ID *id)
void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size)
Definition: icons.cc:291
struct PreviewImage * BKE_previewimg_id_get(const struct ID *id)
void BKE_previewimg_deferred_release(struct PreviewImage *prv)
Definition: icons.cc:425
void BKE_previewimg_finish(struct PreviewImage *prv, int size)
Definition: icons.cc:584
bool BKE_previewimg_is_finished(const struct PreviewImage *prv, int size)
int BKE_icon_id_ensure(struct ID *id)
Definition: icons.cc:699
struct IDProperty * IDP_GetProperties(struct ID *id, bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:778
void IDP_FreePropertyContent_ex(struct IDProperty *prop, bool do_id_user)
Definition: idprop.c:1055
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
struct ImagePool * BKE_image_pool_new(void)
void BKE_imageuser_default(struct ImageUser *iuser)
void BKE_image_pool_free(struct ImagePool *pool)
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
void BKE_layer_collection_sync(const struct Scene *scene, struct ViewLayer *view_layer)
@ LIB_ID_CREATE_LOCAL
Definition: BKE_lib_id.h:139
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
@ LIB_ID_COPY_NO_ANIMDATA
Definition: BKE_lib_id.h:154
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void BKE_libblock_free_datablock(struct ID *id, int flag) ATTR_NONNULL()
General operations, lookup, etc. for blender lights.
struct Main * BKE_main_new(void)
Definition: main.c:32
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_main_free(struct Main *mainvar)
Definition: main.c:40
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:562
General operations, lookup, etc. for materials.
struct Material *** BKE_object_material_array_p(struct Object *ob)
Definition: material.c:311
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
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
Definition: object.cc:2241
void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.cc:2648
struct Scene * BKE_scene_add(struct Main *bmain, const char *name)
Definition: scene.cc:2044
void BKE_screen_view3d_shading_init(struct View3DShading *shading)
Definition: screen.c:1007
void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool)
Definition: texture.c:743
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_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
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:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int max_ii(int a, int b)
#define M_PI
Definition: BLI_math_base.h:20
void mul_m3_m3_post(float R[3][3], const float B[3][3])
Definition: math_matrix.c:409
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:2224
void eul_to_mat3(float mat[3][3], const float eul[3])
void mat3_to_quat(float q[4], const float mat[3][3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w)
#define FILE_MAX
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
Definition: path_util.c:1206
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
void BLI_thread_queue_push(ThreadQueue *queue, void *work)
Definition: threads.cc:641
void * BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
Definition: threads.cc:711
void BLI_thread_queue_free(ThreadQueue *queue)
Definition: threads.cc:629
int BLI_thread_is_main(void)
Definition: threads.cc:207
ThreadQueue * BLI_thread_queue_init(void)
Definition: threads.cc:615
#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:121
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:267
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ DAG_EVAL_VIEWPORT
Definition: DEG_depsgraph.h:45
void DEG_graph_free(Depsgraph *graph)
Definition: depsgraph.cc:295
void DEG_id_tag_update(struct ID *id, int flag)
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)
@ PRV_TAG_DEFFERED_DELETE
Definition: DNA_ID.h:526
@ PRV_TAG_DEFFERED
Definition: DNA_ID.h:524
@ PRV_TAG_DEFFERED_RENDERING
Definition: DNA_ID.h:525
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition: DNA_ID.h:561
#define PRV_DEFERRED_DATA(prv)
Definition: DNA_ID.h:547
@ PRV_RENDERING
Definition: DNA_ID.h:519
@ PRV_USER_EDITED
Definition: DNA_ID.h:518
eIconSizes
Definition: DNA_ID_enums.h:14
@ NUM_ICON_SIZES
Definition: DNA_ID_enums.h:18
ID_Type
Definition: DNA_ID_enums.h:44
@ ID_TE
Definition: DNA_ID_enums.h:52
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_LA
Definition: DNA_ID_enums.h:55
@ ID_BR
Definition: DNA_ID_enums.h:69
@ ID_WO
Definition: DNA_ID_enums.h:59
@ ID_MA
Definition: DNA_ID_enums.h:51
@ ID_AC
Definition: DNA_ID_enums.h:67
@ ID_SCR
Definition: DNA_ID_enums.h:60
@ ID_GR
Definition: DNA_ID_enums.h:65
@ ID_OB
Definition: DNA_ID_enums.h:47
@ ROT_MODE_QUAT
@ BRUSH_CUSTOM_ICON
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_RENDER
@ BASE_VISIBLE_DEPSGRAPH
@ BASE_SELECTED
ePreviewType
@ MA_SPHERE_A
@ MA_FLUID
@ MA_CLOTH
@ MA_SHADERBALL
@ MA_FLAT
@ MA_LAMP
@ MA_SKY
@ MA_CUBE
@ MA_ATMOS
@ MA_SPHERE
@ MA_HAIR
#define MA_PREVIEW_WORLD
@ OB_TEXTURE
@ OB_SOLID
Object is a sort of wrapper for general info.
@ OB_HIDE_RENDER
#define OB_TYPE_IS_GEOMETRY(_type)
@ OB_EMPTY
@ OB_CAMERA
@ OB_LAMP
@ OB_MESH
#define OB_TYPE_SUPPORT_MATERIAL(_type)
@ OB_DUPLICOLLECTION
#define R_NO_IMAGE_LOAD
#define R_TEXNODE_PREVIEW
#define R_BUTS_PREVIEW
@ R_ADDSKY
@ R_ALPHAPREMUL
#define R_MATNODE_PREVIEW
@ SCE_DISPLAY_AA_OFF
@ SCE_DISPLAY_AA_SAMPLES_8
@ SCE_PASS_COMBINED
@ V3D_OFSDRAW_NONE
@ V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS
@ V3D_SHADING_SHADOW
const char datatoc_preview_grease_pencil_blend[]
int datatoc_preview_grease_pencil_blend_size
const char datatoc_preview_blend[]
int datatoc_preview_blend_size
ePreviewRenderMethod
Definition: ED_render.h:67
@ PR_ICON_RENDER
Definition: ED_render.h:69
@ PR_ICON_DEFERRED
Definition: ED_render.h:70
@ PR_BUTS_RENDER
Definition: ED_render.h:68
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_with_set_clipping(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:1980
_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
_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 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
@ GPU_SHADER_2D_IMAGE_COLOR
Definition: GPU_shader.h:217
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:564
@ GPU_RGBA8
Definition: GPU_texture.h:87
struct ImBuf * IMB_dupImBuf(const struct ImBuf *ibuf1)
void IMB_rect_from_float(struct ImBuf *ibuf)
Definition: divers.c:696
struct ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
Definition: readimage.c:209
void IMB_premultiply_alpha(struct ImBuf *ibuf)
Definition: filter.c:662
bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
Definition: scaling.c:1689
Contains defines and structs used throughout the imbuf module.
@ IB_metadata
@ IB_multilayer
@ IB_rect
@ THB_LARGE
Definition: IMB_thumbs.h:24
void IMB_thumb_locks_release(void)
Definition: thumbs.c:655
ThumbSource
Definition: IMB_thumbs.h:28
void IMB_thumb_path_unlock(const char *path)
Definition: thumbs.c:686
struct ImBuf * IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source)
Definition: thumbs.c:516
void IMB_thumb_path_lock(const char *path)
Definition: thumbs.c:670
void IMB_thumb_locks_acquire(void)
Definition: thumbs.c:639
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
Platform independent time functions.
#define RE_USE_PREVIEW
Definition: RE_engine.h:45
#define C
Definition: RandGen.cpp:25
void UI_icon_render_id(const struct bContext *C, struct Scene *scene, struct ID *id, enum eIconSizes size, bool use_job)
@ WM_JOB_EXCL_RENDER
Definition: WM_api.h:1338
@ WM_JOB_TYPE_RENDER_PREVIEW
Definition: WM_api.h:1350
@ WM_JOB_TYPE_LOAD_PREVIEW
Definition: WM_api.h:1352
#define NC_WINDOW
Definition: WM_types.h:325
#define NC_BRUSH
Definition: WM_types.h:335
#define NA_EDITED
Definition: WM_types.h:523
#define NC_MATERIAL
Definition: WM_types.h:330
#define ND_SHADING_DRAW
Definition: WM_types.h:426
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static void load_jobless(PreviewImage *preview, eIconSizes icon_size)
void push_load_request(PreviewImage *preview, eIconSizes icon_size)
static PreviewLoadJob & ensure_job(wmWindowManager *wm, wmWindow *win)
Scene scene
World world
const Depsgraph * depsgraph
SyclQueue void void * src
RenderEngineType * RE_engines_find(const char *idname)
Definition: engine.c:98
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
uint tex_coord
Definition: gpu_viewport.c:47
#define GS(x)
Definition: iris.c:225
const int state
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define G(x, y, z)
static unsigned a[3]
Definition: RandGen.cpp:78
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:92
T abs(const T &a)
static const pxr::TfToken preview("preview", pxr::TfToken::Immortal)
static void update(bNodeTree *ntree)
void RE_ReleaseResultImageViews(Render *re, RenderResult *rr)
Definition: pipeline.c:418
Render * RE_GetRender(const char *name)
Definition: pipeline.c:300
void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
Definition: pipeline.c:2421
Render * RE_NewRender(const char *name)
Definition: pipeline.c:516
void RE_InitState(Render *re, Render *source, RenderData *rd, ListBase *render_layers, ViewLayer *single_layer, int winx, int winy, rcti *disprect)
Definition: pipeline.c:728
void RE_ReleaseResult(Render *re)
Definition: pipeline.c:351
RenderResult * RE_AcquireResultWrite(Render *re)
Definition: pipeline.c:324
void RE_display_update_cb(Render *re, void *handle, void(*f)(void *handle, RenderResult *rr, rcti *rect))
Definition: pipeline.c:862
void RE_test_break_cb(Render *re, void *handle, int(*f)(void *handle))
Definition: pipeline.c:891
void RE_AcquiredResultGet32(Render *re, RenderResult *result, unsigned int *rect, const int view_id)
Definition: pipeline.c:497
void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
Definition: pipeline.c:373
void RE_SetScene(Render *re, Scene *sce)
Definition: pipeline.c:366
void RE_ResultGet32(Render *re, unsigned int *rect)
Definition: pipeline.c:481
void ED_pose_backup_free(PoseBackup *pbd)
Definition: pose_backup.cc:120
PoseBackup * ED_pose_backup_create_all_bones(const Object *ob, const bAction *action)
Definition: pose_backup.cc:89
void ED_pose_backup_restore(const PoseBackup *pbd)
Definition: pose_backup.cc:106
static bool preview_method_is_render(const ePreviewRenderMethod pr_method)
static Scene * preview_get_scene(Main *pr_main)
bool ED_preview_id_is_supported(const ID *id)
static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey)
static void other_id_types_preview_render(IconPreview *ip, IconPreviewSize *cur_size, const ePreviewRenderMethod pr_method, short *stop, short *do_update, float *progress)
static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Render *re)
static void icon_preview_endjob(void *customdata)
static bool render_engine_supports_ray_visibility(const Scene *sce)
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 World * preview_get_world(Main *pr_main, const Scene *sce, const ID_Type id_type, const ePreviewRenderMethod pr_method)
static Main * G_pr_main
void ED_preview_free_dbase()
static ListBase G_restart_previews_queue
static void shader_preview_free(void *customdata)
static Main * load_main_from_memory(const void *blend, int blend_size)
static void preview_sync_exposure(World *dst, const World *src)
static Object * object_preview_camera_create(Main *preview_main, ViewLayer *view_layer, Object *preview_object)
static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
static Scene * object_preview_scene_create(const struct ObjectPreviewData *preview_data, Depsgraph **r_depsgraph)
void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
static void icon_preview_free(void *customdata)
void ED_preview_icon_render(const bContext *C, Scene *scene, PreviewImage *prv_img, ID *id, eIconSizes icon_size)
static const char * preview_collection_name(const ePreviewType pr_type)
static void set_preview_visibility(Main *pr_main, Scene *scene, ViewLayer *view_layer, const ePreviewType pr_type, const ePreviewRenderMethod pr_method)
static World * preview_get_localized_world(ShaderPreview *sp, World *world)
void ED_preview_restart_queue_work(const bContext *C)
static const char * preview_floor_material_name(const Scene *scene, const ePreviewRenderMethod pr_method)
static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
static void switch_preview_floor_material(Main *pr_main, Mesh *me, const Scene *scene, const ePreviewRenderMethod pr_method)
static World * preview_prepare_world(Main *pr_main, const Scene *sce, const World *world, const ID_Type id_type, const ePreviewRenderMethod pr_method)
void ED_preview_restart_queue_add(ID *id, enum eIconSizes size)
static bool collection_preview_contains_geometry_recursive(const Collection *collection)
static Scene * preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
static struct PoseBackup * action_preview_render_prepare(IconPreview *preview)
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 switch_preview_floor_visibility(Main *pr_main, const Scene *scene, ViewLayer *view_layer, const ePreviewRenderMethod pr_method)
static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
void ED_preview_ensure_dbase()
static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
static const char * preview_world_name(const Scene *sce, const ID_Type id_type, const ePreviewRenderMethod pr_method)
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 void switch_preview_collection_visibility(ViewLayer *view_layer, const ePreviewType pr_type)
static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, ePreviewRenderMethod method)
static ImBuf * icon_preview_imbuf_from_brush(Brush *brush)
static int shader_preview_break(void *spv)
static void action_preview_render_cleanup(IconPreview *preview, struct PoseBackup *pose_backup)
static bool object_preview_is_type_supported(const Object *ob)
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
static ID * duplicate_ids(ID *id, const bool allow_failure)
void ED_preview_icon_job(const bContext *C, PreviewImage *prv_img, ID *id, eIconSizes icon_size, const bool delay)
void ED_preview_restart_queue_free()
static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), struct rcti *UNUSED(rect))
static void shader_preview_updatejob(void *UNUSED(spv))
RenderView * RE_RenderViewGetById(RenderResult *rr, const int view_id)
const char * RE_engine_id_BLENDER_EEVEE
Definition: scene.cc:1695
short flag
struct Main * main
Definition: BLO_readfile.h:56
struct ImBuf * icon_imbuf
char icon_filepath[1024]
Definition: DNA_ID.h:368
int icon_id
Definition: DNA_ID.h:389
char name[66]
Definition: DNA_ID.h:378
struct IconPreviewSize * next
struct IconPreviewSize * prev
ListBase sizes
Depsgraph * depsgraph
struct Object * active_object
unsigned int * rect
float * rect_float
struct Scene * scene
struct LayerCollection * next
ListBase layer_collections
struct Collection * collection
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase scenes
Definition: BKE_main.h:168
ListBase textures
Definition: BKE_main.h:175
char filepath[1024]
Definition: BKE_main.h:124
ListBase lights
Definition: BKE_main.h:178
ListBase materials
Definition: BKE_main.h:174
ListBase worlds
Definition: BKE_main.h:182
ListBase objects
Definition: BKE_main.h:170
struct PreviewImage * preview
struct MaterialGPencilStyle * gp_style
struct Material ** mat
short totcol
ustring name
Definition: graph/node.h:174
short transflag
struct Collection * instance_collection
struct bPose * pose
struct Material ** mat
float obmat[4][4]
float color[4]
struct Object * parent
void * data
unsigned int h[2]
Definition: DNA_ID.h:532
short tag
Definition: DNA_ID.h:543
short flag[2]
Definition: DNA_ID.h:533
unsigned int * rect[2]
Definition: DNA_ID.h:535
unsigned int w[2]
Definition: DNA_ID.h:531
struct PreviewRestartQueueEntry * next
struct PreviewRestartQueueEntry * prev
char engine[32]
ListBase views
Definition: RE_pipeline.h:125
float * rectf
Definition: RE_pipeline.h:54
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
ePreviewRenderMethod pr_method
Material * matcopy
int talpha
Definition: RE_texture.h:89
float trgba[4]
Definition: RE_texture.h:87
char use_nodes
struct bNodeTree * nodetree
struct ViewLayerEEVEE eevee
ListBase layer_collections
ListBase object_bases
float horg
float range
short use_nodes
float exp
float horb
float horr
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
Definition: wm_jobs.c:57
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_report(eReportType type, const char *message)
void WM_reportf(eReportType type, const char *format,...)
bool WM_jobs_is_running(const wmJob *wm_job)
Definition: wm_jobs.c:304
void WM_jobs_kill(wmWindowManager *wm, void *owner, void(*startjob)(void *, short int *, short int *, float *))
Definition: wm_jobs.c:594
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:437
void * WM_jobs_customdata_from_type(wmWindowManager *wm, const void *owner, int job_type)
Definition: wm_jobs.c:293
void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
Definition: wm_jobs.c:346
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:351
void * WM_jobs_customdata_get(wmJob *wm_job)
Definition: wm_jobs.c:315
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition: wm_jobs.c:214
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:323
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:339
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:184