Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/render/render_preview.c
| Show First 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | |||||
| typedef struct IconPreviewSize { | typedef struct IconPreviewSize { | ||||
| struct IconPreviewSize *next, *prev; | struct IconPreviewSize *next, *prev; | ||||
| int sizex, sizey; | int sizex, sizey; | ||||
| uint *rect; | uint *rect; | ||||
| } IconPreviewSize; | } IconPreviewSize; | ||||
| typedef struct IconPreview { | typedef struct IconPreview { | ||||
| Main *bmain; | Main *bmain; | ||||
| Depsgraph *depsgraph; /* May be NULL (see #WM_OT_previews_ensure). */ | |||||
| Scene *scene; | Scene *scene; | ||||
| void *owner; | void *owner; | ||||
| ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */ | ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */ | ||||
| ListBase sizes; | ListBase sizes; | ||||
| } IconPreview; | } IconPreview; | ||||
| /** \} */ | /** \} */ | ||||
| ▲ Show 20 Lines • Show All 647 Lines • ▼ Show 20 Lines | static void object_preview_render(IconPreview *preview, IconPreviewSize *preview_sized) | ||||
| DEG_graph_free(depsgraph); | DEG_graph_free(depsgraph); | ||||
| BKE_main_free(preview_main); | BKE_main_free(preview_main); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Action Preview | |||||
| * \{ */ | |||||
| /* Render a pose. It is assumed that the pose has already been applied and that the scene camera is | |||||
| * capturing the pose. In other words, this function just renders from the scene camera without | |||||
| * evaluating the Action stored in preview->id. */ | |||||
| static void action_preview_render(IconPreview *preview, IconPreviewSize *preview_sized) | |||||
| { | |||||
| char err_out[256] = ""; | |||||
| Depsgraph *depsgraph = preview->depsgraph; | |||||
| /* Not all code paths that lead to this function actually provide a depsgraph. | |||||
| * The "Refresh Asset Preview" button (ED_OT_lib_id_generate_preview) does, | |||||
| * but WM_OT_previews_ensure does not. */ | |||||
| BLI_assert(depsgraph != NULL); | |||||
| BLI_assert(preview->scene == DEG_get_input_scene(depsgraph)); | |||||
| Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); | |||||
| Object *camera_eval = scene_eval->camera; | |||||
| if (camera_eval == NULL) { | |||||
| printf("Scene has no camera, unable to render preview of %s without it.\n", | |||||
| preview->id->name + 2); | |||||
| return; | |||||
| } | |||||
| /* This renders with the Workbench engine settings stored on the Scene. */ | |||||
| ImBuf *ibuf = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, | |||||
| scene_eval, | |||||
| NULL, | |||||
| OB_SOLID, | |||||
| camera_eval, | |||||
| preview_sized->sizex, | |||||
| preview_sized->sizey, | |||||
| IB_rect, | |||||
| V3D_OFSDRAW_NONE, | |||||
| R_ALPHAPREMUL, | |||||
| NULL, | |||||
| NULL, | |||||
| err_out); | |||||
| if (err_out[0] != '\0') { | |||||
| printf("Error rendering Action %s preview: %s\n", preview->id->name + 2, err_out); | |||||
| } | |||||
| if (ibuf) { | |||||
| icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect); | |||||
| IMB_freeImBuf(ibuf); | |||||
| } | |||||
| } | |||||
| /** \} */ | |||||
| /* -------------------------------------------------------------------- */ | |||||
| /** \name New Shader Preview System | /** \name New Shader Preview System | ||||
| * \{ */ | * \{ */ | ||||
| /* inside thread, called by renderer, sets job update value */ | /* inside thread, called by renderer, sets job update value */ | ||||
| static void shader_preview_update(void *spv, | static void shader_preview_update(void *spv, | ||||
| RenderResult *UNUSED(rr), | RenderResult *UNUSED(rr), | ||||
| volatile struct rcti *UNUSED(rect)) | volatile struct rcti *UNUSED(rect)) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 616 Lines • ▼ Show 20 Lines | if (*stop) { | ||||
| break; | break; | ||||
| } | } | ||||
| if (prv->tag & PRV_TAG_DEFFERED_DELETE) { | if (prv->tag & PRV_TAG_DEFFERED_DELETE) { | ||||
| /* Non-thread-protected reading is not an issue here. */ | /* Non-thread-protected reading is not an issue here. */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (preview_method_is_render(pr_method) && !check_engine_supports_preview(ip->scene)) { | /* check_engine_supports_preview() checks whether the engine supports "preview mode" (think: | ||||
| * Material Preview). This check is only relevant when the render function called below is | |||||
| * going to use such a mode. Object and Action render functions use Solid mode, though, so they | |||||
| * can skip this test. */ | |||||
| /* TODO: Decouple the ID-type-specific render functions from this function, so that it's not | |||||
| * necessary to know here what happens inside lower-level functions. */ | |||||
| const bool use_solid_render_mode = (ip->id != NULL) && ELEM(GS(ip->id->name), ID_OB, ID_AC); | |||||
| if (!use_solid_render_mode && preview_method_is_render(pr_method) && | |||||
| !check_engine_supports_preview(ip->scene)) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||
| { | { | ||||
| int size_index = icon_previewimg_size_index_get(cur_size, prv); | int size_index = icon_previewimg_size_index_get(cur_size, prv); | ||||
| BLI_assert(!BKE_previewimg_is_finished(prv, size_index)); | BLI_assert(!BKE_previewimg_is_finished(prv, size_index)); | ||||
| } | } | ||||
| #endif | #endif | ||||
| if (ip->id && ELEM(GS(ip->id->name), ID_OB)) { | if (ip->id != NULL) { | ||||
| switch (GS(ip->id->name)) { | |||||
| case ID_OB: | |||||
| /* Much simpler than the ShaderPreview mess used for other ID types. */ | /* Much simpler than the ShaderPreview mess used for other ID types. */ | ||||
| object_preview_render(ip, cur_size); | object_preview_render(ip, cur_size); | ||||
| continue; | |||||
| case ID_AC: | |||||
| action_preview_render(ip, cur_size); | |||||
| continue; | |||||
| default: | |||||
| /* Fall through to the same code as the `ip->id == NULL` case. */ | |||||
| break; | |||||
| } | } | ||||
| else { | |||||
| other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress); | |||||
| } | } | ||||
| other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress); | |||||
| } | } | ||||
| } | } | ||||
| static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey) | static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey) | ||||
| { | { | ||||
| IconPreviewSize *cur_size = ip->sizes.first, *new_size; | IconPreviewSize *cur_size = ip->sizes.first, *new_size; | ||||
| while (cur_size) { | while (cur_size) { | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | static void icon_preview_free(void *customdata) | ||||
| if (ip->id_copy) { | if (ip->id_copy) { | ||||
| preview_id_copy_free(ip->id_copy); | preview_id_copy_free(ip->id_copy); | ||||
| } | } | ||||
| BLI_freelistN(&ip->sizes); | BLI_freelistN(&ip->sizes); | ||||
| MEM_freeN(ip); | MEM_freeN(ip); | ||||
| } | } | ||||
| void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, uint *rect, int sizex, int sizey) | void ED_preview_icon_render( | ||||
| Main *bmain, Depsgraph *depsgraph, Scene *scene, ID *id, uint *rect, int sizex, int sizey) | |||||
| { | { | ||||
| IconPreview ip = {NULL}; | IconPreview ip = {NULL}; | ||||
| short stop = false, update = false; | short stop = false, update = false; | ||||
| float progress = 0.0f; | float progress = 0.0f; | ||||
| ED_preview_ensure_dbase(); | ED_preview_ensure_dbase(); | ||||
| ip.bmain = bmain; | ip.bmain = bmain; | ||||
| ip.scene = scene; | ip.scene = scene; | ||||
| ip.depsgraph = depsgraph; | |||||
| ip.owner = BKE_previewimg_id_ensure(id); | ip.owner = BKE_previewimg_id_ensure(id); | ||||
| ip.id = id; | ip.id = id; | ||||
| /* Control isn't given back to the caller until the preview is done. So we don't need to copy | /* Control isn't given back to the caller until the preview is done. So we don't need to copy | ||||
| * the ID to avoid thread races. */ | * the ID to avoid thread races. */ | ||||
| ip.id_copy = duplicate_ids(id, true); | ip.id_copy = duplicate_ids(id, true); | ||||
| icon_preview_add_size(&ip, rect, sizex, sizey); | icon_preview_add_size(&ip, rect, sizex, sizey); | ||||
| Show All 28 Lines | void ED_preview_icon_job( | ||||
| /* render all resolutions from suspended job too */ | /* render all resolutions from suspended job too */ | ||||
| old_ip = WM_jobs_customdata_get(wm_job); | old_ip = WM_jobs_customdata_get(wm_job); | ||||
| if (old_ip) { | if (old_ip) { | ||||
| BLI_movelisttolist(&ip->sizes, &old_ip->sizes); | BLI_movelisttolist(&ip->sizes, &old_ip->sizes); | ||||
| } | } | ||||
| /* customdata for preview thread */ | /* customdata for preview thread */ | ||||
| ip->bmain = CTX_data_main(C); | ip->bmain = CTX_data_main(C); | ||||
| ip->scene = CTX_data_scene(C); | ip->depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | ||||
| ip->scene = DEG_get_input_scene(ip->depsgraph); | |||||
| ip->owner = owner; | ip->owner = owner; | ||||
| ip->id = id; | ip->id = id; | ||||
| ip->id_copy = duplicate_ids(id, false); | ip->id_copy = duplicate_ids(id, false); | ||||
| icon_preview_add_size(ip, rect, sizex, sizey); | icon_preview_add_size(ip, rect, sizex, sizey); | ||||
| /* Special threading hack: | /* Special threading hack: | ||||
| * warn main code that this preview is being rendered and cannot be freed... */ | * warn main code that this preview is being rendered and cannot be freed... */ | ||||
| ▲ Show 20 Lines • Show All 113 Lines • Show Last 20 Lines | |||||