Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/render/render_preview.c')
-rw-r--r--source/blender/editors/render/render_preview.c2221
1 files changed, 1134 insertions, 1087 deletions
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 77b24a1b4d9..c62d6530c6b 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -21,7 +21,6 @@
* \ingroup edrend
*/
-
/* global includes */
#include <stdlib.h>
@@ -29,9 +28,9 @@
#include <string.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
+# include <io.h>
#endif
#include "MEM_guardedalloc.h"
@@ -102,89 +101,90 @@
ImBuf *get_brush_icon(Brush *brush)
{
- static const int flags = IB_rect | IB_multilayer | IB_metadata;
+ static const int flags = IB_rect | IB_multilayer | IB_metadata;
- char path[FILE_MAX];
- const char *folder;
+ char path[FILE_MAX];
+ const char *folder;
- if (!(brush->icon_imbuf)) {
- if (brush->flag & BRUSH_CUSTOM_ICON) {
+ if (!(brush->icon_imbuf)) {
+ if (brush->flag & BRUSH_CUSTOM_ICON) {
- if (brush->icon_filepath[0]) {
- // first use the path directly to try and load the file
+ if (brush->icon_filepath[0]) {
+ // first use the path directly to try and load the file
- BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
- BLI_path_abs(path, BKE_main_blendfile_path_from_global());
+ BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
+ BLI_path_abs(path, BKE_main_blendfile_path_from_global());
- /* use default colorspaces for brushes */
- brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
+ /* use default colorspaces for brushes */
+ brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
- // otherwise lets try to find it in other directories
- if (!(brush->icon_imbuf)) {
- folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
+ // otherwise lets try to find it in other directories
+ if (!(brush->icon_imbuf)) {
+ folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons");
- BLI_make_file_string(BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath);
+ BLI_make_file_string(
+ BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath);
- if (path[0]) {
- /* use fefault color spaces */
- brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
- }
- }
+ if (path[0]) {
+ /* use fefault color spaces */
+ brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
+ }
+ }
- if (brush->icon_imbuf)
- BKE_icon_changed(BKE_icon_id_ensure(&brush->id));
- }
- }
- }
+ if (brush->icon_imbuf)
+ BKE_icon_changed(BKE_icon_id_ensure(&brush->id));
+ }
+ }
+ }
- if (!(brush->icon_imbuf))
- brush->id.icon_id = 0;
+ if (!(brush->icon_imbuf))
+ brush->id.icon_id = 0;
- return brush->icon_imbuf;
+ return brush->icon_imbuf;
}
typedef struct ShaderPreview {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
-
- Scene *scene;
- Depsgraph *depsgraph;
- ID *id, *id_copy;
- ID *parent;
- MTex *slot;
-
- /* datablocks with nodes need full copy during preview render, glsl uses it too */
- Material *matcopy;
- Tex *texcopy;
- Light *lampcopy;
- World *worldcopy;
-
- /** Copy of the active objects #Object.color */
- float color[4];
-
- int sizex, sizey;
- unsigned int *pr_rect;
- int pr_method;
- bool own_id_copy;
-
- Main *bmain;
- Main *pr_main;
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+
+ Scene *scene;
+ Depsgraph *depsgraph;
+ ID *id, *id_copy;
+ ID *parent;
+ MTex *slot;
+
+ /* datablocks with nodes need full copy during preview render, glsl uses it too */
+ Material *matcopy;
+ Tex *texcopy;
+ Light *lampcopy;
+ World *worldcopy;
+
+ /** Copy of the active objects #Object.color */
+ float color[4];
+
+ int sizex, sizey;
+ unsigned int *pr_rect;
+ int pr_method;
+ bool own_id_copy;
+
+ Main *bmain;
+ Main *pr_main;
} ShaderPreview;
typedef struct IconPreviewSize {
- struct IconPreviewSize *next, *prev;
- int sizex, sizey;
- unsigned int *rect;
+ struct IconPreviewSize *next, *prev;
+ int sizex, sizey;
+ unsigned int *rect;
} IconPreviewSize;
typedef struct IconPreview {
- Main *bmain;
- Scene *scene;
- Depsgraph *depsgraph;
- void *owner;
- ID *id, *id_copy;
- ListBase sizes;
+ Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+ void *owner;
+ ID *id, *id_copy;
+ ListBase sizes;
} IconPreview;
/* *************************** Preview for buttons *********************** */
@@ -195,1195 +195,1242 @@ static Main *G_pr_main_grease_pencil = NULL;
#ifndef WITH_HEADLESS
static Main *load_main_from_memory(const void *blend, int blend_size)
{
- const int fileflags = G.fileflags;
- Main *bmain = NULL;
- BlendFileData *bfd;
+ const int fileflags = G.fileflags;
+ Main *bmain = NULL;
+ BlendFileData *bfd;
- G.fileflags |= G_FILE_NO_UI;
- bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL);
- if (bfd) {
- bmain = bfd->main;
+ G.fileflags |= G_FILE_NO_UI;
+ bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL);
+ if (bfd) {
+ bmain = bfd->main;
- MEM_freeN(bfd);
- }
- G.fileflags = fileflags;
+ MEM_freeN(bfd);
+ }
+ G.fileflags = fileflags;
- return bmain;
+ return bmain;
}
#endif
void ED_preview_ensure_dbase(void)
{
#ifndef WITH_HEADLESS
- static bool base_initialized = false;
- BLI_assert(BLI_thread_is_main());
- if (!base_initialized) {
- G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
- G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend, datatoc_preview_grease_pencil_blend_size);
- base_initialized = true;
- }
+ static bool base_initialized = false;
+ BLI_assert(BLI_thread_is_main());
+ if (!base_initialized) {
+ G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size);
+ G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend,
+ datatoc_preview_grease_pencil_blend_size);
+ base_initialized = true;
+ }
#endif
}
static bool check_engine_supports_preview(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type->flag & RE_USE_PREVIEW) != 0;
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type->flag & RE_USE_PREVIEW) != 0;
}
void ED_preview_free_dbase(void)
{
- if (G_pr_main)
- BKE_main_free(G_pr_main);
+ if (G_pr_main)
+ BKE_main_free(G_pr_main);
- if (G_pr_main_grease_pencil)
- BKE_main_free(G_pr_main_grease_pencil);
+ if (G_pr_main_grease_pencil)
+ BKE_main_free(G_pr_main_grease_pencil);
}
static Scene *preview_get_scene(Main *pr_main)
{
- if (pr_main == NULL) return NULL;
+ if (pr_main == NULL)
+ return NULL;
- return pr_main->scenes.first;
+ return pr_main->scenes.first;
}
static const char *preview_collection_name(const char pr_type)
{
- switch (pr_type) {
- case MA_FLAT:
- return "Flat";
- case MA_SPHERE:
- return "Sphere";
- case MA_CUBE:
- return "Cube";
- case MA_SHADERBALL:
- return "Shader Ball";
- case MA_CLOTH:
- return "Cloth";
- case MA_FLUID:
- return "Fluid";
- case MA_SPHERE_A:
- return "World Shader Ball";
- case MA_LAMP:
- return "Lamp";
- case MA_SKY:
- return "Sky";
- case MA_HAIR:
- return "Hair";
- case MA_ATMOS:
- return "Atmosphere";
- default:
- BLI_assert(!"Unknown preview type");
- return "";
- }
+ switch (pr_type) {
+ case MA_FLAT:
+ return "Flat";
+ case MA_SPHERE:
+ return "Sphere";
+ case MA_CUBE:
+ return "Cube";
+ case MA_SHADERBALL:
+ return "Shader Ball";
+ case MA_CLOTH:
+ return "Cloth";
+ case MA_FLUID:
+ return "Fluid";
+ case MA_SPHERE_A:
+ return "World Shader Ball";
+ case MA_LAMP:
+ return "Lamp";
+ case MA_SKY:
+ return "Sky";
+ case MA_HAIR:
+ return "Hair";
+ case MA_ATMOS:
+ return "Atmosphere";
+ default:
+ BLI_assert(!"Unknown preview type");
+ return "";
+ }
}
-static void set_preview_visibility(Scene *scene, ViewLayer *view_layer, char pr_type, int pr_method)
+static void set_preview_visibility(Scene *scene,
+ ViewLayer *view_layer,
+ char pr_type,
+ int pr_method)
{
- /* Set appropriate layer as visibile. */
- LayerCollection *lc = view_layer->layer_collections.first;
- const char *collection_name = preview_collection_name(pr_type);
-
- for (lc = lc->layer_collections.first; lc; lc = lc->next) {
- if (STREQ(lc->collection->id.name + 2, collection_name)) {
- lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
- }
- else {
- lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
- }
- }
-
- /* Hide floor for icon renders. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (STREQ(base->object->id.name + 2, "Floor")) {
- if (pr_method == PR_ICON_RENDER) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
- else {
- base->object->restrictflag &= ~OB_RESTRICT_RENDER;
- }
- }
- }
-
- BKE_layer_collection_sync(scene, view_layer);
+ /* Set appropriate layer as visibile. */
+ LayerCollection *lc = view_layer->layer_collections.first;
+ const char *collection_name = preview_collection_name(pr_type);
+
+ for (lc = lc->layer_collections.first; lc; lc = lc->next) {
+ if (STREQ(lc->collection->id.name + 2, collection_name)) {
+ lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
+ }
+ else {
+ lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
+ }
+ }
+
+ /* Hide floor for icon renders. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (STREQ(base->object->id.name + 2, "Floor")) {
+ if (pr_method == PR_ICON_RENDER) {
+ base->object->restrictflag |= OB_RESTRICT_RENDER;
+ }
+ else {
+ base->object->restrictflag &= ~OB_RESTRICT_RENDER;
+ }
+ }
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
}
static World *preview_get_localized_world(ShaderPreview *sp, World *world)
{
- if (world == NULL) {
- return NULL;
- }
- if (sp->worldcopy != NULL) {
- return sp->worldcopy;
- }
- sp->worldcopy = BKE_world_localize(world);
- BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
- return sp->worldcopy;
+ if (world == NULL) {
+ return NULL;
+ }
+ if (sp->worldcopy != NULL) {
+ return sp->worldcopy;
+ }
+ sp->worldcopy = BKE_world_localize(world);
+ BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
+ return sp->worldcopy;
}
static ID *duplicate_ids(ID *id, Depsgraph *depsgraph)
{
- if (id == NULL) {
- /* Non-ID preview render. */
- return NULL;
- }
-
- ID *id_eval = id;
-
- if (depsgraph) {
- id_eval = DEG_get_evaluated_id(depsgraph, id);
- }
-
- switch (GS(id->name)) {
- case ID_MA:
- return (ID *)BKE_material_localize((Material *)id_eval);
- case ID_TE:
- return (ID *)BKE_texture_localize((Tex *)id_eval);
- case ID_LA:
- return (ID *)BKE_light_localize((Light *)id_eval);
- case ID_WO:
- return (ID *)BKE_world_localize((World *)id_eval);
- case ID_IM:
- case ID_BR:
- case ID_SCR:
- return NULL;
- default:
- BLI_assert(!"ID type preview not supported.");
- return NULL;
- }
+ if (id == NULL) {
+ /* Non-ID preview render. */
+ return NULL;
+ }
+
+ ID *id_eval = id;
+
+ if (depsgraph) {
+ id_eval = DEG_get_evaluated_id(depsgraph, id);
+ }
+
+ switch (GS(id->name)) {
+ case ID_MA:
+ return (ID *)BKE_material_localize((Material *)id_eval);
+ case ID_TE:
+ return (ID *)BKE_texture_localize((Tex *)id_eval);
+ case ID_LA:
+ return (ID *)BKE_light_localize((Light *)id_eval);
+ case ID_WO:
+ return (ID *)BKE_world_localize((World *)id_eval);
+ case ID_IM:
+ case ID_BR:
+ case ID_SCR:
+ return NULL;
+ default:
+ BLI_assert(!"ID type preview not supported.");
+ return NULL;
+ }
}
/* call this with a pointer to initialize preview scene */
/* call this with NULL to restore assigned ID pointers in preview scene */
-static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
+static Scene *preview_prepare_scene(
+ Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
- Scene *sce;
- Main *pr_main = sp->pr_main;
-
- memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));
-
- sce = preview_get_scene(pr_main);
- if (sce) {
- ViewLayer *view_layer = sce->view_layers.first;
-
- /* this flag tells render to not execute depsgraph or ipos etc */
- sce->r.scemode |= R_BUTS_PREVIEW;
- /* set world always back, is used now */
- sce->world = pr_main->worlds.first;
- /* now: exposure copy */
- if (scene->world) {
- sce->world->exp = scene->world->exp;
- sce->world->range = scene->world->range;
- }
-
- sce->r.color_mgt_flag = scene->r.color_mgt_flag;
- BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
-
- BKE_color_managed_view_settings_free(&sce->view_settings);
- BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
-
- /* prevent overhead for small renders and icons (32) */
- if (id && sp->sizex < 40) {
- sce->r.tilex = sce->r.tiley = 64;
- }
- else {
- sce->r.tilex = sce->r.xsch / 4;
- sce->r.tiley = sce->r.ysch / 4;
- }
-
- if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
- sce->r.alphamode = R_ALPHAPREMUL;
- else
- sce->r.alphamode = R_ADDSKY;
-
- sce->r.cfra = scene->r.cfra;
-
- if (id_type == ID_TE) {
- /* Texture is not actually rendered with engine, just set dummy value. */
- BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
- }
- else {
- BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
- }
-
- if (id_type == ID_MA) {
- Material *mat = NULL, *origmat = (Material *)id;
-
- if (origmat) {
- /* work on a copy */
- BLI_assert(sp->id_copy != NULL);
- mat = sp->matcopy = (Material *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->materials, mat);
-
- /* Use current scene world for lighting. */
- if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
- /* Use current scene world to light sphere. */
- sce->world = preview_get_localized_world(sp, scene->world);
- }
- else if (sce->world) {
- /* Use a default world color. Using the current
- * scene world can be slow if it has big textures. */
- sce->world->use_nodes = false;
- sce->world->horr = 0.05f;
- sce->world->horg = 0.05f;
- sce->world->horb = 0.05f;
- }
-
- set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
-
- if (sp->pr_method != PR_ICON_RENDER) {
- if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origmat is not safe! */
- BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
- }
- }
- }
- else {
- sce->r.mode &= ~(R_OSA);
- }
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->id.name[2] == 'p') {
- /* copy over object color, in case material uses it */
- copy_v4_v4(base->object->color, sp->color);
-
- if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
- /* don't use assign_material, it changed mat->id.us, which shows in the UI */
- Material ***matar = give_matarar(base->object);
- int actcol = max_ii(base->object->actcol - 1, 0);
-
- if (matar && actcol < base->object->totcol)
- (*matar)[actcol] = mat;
- }
- else if (base->object->type == OB_LAMP) {
- base->flag |= BASE_VISIBLE;
- }
- }
- }
- }
- else if (id_type == ID_TE) {
- Tex *tex = NULL, *origtex = (Tex *)id;
-
- if (origtex) {
- BLI_assert(sp->id_copy != NULL);
- tex = sp->texcopy = (Tex *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->textures, tex);
- }
-
- if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origtex is not safe! */
- BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
- }
- }
- else if (id_type == ID_LA) {
- Light *la = NULL, *origla = (Light *)id;
-
- /* work on a copy */
- if (origla) {
- BLI_assert(sp->id_copy != NULL);
- la = sp->lampcopy = (Light *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->lights, la);
- }
-
- set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
-
- if (sce->world) {
- /* Only use lighting from the light. */
- sce->world->use_nodes = false;
- sce->world->horr = 0.0f;
- sce->world->horg = 0.0f;
- sce->world->horb = 0.0f;
- }
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->id.name[2] == 'p') {
- if (base->object->type == OB_LAMP)
- base->object->data = la;
- }
- }
-
- if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origla is not safe! */
- BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
- }
- }
- else if (id_type == ID_WO) {
- World *wrld = NULL, *origwrld = (World *)id;
-
- if (origwrld) {
- BLI_assert(sp->id_copy != NULL);
- wrld = sp->worldcopy = (World *)sp->id_copy;
- sp->id_copy = NULL;
- BLI_addtail(&pr_main->worlds, wrld);
- }
-
- set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
- sce->world = wrld;
-
- if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
- /* two previews, they get copied by wmJob */
- BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
- /* WATCH: Accessing origwrld is not safe! */
- BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
- }
- }
-
- return sce;
- }
-
- return NULL;
+ Scene *sce;
+ Main *pr_main = sp->pr_main;
+
+ memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));
+
+ sce = preview_get_scene(pr_main);
+ if (sce) {
+ ViewLayer *view_layer = sce->view_layers.first;
+
+ /* this flag tells render to not execute depsgraph or ipos etc */
+ sce->r.scemode |= R_BUTS_PREVIEW;
+ /* set world always back, is used now */
+ sce->world = pr_main->worlds.first;
+ /* now: exposure copy */
+ if (scene->world) {
+ sce->world->exp = scene->world->exp;
+ sce->world->range = scene->world->range;
+ }
+
+ sce->r.color_mgt_flag = scene->r.color_mgt_flag;
+ BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
+
+ BKE_color_managed_view_settings_free(&sce->view_settings);
+ BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
+
+ /* prevent overhead for small renders and icons (32) */
+ if (id && sp->sizex < 40) {
+ sce->r.tilex = sce->r.tiley = 64;
+ }
+ else {
+ sce->r.tilex = sce->r.xsch / 4;
+ sce->r.tiley = sce->r.ysch / 4;
+ }
+
+ if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
+ sce->r.alphamode = R_ALPHAPREMUL;
+ else
+ sce->r.alphamode = R_ADDSKY;
+
+ sce->r.cfra = scene->r.cfra;
+
+ if (id_type == ID_TE) {
+ /* Texture is not actually rendered with engine, just set dummy value. */
+ BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
+ }
+ else {
+ BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
+ }
+
+ if (id_type == ID_MA) {
+ Material *mat = NULL, *origmat = (Material *)id;
+
+ if (origmat) {
+ /* work on a copy */
+ BLI_assert(sp->id_copy != NULL);
+ mat = sp->matcopy = (Material *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->materials, mat);
+
+ /* Use current scene world for lighting. */
+ if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
+ /* Use current scene world to light sphere. */
+ sce->world = preview_get_localized_world(sp, scene->world);
+ }
+ else if (sce->world) {
+ /* Use a default world color. Using the current
+ * scene world can be slow if it has big textures. */
+ sce->world->use_nodes = false;
+ sce->world->horr = 0.05f;
+ sce->world->horg = 0.05f;
+ sce->world->horb = 0.05f;
+ }
+
+ set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
+
+ if (sp->pr_method != PR_ICON_RENDER) {
+ if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origmat is not safe! */
+ BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+ }
+ else {
+ sce->r.mode &= ~(R_OSA);
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.name[2] == 'p') {
+ /* copy over object color, in case material uses it */
+ copy_v4_v4(base->object->color, sp->color);
+
+ if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
+ /* don't use assign_material, it changed mat->id.us, which shows in the UI */
+ Material ***matar = give_matarar(base->object);
+ int actcol = max_ii(base->object->actcol - 1, 0);
+
+ if (matar && actcol < base->object->totcol)
+ (*matar)[actcol] = mat;
+ }
+ else if (base->object->type == OB_LAMP) {
+ base->flag |= BASE_VISIBLE;
+ }
+ }
+ }
+ }
+ else if (id_type == ID_TE) {
+ Tex *tex = NULL, *origtex = (Tex *)id;
+
+ if (origtex) {
+ BLI_assert(sp->id_copy != NULL);
+ tex = sp->texcopy = (Tex *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->textures, tex);
+ }
+
+ if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origtex is not safe! */
+ BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+ else if (id_type == ID_LA) {
+ Light *la = NULL, *origla = (Light *)id;
+
+ /* work on a copy */
+ if (origla) {
+ BLI_assert(sp->id_copy != NULL);
+ la = sp->lampcopy = (Light *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->lights, la);
+ }
+
+ set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
+
+ if (sce->world) {
+ /* Only use lighting from the light. */
+ sce->world->use_nodes = false;
+ sce->world->horr = 0.0f;
+ sce->world->horg = 0.0f;
+ sce->world->horb = 0.0f;
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.name[2] == 'p') {
+ if (base->object->type == OB_LAMP)
+ base->object->data = la;
+ }
+ }
+
+ if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origla is not safe! */
+ BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+ else if (id_type == ID_WO) {
+ World *wrld = NULL, *origwrld = (World *)id;
+
+ if (origwrld) {
+ BLI_assert(sp->id_copy != NULL);
+ wrld = sp->worldcopy = (World *)sp->id_copy;
+ sp->id_copy = NULL;
+ BLI_addtail(&pr_main->worlds, wrld);
+ }
+
+ set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
+ sce->world = wrld;
+
+ if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
+ /* two previews, they get copied by wmJob */
+ BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true);
+ /* WATCH: Accessing origwrld is not safe! */
+ BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
+ }
+ }
+
+ return sce;
+ }
+
+ return NULL;
}
/* new UI convention: draw is in pixel space already. */
/* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
{
- Render *re;
- RenderView *rv;
- RenderResult rres;
- char name[32];
- int offx = 0;
- int newx = BLI_rcti_size_x(rect);
- int newy = BLI_rcti_size_y(rect);
- bool ok = false;
-
- if (!split || first) sprintf(name, "Preview %p", (void *)sa);
- else sprintf(name, "SecondPreview %p", (void *)sa);
-
- if (split) {
- if (first) {
- offx = 0;
- newx = newx / 2;
- }
- else {
- offx = newx / 2;
- newx = newx - newx / 2;
- }
- }
-
- /* test if something rendered ok */
- re = RE_GetRender(name);
-
- if (re == NULL)
- return false;
-
- RE_AcquireResultImageViews(re, &rres);
-
- if (!BLI_listbase_is_empty(&rres.views)) {
- /* material preview only needs monoscopy (view 0) */
- rv = RE_RenderViewGetById(&rres, 0);
- }
- else {
- /* possible the job clears the views but we're still drawing T45496 */
- rv = NULL;
- }
-
- if (rv && rv->rectf) {
-
- if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
-
- newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
- newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
-
- if (rres.rectx && rres.recty) {
- unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
- float fx = rect->xmin + offx;
- float fy = rect->ymin;
-
- /* material preview only needs monoscopy (view 0) */
- if (re)
- RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
-
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte,
- 1.0f, 1.0f, NULL);
-
- MEM_freeN(rect_byte);
-
- ok = 1;
- }
- }
- }
-
- RE_ReleaseResultImageViews(re, &rres);
-
- return ok;
+ Render *re;
+ RenderView *rv;
+ RenderResult rres;
+ char name[32];
+ int offx = 0;
+ int newx = BLI_rcti_size_x(rect);
+ int newy = BLI_rcti_size_y(rect);
+ bool ok = false;
+
+ if (!split || first)
+ sprintf(name, "Preview %p", (void *)sa);
+ else
+ sprintf(name, "SecondPreview %p", (void *)sa);
+
+ if (split) {
+ if (first) {
+ offx = 0;
+ newx = newx / 2;
+ }
+ else {
+ offx = newx / 2;
+ newx = newx - newx / 2;
+ }
+ }
+
+ /* test if something rendered ok */
+ re = RE_GetRender(name);
+
+ if (re == NULL)
+ return false;
+
+ RE_AcquireResultImageViews(re, &rres);
+
+ if (!BLI_listbase_is_empty(&rres.views)) {
+ /* material preview only needs monoscopy (view 0) */
+ rv = RE_RenderViewGetById(&rres, 0);
+ }
+ else {
+ /* possible the job clears the views but we're still drawing T45496 */
+ rv = NULL;
+ }
+
+ if (rv && rv->rectf) {
+
+ if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
+
+ newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx);
+ newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
+
+ if (rres.rectx && rres.recty) {
+ unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int),
+ "ed_preview_draw_rect");
+ float fx = rect->xmin + offx;
+ float fy = rect->ymin;
+
+ /* material preview only needs monoscopy (view 0) */
+ if (re)
+ RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state,
+ fx,
+ fy,
+ rres.rectx,
+ rres.recty,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ GL_NEAREST,
+ rect_byte,
+ 1.0f,
+ 1.0f,
+ NULL);
+
+ MEM_freeN(rect_byte);
+
+ ok = 1;
+ }
+ }
+ }
+
+ RE_ReleaseResultImageViews(re, &rres);
+
+ return ok;
}
void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect)
{
- if (idp) {
- wmWindowManager *wm = CTX_wm_manager(C);
- ScrArea *sa = CTX_wm_area(C);
- ID *id = (ID *)idp;
- ID *parent = (ID *)parentp;
- MTex *slot = (MTex *)slotp;
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ShaderPreview *sp = WM_jobs_customdata(wm, sa);
- rcti newrect;
- int ok;
- int newx = BLI_rcti_size_x(rect);
- int newy = BLI_rcti_size_y(rect);
-
- newrect.xmin = rect->xmin;
- newrect.xmax = rect->xmin;
- newrect.ymin = rect->ymin;
- newrect.ymax = rect->ymin;
-
- if (parent) {
- ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
- ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
- }
- else
- ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
-
- if (ok)
- *rect = newrect;
-
- /* start a new preview render job if signaled through sbuts->preview,
- * if no render result was found and no preview render job is running,
- * or if the job is running and the size of preview changed */
- if ((sbuts != NULL && sbuts->preview) ||
- (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) ||
- (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2)))
- {
- if (sbuts != NULL) {
- sbuts->preview = 0;
- }
- ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
- }
- }
+ if (idp) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ID *id = (ID *)idp;
+ ID *parent = (ID *)parentp;
+ MTex *slot = (MTex *)slotp;
+ SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ ShaderPreview *sp = WM_jobs_customdata(wm, sa);
+ rcti newrect;
+ int ok;
+ int newx = BLI_rcti_size_x(rect);
+ int newy = BLI_rcti_size_y(rect);
+
+ newrect.xmin = rect->xmin;
+ newrect.xmax = rect->xmin;
+ newrect.ymin = rect->ymin;
+ newrect.ymax = rect->ymin;
+
+ if (parent) {
+ ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
+ ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
+ }
+ else
+ ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
+
+ if (ok)
+ *rect = newrect;
+
+ /* start a new preview render job if signaled through sbuts->preview,
+ * if no render result was found and no preview render job is running,
+ * or if the job is running and the size of preview changed */
+ if ((sbuts != NULL && sbuts->preview) ||
+ (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) ||
+ (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2))) {
+ if (sbuts != NULL) {
+ sbuts->preview = 0;
+ }
+ ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
+ }
+ }
}
/* **************************** new shader preview system ****************** */
/* inside thread, called by renderer, sets job update value */
-static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
+static void shader_preview_update(void *spv,
+ RenderResult *UNUSED(rr),
+ volatile struct rcti *UNUSED(rect))
{
- ShaderPreview *sp = spv;
+ ShaderPreview *sp = spv;
- *(sp->do_update) = true;
+ *(sp->do_update) = true;
}
/* called by renderer, checks job value */
static int shader_preview_break(void *spv)
{
- ShaderPreview *sp = spv;
+ ShaderPreview *sp = spv;
- return *(sp->stop);
+ return *(sp->stop);
}
/* outside thread, called before redraw notifiers, it moves finished preview over */
static void shader_preview_updatejob(void *spv)
{
- ShaderPreview *sp = spv;
-
- if (sp->id) {
- if (sp->pr_method == PR_NODE_RENDER) {
- if (GS(sp->id->name) == ID_MA) {
- Material *mat = (Material *)sp->id;
-
- if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
- ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
- }
- else if (GS(sp->id->name) == ID_TE) {
- Tex *tex = (Tex *)sp->id;
-
- if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
- ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree);
- }
- else if (GS(sp->id->name) == ID_WO) {
- World *wrld = (World *)sp->id;
-
- if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
- ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree);
- }
- else if (GS(sp->id->name) == ID_LA) {
- Light *la = (Light *)sp->id;
-
- if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
- ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
- }
- }
- }
+ ShaderPreview *sp = spv;
+
+ if (sp->id) {
+ if (sp->pr_method == PR_NODE_RENDER) {
+ if (GS(sp->id->name) == ID_MA) {
+ Material *mat = (Material *)sp->id;
+
+ if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree)
+ ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
+ }
+ else if (GS(sp->id->name) == ID_TE) {
+ Tex *tex = (Tex *)sp->id;
+
+ if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree)
+ ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree);
+ }
+ else if (GS(sp->id->name) == ID_WO) {
+ World *wrld = (World *)sp->id;
+
+ if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree)
+ ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree);
+ }
+ else if (GS(sp->id->name) == ID_LA) {
+ Light *la = (Light *)sp->id;
+
+ if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree)
+ ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree);
+ }
+ }
+ }
}
/* Renders texture directly to render buffer. */
static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Render *re)
{
- /* Setup output buffer. */
- int width = sp->sizex;
- int height = sp->sizey;
-
- /* This is needed otherwise no RenderResult is created. */
- sce->r.scemode &= ~R_BUTS_PREVIEW;
- RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL);
- RE_SetScene(re, sce);
-
- /* Create buffer in empty RenderView created in the init step. */
- RenderResult *rr = RE_AcquireResultWrite(re);
- RenderView *rv = (RenderView *)rr->views.first;
- rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result");
- RE_ReleaseResult(re);
-
- /* Get texture image pool (if any) */
- struct ImagePool *img_pool = BKE_image_pool_new();
- BKE_texture_fetch_images_for_pool(tex, img_pool);
-
- /* Fill in image buffer. */
- float *rect_float = rv->rectf;
- float tex_coord[3] = {0.0f, 0.0f, 0.0f};
- bool color_manage = true;
-
- for (int y = 0; y < height; y++) {
- /* Tex coords between -1.0f and 1.0f. */
- tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f;
-
- for (int x = 0; x < width; x++) {
- tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f;
-
- /* Evaluate texture at tex_coord .*/
- TexResult texres = {0};
- BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
-
- rect_float[0] = texres.tr;
- rect_float[1] = texres.tg;
- rect_float[2] = texres.tb;
- rect_float[3] = 1.0f;
-
- rect_float += 4;
- }
-
- /* Check if we should cancel texture preview. */
- if (shader_preview_break(sp)) {
- break;
- }
- }
-
- BKE_image_pool_free(img_pool);
+ /* Setup output buffer. */
+ int width = sp->sizex;
+ int height = sp->sizey;
+
+ /* This is needed otherwise no RenderResult is created. */
+ sce->r.scemode &= ~R_BUTS_PREVIEW;
+ RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL);
+ RE_SetScene(re, sce);
+
+ /* Create buffer in empty RenderView created in the init step. */
+ RenderResult *rr = RE_AcquireResultWrite(re);
+ RenderView *rv = (RenderView *)rr->views.first;
+ rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result");
+ RE_ReleaseResult(re);
+
+ /* Get texture image pool (if any) */
+ struct ImagePool *img_pool = BKE_image_pool_new();
+ BKE_texture_fetch_images_for_pool(tex, img_pool);
+
+ /* Fill in image buffer. */
+ float *rect_float = rv->rectf;
+ float tex_coord[3] = {0.0f, 0.0f, 0.0f};
+ bool color_manage = true;
+
+ for (int y = 0; y < height; y++) {
+ /* Tex coords between -1.0f and 1.0f. */
+ tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f;
+
+ for (int x = 0; x < width; x++) {
+ tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f;
+
+ /* Evaluate texture at tex_coord .*/
+ TexResult texres = {0};
+ BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
+
+ rect_float[0] = texres.tr;
+ rect_float[1] = texres.tg;
+ rect_float[2] = texres.tb;
+ rect_float[3] = 1.0f;
+
+ rect_float += 4;
+ }
+
+ /* Check if we should cancel texture preview. */
+ if (shader_preview_break(sp)) {
+ break;
+ }
+ }
+
+ BKE_image_pool_free(img_pool);
}
static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
{
- Render *re;
- Scene *sce;
- float oldlens;
- short idtype = GS(id->name);
- char name[32];
- int sizex;
- Main *pr_main = sp->pr_main;
- ID *id_eval = id;
-
- if (sp->depsgraph) {
- id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
- }
-
- /* in case of split preview, use border render */
- if (split) {
- if (first) sizex = sp->sizex / 2;
- else sizex = sp->sizex - sp->sizex / 2;
- }
- else {
- sizex = sp->sizex;
- }
-
- /* we have to set preview variables first */
- sce = preview_get_scene(pr_main);
- if (sce) {
- sce->r.xsch = sizex;
- sce->r.ysch = sp->sizey;
- sce->r.size = 100;
- }
-
-
- /* get the stuff from the builtin preview dbase */
- sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
- if (sce == NULL) return;
-
- if (!split || first) sprintf(name, "Preview %p", sp->owner);
- else sprintf(name, "SecondPreview %p", sp->owner);
- re = RE_GetRender(name);
-
- /* full refreshed render from first tile */
- if (re == NULL)
- re = RE_NewRender(name);
-
- /* sce->r gets copied in RE_InitState! */
- sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW);
- sce->r.scemode &= ~R_NO_IMAGE_LOAD;
-
- if (sp->pr_method == PR_ICON_RENDER) {
- sce->r.scemode |= R_NO_IMAGE_LOAD;
- sce->r.mode |= R_OSA;
- }
- else if (sp->pr_method == PR_NODE_RENDER) {
- if (idtype == ID_MA) sce->r.scemode |= R_MATNODE_PREVIEW;
- else if (idtype == ID_TE) sce->r.scemode |= R_TEXNODE_PREVIEW;
- sce->r.mode &= ~R_OSA;
- }
- else { /* PR_BUTS_RENDER */
- sce->r.mode |= R_OSA;
- }
-
-
- /* callbacs are cleared on GetRender() */
- if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
- RE_display_update_cb(re, sp, shader_preview_update);
- }
- /* set this for all previews, default is react to G.is_break still */
- RE_test_break_cb(re, sp, shader_preview_break);
-
- /* lens adjust */
- oldlens = ((Camera *)sce->camera->data)->lens;
- if (sizex > sp->sizey)
- ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
-
- /* entire cycle for render engine */
- if (idtype == ID_TE) {
- shader_preview_texture(sp, (Tex *)id, sce, re);
- }
- else {
- /* Render preview scene */
- RE_PreviewRender(re, pr_main, sce);
- }
-
- ((Camera *)sce->camera->data)->lens = oldlens;
-
- /* handle results */
- if (sp->pr_method == PR_ICON_RENDER) {
- // char *rct= (char *)(sp->pr_rect + 32*16 + 16);
-
- if (sp->pr_rect)
- RE_ResultGet32(re, sp->pr_rect);
- }
-
- /* unassign the pointers, reset vars */
- preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
-
- /* XXX bad exception, end-exec is not being called in render, because it uses local main */
-// if (idtype == ID_TE) {
-// Tex *tex= (Tex *)id;
-// if (tex->use_nodes && tex->nodetree)
-// ntreeEndExecTree(tex->nodetree);
-// }
-
+ Render *re;
+ Scene *sce;
+ float oldlens;
+ short idtype = GS(id->name);
+ char name[32];
+ int sizex;
+ Main *pr_main = sp->pr_main;
+ ID *id_eval = id;
+
+ if (sp->depsgraph) {
+ id_eval = DEG_get_evaluated_id(sp->depsgraph, id);
+ }
+
+ /* in case of split preview, use border render */
+ if (split) {
+ if (first)
+ sizex = sp->sizex / 2;
+ else
+ sizex = sp->sizex - sp->sizex / 2;
+ }
+ else {
+ sizex = sp->sizex;
+ }
+
+ /* we have to set preview variables first */
+ sce = preview_get_scene(pr_main);
+ if (sce) {
+ sce->r.xsch = sizex;
+ sce->r.ysch = sp->sizey;
+ sce->r.size = 100;
+ }
+
+ /* get the stuff from the builtin preview dbase */
+ sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp);
+ if (sce == NULL)
+ return;
+
+ if (!split || first)
+ sprintf(name, "Preview %p", sp->owner);
+ else
+ sprintf(name, "SecondPreview %p", sp->owner);
+ re = RE_GetRender(name);
+
+ /* full refreshed render from first tile */
+ if (re == NULL)
+ re = RE_NewRender(name);
+
+ /* sce->r gets copied in RE_InitState! */
+ sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW);
+ sce->r.scemode &= ~R_NO_IMAGE_LOAD;
+
+ if (sp->pr_method == PR_ICON_RENDER) {
+ sce->r.scemode |= R_NO_IMAGE_LOAD;
+ sce->r.mode |= R_OSA;
+ }
+ else if (sp->pr_method == PR_NODE_RENDER) {
+ if (idtype == ID_MA)
+ sce->r.scemode |= R_MATNODE_PREVIEW;
+ else if (idtype == ID_TE)
+ sce->r.scemode |= R_TEXNODE_PREVIEW;
+ sce->r.mode &= ~R_OSA;
+ }
+ else { /* PR_BUTS_RENDER */
+ sce->r.mode |= R_OSA;
+ }
+
+ /* callbacs are cleared on GetRender() */
+ if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) {
+ RE_display_update_cb(re, sp, shader_preview_update);
+ }
+ /* set this for all previews, default is react to G.is_break still */
+ RE_test_break_cb(re, sp, shader_preview_break);
+
+ /* lens adjust */
+ oldlens = ((Camera *)sce->camera->data)->lens;
+ if (sizex > sp->sizey)
+ ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
+
+ /* entire cycle for render engine */
+ if (idtype == ID_TE) {
+ shader_preview_texture(sp, (Tex *)id, sce, re);
+ }
+ else {
+ /* Render preview scene */
+ RE_PreviewRender(re, pr_main, sce);
+ }
+
+ ((Camera *)sce->camera->data)->lens = oldlens;
+
+ /* handle results */
+ if (sp->pr_method == PR_ICON_RENDER) {
+ // char *rct= (char *)(sp->pr_rect + 32*16 + 16);
+
+ if (sp->pr_rect)
+ RE_ResultGet32(re, sp->pr_rect);
+ }
+
+ /* unassign the pointers, reset vars */
+ preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp);
+
+ /* XXX bad exception, end-exec is not being called in render, because it uses local main */
+ // if (idtype == ID_TE) {
+ // Tex *tex= (Tex *)id;
+ // if (tex->use_nodes && tex->nodetree)
+ // ntreeEndExecTree(tex->nodetree);
+ // }
}
/* runs inside thread for material and icons */
static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
{
- ShaderPreview *sp = customdata;
+ ShaderPreview *sp = customdata;
- sp->stop = stop;
- sp->do_update = do_update;
+ sp->stop = stop;
+ sp->do_update = do_update;
- if (sp->parent) {
- shader_preview_render(sp, sp->id, 1, 1);
- shader_preview_render(sp, sp->parent, 1, 0);
- }
- else
- shader_preview_render(sp, sp->id, 0, 0);
+ if (sp->parent) {
+ shader_preview_render(sp, sp->id, 1, 1);
+ shader_preview_render(sp, sp->parent, 1, 0);
+ }
+ else
+ shader_preview_render(sp, sp->id, 0, 0);
- *do_update = true;
+ *do_update = true;
}
static void shader_preview_free(void *customdata)
{
- ShaderPreview *sp = customdata;
- Main *pr_main = sp->pr_main;
-
- if (sp->matcopy) {
- sp->id_copy = (ID *)sp->matcopy;
- BLI_remlink(&pr_main->materials, sp->matcopy);
- }
- if (sp->texcopy) {
- sp->id_copy = (ID *)sp->texcopy;
- BLI_remlink(&pr_main->textures, sp->texcopy);
- }
- if (sp->worldcopy) {
- sp->id_copy = (ID *)sp->worldcopy;
- BLI_remlink(&pr_main->worlds, sp->worldcopy);
- }
- if (sp->lampcopy) {
- sp->id_copy = (ID *)sp->lampcopy;
- BLI_remlink(&pr_main->lights, sp->lampcopy);
- }
- if (sp->id_copy) {
- /* node previews */
- shader_preview_updatejob(sp);
- }
- if (sp->id_copy && sp->own_id_copy) {
- struct IDProperty *properties;
- /* get rid of copied ID */
- properties = IDP_GetProperties(sp->id_copy, false);
- if (properties) {
- IDP_FreeProperty_ex(properties, false);
- MEM_freeN(properties);
- }
- switch (GS(sp->id_copy->name)) {
- case ID_MA:
- BKE_material_free((Material *)sp->id_copy);
- break;
- case ID_TE:
- BKE_texture_free((Tex *)sp->id_copy);
- break;
- case ID_LA:
- BKE_light_free((Light *)sp->id_copy);
- break;
- case ID_WO:
- BKE_world_free((World *)sp->id_copy);
- break;
- default:
- BLI_assert(!"ID type preview not supported.");
- break;
- }
- MEM_freeN(sp->id_copy);
- }
-
- MEM_freeN(sp);
+ ShaderPreview *sp = customdata;
+ Main *pr_main = sp->pr_main;
+
+ if (sp->matcopy) {
+ sp->id_copy = (ID *)sp->matcopy;
+ BLI_remlink(&pr_main->materials, sp->matcopy);
+ }
+ if (sp->texcopy) {
+ sp->id_copy = (ID *)sp->texcopy;
+ BLI_remlink(&pr_main->textures, sp->texcopy);
+ }
+ if (sp->worldcopy) {
+ sp->id_copy = (ID *)sp->worldcopy;
+ BLI_remlink(&pr_main->worlds, sp->worldcopy);
+ }
+ if (sp->lampcopy) {
+ sp->id_copy = (ID *)sp->lampcopy;
+ BLI_remlink(&pr_main->lights, sp->lampcopy);
+ }
+ if (sp->id_copy) {
+ /* node previews */
+ shader_preview_updatejob(sp);
+ }
+ if (sp->id_copy && sp->own_id_copy) {
+ struct IDProperty *properties;
+ /* get rid of copied ID */
+ properties = IDP_GetProperties(sp->id_copy, false);
+ if (properties) {
+ IDP_FreeProperty_ex(properties, false);
+ MEM_freeN(properties);
+ }
+ switch (GS(sp->id_copy->name)) {
+ case ID_MA:
+ BKE_material_free((Material *)sp->id_copy);
+ break;
+ case ID_TE:
+ BKE_texture_free((Tex *)sp->id_copy);
+ break;
+ case ID_LA:
+ BKE_light_free((Light *)sp->id_copy);
+ break;
+ case ID_WO:
+ BKE_world_free((World *)sp->id_copy);
+ break;
+ default:
+ BLI_assert(!"ID type preview not supported.");
+ break;
+ }
+ MEM_freeN(sp->id_copy);
+ }
+
+ MEM_freeN(sp);
}
/* ************************* icon preview ********************** */
static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
{
- struct ImBuf *ima;
- unsigned int *drect, *srect;
- float scaledx, scaledy;
- short ex, ey, dx, dy;
+ struct ImBuf *ima;
+ unsigned int *drect, *srect;
+ float scaledx, scaledy;
+ short ex, ey, dx, dy;
- /* paranoia test */
- if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL))
- return;
+ /* paranoia test */
+ if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL))
+ return;
- /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
- ima = IMB_dupImBuf(ibuf);
+ /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */
+ ima = IMB_dupImBuf(ibuf);
- if (!ima)
- return;
+ if (!ima)
+ return;
- if (ima->x > ima->y) {
- scaledx = (float)w;
- scaledy = ( (float)ima->y / (float)ima->x) * (float)w;
- }
- else {
- scaledx = ( (float)ima->x / (float)ima->y) * (float)h;
- scaledy = (float)h;
- }
+ if (ima->x > ima->y) {
+ scaledx = (float)w;
+ scaledy = ((float)ima->y / (float)ima->x) * (float)w;
+ }
+ else {
+ scaledx = ((float)ima->x / (float)ima->y) * (float)h;
+ scaledy = (float)h;
+ }
- ex = (short)scaledx;
- ey = (short)scaledy;
+ ex = (short)scaledx;
+ ey = (short)scaledy;
- dx = (w - ex) / 2;
- dy = (h - ey) / 2;
+ dx = (w - ex) / 2;
+ dy = (h - ey) / 2;
- IMB_scalefastImBuf(ima, ex, ey);
+ IMB_scalefastImBuf(ima, ex, ey);
- /* if needed, convert to 32 bits */
- if (ima->rect == NULL)
- IMB_rect_from_float(ima);
+ /* if needed, convert to 32 bits */
+ if (ima->rect == NULL)
+ IMB_rect_from_float(ima);
- srect = ima->rect;
- drect = rect;
+ srect = ima->rect;
+ drect = rect;
- drect += dy * w + dx;
- for (; ey > 0; ey--) {
- memcpy(drect, srect, ex * sizeof(int));
- drect += w;
- srect += ima->x;
- }
+ drect += dy * w + dx;
+ for (; ey > 0; ey--) {
+ memcpy(drect, srect, ex * sizeof(int));
+ drect += w;
+ srect += ima->x;
+ }
- IMB_freeImBuf(ima);
+ IMB_freeImBuf(ima);
}
static void set_alpha(char *cp, int sizex, int sizey, char alpha)
{
- int a, size = sizex * sizey;
+ int a, size = sizex * sizey;
- for (a = 0; a < size; a++, cp += 4)
- cp[3] = alpha;
+ for (a = 0; a < size; a++, cp += 4)
+ cp[3] = alpha;
}
static void icon_preview_startjob(void *customdata, short *stop, short *do_update)
{
- ShaderPreview *sp = customdata;
-
- if (sp->pr_method == PR_ICON_DEFERRED) {
- PreviewImage *prv = sp->owner;
- ImBuf *thumb;
- char *deferred_data = PRV_DEFERRED_DATA(prv);
- int source = deferred_data[0];
- char *path = &deferred_data[1];
-
-// printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
-
- thumb = IMB_thumb_manage(path, THB_LARGE, source);
-
- if (thumb) {
- /* PreviewImage assumes premultiplied alhpa... */
- IMB_premultiply_alpha(thumb);
-
- icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
- IMB_freeImBuf(thumb);
- }
- }
- else {
- ID *id = sp->id;
- short idtype = GS(id->name);
-
- if (idtype == ID_IM) {
- Image *ima = (Image *)id;
- ImBuf *ibuf = NULL;
- ImageUser iuser = {NULL};
-
- /* ima->ok is zero when Image cannot load */
- if (ima == NULL || ima->ok == 0)
- return;
-
- /* setup dummy image user */
- iuser.ok = iuser.framenr = 1;
- iuser.scene = sp->scene;
-
- /* elubie: this needs to be changed: here image is always loaded if not
- * already there. Very expensive for large images. Need to find a way to
- * only get existing ibuf */
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
-
- *do_update = true;
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- else if (idtype == ID_BR) {
- Brush *br = (Brush *)id;
-
- br->icon_imbuf = get_brush_icon(br);
-
- memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
-
- if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
- return;
-
- icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
-
- *do_update = true;
- }
- else if (idtype == ID_SCR) {
- bScreen *screen = (bScreen *)id;
-
- ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
- *do_update = true;
- }
- else {
- /* re-use shader job */
- shader_preview_startjob(customdata, stop, do_update);
-
- /* world is rendered with alpha=0, so it wasn't displayed
- * this could be render option for sky to, for later */
- if (idtype == ID_WO) {
- set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
- }
- }
- }
+ ShaderPreview *sp = customdata;
+
+ if (sp->pr_method == PR_ICON_DEFERRED) {
+ PreviewImage *prv = sp->owner;
+ ImBuf *thumb;
+ char *deferred_data = PRV_DEFERRED_DATA(prv);
+ int source = deferred_data[0];
+ char *path = &deferred_data[1];
+
+ // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path);
+
+ thumb = IMB_thumb_manage(path, THB_LARGE, source);
+
+ if (thumb) {
+ /* PreviewImage assumes premultiplied alhpa... */
+ IMB_premultiply_alpha(thumb);
+
+ icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect);
+ IMB_freeImBuf(thumb);
+ }
+ }
+ else {
+ ID *id = sp->id;
+ short idtype = GS(id->name);
+
+ if (idtype == ID_IM) {
+ Image *ima = (Image *)id;
+ ImBuf *ibuf = NULL;
+ ImageUser iuser = {NULL};
+
+ /* ima->ok is zero when Image cannot load */
+ if (ima == NULL || ima->ok == 0)
+ return;
+
+ /* setup dummy image user */
+ iuser.ok = iuser.framenr = 1;
+ iuser.scene = sp->scene;
+
+ /* elubie: this needs to be changed: here image is always loaded if not
+ * already there. Very expensive for large images. Need to find a way to
+ * only get existing ibuf */
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ if (ibuf == NULL || ibuf->rect == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
+ icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
+
+ *do_update = true;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ else if (idtype == ID_BR) {
+ Brush *br = (Brush *)id;
+
+ br->icon_imbuf = get_brush_icon(br);
+
+ memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int));
+
+ if (!(br->icon_imbuf) || !(br->icon_imbuf->rect))
+ return;
+
+ icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect);
+
+ *do_update = true;
+ }
+ else if (idtype == ID_SCR) {
+ bScreen *screen = (bScreen *)id;
+
+ ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
+ *do_update = true;
+ }
+ else {
+ /* re-use shader job */
+ shader_preview_startjob(customdata, stop, do_update);
+
+ /* world is rendered with alpha=0, so it wasn't displayed
+ * this could be render option for sky to, for later */
+ if (idtype == ID_WO) {
+ set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255);
+ }
+ }
+ }
}
/* use same function for icon & shader, so the job manager
* does not run two of them at the same time. */
-static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
+static void common_preview_startjob(void *customdata,
+ short *stop,
+ short *do_update,
+ float *UNUSED(progress))
{
- ShaderPreview *sp = customdata;
+ ShaderPreview *sp = customdata;
- if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED))
- icon_preview_startjob(customdata, stop, do_update);
- else
- shader_preview_startjob(customdata, stop, do_update);
+ if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED))
+ icon_preview_startjob(customdata, stop, do_update);
+ else
+ shader_preview_startjob(customdata, stop, do_update);
}
/* exported functions */
static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex, int sizey)
{
- IconPreviewSize *cur_size = ip->sizes.first, *new_size;
+ IconPreviewSize *cur_size = ip->sizes.first, *new_size;
- while (cur_size) {
- if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
- /* requested size is already in list, no need to add it again */
- return;
- }
+ while (cur_size) {
+ if (cur_size->sizex == sizex && cur_size->sizey == sizey) {
+ /* requested size is already in list, no need to add it again */
+ return;
+ }
- cur_size = cur_size->next;
- }
+ cur_size = cur_size->next;
+ }
- new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
- new_size->sizex = sizex;
- new_size->sizey = sizey;
- new_size->rect = rect;
+ new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize");
+ new_size->sizex = sizex;
+ new_size->sizey = sizey;
+ new_size->rect = rect;
- BLI_addtail(&ip->sizes, new_size);
+ BLI_addtail(&ip->sizes, new_size);
}
-static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress)
+static void icon_preview_startjob_all_sizes(void *customdata,
+ short *stop,
+ short *do_update,
+ float *progress)
{
- IconPreview *ip = (IconPreview *)customdata;
- IconPreviewSize *cur_size;
-
- for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
- PreviewImage *prv = ip->owner;
-
- if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
- /* Non-thread-protected reading is not an issue here. */
- continue;
- }
-
- if (!check_engine_supports_preview(ip->scene)) {
- continue;
- }
-
- ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
- const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
-
- /* construct shader preview from image size and previewcustomdata */
- sp->scene = ip->scene;
- sp->depsgraph = ip->depsgraph;
- sp->owner = ip->owner;
- sp->sizex = cur_size->sizex;
- sp->sizey = cur_size->sizey;
- sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
- sp->pr_rect = cur_size->rect;
- sp->id = ip->id;
- sp->id_copy = ip->id_copy;
- sp->bmain = ip->bmain;
- sp->own_id_copy = false;
- Material *ma = NULL;
-
- if (is_render) {
- BLI_assert(ip->id);
-
- /* grease pencil use its own preview file */
- if (GS(ip->id->name) == ID_MA) {
- ma = (Material *)ip->id;
- }
-
- if ((ma == NULL) || (ma->gp_style == NULL)) {
- sp->pr_main = G_pr_main;
- }
- else {
- sp->pr_main = G_pr_main_grease_pencil;
- }
- }
-
- common_preview_startjob(sp, stop, do_update, progress);
- shader_preview_free(sp);
- }
+ IconPreview *ip = (IconPreview *)customdata;
+ IconPreviewSize *cur_size;
+
+ for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
+ PreviewImage *prv = ip->owner;
+
+ if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
+ /* Non-thread-protected reading is not an issue here. */
+ continue;
+ }
+
+ if (!check_engine_supports_preview(ip->scene)) {
+ continue;
+ }
+
+ ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
+
+ /* construct shader preview from image size and previewcustomdata */
+ sp->scene = ip->scene;
+ sp->depsgraph = ip->depsgraph;
+ sp->owner = ip->owner;
+ sp->sizex = cur_size->sizex;
+ sp->sizey = cur_size->sizey;
+ sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED;
+ sp->pr_rect = cur_size->rect;
+ sp->id = ip->id;
+ sp->id_copy = ip->id_copy;
+ sp->bmain = ip->bmain;
+ sp->own_id_copy = false;
+ Material *ma = NULL;
+
+ if (is_render) {
+ BLI_assert(ip->id);
+
+ /* grease pencil use its own preview file */
+ if (GS(ip->id->name) == ID_MA) {
+ ma = (Material *)ip->id;
+ }
+
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
+ }
+
+ common_preview_startjob(sp, stop, do_update, progress);
+ shader_preview_free(sp);
+ }
}
static void icon_preview_endjob(void *customdata)
{
- IconPreview *ip = customdata;
+ IconPreview *ip = customdata;
- if (ip->id) {
+ if (ip->id) {
- if (GS(ip->id->name) == ID_BR)
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
+ if (GS(ip->id->name) == ID_BR)
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
#if 0
- if (GS(ip->id->name) == ID_MA) {
- Material *ma = (Material *)ip->id;
- PreviewImage *prv_img = ma->preview;
- int i;
-
- /* signal to gpu texture */
- for (i = 0; i < NUM_ICON_SIZES; ++i) {
- if (prv_img->gputexture[i]) {
- GPU_texture_free(prv_img->gputexture[i]);
- prv_img->gputexture[i] = NULL;
- WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
- }
- }
- }
+ if (GS(ip->id->name) == ID_MA) {
+ Material *ma = (Material *)ip->id;
+ PreviewImage *prv_img = ma->preview;
+ int i;
+
+ /* signal to gpu texture */
+ for (i = 0; i < NUM_ICON_SIZES; ++i) {
+ if (prv_img->gputexture[i]) {
+ GPU_texture_free(prv_img->gputexture[i]);
+ prv_img->gputexture[i] = NULL;
+ WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
+ }
+ }
+ }
#endif
- }
-
- if (ip->owner) {
- PreviewImage *prv_img = ip->owner;
- prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
- if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
- BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
- BKE_previewimg_cached_release_pointer(prv_img);
- }
- }
+ }
+
+ if (ip->owner) {
+ PreviewImage *prv_img = ip->owner;
+ prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
+ if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
+ BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
+ BKE_previewimg_cached_release_pointer(prv_img);
+ }
+ }
}
static void icon_preview_free(void *customdata)
{
- IconPreview *ip = (IconPreview *)customdata;
-
- if (ip->id_copy) {
- /* Feels a bit hacky just to reuse shader_preview_free() */
- ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
- sp->id_copy = ip->id_copy;
- sp->own_id_copy = true;
- shader_preview_free(sp);
- ip->id_copy = NULL;
- }
-
- BLI_freelistN(&ip->sizes);
- MEM_freeN(ip);
+ IconPreview *ip = (IconPreview *)customdata;
+
+ if (ip->id_copy) {
+ /* Feels a bit hacky just to reuse shader_preview_free() */
+ ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
+ sp->id_copy = ip->id_copy;
+ sp->own_id_copy = true;
+ shader_preview_free(sp);
+ ip->id_copy = NULL;
+ }
+
+ BLI_freelistN(&ip->sizes);
+ MEM_freeN(ip);
}
-void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_render(
+ Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
{
- IconPreview ip = {NULL};
- short stop = false, update = false;
- float progress = 0.0f;
+ IconPreview ip = {NULL};
+ short stop = false, update = false;
+ float progress = 0.0f;
- ED_preview_ensure_dbase();
+ ED_preview_ensure_dbase();
- ip.bmain = bmain;
- ip.scene = scene;
- ip.owner = BKE_previewimg_id_ensure(id);
- ip.id = id;
- ip.id_copy = duplicate_ids(id, NULL);
+ ip.bmain = bmain;
+ ip.scene = scene;
+ ip.owner = BKE_previewimg_id_ensure(id);
+ ip.id = id;
+ ip.id_copy = duplicate_ids(id, NULL);
- icon_preview_add_size(&ip, rect, sizex, sizey);
+ icon_preview_add_size(&ip, rect, sizex, sizey);
- icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
+ icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress);
- icon_preview_endjob(&ip);
+ icon_preview_endjob(&ip);
- BLI_freelistN(&ip.sizes);
+ BLI_freelistN(&ip.sizes);
}
-void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_job(
+ const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
{
- wmJob *wm_job;
- IconPreview *ip, *old_ip;
-
- ED_preview_ensure_dbase();
-
- /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview",
- WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, WM_JOB_TYPE_RENDER_PREVIEW);
-
- ip = MEM_callocN(sizeof(IconPreview), "icon preview");
-
- /* render all resolutions from suspended job too */
- old_ip = WM_jobs_customdata_get(wm_job);
- if (old_ip)
- BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
-
- /* customdata for preview thread */
- ip->bmain = CTX_data_main(C);
- ip->scene = CTX_data_scene(C);
- ip->depsgraph = CTX_data_depsgraph(C);
- ip->owner = owner;
- ip->id = id;
- ip->id_copy = duplicate_ids(id, ip->depsgraph);
-
- icon_preview_add_size(ip, rect, sizex, sizey);
-
- /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */
- {
- PreviewImage *prv_img = owner;
- if (prv_img->tag & PRV_TAG_DEFFERED) {
- prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
- }
- }
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
- WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
- WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ wmJob *wm_job;
+ IconPreview *ip, *old_ip;
+
+ ED_preview_ensure_dbase();
+
+ /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ owner,
+ "Icon Preview",
+ WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND,
+ WM_JOB_TYPE_RENDER_PREVIEW);
+
+ ip = MEM_callocN(sizeof(IconPreview), "icon preview");
+
+ /* render all resolutions from suspended job too */
+ old_ip = WM_jobs_customdata_get(wm_job);
+ if (old_ip)
+ BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
+
+ /* customdata for preview thread */
+ ip->bmain = CTX_data_main(C);
+ ip->scene = CTX_data_scene(C);
+ ip->depsgraph = CTX_data_depsgraph(C);
+ ip->owner = owner;
+ ip->id = id;
+ ip->id_copy = duplicate_ids(id, ip->depsgraph);
+
+ icon_preview_add_size(ip, rect, sizex, sizey);
+
+ /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */
+ {
+ PreviewImage *prv_img = owner;
+ if (prv_img->tag & PRV_TAG_DEFFERED) {
+ prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
+ }
+ }
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
+ WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
+ WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method)
+void ED_preview_shader_job(const bContext *C,
+ void *owner,
+ ID *id,
+ ID *parent,
+ MTex *slot,
+ int sizex,
+ int sizey,
+ int method)
{
- Object *ob = CTX_data_active_object(C);
- wmJob *wm_job;
- ShaderPreview *sp;
- Scene *scene = CTX_data_scene(C);
- short id_type = GS(id->name);
-
- /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
-
- if (!check_engine_supports_preview(scene)) {
- return;
- }
-
- /* Only texture node preview is supported with Cycles. */
- if (method == PR_NODE_RENDER && id_type != ID_TE) {
- return;
- }
-
- ED_preview_ensure_dbase();
-
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview",
- WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
- sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
-
- /* customdata for preview thread */
- sp->scene = scene;
- sp->depsgraph = CTX_data_depsgraph(C);
- sp->owner = owner;
- sp->sizex = sizex;
- sp->sizey = sizey;
- sp->pr_method = method;
- sp->id = id;
- sp->id_copy = duplicate_ids(id, sp->depsgraph);
- sp->own_id_copy = true;
- sp->parent = parent;
- sp->slot = slot;
- sp->bmain = CTX_data_main(C);
- Material *ma = NULL;
-
- /* hardcoded preview .blend for Eevee + Cycles, this should be solved
- * once with custom preview .blend path for external engines */
-
- /* grease pencil use its own preview file */
- if (GS(id->name) == ID_MA) {
- ma = (Material *)id;
- }
-
- if ((ma == NULL) || (ma->gp_style == NULL)) {
- sp->pr_main = G_pr_main;
- }
- else {
- sp->pr_main = G_pr_main_grease_pencil;
- }
-
- if (ob && ob->totcol) {
- copy_v4_v4(sp->color, ob->color);
- }
- else {
- ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
- }
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
- WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
- WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ Object *ob = CTX_data_active_object(C);
+ wmJob *wm_job;
+ ShaderPreview *sp;
+ Scene *scene = CTX_data_scene(C);
+ short id_type = GS(id->name);
+
+ /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
+
+ if (!check_engine_supports_preview(scene)) {
+ return;
+ }
+
+ /* Only texture node preview is supported with Cycles. */
+ if (method == PR_NODE_RENDER && id_type != ID_TE) {
+ return;
+ }
+
+ ED_preview_ensure_dbase();
+
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ owner,
+ "Shader Preview",
+ WM_JOB_EXCL_RENDER,
+ WM_JOB_TYPE_RENDER_PREVIEW);
+ sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
+
+ /* customdata for preview thread */
+ sp->scene = scene;
+ sp->depsgraph = CTX_data_depsgraph(C);
+ sp->owner = owner;
+ sp->sizex = sizex;
+ sp->sizey = sizey;
+ sp->pr_method = method;
+ sp->id = id;
+ sp->id_copy = duplicate_ids(id, sp->depsgraph);
+ sp->own_id_copy = true;
+ sp->parent = parent;
+ sp->slot = slot;
+ sp->bmain = CTX_data_main(C);
+ Material *ma = NULL;
+
+ /* hardcoded preview .blend for Eevee + Cycles, this should be solved
+ * once with custom preview .blend path for external engines */
+
+ /* grease pencil use its own preview file */
+ if (GS(id->name) == ID_MA) {
+ ma = (Material *)id;
+ }
+
+ if ((ma == NULL) || (ma->gp_style == NULL)) {
+ sp->pr_main = G_pr_main;
+ }
+ else {
+ sp->pr_main = G_pr_main_grease_pencil;
+ }
+
+ if (ob && ob->totcol) {
+ copy_v4_v4(sp->color, ob->color);
+ }
+ else {
+ ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, sp, shader_preview_free);
+ WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
+ WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain))
{
- if (wm)
- WM_jobs_kill(wm, NULL, common_preview_startjob);
+ if (wm)
+ WM_jobs_kill(wm, NULL, common_preview_startjob);
}