WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
177 changed files with 2882 additions and 788 deletions
Showing only changes of commit 85ebff0e0a - Show all commits

View File

@ -703,12 +703,7 @@ mark_as_advanced(WITH_DRAW_DEBUG)
# LLVM
option(WITH_LLVM "Use LLVM" OFF)
if(APPLE)
# We prefer static llvm build on Apple, dyn build possible though.
option(LLVM_STATIC "Link with LLVM static libraries" ON)
else()
option(LLVM_STATIC "Link with LLVM static libraries" OFF)
endif()
option(LLVM_STATIC "Link with LLVM static libraries" OFF)
mark_as_advanced(LLVM_STATIC)
option(WITH_CLANG "Use Clang" OFF)
@ -1156,14 +1151,7 @@ set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_CYCLES_OSL OFF)
# Hydra requires USD.
set_and_warn_dependency(WITH_USD WITH_HYDRA OFF)
# auto enable openimageio for cycles
if(WITH_CYCLES)
# auto enable llvm for cycles_osl
if(WITH_CYCLES_OSL)
set(WITH_LLVM ON CACHE BOOL "" FORCE)
set(WITH_CLANG ON CACHE BOOL "" FORCE)
endif()
else()
if(NOT WITH_CYCLES)
set(WITH_CYCLES_OSL OFF)
endif()
@ -1382,18 +1370,6 @@ if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM)
message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON")
endif()
if(WITH_CYCLES)
if(WITH_CYCLES_OSL)
if(NOT WITH_LLVM)
message(
FATAL_ERROR
"Cycles OSL requires WITH_LLVM, the library may not have been found. "
"Configure LLVM or disable WITH_CYCLES_OSL"
)
endif()
endif()
endif()
if(WITH_INTERNATIONAL)
if(NOT WITH_BOOST)
message(

View File

@ -176,19 +176,6 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
} \
((void)0)
#define CLOG_STR_AT_SEVERITY_N(clg_ref, severity, verbose_level, str) \
{ \
CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || \
(severity >= CLG_SEVERITY_WARN)) \
{ \
const char *_str = str; \
CLG_log_str(_lg_ty, severity, __FILE__ ":" STRINGIFY(__LINE__), __func__, _str); \
MEM_freeN((void *)_str); \
} \
} \
((void)0)
#define CLOG_INFO(clg_ref, level, ...) \
CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_INFO, level, __VA_ARGS__)
#define CLOG_WARN(clg_ref, ...) CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_WARN, 0, __VA_ARGS__)
@ -201,13 +188,6 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
#define CLOG_STR_ERROR(clg_ref, str) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_ERROR, 0, str)
#define CLOG_STR_FATAL(clg_ref, str) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_FATAL, 0, str)
/* Allocated string which is immediately freed. */
#define CLOG_STR_INFO_N(clg_ref, level, str) \
CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_INFO, level, str)
#define CLOG_STR_WARN_N(clg_ref, str) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_WARN, 0, str)
#define CLOG_STR_ERROR_N(clg_ref, str) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_ERROR, 0, str)
#define CLOG_STR_FATAL_N(clg_ref, str) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_FATAL, 0, str)
#ifdef __cplusplus
}
#endif

View File

@ -93,7 +93,7 @@ macro(cycles_external_libraries_append libraries)
list(APPEND ${libraries} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
endif()
if(WITH_CYCLES_OSL)
list(APPEND ${libraries} ${OSL_LIBRARIES} ${CLANG_LIBRARIES} ${LLVM_LIBRARY})
list(APPEND ${libraries} ${OSL_LIBRARIES})
endif()
if(WITH_CYCLES_EMBREE)
list(APPEND ${libraries} ${EMBREE_LIBRARIES})

View File

@ -32,8 +32,6 @@ set(LIB
${OSL_LIBRARIES}
${OPENIMAGEIO_LIBRARIES}
${PUGIXML_LIBRARIES}
${CLANG_LIBRARIES}
${LLVM_LIBRARY}
)
if(APPLE)

View File

@ -3286,10 +3286,10 @@ static void data_device_handle_drop(void *data, wl_data_device * /*wl_data_devic
GHOST_SystemWayland *const system = seat->system;
if (mime_receive == ghost_wl_mime_text_uri) {
static constexpr const char *file_proto = "file://";
const char file_proto[] = "file://";
/* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`.
* So support both, once `\n` is found, strip the preceding `\r` if found. */
static constexpr const char *lf = "\n";
const char lf = '\n';
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_window);
std::vector<std::string> uris;

View File

@ -55,6 +55,10 @@ class GREASE_PENCIL_MT_grease_pencil_add_layer_extra(Menu):
layout.operator("grease_pencil.layer_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
layout.operator("grease_pencil.layer_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
layout.separator()
layout.operator("grease_pencil.layer_lock_all", icon='LOCKED', text="Lock All")
layout.operator("grease_pencil.layer_lock_all", icon='UNLOCKED', text="Unlock All").lock = False
class DATA_PT_grease_pencil_layers(DataButtonsPanel, Panel):
bl_label = "Layers"

View File

@ -151,7 +151,9 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
self.operator_modifier_add(layout, 'WIREFRAME')
if ob_type == 'GREASEPENCIL':
self.operator_modifier_add(layout, 'GREASE_PENCIL_DASH')
self.operator_modifier_add(layout, 'GREASE_PENCIL_LENGTH')
self.operator_modifier_add(layout, 'GREASE_PENCIL_MIRROR')
self.operator_modifier_add(layout, 'GREASE_PENCIL_MULTIPLY')
self.operator_modifier_add(layout, 'GREASE_PENCIL_SUBDIV')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)

View File

@ -94,7 +94,6 @@ std::string AS_asset_library_find_suitable_root_path_from_main(const Main *bmain
return AS_asset_library_find_suitable_root_path_from_path(bmain->filepath);
}
void AS_asset_library_remap_ids(const bke::id::IDRemapper &mappings)
{
AssetLibraryService *service = AssetLibraryService::get();

View File

@ -212,12 +212,13 @@ enum {
G_DEBUG_GPU = (1 << 16), /* gpu debug */
G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...). */
G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 18), /* force gpu workarounds bypassing detections. */
G_DEBUG_GPU_RENDERDOC = (1 << 19), /* Enable RenderDoc integration. */
G_DEBUG_XR = (1 << 20), /* XR/OpenXR messages */
G_DEBUG_XR_TIME = (1 << 21), /* XR/OpenXR timing messages */
G_DEBUG_GPU_COMPILE_SHADERS = (1 << 19), /* Compile all statically defined shaders. . */
G_DEBUG_GPU_RENDERDOC = (1 << 20), /* Enable RenderDoc integration. */
G_DEBUG_XR = (1 << 21), /* XR/OpenXR messages */
G_DEBUG_XR_TIME = (1 << 22), /* XR/OpenXR timing messages */
G_DEBUG_GHOST = (1 << 22), /* Debug GHOST module. */
G_DEBUG_WINTAB = (1 << 23), /* Debug Wintab. */
G_DEBUG_GHOST = (1 << 23), /* Debug GHOST module. */
G_DEBUG_WINTAB = (1 << 24), /* Debug Wintab. */
};
#define G_DEBUG_ALL \

View File

@ -513,6 +513,8 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
LayerGroup(const LayerGroup &other);
~LayerGroup();
LayerGroup &operator=(const LayerGroup &other);
public:
/* Define the common functions for #TreeNode. */
TREENODE_COMMON_METHODS;

View File

@ -33,6 +33,8 @@
#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#include "BLI_set.hh"
#include "DNA_userdef_enums.h"
struct BlendWriter;
@ -319,11 +321,23 @@ void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags) A
* This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
* (several times faster when deleting most of the IDs at once).
*
* \warning Considered experimental for now, seems to be working OK but this is
* risky code in a complicated area.
* \return Number of deleted data-blocks.
*/
size_t BKE_id_multi_tagged_delete(Main *bmain) ATTR_NONNULL();
/**
* Properly delete all IDs from \a ids_to_delete, from given \a bmain database.
*
* This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
* (several times faster when deleting most of the IDs at once).
*
* \note The ID pointers are not removed from the Set (which may contain more pointers than
* originally given, when extra users or dependencies also had to be deleted with the original set
* of IDs). They are all freed though, so these pointers are all invalid after calling this
* function.
*
* \return Number of deleted data-blocks.
*/
size_t BKE_id_multi_delete(Main *bmain, blender::Set<ID *> &ids_to_delete);
/**
* Add a 'NO_MAIN' data-block to given main (also sets user-counts of its IDs if needed).

View File

@ -22,6 +22,7 @@
#include "BLI_compiler_attrs.h"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
@ -48,10 +49,11 @@ enum {
*/
ID_REMAP_SKIP_NEVER_NULL_USAGE = 1 << 1,
/**
* This tells the callback func to flag with #LIB_DOIT all IDs
* using target one with a 'never NULL' pointer (like e.g. #Object.data).
* Store in the #IDRemapper all IDs using target one with a 'never NULL' pointer (like e.g.
* #Object.data), when such ID usage has (or should have) been remapped to `nullptr`. See also
* #ID_REMAP_FORCE_NEVER_NULL_USAGE and #ID_REMAP_SKIP_NEVER_NULL_USAGE.
*/
ID_REMAP_FLAG_NEVER_NULL_USAGE = 1 << 2,
ID_REMAP_STORE_NEVER_NULL_USAGE = 1 << 2,
/**
* This tells the callback func to force setting IDs
* using target one with a 'never NULL' pointer to NULL.
@ -163,12 +165,8 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_fla
/**
* Unlink given \a id from given \a bmain
* (does not touch to indirect, i.e. library, usages of the ID).
*
* \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by
* #LIB_TAG_DOIT flag (quite obviously, 'non-NULL' usages can never be unlinked by this function).
*/
void BKE_libblock_unlink(Main *bmain, void *idv, bool do_flag_never_null, bool do_skip_indirect)
ATTR_NONNULL();
void BKE_libblock_unlink(Main *bmain, void *idv, bool do_skip_indirect) ATTR_NONNULL();
/**
* Similar to libblock_remap, but only affects IDs used by given \a idv ID.
@ -263,10 +261,17 @@ class IDRemapper {
blender::Map<ID *, ID *> mappings_;
IDTypeFilter source_types_ = 0;
/**
* Store all IDs using another ID with the 'NEVER_NULL' flag, which have (or
* should have been) remapped to `nullptr`.
*/
blender::Set<ID *> never_null_users_;
public:
void clear(void)
{
mappings_.clear();
never_null_users_.clear();
source_types_ = 0;
}
@ -302,6 +307,16 @@ class IDRemapper {
IDRemapperApplyOptions options,
ID *id_self = nullptr) const;
void never_null_users_add(ID *id)
{
never_null_users_.add(id);
}
const blender::Set<ID *> &never_null_users(void) const
{
return never_null_users_;
}
/** Iterate over all remapping pairs in the remapper, and call the callback function on them. */
void iter(IDRemapperIterFunction func, void *user_data) const
{

View File

@ -17,6 +17,7 @@ struct UndoType;
struct bContext;
/* IDs */
struct GreasePencil;
struct Main;
struct Mesh;
struct Object;
@ -33,6 +34,7 @@ struct UndoRefID {
struct ptr_ty *ptr; \
char name[MAX_ID_NAME]; \
}
UNDO_REF_ID_TYPE(GreasePencil);
UNDO_REF_ID_TYPE(Mesh);
UNDO_REF_ID_TYPE(Object);
UNDO_REF_ID_TYPE(Scene);

View File

@ -4,12 +4,20 @@
#pragma once
#include "DNA_windowmanager_types.h"
namespace blender::bke {
class WindowManagerRuntime {
public:
/** Indicates whether interface is locked for user interaction. */
bool is_interface_locked = false;
/** Information and error reports. */
ReportList reports;
WindowManagerRuntime();
~WindowManagerRuntime();
};
} // namespace blender::bke

View File

@ -71,8 +71,18 @@ bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd);
void *BKE_ffmpeg_context_create(void);
void BKE_ffmpeg_context_free(void *context_v);
void BKE_ffmpeg_exit();
/**
* Gets a libswscale context for given size and format parameters.
* After you're done using the context, call #BKE_ffmpeg_sws_release_context
* to release it. Internally the contexts are coming from the context
* pool/cache.
*/
SwsContext *BKE_ffmpeg_sws_get_context(
int width, int height, int av_src_format, int av_dst_format, int sws_flags);
void BKE_ffmpeg_sws_release_context(SwsContext *ctx);
void BKE_ffmpeg_sws_scale_frame(SwsContext *ctx, AVFrame *dst, const AVFrame *src);
#endif

View File

@ -315,6 +315,7 @@ set(SRC
intern/volume_grid_file_cache.cc
intern/volume_render.cc
intern/volume_to_mesh.cc
intern/wm_runtime.cc
intern/workspace.cc
intern/world.cc
intern/writeavi.cc

View File

@ -36,6 +36,7 @@
#include "BKE_report.hh"
#include "BKE_screen.hh"
#include "BKE_studiolight.h"
#include "BKE_writeffmpeg.hh"
#include "DEG_depsgraph.hh"
@ -75,6 +76,9 @@ void BKE_blender_free()
BKE_callback_global_finalize();
IMB_moviecache_destruct();
#ifdef WITH_FFMPEG
BKE_ffmpeg_exit();
#endif
BKE_node_system_exit();
}

View File

@ -1131,7 +1131,7 @@ static void setup_app_data(bContext *C,
BLI_assert(BKE_main_namemap_validate(bmain));
if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
reports->duration.lib_overrides_resync = BLI_check_seconds_timer();
reports->duration.lib_overrides_resync = BLI_time_now_seconds();
BKE_lib_override_library_main_resync(
bmain,
@ -1139,7 +1139,7 @@ static void setup_app_data(bContext *C,
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene),
reports);
reports->duration.lib_overrides_resync = BLI_check_seconds_timer() -
reports->duration.lib_overrides_resync = BLI_time_now_seconds() -
reports->duration.lib_overrides_resync;
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */

View File

@ -767,7 +767,7 @@ wmMsgBus *CTX_wm_message_bus(const bContext *C)
ReportList *CTX_wm_reports(const bContext *C)
{
if (C->wm.manager) {
return &(C->wm.manager->reports);
return &(C->wm.manager->runtime->reports);
}
return nullptr;

View File

@ -79,7 +79,7 @@ PartDeflect *BKE_partdeflect_new(int type)
pd->pdef_sbift = 0.2f;
pd->pdef_sboft = 0.02f;
pd->pdef_cfrict = 5.0f;
pd->seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
pd->seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
pd->f_strength = 1.0f;
pd->f_damp = 1.0f;

View File

@ -1065,6 +1065,18 @@ LayerGroup::~LayerGroup()
this->runtime = nullptr;
}
LayerGroup &LayerGroup::operator=(const LayerGroup &other)
{
if (this == &other) {
return *this;
}
this->~LayerGroup();
new (this) LayerGroup(other);
return *this;
}
Layer &LayerGroup::add_layer(StringRefNull name)
{
Layer *new_layer = MEM_new<Layer>(__func__, name);
@ -1715,6 +1727,32 @@ blender::MutableSpan<GreasePencilDrawingBase *> GreasePencil::drawings()
this->drawing_array_num};
}
void GreasePencil::resize_drawings(const int new_num)
{
using namespace blender;
BLI_assert(new_num > 0);
const int prev_num = int(this->drawings().size());
if (new_num == prev_num) {
return;
}
if (new_num > prev_num) {
const int add_num = new_num - prev_num;
grow_array<GreasePencilDrawingBase *>(&this->drawing_array, &this->drawing_array_num, add_num);
}
else { /* if (new_num < prev_num) */
const int shrink_num = prev_num - new_num;
MutableSpan<GreasePencilDrawingBase *> old_drawings = this->drawings().drop_front(new_num);
for (const int64_t i : old_drawings.index_range()) {
if (old_drawings[i]) {
MEM_delete(old_drawings[i]);
}
}
shrink_array<GreasePencilDrawingBase *>(
&this->drawing_array, &this->drawing_array_num, shrink_num);
}
}
void GreasePencil::add_empty_drawings(const int add_num)
{
using namespace blender;

View File

@ -1494,7 +1494,7 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
void BKE_image_tag_time(Image *ima)
{
ima->lastused = BLI_check_seconds_timer_i();
ima->lastused = BLI_time_now_seconds_i();
}
static uintptr_t image_mem_size(Image *image)

View File

@ -585,7 +585,7 @@ void BKE_image_free_anim_gputextures(Main *bmain)
void BKE_image_free_old_gputextures(Main *bmain)
{
static int lasttime = 0;
int ctime = int(BLI_check_seconds_timer());
int ctime = int(BLI_time_now_seconds());
/*
* Run garbage collector once for every collecting period of time

View File

@ -8,8 +8,6 @@
* Contains management of ID's for freeing & deletion.
*/
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
/* all types are needed here, in order to do memory operations */
@ -18,8 +16,8 @@
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_set.hh"
#include "BLI_vector.hh"
#include "BKE_anim_data.h"
@ -44,8 +42,6 @@
using namespace blender::bke::id;
static CLG_LogRef LOG = {"bke.lib_id_delete"};
void BKE_libblock_free_data(ID *id, const bool do_id_user)
{
if (id->properties) {
@ -214,213 +210,132 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */
}
if (id->us == 0) {
BKE_libblock_unlink(bmain, id, false, false);
BKE_libblock_unlink(bmain, id, false);
BKE_id_free(bmain, id);
}
}
static size_t id_delete(Main *bmain,
const bool do_tagged_deletion,
blender::Set<ID *> &ids_to_delete,
const int extra_remapping_flags)
{
const int tag = LIB_TAG_DOIT;
ListBase *lbarray[INDEX_ID_MAX];
int base_count, i;
/* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database,
* and has already properly unlinked its other IDs usages.
* UI users are always cleared in BKE_libblock_remap_locked() call, so we can always skip it. */
const int free_flag = LIB_ID_FREE_NO_UI_USER |
(do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT :
0);
const int remapping_flags = (ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE |
const int free_flag = LIB_ID_FREE_NO_UI_USER | LIB_ID_FREE_NO_MAIN |
LIB_ID_FREE_NO_USER_REFCOUNT;
const int remapping_flags = (ID_REMAP_STORE_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE |
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | extra_remapping_flags);
ListBase tagged_deleted_ids = {nullptr};
base_count = set_listbasepointers(bmain, lbarray);
ListBase *lbarray[INDEX_ID_MAX];
const int base_count = set_listbasepointers(bmain, lbarray);
BKE_main_lock(bmain);
if (do_tagged_deletion) {
IDRemapper id_remapper;
BKE_layer_collection_resync_forbid();
BKE_layer_collection_resync_forbid();
IDRemapper id_remapper;
/* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
* This means that we won't have to loop over all deleted IDs to remove usages
* of other deleted IDs.
* This gives tremendous speed-up when deleting a large amount of IDs from a Main
* containing thousands of those.
* This also means that we have to be very careful here, as we by-pass many 'common'
* processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
bool keep_looping = true;
while (keep_looping) {
ID *id, *id_next;
keep_looping = false;
/* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
* This means that we won't have to loop over all deleted IDs to remove usages
* of other deleted IDs.
* This gives tremendous speed-up when deleting a large amount of IDs from a Main
* containing thousands of these.
* This also means that we have to be very careful here, as we by-pass many 'common'
* processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
bool keep_looping = true;
while (keep_looping) {
keep_looping = false;
/* First tag and remove from Main all datablocks directly from target lib.
* Note that we go forward here, since we want to check dependencies before users
* (e.g. meshes before objects). Avoids to have to loop twice. */
for (i = 0; i < base_count; i++) {
ListBase *lb = lbarray[i];
for (id = static_cast<ID *>(lb->first); id; id = id_next) {
id_next = static_cast<ID *>(id->next);
/* NOTE: in case we delete a library, we also delete all its datablocks! */
if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
BLI_remlink(lb, id);
BKE_main_namemap_remove_name(bmain, id, id->name + 2);
BLI_addtail(&tagged_deleted_ids, id);
id_remapper.add(id, nullptr);
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
* code has some specific handling of 'no main' IDs that would be a problem in that
* case). */
id->tag |= tag;
/* Forcefully also delete shapekeys of the deleted ID if any, 'orphaned' shapekeys are
* not allowed in Blender and will cause lots of problem in modern code (liboverrides,
* warning on write & read, etc.). */
Key *shape_key = BKE_key_from_id(id);
if (shape_key && (shape_key->id.tag & tag) == 0) {
BLI_remlink(&bmain->shapekeys, &shape_key->id);
BKE_main_namemap_remove_name(bmain, &shape_key->id, shape_key->id.name + 2);
BLI_addtail(&tagged_deleted_ids, &shape_key->id);
id_remapper.add(&shape_key->id, nullptr);
shape_key->id.tag |= tag;
}
keep_looping = true;
}
}
}
/* Will tag 'never nullptr' users of this ID too.
*
* NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags);
id_remapper.clear();
}
/* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */
blender::Vector<ID *> cleanup_ids;
for (ID *id = static_cast<ID *>(tagged_deleted_ids.first); id;
id = static_cast<ID *>(id->next))
{
cleanup_ids.append(id);
}
BKE_libblock_relink_multiple(bmain,
cleanup_ids,
ID_REMAP_TYPE_CLEANUP,
id_remapper,
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS |
ID_REMAP_SKIP_USER_CLEAR);
cleanup_ids.clear();
BKE_layer_collection_resync_allow();
BKE_main_collection_sync_remap(bmain);
/* Now we can safely mark that ID as not being in Main database anymore. */
/* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of
* deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID user-counts
* is never affected). */
for (ID *id = static_cast<ID *>(tagged_deleted_ids.first); id;
id = static_cast<ID *>(id->next))
{
id->tag |= LIB_TAG_NO_MAIN;
/* User-count needs to be reset artificially, since some usages may not be cleared in batch
* deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by
* remapping code, depending on order in which these are handled). */
id->us = ID_FAKE_USERS(id);
}
}
else {
/* First tag all data-blocks directly from target lib.
/* First tag and remove from Main all datablocks directly from target lib.
* Note that we go forward here, since we want to check dependencies before users
* (e.g. meshes before objects).
* Avoids to have to loop twice. */
IDRemapper remapper;
for (i = 0; i < base_count; i++) {
* (e.g. meshes before objects). Reduces the chances to have to loop many times in the
* `while (keep_looking)` outer loop. */
for (int i = 0; i < base_count; i++) {
ListBase *lb = lbarray[i];
ID *id, *id_next;
remapper.clear();
ID *id_iter;
for (id = static_cast<ID *>(lb->first); id; id = id_next) {
id_next = static_cast<ID *>(id->next);
FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
/* NOTE: in case we delete a library, we also delete all its datablocks! */
if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
id->tag |= tag;
remapper.add(id, nullptr);
if (ids_to_delete.contains(id_iter) ||
(ID_IS_LINKED(id_iter) && ids_to_delete.contains(&id_iter->lib->id)))
{
BLI_remlink(lb, id_iter);
BKE_main_namemap_remove_name(bmain, id_iter, id_iter->name + 2);
ids_to_delete.add(id_iter);
id_remapper.add(id_iter, nullptr);
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
* code has some specific handling of 'no main' IDs that would be a problem in that
* case). */
/* Forcefully also delete shapekeys of the deleted ID if any, 'orphaned' shapekeys are
* not allowed in Blender and will cause lots of problem in modern code (liboverrides,
* warning on write & read, etc.). */
Key *shape_key = BKE_key_from_id(id_iter);
if (shape_key && !ids_to_delete.contains(&shape_key->id)) {
BLI_remlink(&bmain->shapekeys, &shape_key->id);
BKE_main_namemap_remove_name(bmain, &shape_key->id, shape_key->id.name + 2);
ids_to_delete.add(&shape_key->id);
id_remapper.add(&shape_key->id, nullptr);
}
keep_looping = true;
}
}
if (remapper.is_empty()) {
continue;
}
/* Will tag 'never nullptr' users of this ID too.
*
* NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain, remapper, remapping_flags);
FOREACH_MAIN_LISTBASE_ID_END;
}
/* Will tag 'never nullptr' users of this ID too.
*
* NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags);
for (ID *id_never_null_iter : id_remapper.never_null_users()) {
ids_to_delete.add(id_never_null_iter);
}
id_remapper.clear();
}
/* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */
blender::Vector<ID *> cleanup_ids{ids_to_delete.begin(), ids_to_delete.end()};
BKE_libblock_relink_multiple(
bmain,
cleanup_ids,
ID_REMAP_TYPE_CLEANUP,
id_remapper,
(ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR));
cleanup_ids.clear();
/* Now we can safely mark that ID as not being in Main database anymore. */
/* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of
* deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID user-counts
* is never affected). */
for (ID *id : ids_to_delete) {
id->tag |= LIB_TAG_NO_MAIN;
/* User-count needs to be reset artificially, since some usages may not be cleared in batch
* deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by
* remapping code, depending on order in which these are handled). */
id->us = ID_FAKE_USERS(id);
id_free(bmain, id, free_flag, false);
}
BKE_main_unlock(bmain);
/* ViewLayer resync needs to be delayed during Scene freeing, since internal relationships
* between the Scene's master collection and its view_layers become invalid
* (due to remapping). */
BKE_layer_collection_resync_forbid();
/* In usual reversed order, such that all usage of a given ID, even 'never nullptr' ones,
* have been already cleared when we reach it
* (e.g. Objects being processed before meshes, they'll have already released their 'reference'
* over meshes when we come to freeing obdata). */
size_t num_datablocks_deleted = 0;
for (i = do_tagged_deletion ? 1 : base_count; i--;) {
ListBase *lb = lbarray[i];
ID *id, *id_next;
for (id = static_cast<ID *>(do_tagged_deletion ? tagged_deleted_ids.first : lb->first); id;
id = id_next)
{
id_next = static_cast<ID *>(id->next);
if (id->tag & tag) {
if (((id->tag & LIB_TAG_EXTRAUSER_SET) == 0 && ID_REAL_USERS(id) != 0) ||
((id->tag & LIB_TAG_EXTRAUSER_SET) != 0 && ID_REAL_USERS(id) != 1))
{
CLOG_ERROR(&LOG,
"Deleting %s which still has %d users (including %d 'extra' shallow users)\n",
id->name,
ID_REAL_USERS(id),
(id->tag & LIB_TAG_EXTRAUSER_SET) != 0 ? 1 : 0);
}
id_free(bmain, id, free_flag, !do_tagged_deletion);
++num_datablocks_deleted;
}
}
}
BKE_layer_collection_resync_allow();
BKE_main_collection_sync_remap(bmain);
bmain->is_memfile_undo_written = false;
return num_datablocks_deleted;
return size_t(ids_to_delete.size());
}
void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags)
{
BLI_assert_msg((((ID *)idv)->tag & LIB_TAG_NO_MAIN) == 0,
"Cannot be used with IDs outside of Main");
ID *id = static_cast<ID *>(idv);
BLI_assert_msg((id->tag & LIB_TAG_NO_MAIN) == 0, "Cannot be used with IDs outside of Main");
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
((ID *)idv)->tag |= LIB_TAG_DOIT;
id_delete(bmain, false, extra_remapping_flags);
blender::Set<ID *> ids_to_delete = {id};
id_delete(bmain, ids_to_delete, extra_remapping_flags);
}
void BKE_id_delete(Main *bmain, void *idv)
@ -430,7 +345,20 @@ void BKE_id_delete(Main *bmain, void *idv)
size_t BKE_id_multi_tagged_delete(Main *bmain)
{
return id_delete(bmain, true, 0);
blender::Set<ID *> ids_to_delete;
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
if (id_iter->tag & LIB_TAG_DOIT) {
ids_to_delete.add(id_iter);
}
}
FOREACH_MAIN_ID_END;
return id_delete(bmain, ids_to_delete, 0);
}
size_t BKE_id_multi_delete(Main *bmain, blender::Set<ID *> &ids_to_delete)
{
return id_delete(bmain, ids_to_delete, 0);
}
/* -------------------------------------------------------------------- */

View File

@ -3212,7 +3212,7 @@ static bool lib_override_library_main_resync_on_library_indirect_level(
BlendFileReadReport *reports)
{
const bool do_reports_recursive_resync_timing = (library_indirect_level != 0);
const double init_time = do_reports_recursive_resync_timing ? BLI_check_seconds_timer() : 0.0;
const double init_time = do_reports_recursive_resync_timing ? BLI_time_now_seconds() : 0.0;
BKE_main_relations_create(bmain, 0);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
@ -3518,7 +3518,7 @@ static bool lib_override_library_main_resync_on_library_indirect_level(
BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
if (do_reports_recursive_resync_timing) {
reports->duration.lib_overrides_recursive_resync += BLI_check_seconds_timer() - init_time;
reports->duration.lib_overrides_recursive_resync += BLI_time_now_seconds() - init_time;
}
return process_lib_level_again;

View File

@ -256,8 +256,11 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
skip_reference);
#endif
if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) {
id_owner->tag |= LIB_TAG_DOIT;
if ((id_remap_data->flag & ID_REMAP_STORE_NEVER_NULL_USAGE) &&
(cb_flag & IDWALK_CB_NEVER_NULL) &&
(expected_mapping_result == ID_REMAP_RESULT_SOURCE_UNASSIGNED))
{
id_remapper.never_null_users_add(id_owner);
}
/* Special hack in case it's Object->data and we are in edit mode, and new_id is not nullptr
@ -715,13 +718,9 @@ void BKE_libblock_remap_multiple(Main *bmain, IDRemapper &mappings, const int re
BKE_main_unlock(bmain);
}
void BKE_libblock_unlink(Main *bmain,
void *idv,
const bool do_flag_never_null,
const bool do_skip_indirect)
void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_skip_indirect)
{
const int remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0) |
(do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
const int remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0);
BKE_main_lock(bmain);

View File

@ -32,6 +32,8 @@
#include "MEM_guardedalloc.h"
using namespace blender::bke::id;
namespace blender::bke::tests {
class TestData {
@ -298,7 +300,7 @@ TEST(lib_remap, never_null_usage_flag_not_requested_on_delete)
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
}
TEST(lib_remap, never_null_usage_flag_requested_on_delete)
TEST(lib_remap, never_null_usage_storage_requested_on_delete)
{
Context<MeshObjectTestData> context;
@ -306,14 +308,19 @@ TEST(lib_remap, never_null_usage_flag_requested_on_delete)
EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
/* Never null usage is requested so the flag should be set. */
BKE_libblock_remap(context.test_data.bmain,
context.test_data.mesh,
nullptr,
ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_FLAG_NEVER_NULL_USAGE);
/* Never null usage is requested so the owner ID (the Object) should be added to the set. */
IDRemapper remapper;
remapper.add(&context.test_data.mesh->id, nullptr);
BKE_libblock_remap_multiple_locked(
context.test_data.bmain,
remapper,
(ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_STORE_NEVER_NULL_USAGE));
/* Never null usages unassignement is not enforced (no #ID_REMAP_FORCE_NEVER_NULL_USAGE), so the
* obdta should still use the original mesh. */
EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
EXPECT_NE(context.test_data.object->data, nullptr);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, LIB_TAG_DOIT);
EXPECT_TRUE(remapper.never_null_users().contains(&context.test_data.object->id));
}
TEST(lib_remap, never_null_usage_flag_not_requested_on_remap)
@ -332,7 +339,7 @@ TEST(lib_remap, never_null_usage_flag_not_requested_on_remap)
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
}
TEST(lib_remap, never_null_usage_flag_requested_on_remap)
TEST(lib_remap, never_null_usage_storage_requested_on_remap)
{
Context<MeshObjectTestData> context;
Mesh *other_mesh = BKE_mesh_add(context.test_data.bmain, nullptr);
@ -341,13 +348,16 @@ TEST(lib_remap, never_null_usage_flag_requested_on_remap)
EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
/* Never null usage is requested so the flag should be set. */
BKE_libblock_remap(context.test_data.bmain,
context.test_data.mesh,
other_mesh,
ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_FLAG_NEVER_NULL_USAGE);
/* Never null usage is requested, but the obdata is remapped to another Mesh, not to `nullptr`,
* so the `never_null_users` set should remain empty. */
IDRemapper remapper;
remapper.add(&context.test_data.mesh->id, &other_mesh->id);
BKE_libblock_remap_multiple_locked(
context.test_data.bmain,
remapper,
(ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_STORE_NEVER_NULL_USAGE));
EXPECT_EQ(context.test_data.object->data, other_mesh);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, LIB_TAG_DOIT);
EXPECT_TRUE(remapper.never_null_users().is_empty());
}
/** \} */

View File

@ -96,7 +96,7 @@ static void mesh_init_data(ID *id)
mesh->runtime = new blender::bke::MeshRuntime();
mesh->face_sets_color_seed = BLI_hash_int(BLI_check_seconds_timer_i() & UINT_MAX);
mesh->face_sets_color_seed = BLI_hash_int(BLI_time_now_seconds_i() & UINT_MAX);
}
static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)

View File

@ -2539,7 +2539,7 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node)
void nodeUniqueID(bNodeTree *ntree, bNode *node)
{
/* Use a pointer cast to avoid overflow warnings. */
const double time = BLI_check_seconds_timer() * 1000000.0;
const double time = BLI_time_now_seconds() * 1000000.0;
blender::RandomNumberGenerator id_rng{*reinterpret_cast<const uint32_t *>(&time)};
/* In the unlikely case that the random ID doesn't match, choose a new one until it does. */

View File

@ -1224,7 +1224,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *pbvh, BMEdge *
static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh)
{
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
bool any_subdivided = false;
@ -1267,7 +1267,7 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh
#endif
CLOG_INFO(
&LOG, 2, "Long edge subdivision took %f seconds.", BLI_check_seconds_timer() - start_time);
&LOG, 2, "Long edge subdivision took %f seconds.", BLI_time_now_seconds() - start_time);
return any_subdivided;
}
@ -1701,7 +1701,7 @@ static void pbvh_bmesh_collapse_edge(
static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh)
{
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
const float min_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
bool any_collapsed = false;
@ -1751,8 +1751,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh
BLI_ghash_free(deleted_verts, nullptr, nullptr);
CLOG_INFO(
&LOG, 2, "Short edge collapse took %f seconds.", BLI_check_seconds_timer() - start_time);
CLOG_INFO(&LOG, 2, "Short edge collapse took %f seconds.", BLI_time_now_seconds() - start_time);
return any_collapsed;
}

View File

@ -3297,7 +3297,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
char run[32], cur[32], etd[32];
int cancel = 0;
stime = ptime = BLI_check_seconds_timer();
stime = ptime = BLI_time_now_seconds();
for (int fr = scene->r.cfra; fr <= endframe; fr += baker->quick_step, scene->r.cfra = fr) {
BKE_scene_graph_update_for_newframe(depsgraph);
@ -3311,7 +3311,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
printf("bake: frame %d :: %d\n", scene->r.cfra, endframe);
}
else {
ctime = BLI_check_seconds_timer();
ctime = BLI_time_now_seconds();
fetd = (ctime - ptime) * (endframe - scene->r.cfra) / baker->quick_step;
@ -3343,7 +3343,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
if (use_timer) {
/* start with newline because of \r above */
ptcache_dt_to_str(run, sizeof(run), BLI_check_seconds_timer() - stime);
ptcache_dt_to_str(run, sizeof(run), BLI_time_now_seconds() - stime);
printf("\nBake %s %s (%i frames simulated).\n",
(cancel ? "canceled after" : "finished in"),
run,

View File

@ -3357,7 +3357,7 @@ static void softbody_step(
float forcetime;
double sct, sst;
sst = BLI_check_seconds_timer();
sst = BLI_time_now_seconds();
/* Integration back in time is possible in theory, but pretty useless here.
* So we refuse to do so. Since we do not know anything about 'outside' changes
* especially colliders we refuse to go more than 10 frames.
@ -3453,7 +3453,7 @@ static void softbody_step(
}
loops++;
if (sb->solverflags & SBSO_MONITOR) {
sct = BLI_check_seconds_timer();
sct = BLI_time_now_seconds();
if (sct - sst > 0.5) {
printf("%3.0f%% \r", 100.0f * timedone / dtime);
}
@ -3494,7 +3494,7 @@ static void softbody_step(
}
if (sb->solverflags & SBSO_MONITOR) {
sct = BLI_check_seconds_timer();
sct = BLI_time_now_seconds();
if ((sct - sst > 0.5) || (G.debug & G_DEBUG)) {
printf(" solver time %f sec %s\n", sct - sst, ob->id.name);
}

View File

@ -26,12 +26,12 @@ void BKE_subdiv_stats_init(SubdivStats *stats)
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
{
stats->begin_timestamp_[value] = BLI_check_seconds_timer();
stats->begin_timestamp_[value] = BLI_time_now_seconds();
}
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
{
stats->values_[value] = BLI_check_seconds_timer() - stats->begin_timestamp_[value];
stats->values_[value] = BLI_time_now_seconds() - stats->begin_timestamp_[value];
}
void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value)

View File

@ -0,0 +1,24 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include "BKE_report.hh"
#include "BKE_wm_runtime.hh"
namespace blender::bke {
WindowManagerRuntime::WindowManagerRuntime()
{
BKE_reports_init(&this->reports, RPT_STORE);
}
WindowManagerRuntime::~WindowManagerRuntime()
{
BKE_reports_free(&this->reports);
}
} // namespace blender::bke

View File

@ -28,6 +28,7 @@
# include "BLI_math_base.h"
# include "BLI_threads.h"
# include "BLI_utildefines.h"
# include "BLI_vector.hh"
# include "BKE_global.hh"
# include "BKE_image.h"
@ -56,6 +57,25 @@ extern "C" {
struct StampData;
/* libswscale context creation and destruction is expensive.
* Maintain a cache of already created contexts. */
constexpr int64_t swscale_cache_max_entries = 32;
struct SwscaleContext {
int width = 0, height = 0;
AVPixelFormat src_format = AV_PIX_FMT_NONE, dst_format = AV_PIX_FMT_NONE;
int flags = 0;
SwsContext *context = nullptr;
int64_t last_use_timestamp = 0;
bool is_used = false;
};
static ThreadMutex swscale_cache_lock = PTHREAD_MUTEX_INITIALIZER;
static int64_t swscale_cache_timestamp = 0;
static blender::Vector<SwscaleContext> *swscale_cache = nullptr;
struct FFMpegContext {
int ffmpeg_type;
AVCodecID ffmpeg_codec;
@ -665,7 +685,7 @@ static const AVCodec *get_av1_encoder(
return codec;
}
SwsContext *BKE_ffmpeg_sws_get_context(
static SwsContext *sws_create_context(
int width, int height, int av_src_format, int av_dst_format, int sws_flags)
{
# if defined(FFMPEG_SWSCALE_THREADING)
@ -703,6 +723,128 @@ SwsContext *BKE_ffmpeg_sws_get_context(
return c;
}
static void init_swscale_cache_if_needed()
{
if (swscale_cache == nullptr) {
swscale_cache = new blender::Vector<SwscaleContext>();
swscale_cache_timestamp = 0;
}
}
static bool remove_oldest_swscale_context()
{
int64_t oldest_index = -1;
int64_t oldest_time = 0;
for (int64_t index = 0; index < swscale_cache->size(); index++) {
SwscaleContext &ctx = (*swscale_cache)[index];
if (ctx.is_used) {
continue;
}
int64_t time = swscale_cache_timestamp - ctx.last_use_timestamp;
if (time > oldest_time) {
oldest_time = time;
oldest_index = index;
}
}
if (oldest_index >= 0) {
SwscaleContext &ctx = (*swscale_cache)[oldest_index];
sws_freeContext(ctx.context);
swscale_cache->remove_and_reorder(oldest_index);
return true;
}
return false;
}
static void maintain_swscale_cache_size()
{
while (swscale_cache->size() > swscale_cache_max_entries) {
if (!remove_oldest_swscale_context()) {
/* Could not remove anything (all contexts are actively used),
* stop trying. */
break;
}
}
}
SwsContext *BKE_ffmpeg_sws_get_context(
int width, int height, int av_src_format, int av_dst_format, int sws_flags)
{
BLI_mutex_lock(&swscale_cache_lock);
init_swscale_cache_if_needed();
swscale_cache_timestamp++;
/* Search for unused context that has suitable parameters. */
SwsContext *ctx = nullptr;
for (SwscaleContext &c : *swscale_cache) {
if (!c.is_used && c.width == width && c.height == height && c.src_format == av_src_format &&
c.dst_format == av_dst_format && c.flags == sws_flags)
{
ctx = c.context;
/* Mark as used. */
c.is_used = true;
c.last_use_timestamp = swscale_cache_timestamp;
break;
}
}
if (ctx == nullptr) {
/* No free matching context in cache: create a new one. */
ctx = sws_create_context(width, height, av_src_format, av_dst_format, sws_flags);
SwscaleContext c;
c.width = width;
c.height = height;
c.src_format = AVPixelFormat(av_src_format);
c.dst_format = AVPixelFormat(av_dst_format);
c.flags = sws_flags;
c.context = ctx;
c.is_used = true;
c.last_use_timestamp = swscale_cache_timestamp;
swscale_cache->append(c);
maintain_swscale_cache_size();
}
BLI_mutex_unlock(&swscale_cache_lock);
return ctx;
}
void BKE_ffmpeg_sws_release_context(SwsContext *ctx)
{
BLI_mutex_lock(&swscale_cache_lock);
init_swscale_cache_if_needed();
bool found = false;
for (SwscaleContext &c : *swscale_cache) {
if (c.context == ctx) {
BLI_assert_msg(c.is_used, "Releasing ffmpeg swscale context that is not in use");
c.is_used = false;
found = true;
break;
}
}
BLI_assert_msg(found, "Releasing ffmpeg swscale context that is not in cache");
UNUSED_VARS_NDEBUG(found);
maintain_swscale_cache_size();
BLI_mutex_unlock(&swscale_cache_lock);
}
void BKE_ffmpeg_exit()
{
BLI_mutex_lock(&swscale_cache_lock);
if (swscale_cache != nullptr) {
for (SwscaleContext &c : *swscale_cache) {
sws_freeContext(c.context);
}
delete swscale_cache;
swscale_cache = nullptr;
}
BLI_mutex_unlock(&swscale_cache_lock);
}
void BKE_ffmpeg_sws_scale_frame(SwsContext *ctx, AVFrame *dst, const AVFrame *src)
{
# if defined(FFMPEG_SWSCALE_THREADING)
@ -1677,7 +1819,7 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
}
if (context->img_convert_ctx != nullptr) {
sws_freeContext(context->img_convert_ctx);
BKE_ffmpeg_sws_release_context(context->img_convert_ctx);
context->img_convert_ctx = nullptr;
}
}

View File

@ -13,24 +13,20 @@
extern "C" {
#endif
extern
/** Return an indication of time, expressed as
* seconds since some fixed point. Successive calls
* are guaranteed to generate values greater than or
* equal to the last call. */
double
BLI_check_seconds_timer(void);
/**
* Return an indication of time, expressed as seconds since some fixed point.
* Successive calls are guaranteed to generate values greater than or equal to the last call.
*/
extern double BLI_time_now_seconds(void);
extern
/** `int` version of #BLI_check_seconds_timer. */
long int
BLI_check_seconds_timer_i(void);
/** `int` version of #BLI_time_now_seconds. */
extern long int BLI_time_now_seconds_i(void);
/**
* Platform-independent sleep function.
* \param ms: Number of milliseconds to sleep
*/
void BLI_sleep_ms(int ms);
void BLI_time_sleep_ms(int ms);
#ifdef __cplusplus
}

View File

@ -9,12 +9,12 @@
#pragma once
#include "BLI_time.h" /* for BLI_check_seconds_timer */
#include "BLI_time.h" /* for BLI_time_now_seconds */
#include "BLI_utildefines.h" /* for AT */
#define TIMEIT_START(var) \
{ \
double _timeit_##var = BLI_check_seconds_timer(); \
double _timeit_##var = BLI_time_now_seconds(); \
printf("time start (" #var "): " AT "\n"); \
fflush(stdout); \
{ \
@ -23,7 +23,7 @@
/**
* \return the time since TIMEIT_START was called.
*/
#define TIMEIT_VALUE(var) (float)(BLI_check_seconds_timer() - _timeit_##var)
#define TIMEIT_VALUE(var) (float)(BLI_time_now_seconds() - _timeit_##var)
#define TIMEIT_VALUE_PRINT(var) \
{ \
@ -54,7 +54,7 @@
{ \
static float _sum_##var = 0.0f; \
static float _num_##var = 0.0f; \
double _timeit_##var = BLI_check_seconds_timer(); \
double _timeit_##var = BLI_time_now_seconds(); \
printf("time start (" #var "): " AT "\n"); \
fflush(stdout); \
{ \
@ -95,13 +95,13 @@
#define TIMEIT_BLOCK_START(id) \
{ \
double _timeit_block_start_##id = BLI_check_seconds_timer(); \
double _timeit_block_start_##id = BLI_time_now_seconds(); \
{ \
(void)0
#define TIMEIT_BLOCK_END(id) \
} \
_timeit_var_##id += (BLI_check_seconds_timer() - _timeit_block_start_##id); \
_timeit_var_##id += (BLI_time_now_seconds() - _timeit_block_start_##id); \
} \
(void)0

View File

@ -12,7 +12,7 @@
#include "MEM_guardedalloc.h"
#define GET_TIME() BLI_check_seconds_timer()
#define GET_TIME() BLI_time_now_seconds()
typedef struct TimedFunction {
struct TimedFunction *next, *prev;

View File

@ -3557,7 +3557,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
return IMesh(tm_in);
}
# ifdef PERFDEBUG
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
std::cout << " boolean_trimesh, timing begins\n";
# endif
@ -3567,7 +3567,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "\nboolean_tm_input after intersection:\n" << tm_si;
}
# ifdef PERFDEBUG
double intersect_time = BLI_check_seconds_timer();
double intersect_time = BLI_time_now_seconds();
std::cout << " intersected, time = " << intersect_time - start_time << "\n";
# endif
@ -3578,12 +3578,12 @@ IMesh boolean_trimesh(IMesh &tm_in,
auto si_shape_fn = [shape_fn, tm_si](int t) { return shape_fn(tm_si.face(t)->orig); };
TriMeshTopology tm_si_topo(tm_si);
# ifdef PERFDEBUG
double topo_time = BLI_check_seconds_timer();
double topo_time = BLI_time_now_seconds();
std::cout << " topology built, time = " << topo_time - intersect_time << "\n";
# endif
bool pwn = is_pwn(tm_si, tm_si_topo);
# ifdef PERFDEBUG
double pwn_time = BLI_check_seconds_timer();
double pwn_time = BLI_time_now_seconds();
std::cout << " pwn checked, time = " << pwn_time - topo_time << "\n";
# endif
IMesh tm_out;
@ -3599,14 +3599,14 @@ IMesh boolean_trimesh(IMesh &tm_in,
tm_out = raycast_patches_boolean(tm_si, op, nshapes, shape_fn, pinfo, arena);
}
# ifdef PERFDEBUG
double raycast_time = BLI_check_seconds_timer();
double raycast_time = BLI_time_now_seconds();
std::cout << " raycast_boolean done, time = " << raycast_time - pwn_time << "\n";
# endif
}
else {
PatchesInfo pinfo = find_patches(tm_si, tm_si_topo);
# ifdef PERFDEBUG
double patch_time = BLI_check_seconds_timer();
double patch_time = BLI_time_now_seconds();
std::cout << " patches found, time = " << patch_time - pwn_time << "\n";
# endif
CellsInfo cinfo = find_cells(tm_si, tm_si_topo, pinfo);
@ -3614,12 +3614,12 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "Input is PWN\n";
}
# ifdef PERFDEBUG
double cell_time = BLI_check_seconds_timer();
double cell_time = BLI_time_now_seconds();
std::cout << " cells found, time = " << cell_time - pwn_time << "\n";
# endif
finish_patch_cell_graph(tm_si, cinfo, pinfo, tm_si_topo, arena);
# ifdef PERFDEBUG
double finish_pc_time = BLI_check_seconds_timer();
double finish_pc_time = BLI_time_now_seconds();
std::cout << " finished patch-cell graph, time = " << finish_pc_time - cell_time << "\n";
# endif
bool pc_ok = patch_cell_graph_ok(cinfo, pinfo);
@ -3631,7 +3631,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
cinfo.init_windings(nshapes);
int c_ambient = find_ambient_cell(tm_si, nullptr, tm_si_topo, pinfo, arena);
# ifdef PERFDEBUG
double amb_time = BLI_check_seconds_timer();
double amb_time = BLI_time_now_seconds();
std::cout << " ambient cell found, time = " << amb_time - finish_pc_time << "\n";
# endif
if (c_ambient == NO_INDEX) {
@ -3641,12 +3641,12 @@ IMesh boolean_trimesh(IMesh &tm_in,
}
propagate_windings_and_in_output_volume(pinfo, cinfo, c_ambient, op, nshapes, si_shape_fn);
# ifdef PERFDEBUG
double propagate_time = BLI_check_seconds_timer();
double propagate_time = BLI_time_now_seconds();
std::cout << " windings propagated, time = " << propagate_time - amb_time << "\n";
# endif
tm_out = extract_from_in_output_volume_diffs(tm_si, pinfo, cinfo, arena);
# ifdef PERFDEBUG
double extract_time = BLI_check_seconds_timer();
double extract_time = BLI_time_now_seconds();
std::cout << " extracted, time = " << extract_time - propagate_time << "\n";
# endif
if (dbg_level > 0) {
@ -3662,7 +3662,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "boolean tm output:\n" << tm_out;
}
# ifdef PERFDEBUG
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
std::cout << " boolean_trimesh done, total time = " << end_time - start_time << "\n";
# endif
return tm_out;
@ -3708,7 +3708,7 @@ IMesh boolean_mesh(IMesh &imesh,
IMesh *tm_in = imesh_triangulated;
IMesh our_triangulation;
# ifdef PERFDEBUG
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
std::cout << "boolean_mesh, timing begins\n";
# endif
if (tm_in == nullptr) {
@ -3716,7 +3716,7 @@ IMesh boolean_mesh(IMesh &imesh,
tm_in = &our_triangulation;
}
# ifdef PERFDEBUG
double tri_time = BLI_check_seconds_timer();
double tri_time = BLI_time_now_seconds();
std::cout << "triangulated, time = " << tri_time - start_time << "\n";
# endif
if (dbg_level > 1) {
@ -3724,7 +3724,7 @@ IMesh boolean_mesh(IMesh &imesh,
}
IMesh tm_out = boolean_trimesh(*tm_in, op, nshapes, shape_fn, use_self, hole_tolerant, arena);
# ifdef PERFDEBUG
double bool_tri_time = BLI_check_seconds_timer();
double bool_tri_time = BLI_time_now_seconds();
std::cout << "boolean_trimesh done, time = " << bool_tri_time - tri_time << "\n";
# endif
if (dbg_level > 1) {
@ -3733,7 +3733,7 @@ IMesh boolean_mesh(IMesh &imesh,
}
IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, imesh, arena);
# ifdef PERFDEBUG
double dissolve_time = BLI_check_seconds_timer();
double dissolve_time = BLI_time_now_seconds();
std::cout << "polymesh from dissolving, time = " << dissolve_time - bool_tri_time << "\n";
# endif
if (dbg_level > 0) {
@ -3744,7 +3744,7 @@ IMesh boolean_mesh(IMesh &imesh,
}
}
# ifdef PERFDEBUG
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
std::cout << "boolean_mesh done, total time = " << end_time - start_time << "\n";
# endif
return ans;

View File

@ -2954,7 +2954,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
# ifdef PERFDEBUG
perfdata_init();
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
std::cout << "trimesh_nary_intersect start\n";
# endif
/* Usually can use tm_in but if it has degenerate or illegal triangles,
@ -2972,17 +2972,17 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
}
# ifdef PERFDEBUG
double clean_time = BLI_check_seconds_timer();
double clean_time = BLI_time_now_seconds();
std::cout << "cleaned, time = " << clean_time - start_time << "\n";
# endif
Array<BoundingBox> tri_bb = calc_face_bounding_boxes(*tm_clean);
# ifdef PERFDEBUG
double bb_calc_time = BLI_check_seconds_timer();
double bb_calc_time = BLI_time_now_seconds();
std::cout << "bbs calculated, time = " << bb_calc_time - clean_time << "\n";
# endif
TriOverlaps tri_ov(*tm_clean, tri_bb, nshapes, shape_fn, use_self);
# ifdef PERFDEBUG
double overlap_time = BLI_check_seconds_timer();
double overlap_time = BLI_time_now_seconds();
std::cout << "intersect overlaps calculated, time = " << overlap_time - bb_calc_time << "\n";
# endif
Array<IMesh> tri_subdivided(tm_clean->face_size(), NoInitialization());
@ -2995,7 +2995,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
});
# ifdef PERFDEBUG
double plane_populate = BLI_check_seconds_timer();
double plane_populate = BLI_time_now_seconds();
std::cout << "planes populated, time = " << plane_populate - overlap_time << "\n";
# endif
/* itt_map((a,b)) will hold the intersection value resulting from intersecting
@ -3004,7 +3004,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
itt_map.reserve(tri_ov.overlap().size());
calc_overlap_itts(itt_map, *tm_clean, tri_ov, arena);
# ifdef PERFDEBUG
double itt_time = BLI_check_seconds_timer();
double itt_time = BLI_time_now_seconds();
std::cout << "itts found, time = " << itt_time - plane_populate << "\n";
# endif
CoplanarClusterInfo clinfo = find_clusters(*tm_clean, tri_bb, itt_map);
@ -3012,7 +3012,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
std::cout << clinfo;
}
# ifdef PERFDEBUG
double find_cluster_time = BLI_check_seconds_timer();
double find_cluster_time = BLI_time_now_seconds();
std::cout << "clusters found, time = " << find_cluster_time - itt_time << "\n";
doperfmax(0, tm_in.face_size());
doperfmax(1, clinfo.tot_cluster());
@ -3020,7 +3020,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
# endif
calc_subdivided_non_cluster_tris(tri_subdivided, *tm_clean, itt_map, clinfo, tri_ov, arena);
# ifdef PERFDEBUG
double subdivided_tris_time = BLI_check_seconds_timer();
double subdivided_tris_time = BLI_time_now_seconds();
std::cout << "subdivided non-cluster tris found, time = " << subdivided_tris_time - itt_time
<< "\n";
# endif
@ -3029,13 +3029,13 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
cluster_subdivided[c] = calc_cluster_subdivided(clinfo, c, *tm_clean, tri_ov, itt_map, arena);
}
# ifdef PERFDEBUG
double cluster_subdivide_time = BLI_check_seconds_timer();
double cluster_subdivide_time = BLI_time_now_seconds();
std::cout << "subdivided clusters found, time = "
<< cluster_subdivide_time - subdivided_tris_time << "\n";
# endif
calc_cluster_tris(tri_subdivided, *tm_clean, clinfo, cluster_subdivided, arena);
# ifdef PERFDEBUG
double extract_time = BLI_check_seconds_timer();
double extract_time = BLI_time_now_seconds();
std::cout << "subdivided cluster tris found, time = " << extract_time - cluster_subdivide_time
<< "\n";
# endif
@ -3045,7 +3045,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
std::cout << combined;
}
# ifdef PERFDEBUG
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
std::cout << "triangles combined, time = " << end_time - extract_time << "\n";
std::cout << "trimesh_nary_intersect done, total time = " << end_time - start_time << "\n";
dump_perfdata();

View File

@ -63,7 +63,7 @@
* // tag job 'processed
* BLI_threadpool_insert(&lb, job);
* }
* else BLI_sleep_ms(50);
* else BLI_time_sleep_ms(50);
*
* // Find if a job is ready, this the do_something_func() should write in job somewhere.
* cont = 0;
@ -687,7 +687,7 @@ void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
void *work = nullptr;
timespec timeout;
t = BLI_check_seconds_timer();
t = BLI_time_now_seconds();
wait_timeout(&timeout, ms);
/* wait until there is work */
@ -696,7 +696,7 @@ void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) {
break;
}
if (BLI_check_seconds_timer() - t >= ms * 0.001) {
if (BLI_time_now_seconds() - t >= ms * 0.001) {
break;
}
}

View File

@ -12,7 +12,7 @@
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
double BLI_check_seconds_timer(void)
double BLI_time_now_seconds(void)
{
static int hasperfcounter = -1; /* (-1 == unknown) */
static double perffreq;
@ -47,12 +47,12 @@ double BLI_check_seconds_timer(void)
}
}
long int BLI_check_seconds_timer_i(void)
long int BLI_time_now_seconds_i(void)
{
return (long int)BLI_check_seconds_timer();
return (long int)BLI_time_now_seconds();
}
void BLI_sleep_ms(int ms)
void BLI_time_sleep_ms(int ms)
{
Sleep(ms);
}
@ -62,7 +62,7 @@ void BLI_sleep_ms(int ms)
# include <sys/time.h>
# include <unistd.h>
double BLI_check_seconds_timer(void)
double BLI_time_now_seconds(void)
{
struct timeval tv;
struct timezone tz;
@ -72,7 +72,7 @@ double BLI_check_seconds_timer(void)
return ((double)tv.tv_sec + tv.tv_usec / 1000000.0);
}
long int BLI_check_seconds_timer_i(void)
long int BLI_time_now_seconds_i(void)
{
struct timeval tv;
struct timezone tz;
@ -82,7 +82,7 @@ long int BLI_check_seconds_timer_i(void)
return tv.tv_sec;
}
void BLI_sleep_ms(int ms)
void BLI_time_sleep_ms(int ms)
{
if (ms >= 1000) {
sleep(ms / 1000);

View File

@ -1877,9 +1877,9 @@ void text_test(
}
in.epsilon = b_before_arcs_in.epsilon;
in.need_ids = need_ids;
double tstart = BLI_check_seconds_timer();
double tstart = BLI_time_now_seconds();
CDT_result<T> out = delaunay_2d_calc(in, otype);
double tend = BLI_check_seconds_timer();
double tend = BLI_time_now_seconds();
if (print_timing) {
std::cout << "time = " << tend - tstart << "\n";
}
@ -2190,10 +2190,10 @@ void rand_delaunay_test(int test_kind,
}
/* Run the test. */
double tstart = BLI_check_seconds_timer();
double tstart = BLI_time_now_seconds();
CDT_result<T> out = delaunay_2d_calc(in, otype);
EXPECT_NE(out.vert.size(), 0);
times[lg_size] += BLI_check_seconds_timer() - tstart;
times[lg_size] += BLI_time_now_seconds() - tstart;
if (DO_DRAW) {
graph_draw<T>(test_label, out.vert, out.edge, out.face);
}

View File

@ -980,7 +980,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
return;
}
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = BLI_check_seconds_timer();
double time_start = BLI_time_now_seconds();
IMeshArena arena;
int nsegs = 2 * nrings;
int sphere_verts_num;
@ -1009,7 +1009,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
sphere_verts_num,
&arena);
IMesh mesh(tris);
double time_create = BLI_check_seconds_timer();
double time_create = BLI_time_now_seconds();
// write_obj_mesh(mesh, "spheresphere_in");
IMesh out;
if (use_self) {
@ -1020,7 +1020,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
double time_intersect = BLI_check_seconds_timer();
double time_intersect = BLI_time_now_seconds();
std::cout << "Create time: " << time_create - time_start << "\n";
std::cout << "Intersect time: " << time_intersect - time_create << "\n";
std::cout << "Total time: " << time_intersect - time_start << "\n";
@ -1120,7 +1120,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
return;
}
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = BLI_check_seconds_timer();
double time_start = BLI_time_now_seconds();
IMeshArena arena;
int sphere_verts_num;
int sphere_tris_num;
@ -1154,7 +1154,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
sphere_tris_num,
&arena);
IMesh mesh(tris);
double time_create = BLI_check_seconds_timer();
double time_create = BLI_time_now_seconds();
// write_obj_mesh(mesh, "spheregrid_in");
IMesh out;
if (use_self) {
@ -1165,7 +1165,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
double time_intersect = BLI_check_seconds_timer();
double time_intersect = BLI_time_now_seconds();
std::cout << "Create time: " << time_create - time_start << "\n";
std::cout << "Intersect time: " << time_intersect - time_create << "\n";
std::cout << "Total time: " << time_intersect - time_start << "\n";
@ -1187,7 +1187,7 @@ static void gridgrid_test(int x_level_1,
/* Make two grids, each 4x4, with given subdivision levels in x and y,
* and the second offset from the first by x_off, y_off, and rotated by rot_deg degrees. */
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = BLI_check_seconds_timer();
double time_start = BLI_time_now_seconds();
IMeshArena arena;
int x_subdivs_1 = 1 << x_level_1;
int y_subdivs_1 = 1 << y_level_1;
@ -1223,7 +1223,7 @@ static void gridgrid_test(int x_level_1,
grid_tris_1_num,
&arena);
IMesh mesh(tris);
double time_create = BLI_check_seconds_timer();
double time_create = BLI_time_now_seconds();
// write_obj_mesh(mesh, "gridgrid_in");
IMesh out;
if (use_self) {
@ -1234,7 +1234,7 @@ static void gridgrid_test(int x_level_1,
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
double time_intersect = BLI_check_seconds_timer();
double time_intersect = BLI_time_now_seconds();
std::cout << "Create time: " << time_create - time_start << "\n";
std::cout << "Intersect time: " << time_intersect - time_create << "\n";
std::cout << "Total time: " << time_intersect - time_start << "\n";

View File

@ -3666,7 +3666,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
}
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
fd->reports->duration.libraries = BLI_check_seconds_timer();
fd->reports->duration.libraries = BLI_time_now_seconds();
read_libraries(fd, &mainlist);
blo_join_main(&mainlist);
@ -3681,7 +3681,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
read_undo_remap_noundo_data(fd);
}
fd->reports->duration.libraries = BLI_check_seconds_timer() - fd->reports->duration.libraries;
fd->reports->duration.libraries = BLI_time_now_seconds() - fd->reports->duration.libraries;
/* Skip in undo case. */
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
@ -3739,7 +3739,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
* we can re-generate overrides from their references. */
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
/* Do not apply in undo case! */
fd->reports->duration.lib_overrides = BLI_check_seconds_timer();
fd->reports->duration.lib_overrides = BLI_time_now_seconds();
std::string cur_view_layer_name = bfd->cur_view_layer != nullptr ?
bfd->cur_view_layer->name :
@ -3760,7 +3760,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
* Proper fix involves first addressing #90610. */
BKE_main_collections_parent_relations_rebuild(bfd->main);
fd->reports->duration.lib_overrides = BLI_check_seconds_timer() -
fd->reports->duration.lib_overrides = BLI_time_now_seconds() -
fd->reports->duration.lib_overrides;
}

View File

@ -2592,7 +2592,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
ob = static_cast<Object *>(ob->id.next))
{
if (ob->pd) {
ob->pd->seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
ob->pd->seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
}
}
}

View File

@ -7763,7 +7763,7 @@ void BM_mesh_bevel(BMesh *bm,
}
#ifdef BEVEL_DEBUG_TIME
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
#endif
/* Disable the miters with the cutoff vertex mesh method, the combination isn't useful anyway. */
@ -7931,7 +7931,7 @@ void BM_mesh_bevel(BMesh *bm,
BLI_memarena_free(bp.mem_arena);
#ifdef BEVEL_DEBUG_TIME
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
printf("BMESH BEVEL TIME = %.3f\n", end_time - start_time);
#endif
}

View File

@ -350,11 +350,11 @@ static bool bmesh_boolean(BMesh *bm,
IMeshArena arena;
IMesh m_triangulated;
# ifdef PERF_DEBUG
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
# endif
IMesh m_in = mesh_from_bm(bm, looptris, looptris_tot, &m_triangulated, &arena);
# ifdef PERF_DEBUG
double mesh_time = BLI_check_seconds_timer();
double mesh_time = BLI_time_now_seconds();
std::cout << "bmesh_boolean, imesh_from_bm done, time = " << mesh_time - start_time << "\n";
# endif
std::function<int(int)> shape_fn;
@ -382,12 +382,12 @@ static bool bmesh_boolean(BMesh *bm,
IMesh m_out = boolean_mesh(
m_in, boolean_mode, nshapes, shape_fn, use_self, hole_tolerant, &m_triangulated, &arena);
# ifdef PERF_DEBUG
double boolean_time = BLI_check_seconds_timer();
double boolean_time = BLI_time_now_seconds();
std::cout << "boolean done, time = " << boolean_time - mesh_time << "\n";
# endif
bool any_change = apply_mesh_output_to_bmesh(bm, m_out, keep_hidden);
# ifdef PERF_DEBUG
double apply_mesh_time = BLI_check_seconds_timer();
double apply_mesh_time = BLI_time_now_seconds();
std::cout << "applied boolean output to bmesh, time = " << apply_mesh_time - boolean_time
<< "\n";
# endif

View File

@ -304,7 +304,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
} /** \note Early break out. */
uint chunk_index;
execution_start_time_ = BLI_check_seconds_timer();
execution_start_time_ = BLI_time_now_seconds();
chunks_finished_ = 0;
bTree_ = bTree;

View File

@ -73,7 +73,7 @@ void ScreenLensDistortionOperation::init_execution()
input_program_ = this->get_input_socket_reader(0);
this->init_mutex();
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= uint(POINTER_AS_INT(input_program_));
rng_ = BLI_rng_new(rng_seed);
}

View File

@ -7,6 +7,11 @@
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
ivec2 output_texel = texel + lower_bound;
if (any(greaterThan(output_texel, upper_bound))) {
return;
}
vec4 input_color = texture_load(input_tx, texel);
#if defined(DIRECT_OUTPUT)

View File

@ -7,6 +7,7 @@
GPU_SHADER_CREATE_INFO(compositor_write_output_shared)
.local_group_size(16, 16)
.push_constant(Type::IVEC2, "lower_bound")
.push_constant(Type::IVEC2, "upper_bound")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.compute_source("compositor_write_output.glsl");

View File

@ -29,7 +29,7 @@ void AbstractBuilderPipeline::build()
{
double start_time = 0.0;
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
start_time = BLI_check_seconds_timer();
start_time = BLI_time_now_seconds();
}
build_step_sanity_check();
@ -38,7 +38,7 @@ void AbstractBuilderPipeline::build()
build_step_finalize();
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
printf("Depsgraph built in %f seconds.\n", BLI_check_seconds_timer() - start_time);
printf("Depsgraph built in %f seconds.\n", BLI_time_now_seconds() - start_time);
}
}

View File

@ -33,7 +33,7 @@ void DepsgraphDebug::begin_graph_evaluation()
return;
}
const double current_time = BLI_check_seconds_timer();
const double current_time = BLI_time_now_seconds();
graph_evaluation_start_time_ = current_time;
}
@ -44,7 +44,7 @@ void DepsgraphDebug::end_graph_evaluation()
return;
}
const double graph_eval_end_time = BLI_check_seconds_timer();
const double graph_eval_end_time = BLI_time_now_seconds();
const double graph_eval_time = graph_eval_end_time - graph_evaluation_start_time_;
if (name.empty()) {

View File

@ -93,9 +93,9 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod
BLI_assert_msg(!operation_node->is_noop(), "NOOP nodes should not actually be scheduled");
/* Perform operation. */
if (state->do_stats) {
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
operation_node->evaluate(depsgraph);
operation_node->stats.current_time += BLI_check_seconds_timer() - start_time;
operation_node->stats.current_time += BLI_time_now_seconds() - start_time;
}
else {
operation_node->evaluate(depsgraph);

View File

@ -91,42 +91,14 @@ class Context : public realtime_compositor::Context {
return int2(float2(DRW_viewport_size_get()));
}
/* Returns true if the viewport is in camera view and has an opaque passepartout, that is, the
* area outside of the camera border is not visible. */
bool is_opaque_camera_view() const
{
/* Check if the viewport is in camera view. */
if (DRW_context_state_get()->rv3d->persp != RV3D_CAMOB) {
return false;
}
/* Check if the camera object that is currently in view is an actual camera. It is possible for
* a non camera object to be used as a camera, in which case, there will be no passepartout or
* any other camera setting, so those pseudo cameras can be ignored. */
Object *camera_object = DRW_context_state_get()->v3d->camera;
if (camera_object->type != OB_CAMERA) {
return false;
}
/* Check if the camera has passepartout active and is totally opaque. */
Camera *cam = static_cast<Camera *>(camera_object->data);
if (!(cam->flag & CAM_SHOWPASSEPARTOUT) || cam->passepartalpha != 1.0f) {
return false;
}
return true;
}
/* We limit the compositing region to the camera region if in camera view, while we use the
* entire viewport otherwise. */
rcti get_compositing_region() const override
{
const int2 viewport_size = int2(float2(DRW_viewport_size_get()));
const rcti render_region = rcti{0, viewport_size.x, 0, viewport_size.y};
/* If the camera view is not opaque, that means the content outside of the camera region is
* visible to some extent, so it would make sense to include them in the compositing region.
* Otherwise, we limit the compositing region to the visible camera region because anything
* outside of the camera region will not be visible anyways. */
if (!is_opaque_camera_view()) {
if (DRW_context_state_get()->rv3d->persp != RV3D_CAMOB) {
return render_region;
}

View File

@ -1453,7 +1453,7 @@ void EEVEE_lightbake_job(void *custom_data, wmJobWorkerStatus *worker_status)
* because this step is locking at this moment. */
/* TODO: remove this. */
if (lbake->delay) {
BLI_sleep_ms(lbake->delay);
BLI_time_sleep_ms(lbake->delay);
}
/* Render world irradiance and reflection first */

View File

@ -142,7 +142,7 @@ class LightBake {
DEG_evaluate_on_framechange(depsgraph_, frame_);
if (delay_ms_ > 0) {
BLI_sleep_ms(delay_ms_);
BLI_time_sleep_ms(delay_ms_);
}
context_enable();

View File

@ -25,7 +25,7 @@ void OVERLAY_mode_transfer_cache_init(OVERLAY_Data *vedata)
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
pd->mode_transfer.time = BLI_check_seconds_timer();
pd->mode_transfer.time = BLI_time_now_seconds();
for (int i = 0; i < 2; i++) {
/* Non Meshes Pass (Camera, empties, lights ...) */

View File

@ -692,7 +692,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
}
#ifdef DEBUG_TIME
double rdata_start = BLI_check_seconds_timer();
double rdata_start = BLI_time_now_seconds();
#endif
MeshRenderData *mr = mesh_render_data_create(
@ -703,7 +703,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
mr->use_simplify_normals = (scene->r.mode & R_SIMPLIFY) && (scene->r.mode & R_SIMPLIFY_NORMALS);
#ifdef DEBUG_TIME
double rdata_end = BLI_check_seconds_timer();
double rdata_end = BLI_time_now_seconds();
#endif
eMRIterType iter_type = extractors.iter_types();
@ -757,7 +757,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
#ifdef DEBUG_TIME
BLI_task_graph_work_and_wait(task_graph);
double end = BLI_check_seconds_timer();
double end = BLI_time_now_seconds();
static double avg = 0;
static double avg_fps = 0;

View File

@ -2323,7 +2323,7 @@ void DRW_create_subdivision(Object *ob,
#undef TIME_SUBDIV
#ifdef TIME_SUBDIV
const double begin_time = BLI_check_seconds_timer();
const double begin_time = BLI_time_now_seconds();
#endif
if (!draw_subdiv_create_requested_buffers(ob,
@ -2345,7 +2345,7 @@ void DRW_create_subdivision(Object *ob,
}
#ifdef TIME_SUBDIV
const double end_time = BLI_check_seconds_timer();
const double end_time = BLI_time_now_seconds();
fprintf(stderr, "Time to update subdivision: %f\n", end_time - begin_time);
fprintf(stderr, "Maximum FPS: %f\n", 1.0 / (end_time - begin_time));
#endif

View File

@ -58,19 +58,19 @@ struct CurvesUniformBufPool;
# define PROFILE_TIMER_FALLOFF 0.04
# define PROFILE_START(time_start) \
double time_start = BLI_check_seconds_timer(); \
double time_start = BLI_time_now_seconds(); \
((void)0)
# define PROFILE_END_ACCUM(time_accum, time_start) \
{ \
time_accum += (BLI_check_seconds_timer() - time_start) * 1e3; \
time_accum += (BLI_time_now_seconds() - time_start) * 1e3; \
} \
((void)0)
/* exp average */
# define PROFILE_END_UPDATE(time_update, time_start) \
{ \
double _time_delta = (BLI_check_seconds_timer() - time_start) * 1e3; \
double _time_delta = (BLI_time_now_seconds() - time_start) * 1e3; \
time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \
(_time_delta * PROFILE_TIMER_FALLOFF); \
} \

View File

@ -976,7 +976,7 @@ void DRW_cache_free_old_batches(Main *bmain)
using namespace blender::draw;
Scene *scene;
static int lasttime = 0;
int ctime = int(BLI_check_seconds_timer());
int ctime = int(BLI_time_now_seconds());
if (U.vbotimeout == 0 || (ctime - lasttime) < U.vbocollectrate || ctime == lasttime) {
return;

View File

@ -270,7 +270,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
DRW_deferred_shader_remove(mat);
/* Shaders could already be compiling. Have to wait for compilation to finish. */
while (GPU_material_status(mat) == GPU_MAT_QUEUED) {
BLI_sleep_ms(20);
BLI_time_sleep_ms(20);
}
if (GPU_material_status(mat) == GPU_MAT_CREATED) {
GPU_material_compile(mat);
@ -568,7 +568,7 @@ void DRW_shader_queue_optimize_material(GPUMaterial *mat)
DRW_deferred_shader_optimize_remove(mat);
/* If optimization job had already started, wait for it to complete. */
while (GPU_material_optimization_status(mat) == GPU_MAT_OPTIMIZATION_QUEUED) {
BLI_sleep_ms(20);
BLI_time_sleep_ms(20);
}
}
return;

View File

@ -4477,36 +4477,33 @@ static void ANIM_OT_channels_bake(wmOperatorType *ot)
"Bake Modifiers into keyframes and delete them after");
}
/* Find a Graph Editor area and modify the given context to be the window region of it. */
static bool move_context_to_graph_editor(bContext *C)
/**
* Find a Graph Editor area and set the context arguments accordingly.
*/
static bool context_find_graph_editor(bContext *C,
wmWindow **r_win,
ScrArea **r_area,
ARegion **r_region)
{
bool found_graph_editor = false;
LISTBASE_FOREACH (wmWindow *, win, &CTX_wm_manager(C)->windows) {
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype != SPACE_GRAPH) {
continue;
}
ARegion *window_region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (!window_region) {
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (!region) {
continue;
}
CTX_wm_window_set(C, win);
CTX_wm_screen_set(C, screen);
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, window_region);
found_graph_editor = true;
break;
}
if (found_graph_editor) {
break;
*r_win = win;
*r_area = area;
*r_region = region;
return true;
}
}
return found_graph_editor;
return false;
}
static void deselect_all_fcurves(bAnimContext *ac, const bool hide)
@ -4628,8 +4625,16 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
int retval = OPERATOR_FINISHED;
ListBase selection = {nullptr, nullptr};
struct {
wmWindow *win;
ScrArea *area;
ARegion *region;
} wm_context_prev = {nullptr}, wm_context_temp = {nullptr};
bool path_from_id;
std::optional<std::string> id_to_prop_path;
const bool selected_list_success = UI_context_copy_to_selected_list(
@ -4637,49 +4642,63 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
if (BLI_listbase_is_empty(&selection) || !selected_list_success) {
WM_report(RPT_ERROR, "Nothing selected");
BLI_freelistN(&selection);
return OPERATOR_CANCELLED;
retval = OPERATOR_CANCELLED;
}
const bool found_graph_editor = move_context_to_graph_editor(C);
if (!found_graph_editor) {
else if (!context_find_graph_editor(
C, &wm_context_temp.win, &wm_context_temp.area, &wm_context_temp.region))
{
WM_report(RPT_WARNING, "No open Graph Editor window found");
return OPERATOR_CANCELLED;
retval = OPERATOR_CANCELLED;
}
else {
wm_context_prev.win = CTX_wm_window(C);
wm_context_prev.area = CTX_wm_area(C);
wm_context_prev.region = CTX_wm_region(C);
bAnimContext ac;
if (!ANIM_animdata_get_context(C, &ac)) {
/* This might never be called since we are manually setting the Graph Editor just before. */
WM_report(RPT_ERROR, "Cannot create the Animation Context");
return OPERATOR_CANCELLED;
CTX_wm_window_set(C, wm_context_temp.win);
CTX_wm_area_set(C, wm_context_temp.area);
CTX_wm_region_set(C, wm_context_temp.region);
bAnimContext ac;
if (!ANIM_animdata_get_context(C, &ac)) {
/* This might never be called since we are manually setting the Graph Editor just before. */
WM_report(RPT_ERROR, "Cannot create the Animation Context");
retval = OPERATOR_CANCELLED;
}
else {
const bool isolate = RNA_boolean_get(op->ptr, "isolate");
deselect_all_fcurves(&ac, isolate);
const bool whole_array = RNA_boolean_get(op->ptr, "all");
rctf bounds = calculate_selection_fcurve_bounds_and_unhide(
C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array);
if (!BLI_rctf_is_valid(&bounds)) {
WM_report(RPT_ERROR, "F-Curves have no valid size");
retval = OPERATOR_CANCELLED;
}
else {
ARegion *region = wm_context_temp.region;
ScrArea *area = wm_context_temp.area;
add_region_padding(C, region, &bounds);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
UI_view2d_smooth_view(C, region, &bounds, smooth_viewtx);
/* This ensures the channel list updates. */
ED_area_tag_redraw(area);
}
}
CTX_wm_window_set(C, wm_context_prev.win);
CTX_wm_area_set(C, wm_context_prev.area);
CTX_wm_region_set(C, wm_context_prev.region);
}
const bool isolate = RNA_boolean_get(op->ptr, "isolate");
deselect_all_fcurves(&ac, isolate);
const bool whole_array = RNA_boolean_get(op->ptr, "all");
rctf bounds = calculate_selection_fcurve_bounds_and_unhide(
C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array);
BLI_freelistN(&selection);
if (!BLI_rctf_is_valid(&bounds)) {
WM_report(RPT_ERROR, "F-Curves have no valid size");
return OPERATOR_CANCELLED;
}
ARegion *region = CTX_wm_region(C);
add_region_padding(C, region, &bounds);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
UI_view2d_smooth_view(C, region, &bounds, smooth_viewtx);
/* This ensures the channel list updates. */
ED_area_tag_redraw(CTX_wm_area(C));
return OPERATOR_FINISHED;
return retval;
}
static void ANIM_OT_view_curve_in_graph_editor(wmOperatorType *ot)

View File

@ -2146,7 +2146,7 @@ static void annotation_draw_apply_event(
}
}
p->curtime = BLI_check_seconds_timer();
p->curtime = BLI_time_now_seconds();
/* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */
p->pressure = event->tablet.pressure;

View File

@ -2159,7 +2159,7 @@ static tGPsdata *gpencil_session_initpaint(bContext *C, wmOperator *op)
}
/* Random generator, only init once. */
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= POINTER_AS_UINT(p);
p->rng = BLI_rng_new(rng_seed);
@ -2961,7 +2961,7 @@ static void gpencil_draw_apply_event(bContext *C,
}
}
p->curtime = BLI_check_seconds_timer();
p->curtime = BLI_time_now_seconds();
/* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */
p->pressure = event->tablet.pressure;

View File

@ -363,7 +363,7 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
gpencil_primitive_allocate_memory(tgpi);
/* Random generator, only init once. */
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
tgpi->rng = BLI_rng_new(rng_seed);
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);

View File

@ -1165,7 +1165,7 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->settings = gpencil_sculpt_get_settings(scene);
/* Random generator, only init once. */
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= POINTER_AS_UINT(gso);
gso->rng = BLI_rng_new(rng_seed);

View File

@ -2838,7 +2838,7 @@ void ED_gpencil_init_random_settings(Brush *brush,
const int mval[2],
GpRandomSettings *random_settings)
{
int seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
int seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
/* Use mouse position to get randomness. */
int ix = mval[0] * seed;
int iy = mval[1] * seed;
@ -2884,7 +2884,7 @@ static void gpencil_sbuffer_vertex_color_random(
{
BrushGpencilSettings *brush_settings = brush->gpencil_settings;
if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
int seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
int seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
int ix = int(tpt->m_xy[0] * seed);
int iy = int(tpt->m_xy[1] * seed);

View File

@ -29,6 +29,7 @@ set(SRC
intern/grease_pencil_material.cc
intern/grease_pencil_ops.cc
intern/grease_pencil_select.cc
intern/grease_pencil_undo.cc
intern/grease_pencil_utils.cc
)
@ -38,6 +39,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
PRIVATE bf::intern::clog
extern_curve_fit_nd
)

View File

@ -428,6 +428,47 @@ static void GREASE_PENCIL_OT_layer_isolate(wmOperatorType *ot)
RNA_def_boolean(
ot->srna, "affect_visibility", false, "Affect Visibility", "Also affect the visibility");
}
static int grease_pencil_layer_lock_all_exec(bContext *C, wmOperator *op)
{
using namespace blender::bke::greasepencil;
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
const bool lock_value = RNA_boolean_get(op->ptr, "lock");
if (grease_pencil.layers().is_empty()) {
return OPERATOR_CANCELLED;
}
for (Layer *layer : grease_pencil.layers_for_write()) {
layer->set_locked(lock_value);
}
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, nullptr);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_layer_lock_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Lock All Layers";
ot->idname = "GREASE_PENCIL_OT_layer_lock_all";
ot->description =
"Lock all Grease Pencil layers to prevent them from being accidentally modified";
/* callbacks */
ot->exec = grease_pencil_layer_lock_all_exec;
ot->poll = active_grease_pencil_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_boolean(ot->srna, "lock", true, "Lock Value", "Lock/Unlock all layers");
}
} // namespace blender::ed::greasepencil
void ED_operatortypes_grease_pencil_layers()
@ -440,6 +481,7 @@ void ED_operatortypes_grease_pencil_layers()
WM_operatortype_append(GREASE_PENCIL_OT_layer_hide);
WM_operatortype_append(GREASE_PENCIL_OT_layer_reveal);
WM_operatortype_append(GREASE_PENCIL_OT_layer_isolate);
WM_operatortype_append(GREASE_PENCIL_OT_layer_lock_all);
WM_operatortype_append(GREASE_PENCIL_OT_layer_group_add);
}

View File

@ -0,0 +1,424 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgrease_pencil
*/
#include "BLI_string.h"
#include "BLI_task.hh"
#include "BKE_context.hh"
#include "BKE_curves.hh"
#include "BKE_customdata.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_undo_system.hh"
#include "CLG_log.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"
#include "ED_grease_pencil.hh"
#include "ED_undo.hh"
#include "MEM_guardedalloc.h"
#include "WM_api.hh"
#include "WM_types.hh"
#include <iostream>
#include <ostream>
static CLG_LogRef LOG = {"ed.undo.greasepencil"};
namespace blender::ed::greasepencil::undo {
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
*
* \note This is similar for all edit-mode types.
* \{ */
/**
* Store all drawings, layers and layers data, in each undo step.
*
* Each drawing type has its own array in the undo #StepObject data.
*
* NOTE: Storing Reference drawings is also needed, since drawings can be added or removed, data
* from Reference ones also needs to be stored.
*/
/* Store contextual data and status info during undo step encoding or decoding. */
struct StepEncodeStatus {};
struct StepDecodeStatus {
/**
* In case some reference drawing needs to be re-created, the GreasePencil ID gets a new
* relation to another GreasePencil ID.
*/
bool needs_relationships_update = false;
};
class StepDrawingGeometryBase {
protected:
/* Index of this drawing in the original combined array of all drawings in GreasePencil ID. */
int index_;
/* Data from #GreasePencilDrawingBase that needs to be saved in udo steps. */
uint32_t flag_;
protected:
/* Ensures that the drawing from the given array at the current index exists, and has the propoer
* type.
*
* Non-existing drawings can happen after extenting the drawings array.
*
* Mismatch in drawing types can happen when some drawings have been deleted between the undo
* step storage, and the current state of the GreasePencil data. */
void decode_valid_drawingtype_at_index_ensure(MutableSpan<GreasePencilDrawingBase *> &drawings,
const GreasePencilDrawingType drawing_type) const
{
/* TODO: Maybe that code should rather be part of GreasePencil:: API, together with
* `add_empty_drawings` and such? */
GreasePencilDrawingBase *drawing = drawings[index_];
if (drawing != nullptr) {
if (drawing->type == drawing_type) {
return;
}
switch (drawing->type) {
case GP_DRAWING:
MEM_delete(&reinterpret_cast<GreasePencilDrawing *>(drawing)->wrap());
break;
case GP_DRAWING_REFERENCE:
MEM_delete(&reinterpret_cast<GreasePencilDrawingReference *>(drawing)->wrap());
break;
}
drawing = nullptr;
}
if (drawing == nullptr) {
switch (drawing_type) {
case GP_DRAWING:
drawings[index_] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::Drawing>(__func__));
break;
case GP_DRAWING_REFERENCE:
drawings[index_] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::DrawingReference>(__func__));
break;
}
}
}
};
class StepDrawingGeometry : public StepDrawingGeometryBase {
bke::CurvesGeometry geometry_;
public:
void encode(const GreasePencilDrawing &drawing_geometry,
const int64_t drawing_index,
StepEncodeStatus & /* encode_status */)
{
BLI_assert(drawing_index >= 0 && drawing_index < INT32_MAX);
index_ = int(drawing_index);
flag_ = drawing_geometry.base.flag;
geometry_ = drawing_geometry.geometry.wrap();
}
void decode(GreasePencil &grease_pencil, StepDecodeStatus & /*decode_status*/) const
{
MutableSpan<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
this->decode_valid_drawingtype_at_index_ensure(drawings, GP_DRAWING);
BLI_assert(drawings[index_]->type == GP_DRAWING);
GreasePencilDrawing &drawing_geometry = *reinterpret_cast<GreasePencilDrawing *>(
drawings[index_]);
drawing_geometry.base.flag = flag_;
drawing_geometry.geometry.wrap() = geometry_;
/* TODO: Check if there is a way to tell if both stored and current geometry are still the
* same, to avoid recomputing the cache all the time for all drawings? */
drawing_geometry.runtime->triangles_cache.tag_dirty();
}
};
class StepDrawingReference : public StepDrawingGeometryBase {
UndoRefID_GreasePencil grease_pencil_ref_ = {};
public:
void encode(const GreasePencilDrawingReference &drawing_reference,
const int64_t drawing_index,
StepEncodeStatus & /* encode_status */)
{
BLI_assert(drawing_index >= 0 && drawing_index < INT32_MAX);
index_ = int(drawing_index);
flag_ = drawing_reference.base.flag;
grease_pencil_ref_.ptr = drawing_reference.id_reference;
}
void decode(GreasePencil &grease_pencil, StepDecodeStatus &decode_status) const
{
MutableSpan<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
this->decode_valid_drawingtype_at_index_ensure(drawings, GP_DRAWING_REFERENCE);
BLI_assert(drawings[index_]->type == GP_DRAWING_REFERENCE);
GreasePencilDrawingReference &drawing_reference =
*reinterpret_cast<GreasePencilDrawingReference *>(drawings[index_]);
drawing_reference.base.flag = flag_;
if (drawing_reference.id_reference != grease_pencil_ref_.ptr) {
id_us_min(reinterpret_cast<ID *>(drawing_reference.id_reference));
drawing_reference.id_reference = grease_pencil_ref_.ptr;
id_us_plus(reinterpret_cast<ID *>(drawing_reference.id_reference));
decode_status.needs_relationships_update = true;
}
}
void foreach_id_ref(UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
{
foreach_ID_ref_fn(user_data, reinterpret_cast<UndoRefID *>(&grease_pencil_ref_));
}
};
class StepObject {
public:
UndoRefID_Object obedit_ref = {};
private:
Array<StepDrawingGeometry> drawings_geometry_;
Array<StepDrawingReference> drawings_reference_;
int layers_num_ = 0;
bke::greasepencil::LayerGroup root_group_;
std::string active_layer_name_;
CustomData layers_data_ = {};
private:
void encode_drawings(const GreasePencil &grease_pencil, StepEncodeStatus &encode_status)
{
const Span<const GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
int64_t drawings_geometry_num = 0;
int64_t drawings_reference_num = 0;
for (const int64_t idx : drawings.index_range()) {
const GreasePencilDrawingBase &drawing = *drawings[idx];
switch (drawing.type) {
case GP_DRAWING:
drawings_geometry_num++;
break;
case GP_DRAWING_REFERENCE:
drawings_reference_num++;
break;
}
}
drawings_geometry_.reinitialize(drawings_geometry_num);
drawings_reference_.reinitialize(drawings_reference_num);
int drawings_geometry_idx = 0;
int drawings_reference_idx = 0;
for (const int64_t idx : drawings.index_range()) {
const GreasePencilDrawingBase &drawing = *drawings[idx];
switch (drawing.type) {
case GP_DRAWING:
drawings_geometry_[drawings_geometry_idx++].encode(
reinterpret_cast<const GreasePencilDrawing &>(drawing), idx, encode_status);
break;
case GP_DRAWING_REFERENCE:
drawings_reference_[drawings_reference_idx++].encode(
reinterpret_cast<const GreasePencilDrawingReference &>(drawing), idx, encode_status);
break;
}
}
}
void decode_drawings(GreasePencil &grease_pencil, StepDecodeStatus &decode_status) const
{
const int drawing_array_num = int(drawings_geometry_.size() + drawings_reference_.size());
grease_pencil.resize_drawings(drawing_array_num);
for (const StepDrawingGeometry &drawing : drawings_geometry_) {
drawing.decode(grease_pencil, decode_status);
}
for (const StepDrawingReference &drawing : drawings_reference_) {
drawing.decode(grease_pencil, decode_status);
}
}
void encode_layers(const GreasePencil &grease_pencil, StepEncodeStatus & /*encode_status*/)
{
layers_num_ = int(grease_pencil.layers().size());
CustomData_copy(
&grease_pencil.layers_data, &layers_data_, eCustomDataMask(CD_MASK_ALL), layers_num_);
if (grease_pencil.has_active_layer()) {
active_layer_name_ = grease_pencil.get_active_layer()->name();
}
root_group_ = grease_pencil.root_group();
}
void decode_layers(GreasePencil &grease_pencil, StepDecodeStatus & /*decode_status*/) const
{
if (grease_pencil.root_group_ptr) {
MEM_delete(&grease_pencil.root_group());
}
grease_pencil.root_group_ptr = MEM_new<bke::greasepencil::LayerGroup>(__func__, root_group_);
BLI_assert(layers_num_ == grease_pencil.layers().size());
if (!active_layer_name_.empty()) {
const bke::greasepencil::TreeNode *active_node =
grease_pencil.root_group().find_node_by_name(active_layer_name_);
if (active_node && active_node->is_layer()) {
grease_pencil.set_active_layer(&active_node->as_layer());
}
}
CustomData_copy(
&layers_data_, &grease_pencil.layers_data, eCustomDataMask(CD_MASK_ALL), layers_num_);
}
public:
void encode(Object *ob, StepEncodeStatus &encode_status)
{
const GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
this->obedit_ref.ptr = ob;
this->encode_drawings(grease_pencil, encode_status);
this->encode_layers(grease_pencil, encode_status);
}
void decode(StepDecodeStatus &decode_status) const
{
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(this->obedit_ref.ptr->data);
this->decode_drawings(grease_pencil, decode_status);
this->decode_layers(grease_pencil, decode_status);
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
}
void foreach_id_ref(UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
{
foreach_ID_ref_fn(user_data, reinterpret_cast<UndoRefID *>(&this->obedit_ref));
for (StepDrawingReference &drawing_ref : drawings_reference_) {
drawing_ref.foreach_id_ref(foreach_ID_ref_fn, user_data);
}
}
};
struct GreasePencilUndoStep {
UndoStep step;
/** See #ED_undo_object_editmode_validate_scene_from_windows code comment for details. */
UndoRefID_Scene scene_ref = {};
Array<StepObject> objects;
};
static bool step_encode(bContext *C, Main *bmain, UndoStep *us_p)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
StepEncodeStatus encode_status;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_num = 0;
Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_num);
BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(objects); })
us->scene_ref.ptr = scene;
new (&us->objects) Array<StepObject>(objects_num);
threading::parallel_for(us->objects.index_range(), 8, [&](const IndexRange range) {
for (const int64_t i : range) {
Object *ob = objects[i];
us->objects[i].encode(ob, encode_status);
}
});
bmain->is_memfile_undo_flush_needed = true;
return true;
}
static void step_decode(
bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
StepDecodeStatus decode_status;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
ED_undo_object_editmode_validate_scene_from_windows(
CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
ED_undo_object_editmode_restore_helper(scene,
view_layer,
&us->objects.first().obedit_ref.ptr,
uint(us->objects.size()),
sizeof(decltype(us->objects)::value_type));
BLI_assert(BKE_object_is_in_editmode(us->objects.first().obedit_ref.ptr));
for (const StepObject &step_object : us->objects) {
step_object.decode(decode_status);
}
if (decode_status.needs_relationships_update) {
DEG_relations_tag_update(bmain);
}
ED_undo_object_set_active_or_warn(
scene, view_layer, us->objects.first().obedit_ref.ptr, us_p->name, &LOG);
bmain->is_memfile_undo_flush_needed = true;
WM_event_add_notifier(C, NC_GEOM | ND_DATA, nullptr);
}
static void step_free(UndoStep *us_p)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
us->objects.~Array();
}
static void foreach_ID_ref(UndoStep *us_p,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void *user_data)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
foreach_ID_ref_fn(user_data, reinterpret_cast<UndoRefID *>(&us->scene_ref));
for (StepObject &object : us->objects) {
object.foreach_id_ref(foreach_ID_ref_fn, user_data);
}
}
/** \} */
} // namespace blender::ed::greasepencil::undo
void ED_undosys_type_grease_pencil(UndoType *ut)
{
using namespace blender::ed;
ut->name = "Edit GreasePencil";
ut->poll = greasepencil::editable_grease_pencil_poll;
ut->step_encode = greasepencil::undo::step_encode;
ut->step_decode = greasepencil::undo::step_decode;
ut->step_free = greasepencil::undo::step_free;
ut->step_foreach_ID_ref = greasepencil::undo::foreach_ID_ref;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(greasepencil::undo::GreasePencilUndoStep);
}

View File

@ -25,6 +25,7 @@ struct KeyframeEditData;
struct wmKeyConfig;
struct ToolSettings;
struct Scene;
struct UndoType;
struct ViewDepths;
struct View3D;
namespace blender {
@ -51,6 +52,8 @@ void ED_operatortypes_grease_pencil_edit();
void ED_operatortypes_grease_pencil_material();
void ED_operatormacros_grease_pencil();
void ED_keymap_grease_pencil(wmKeyConfig *keyconf);
void ED_undosys_type_grease_pencil(UndoType *undo_type);
/**
* Get the selection mode for Grease Pencil selection operators: point, stroke, segment.
*/

View File

@ -54,7 +54,7 @@ struct SceneFPS_State {
/**
* Update frame rate info for viewport drawing.
* \param ltime: Time since the last update,
* compatible with the result of #BLI_check_seconds_timer.
* compatible with the result of #BLI_time_now_seconds.
*/
void ED_scene_fps_average_accumulate(Scene *scene, short fps_samples, double ltime)
ATTR_NONNULL(1);

View File

@ -4398,7 +4398,7 @@ static void ui_block_open_end(bContext *C, uiBut *but, uiHandleButtonData *data)
but->editval = nullptr;
but->editvec = nullptr;
but->block->auto_open_last = BLI_check_seconds_timer();
but->block->auto_open_last = BLI_time_now_seconds();
}
if (data->menu) {
@ -8650,7 +8650,7 @@ static void button_activate_init(bContext *C,
* want to allow auto opening adjacent menus even if no button is activated
* in between going over to the other button, but only for a short while */
if (type == BUTTON_ACTIVATE_OVER && but->block->auto_open == true) {
if (but->block->auto_open_last + BUTTON_AUTO_OPEN_THRESH < BLI_check_seconds_timer()) {
if (but->block->auto_open_last + BUTTON_AUTO_OPEN_THRESH < BLI_time_now_seconds()) {
but->block->auto_open = false;
}
}
@ -8696,7 +8696,7 @@ static void button_activate_init(bContext *C,
if (UI_but_has_tooltip_label(but)) {
/* Show a label for this button. */
bScreen *screen = WM_window_get_active_screen(data->window);
if ((BLI_check_seconds_timer() - WM_tooltip_time_closed()) < 0.1) {
if ((BLI_time_now_seconds() - WM_tooltip_time_closed()) < 0.1) {
WM_tooltip_immediate_init(C, CTX_wm_window(C), data->area, region, ui_but_tooltip_init);
if (screen->tool_tip) {
screen->tool_tip->pass = 1;
@ -9977,7 +9977,7 @@ static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu,
menu->towardstime = DBL_MAX; /* unlimited time */
}
else {
menu->towardstime = BLI_check_seconds_timer();
menu->towardstime = BLI_time_now_seconds();
}
}
}
@ -10057,7 +10057,7 @@ static bool ui_mouse_motion_towards_check(uiBlock *block,
}
/* 1 second timer */
if (BLI_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) {
if (BLI_time_now_seconds() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) {
menu->dotowards = false;
}

View File

@ -1791,7 +1791,7 @@ static void ui_do_animate(bContext *C, Panel *panel)
uiHandlePanelData *data = static_cast<uiHandlePanelData *>(panel->activedata);
ARegion *region = CTX_wm_region(C);
float fac = (BLI_check_seconds_timer() - data->starttime) / ANIMATION_TIME;
float fac = (BLI_time_now_seconds() - data->starttime) / ANIMATION_TIME;
fac = min_ff(sqrtf(fac), 1.0f);
if (uiAlignPanelStep(region, fac, false)) {
@ -2649,7 +2649,7 @@ static void panel_handle_data_ensure(const bContext *C,
data->startofsy = panel->ofsy;
data->start_cur_xmin = region->v2d.cur.xmin;
data->start_cur_ymin = region->v2d.cur.ymin;
data->starttime = BLI_check_seconds_timer();
data->starttime = BLI_time_now_seconds();
}
/**

View File

@ -191,7 +191,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
menu = ui_popup_block_create(C, nullptr, nullptr, nullptr, ui_block_func_PIE, pie, nullptr);
menu->popup = true;
menu->towardstime = BLI_check_seconds_timer();
menu->towardstime = BLI_time_now_seconds();
UI_popup_handlers_add(C, &window->modalhandlers, menu, WM_HANDLER_ACCEPT_DBL_CLICK);
WM_event_add_mousemove(window);

View File

@ -6091,7 +6091,7 @@ static std::string progress_tooltip_func(bContext * /*C*/, void *argN, const cha
/* create tooltip text and associate it with the job */
char elapsed_str[32];
char remaining_str[32] = "Unknown";
const double elapsed = BLI_check_seconds_timer() - WM_jobs_starttime(wm, owner);
const double elapsed = BLI_time_now_seconds() - WM_jobs_starttime(wm, owner);
BLI_timecode_string_from_time_simple(elapsed_str, sizeof(elapsed_str), elapsed);
if (progress) {

View File

@ -98,7 +98,7 @@ void UI_view2d_edge_pan_reset(View2DEdgePanData *vpd)
{
vpd->edge_pan_start_time_x = 0.0;
vpd->edge_pan_start_time_y = 0.0;
vpd->edge_pan_last_time = BLI_check_seconds_timer();
vpd->edge_pan_last_time = BLI_time_now_seconds();
vpd->initial_rect = vpd->region->v2d.cur;
}
@ -250,7 +250,7 @@ void UI_view2d_edge_pan_apply(bContext *C, View2DEdgePanData *vpd, const int xy[
}
}
const double current_time = BLI_check_seconds_timer();
const double current_time = BLI_time_now_seconds();
edge_pan_manage_delay_timers(vpd, pan_dir_x, pan_dir_y, current_time);
/* Calculate the delta since the last time the operator was called. */

View File

@ -1031,7 +1031,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
/* Check if the 'timer' is initialized, as zooming with the trackpad
* never uses the "Continuous" zoom method, and the 'timer' is not initialized. */
if ((U.viewzoom == USER_ZOOM_CONTINUE) && vzd->timer) { /* XXX store this setting as RNA prop? */
const double time = BLI_check_seconds_timer();
const double time = BLI_time_now_seconds();
const float time_step = float(time - vzd->timer_lastdraw);
dx *= time_step * 5.0f;
@ -1231,7 +1231,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
if (U.viewzoom == USER_ZOOM_CONTINUE) {
/* needs a timer to continue redrawing */
vzd->timer = WM_event_timer_add(CTX_wm_manager(C), window, TIMER, 0.01f);
vzd->timer_lastdraw = BLI_check_seconds_timer();
vzd->timer_lastdraw = BLI_time_now_seconds();
}
return OPERATOR_RUNNING_MODAL;

View File

@ -92,13 +92,13 @@ void EDBM_automerge_and_split(Object *obedit,
#ifdef DEBUG_TIME
em->bm = BM_mesh_copy(bm);
double t1 = BLI_check_seconds_timer();
double t1 = BLI_time_now_seconds();
EDBM_automerge(obedit, false, hflag, dist);
t1 = BLI_check_seconds_timer() - t1;
t1 = BLI_time_now_seconds() - t1;
BM_mesh_free(em->bm);
em->bm = bm;
double t2 = BLI_check_seconds_timer();
double t2 = BLI_time_now_seconds();
#endif
BMOperator weldop;
@ -118,7 +118,7 @@ void EDBM_automerge_and_split(Object *obedit,
BMO_op_finish(bm, &weldop);
#ifdef DEBUG_TIME
t2 = BLI_check_seconds_timer() - t2;
t2 = BLI_time_now_seconds() - t2;
printf("t1: %lf; t2: %lf; fac: %lf\n", t1, t2, t1 / t2);
#endif

View File

@ -3982,6 +3982,9 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op)
/* select the newly generated faces */
BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
/* No need to flush the selection, any selection history is no longer valid. */
BM_select_history_clear(bm);
if (!EDBM_op_finish(em, &bmop, op, true)) {
continue;
}

View File

@ -433,7 +433,7 @@ static void object_overlay_mode_transfer_animation_start(bContext *C, Object *ob
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
ob_dst_eval->runtime->overlay_mode_transfer_start_time = BLI_check_seconds_timer();
ob_dst_eval->runtime->overlay_mode_transfer_start_time = BLI_time_now_seconds();
}
static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base_dst)

View File

@ -327,7 +327,7 @@ static void dpaint_bake_endjob(void *customdata)
if (job->success) {
/* Show bake info */
WM_reportf(
RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", BLI_check_seconds_timer() - job->start);
RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", BLI_time_now_seconds() - job->start);
}
else {
if (strlen(canvas->error)) { /* If an error occurred */
@ -438,7 +438,7 @@ static void dpaint_bake_startjob(void *customdata, wmJobWorkerStatus *worker_sta
job->stop = &worker_status->stop;
job->do_update = &worker_status->do_update;
job->progress = &worker_status->progress;
job->start = BLI_check_seconds_timer();
job->start = BLI_time_now_seconds();
job->success = 1;
G.is_break = false;

View File

@ -550,7 +550,7 @@ static void PE_free_shape_tree(PEData *data)
static void PE_create_random_generator(PEData *data)
{
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= POINTER_AS_UINT(data->ob);
rng_seed ^= POINTER_AS_UINT(data->edit);
data->rng = BLI_rng_new(rng_seed);

View File

@ -338,7 +338,7 @@ static void fluid_bake_endjob(void *customdata)
if (job->success) {
/* Show bake info. */
WM_reportf(
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_check_seconds_timer() - job->start);
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_time_now_seconds() - job->start);
}
else {
if (fds->error[0] != '\0') {
@ -361,7 +361,7 @@ static void fluid_bake_startjob(void *customdata, wmJobWorkerStatus *worker_stat
job->stop = &worker_status->stop;
job->do_update = &worker_status->do_update;
job->progress = &worker_status->progress;
job->start = BLI_check_seconds_timer();
job->start = BLI_time_now_seconds();
job->success = 1;
G.is_break = false;
@ -446,7 +446,7 @@ static void fluid_free_endjob(void *customdata)
if (job->success) {
/* Show free job info */
WM_reportf(
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_check_seconds_timer() - job->start);
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_time_now_seconds() - job->start);
}
else {
if (fds->error[0] != '\0') {
@ -466,7 +466,7 @@ static void fluid_free_startjob(void *customdata, wmJobWorkerStatus *worker_stat
job->stop = &worker_status->stop;
job->do_update = &worker_status->do_update;
job->progress = &worker_status->progress;
job->start = BLI_check_seconds_timer();
job->start = BLI_time_now_seconds();
job->success = 1;
G.is_break = false;

View File

@ -459,7 +459,7 @@ static void make_renderinfo_string(const RenderStats *rs,
info_time = info_buffers.time_elapsed;
BLI_timecode_string_from_time_simple(info_buffers.time_elapsed,
sizeof(info_buffers.time_elapsed),
BLI_check_seconds_timer() - rs->starttime);
BLI_time_now_seconds() - rs->starttime);
}
ret_array[i++] = RPT_("Time:");

View File

@ -858,7 +858,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
BLI_condition_init(&oglrender->task_condition);
#ifdef DEBUG_TIME
oglrender->time_start = BLI_check_seconds_timer();
oglrender->time_start = BLI_time_now_seconds();
#endif
return true;
@ -894,7 +894,7 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
BLI_condition_end(&oglrender->task_condition);
#ifdef DEBUG_TIME
printf("Total render time: %f\n", BLI_check_seconds_timer() - oglrender->time_start);
printf("Total render time: %f\n", BLI_time_now_seconds() - oglrender->time_start);
#endif
MEM_SAFE_FREE(oglrender->render_frames);

View File

@ -69,6 +69,7 @@
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_gpencil_legacy.hh"
#include "ED_paint.hh"
#include "ED_screen.hh"
#include "ED_sculpt.hh"
@ -3958,7 +3959,7 @@ bool SCULPT_mode_poll(bContext *C)
bool SCULPT_mode_poll_view3d(bContext *C)
{
return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C));
return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C) && !ED_gpencil_session_active());
}
bool SCULPT_poll(bContext *C)

View File

@ -116,7 +116,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
undo::push_begin(ob, op);
undo::push_node(ob, nullptr, undo::Type::Position);
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
while (bke::pbvh::bmesh_update_topology(
ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, nullptr, size, false, false))
@ -126,7 +126,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
}
}
CLOG_INFO(&LOG, 2, "Detail flood fill took %f seconds.", BLI_check_seconds_timer() - start_time);
CLOG_INFO(&LOG, 2, "Detail flood fill took %f seconds.", BLI_time_now_seconds() - start_time);
undo::push_end(ob);

View File

@ -100,7 +100,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
SCULPT_topology_islands_ensure(ob);
}
const int mask_init_seed = BLI_check_seconds_timer();
const int mask_init_seed = BLI_time_now_seconds();
const SculptMaskWriteInfo mask_write = SCULPT_mask_get_for_write(ss);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {

View File

@ -556,7 +556,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
if (U.viewzoom == USER_ZOOM_CONTINUE) {
/* needs a timer to continue redrawing */
vpd->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
vpd->timer_lastdraw = BLI_check_seconds_timer();
vpd->timer_lastdraw = BLI_time_now_seconds();
}
vpd->x = event->xy[0];
@ -648,7 +648,7 @@ static void view_zoom_apply(
if (U.viewzoom == USER_ZOOM_CONTINUE) {
SpaceClip *sclip = CTX_wm_space_clip(C);
double time = BLI_check_seconds_timer();
double time = BLI_time_now_seconds();
float time_step = float(time - vpd->timer_lastdraw);
float zfac;

View File

@ -216,15 +216,15 @@ static void track_markers_startjob(void *tmv, wmJobWorkerStatus *worker_status)
* exec_time for "Fastest" tracking
*/
double start_time = BLI_check_seconds_timer(), exec_time;
double start_time = BLI_time_now_seconds(), exec_time;
if (!BKE_autotrack_context_step(tmj->context)) {
break;
}
exec_time = BLI_check_seconds_timer() - start_time;
exec_time = BLI_time_now_seconds() - start_time;
if (tmj->delay > float(exec_time)) {
BLI_sleep_ms(tmj->delay - float(exec_time));
BLI_time_sleep_ms(tmj->delay - float(exec_time));
}
}
else if (!BKE_autotrack_context_step(tmj->context)) {

View File

@ -181,11 +181,14 @@ class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
AssetCatalogTreeView::AssetCatalogTreeView(asset_system::AssetLibrary *library,
FileAssetSelectParams *params,
SpaceFile &space_file)
: asset_library_(library),
catalog_tree_(library->catalog_service->get_catalog_tree()),
params_(params),
space_file_(space_file)
: asset_library_(library), params_(params), space_file_(space_file)
{
if (library && library->catalog_service) {
catalog_tree_ = library->catalog_service->get_catalog_tree();
}
else {
catalog_tree_ = nullptr;
}
}
void AssetCatalogTreeView::build_tree()

View File

@ -536,7 +536,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve
if (U.viewzoom == USER_ZOOM_CONTINUE) {
/* needs a timer to continue redrawing */
vpd->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
vpd->timer_lastdraw = BLI_check_seconds_timer();
vpd->timer_lastdraw = BLI_time_now_seconds();
}
vpd->sima = sima;
@ -646,7 +646,7 @@ static void image_zoom_apply(ViewZoomData *vpd,
}
if (viewzoom == USER_ZOOM_CONTINUE) {
double time = BLI_check_seconds_timer();
double time = BLI_time_now_seconds();
float time_step = float(time - vpd->timer_lastdraw);
float zfac;
zfac = 1.0f + ((delta / 20.0f) * time_step);

View File

@ -188,7 +188,11 @@ static bool sequencer_write_copy_paste_file(Main *bmain_src,
BKE_library_foreach_ID_link(
bmain_src, &scene_dst->id, gather_strip_data_ids_to_null, &id_remapper, IDWALK_RECURSE);
BKE_libblock_remap_multiple(bmain_src, id_remapper, 0);
BKE_libblock_relink_multiple(bmain_src,
{&scene_dst->id},
ID_REMAP_TYPE_REMAP,
id_remapper,
(ID_REMAP_SKIP_USER_CLEAR | ID_REMAP_SKIP_USER_REFCOUNT));
/* Ensure that there are no old copy tags around */
BKE_blendfile_write_partial_begin(bmain_src);

View File

@ -113,7 +113,7 @@ ImBuf *make_waveform_view_from_ibuf(const ImBuf *ibuf)
#endif
const int w = ibuf->x;
const int h = 256;
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect);
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect | IB_uninitialized_pixels);
uchar *tgt = rval->byte_buffer.data;
uchar wtable[256];
@ -172,7 +172,7 @@ ImBuf *make_sep_waveform_view_from_ibuf(const ImBuf *ibuf)
#endif
int w = ibuf->x;
int h = 256;
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect);
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect | IB_uninitialized_pixels);
uchar *tgt = rval->byte_buffer.data;
int sw = ibuf->x / 3;
@ -222,7 +222,7 @@ ImBuf *make_zebra_view_from_ibuf(const ImBuf *ibuf, float perc)
#ifdef DEBUG_TIME
SCOPED_TIMER(__func__);
#endif
ImBuf *res = IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rect);
ImBuf *res = IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rect | IB_uninitialized_pixels);
threading::parallel_for(IndexRange(ibuf->y), 16, [&](IndexRange y_range) {
if (ibuf->float_buffer.data) {
@ -346,7 +346,7 @@ ImBuf *make_vectorscope_view_from_ibuf(const ImBuf *ibuf)
#endif
const int size = 512;
const float size_mul = size - 1.0f;
ImBuf *rval = IMB_allocImBuf(size, size, 32, IB_rect);
ImBuf *rval = IMB_allocImBuf(size, size, 32, IB_rect | IB_uninitialized_pixels);
uchar *dst = rval->byte_buffer.data;
float rgb[3];

View File

@ -3520,7 +3520,7 @@ static int text_line_number_invoke(bContext *C, wmOperator * /*op*/, const wmEve
return OPERATOR_PASS_THROUGH;
}
time = BLI_check_seconds_timer();
time = BLI_time_now_seconds();
if (last_jump < time - 1) {
jump_to = 0;
}

View File

@ -366,7 +366,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->ndof = nullptr;
#endif
fly->time_lastdraw = fly->time_lastwheel = BLI_check_seconds_timer();
fly->time_lastdraw = fly->time_lastwheel = BLI_time_now_seconds();
fly->draw_handle_pixel = ED_region_draw_cb_activate(
fly->region->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);
@ -513,7 +513,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->ndof = nullptr;
}
/* Update the time else the view will jump when 2D mouse/timer resume. */
fly->time_lastdraw = BLI_check_seconds_timer();
fly->time_lastdraw = BLI_time_now_seconds();
break;
}
default: {
@ -561,7 +561,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->speed = fabsf(fly->speed);
}
time_currwheel = BLI_check_seconds_timer();
time_currwheel = BLI_time_now_seconds();
time_wheel = float(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
/* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast). */
@ -586,7 +586,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->speed = -fabsf(fly->speed);
}
time_currwheel = BLI_check_seconds_timer();
time_currwheel = BLI_time_now_seconds();
time_wheel = float(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
/* 0-0.5 -> 0-5.0 */
@ -843,7 +843,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
#ifdef NDOF_FLY_DRAW_TOOMUCH
fly->redraw = 1;
#endif
time_current = BLI_check_seconds_timer();
time_current = BLI_time_now_seconds();
time_redraw = float(time_current - fly->time_lastdraw);
/* Clamp redraw time to avoid jitter in roll correction. */
@ -1017,7 +1017,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
}
else {
/* We're not redrawing but we need to update the time else the view will jump. */
fly->time_lastdraw = BLI_check_seconds_timer();
fly->time_lastdraw = BLI_time_now_seconds();
}
/* End drawing. */
copy_v3_v3(fly->dvec_prev, dvec);

Some files were not shown because too many files have changed in this diff Show More