diff options
author | Jacques Lucke <jacques@blender.org> | 2021-12-27 19:26:09 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-12-27 19:26:09 +0300 |
commit | 1c9d8fcb477c5aea5555781cc209d60da126f48f (patch) | |
tree | 0dfd7e47181b1750d9f6521ef71150ae7178fce5 /source/blender/editors/render/render_update.cc | |
parent | 644e6c7a3e99ae1d43edb25a7d4c3ed86727faba (diff) |
Render: move editor/render module to c++
Doing this in preparation for some work on asset preview generation.
Differential Revision: https://developer.blender.org/D13676
Diffstat (limited to 'source/blender/editors/render/render_update.cc')
-rw-r--r-- | source/blender/editors/render/render_update.cc | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/source/blender/editors/render/render_update.cc b/source/blender/editors/render/render_update.cc new file mode 100644 index 00000000000..24127cd6840 --- /dev/null +++ b/source/blender/editors/render/render_update.cc @@ -0,0 +1,351 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edrend + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_cachefile_types.h" +#include "DNA_light_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_world_types.h" + +#include "DRW_engine.h" + +#include "BLI_listbase.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_icons.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_node.h" +#include "BKE_paint.h" +#include "BKE_scene.h" + +#include "RE_engine.h" +#include "RE_pipeline.h" + +#include "ED_node.h" +#include "ED_paint.h" +#include "ED_render.h" +#include "ED_view3d.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "WM_api.h" + +#include <stdio.h> + +/* -------------------------------------------------------------------- */ +/** \name Render Engines + * \{ */ + +void ED_render_view3d_update(Depsgraph *depsgraph, + wmWindow *window, + ScrArea *area, + const bool updated) +{ + Main *bmain = DEG_get_bmain(depsgraph); + Scene *scene = DEG_get_input_scene(depsgraph); + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); + + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->regiontype != RGN_TYPE_WINDOW) { + continue; + } + + View3D *v3d = static_cast<View3D *>(area->spacedata.first); + RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); + RenderEngine *engine = rv3d->render_engine; + + /* call update if the scene changed, or if the render engine + * tagged itself for update (e.g. because it was busy at the + * time of the last update) */ + if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) { + /* Create temporary context to execute callback in. */ + bContext *C = CTX_create(); + CTX_data_main_set(C, bmain); + CTX_data_scene_set(C, scene); + CTX_wm_manager_set(C, static_cast<wmWindowManager *>(bmain->wm.first)); + CTX_wm_window_set(C, window); + CTX_wm_screen_set(C, WM_window_get_active_screen(window)); + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + + engine->flag &= ~RE_ENGINE_DO_UPDATE; + /* NOTE: Important to pass non-updated depsgraph, This is because this function is called + * from inside dependency graph evaluation. Additionally, if we pass fully evaluated one + * we will lose updates stored in the graph. */ + engine->type->view_update(engine, C, CTX_data_depsgraph_pointer(C)); + + CTX_free(C); + } + else { + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); + if (updated) { + DRWUpdateContext drw_context = {0}; + drw_context.bmain = bmain; + drw_context.depsgraph = depsgraph; + drw_context.scene = scene; + drw_context.view_layer = view_layer; + drw_context.region = region; + drw_context.v3d = v3d; + drw_context.engine_type = engine_type; + DRW_notify_view_update(&drw_context); + } + } + } +} + +void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, const bool updated) +{ + Main *bmain = update_ctx->bmain; + static bool recursive_check = false; + + /* don't do this render engine update if we're updating the scene from + * other threads doing e.g. rendering or baking jobs */ + if (!BLI_thread_is_main()) { + return; + } + + /* don't call this recursively for frame updates */ + if (recursive_check) { + return; + } + + /* Do not call if no WM available, see T42688. */ + if (BLI_listbase_is_empty(&bmain->wm)) { + return; + } + + recursive_check = true; + + wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + bScreen *screen = WM_window_get_active_screen(window); + + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + if (area->spacetype == SPACE_VIEW3D) { + ED_render_view3d_update(update_ctx->depsgraph, window, area, updated); + } + } + } + + recursive_check = false; +} + +void ED_render_engine_area_exit(Main *bmain, ScrArea *area) +{ + /* clear all render engines in this area */ + ARegion *region; + wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); + + if (area->spacetype != SPACE_VIEW3D) { + return; + } + + for (region = static_cast<ARegion *>(area->regionbase.first); region; region = region->next) { + if (region->regiontype != RGN_TYPE_WINDOW || !(region->regiondata)) { + continue; + } + ED_view3d_stop_render_preview(wm, region); + } +} + +void ED_render_engine_changed(Main *bmain, const bool update_scene_data) +{ + /* on changing the render engine type, clear all running render engines */ + for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen; + screen = static_cast<bScreen *>(screen->id.next)) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + ED_render_engine_area_exit(bmain, area); + } + } + RE_FreePersistentData(NULL); + /* Inform all render engines and draw managers. */ + DEGEditorUpdateContext update_ctx = {NULL}; + update_ctx.bmain = bmain; + for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene; + scene = static_cast<Scene *>(scene->id.next)) { + update_ctx.scene = scene; + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + /* TDODO(sergey): Iterate over depsgraphs instead? */ + update_ctx.depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer); + update_ctx.view_layer = view_layer; + ED_render_id_flush_update(&update_ctx, &scene->id); + } + if (scene->nodetree && update_scene_data) { + ntreeCompositUpdateRLayers(scene->nodetree); + } + } + + /* Update #CacheFiles to ensure that procedurals are properly taken into account. */ + LISTBASE_FOREACH (CacheFile *, cachefile, &bmain->cachefiles) { + /* Only update cache-files which are set to use a render procedural. + * We do not use #BKE_cachefile_uses_render_procedural here as we need to update regardless of + * the current engine or its settings. */ + if (cachefile->use_render_procedural) { + DEG_id_tag_update(&cachefile->id, ID_RECALC_COPY_ON_WRITE); + /* Rebuild relations so that modifiers are reconnected to or disconnected from the + * cache-file. */ + DEG_relations_tag_update(bmain); + } + } +} + +void ED_render_view_layer_changed(Main *bmain, bScreen *screen) +{ + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + ED_render_engine_area_exit(bmain, area); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Updates + * + * #ED_render_id_flush_update gets called from #DEG_id_tag_update, + * to do editor level updates when the ID changes. + * When these ID blocks are in the dependency graph, + * we can get rid of the manual dependency checks. + * \{ */ + +static void material_changed(Main *UNUSED(bmain), Material *ma) +{ + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&ma->id)); +} + +static void lamp_changed(Main *UNUSED(bmain), Light *la) +{ + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&la->id)); +} + +static void texture_changed(Main *bmain, Tex *tex) +{ + Scene *scene; + ViewLayer *view_layer; + bNode *node; + + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&tex->id)); + + for (scene = static_cast<Scene *>(bmain->scenes.first); scene; + scene = static_cast<Scene *>(scene->id.next)) { + /* paint overlays */ + for (view_layer = static_cast<ViewLayer *>(scene->view_layers.first); view_layer; + view_layer = view_layer->next) { + BKE_paint_invalidate_overlay_tex(scene, view_layer, tex); + } + /* find compositing nodes */ + if (scene->use_nodes && scene->nodetree) { + for (node = static_cast<bNode *>(scene->nodetree->nodes.first); node; node = node->next) { + if (node->id == &tex->id) { + ED_node_tag_update_id(&scene->id); + } + } + } + } +} + +static void world_changed(Main *UNUSED(bmain), World *wo) +{ + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); +} + +static void image_changed(Main *bmain, Image *ima) +{ + Tex *tex; + + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&ima->id)); + + /* textures */ + for (tex = static_cast<Tex *>(bmain->textures.first); tex; + tex = static_cast<Tex *>(tex->id.next)) { + if (tex->type == TEX_IMAGE && tex->ima == ima) { + texture_changed(bmain, tex); + } + } +} + +static void scene_changed(Main *bmain, Scene *scene) +{ + Object *ob; + + /* glsl */ + for (ob = static_cast<Object *>(bmain->objects.first); ob; + ob = static_cast<Object *>(ob->id.next)) { + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + BKE_texpaint_slots_refresh_object(scene, ob); + ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + } + } +} + +void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id) +{ + /* this can be called from render or baking thread when a python script makes + * changes, in that case we don't want to do any editor updates, and making + * GPU changes is not possible because OpenGL only works in the main thread */ + if (!BLI_thread_is_main()) { + return; + } + Main *bmain = update_ctx->bmain; + /* Internal ID update handlers. */ + switch (GS(id->name)) { + case ID_MA: + material_changed(bmain, (Material *)id); + break; + case ID_TE: + texture_changed(bmain, (Tex *)id); + break; + case ID_WO: + world_changed(bmain, (World *)id); + break; + case ID_LA: + lamp_changed(bmain, (Light *)id); + break; + case ID_IM: + image_changed(bmain, (Image *)id); + break; + case ID_SCE: + scene_changed(bmain, (Scene *)id); + break; + default: + break; + } +} + +/** \} */ |