diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-05-31 16:51:17 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-05-31 16:52:11 +0300 |
commit | f32a18994ad7f37eb568771f01bab9db53d38d54 (patch) | |
tree | dc014ea9a34c0d1fc414f1afa937daf1f55a5f97 /source/blender | |
parent | 82276d6cf7d3e18a0e5654d472bdff2b716b0d54 (diff) | |
parent | a481908232ef20449e6ad6951769677e0b108ca8 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender')
47 files changed, 512 insertions, 266 deletions
diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h index 6228ae60c56..70250310213 100644 --- a/source/blender/alembic/ABC_alembic.h +++ b/source/blender/alembic/ABC_alembic.h @@ -47,8 +47,8 @@ struct AlembicExportParams { double frame_start; double frame_end; - double frame_step_xform; - double frame_step_shape; + unsigned int frame_samples_xform; + unsigned int frame_samples_shape; double shutter_open; double shutter_close; diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index d974509d0ae..59a4cb082df 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -72,8 +72,8 @@ ExportSettings::ExportSettings() , renderable_only(false) , frame_start(1) , frame_end(1) - , frame_step_xform(1) - , frame_step_shape(1) + , frame_samples_xform(1) + , frame_samples_shape(1) , shutter_open(0.0) , shutter_close(1.0) , global_scale(1.0f) @@ -189,60 +189,56 @@ AbcExporter::~AbcExporter() delete m_writer; } -void AbcExporter::getShutterSamples(double step, bool time_relative, +void AbcExporter::getShutterSamples(unsigned int nr_of_samples, + bool time_relative, std::vector<double> &samples) { + Scene *scene = m_scene; /* for use in the FPS macro */ samples.clear(); - const double time_factor = time_relative ? m_scene->r.frs_sec : 1.0; - const double shutter_open = m_settings.shutter_open; - const double shutter_close = m_settings.shutter_close; + unsigned int frame_offset = time_relative ? m_settings.frame_start : 0; + double time_factor = time_relative ? FPS : 1.0; + double shutter_open = m_settings.shutter_open; + double shutter_close = m_settings.shutter_close; + double time_inc = (shutter_close - shutter_open) / nr_of_samples; - /* sample all frame */ - if (shutter_open == 0.0 && shutter_close == 1.0) { - for (double t = 0.0; t < 1.0; t += step) { - samples.push_back((t + m_settings.frame_start) / time_factor); - } - } - else { - /* sample between shutter open & close */ - const int nsamples = static_cast<int>(std::max((1.0 / step) - 1.0, 1.0)); - const double time_inc = (shutter_close - shutter_open) / nsamples; + /* sample between shutter open & close */ + for (int sample=0; sample < nr_of_samples; ++sample) { + double sample_time = shutter_open + time_inc * sample; + double time = (frame_offset + sample_time) / time_factor; - for (double t = shutter_open; t <= shutter_close; t += time_inc) { - samples.push_back((t + m_settings.frame_start) / time_factor); - } + samples.push_back(time); } } Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step) { - TimeSamplingPtr time_sampling; std::vector<double> samples; if (m_settings.frame_start == m_settings.frame_end) { - time_sampling.reset(new Alembic::Abc::TimeSampling()); - return time_sampling; + return TimeSamplingPtr(new Alembic::Abc::TimeSampling()); } getShutterSamples(step, true, samples); - Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / m_scene->r.frs_sec); - time_sampling.reset(new Alembic::Abc::TimeSampling(ts, samples)); + Alembic::Abc::TimeSamplingType ts( + static_cast<uint32_t>(samples.size()), + 1.0 / m_scene->r.frs_sec); - return time_sampling; + return TimeSamplingPtr(new Alembic::Abc::TimeSampling(ts, samples)); } -void AbcExporter::getFrameSet(double step, std::set<double> &frames) +void AbcExporter::getFrameSet(unsigned int nr_of_samples, + std::set<double> &frames) { frames.clear(); std::vector<double> shutter_samples; - getShutterSamples(step, false, shutter_samples); + getShutterSamples(nr_of_samples, false, shutter_samples); for (double frame = m_settings.frame_start; frame <= m_settings.frame_end; frame += 1.0) { - for (int j = 0, e = shutter_samples.size(); j < e; ++j) { + for (size_t j = 0; j < nr_of_samples; ++j) { frames.insert(frame + shutter_samples[j]); } } @@ -274,20 +270,20 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) /* Create time samplings for transforms and shapes. */ - TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform); + TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_samples_xform); m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time); TimeSamplingPtr shape_time; - if ((m_settings.frame_step_shape == m_settings.frame_step_xform) || + if ((m_settings.frame_samples_shape == m_settings.frame_samples_xform) || (m_settings.frame_start == m_settings.frame_end)) { shape_time = trans_time; m_shape_sampling_index = m_trans_sampling_index; } else { - shape_time = createTimeSampling(m_settings.frame_step_shape); + shape_time = createTimeSampling(m_settings.frame_samples_shape); m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time); } @@ -299,13 +295,12 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) /* Make a list of frames to export. */ std::set<double> xform_frames; - getFrameSet(m_settings.frame_step_xform, xform_frames); + getFrameSet(m_settings.frame_samples_xform, xform_frames); std::set<double> shape_frames; - getFrameSet(m_settings.frame_step_shape, shape_frames); + getFrameSet(m_settings.frame_samples_shape, shape_frames); /* Merge all frames needed. */ - std::set<double> frames(xform_frames); frames.insert(shape_frames.begin(), shape_frames.end()); @@ -328,7 +323,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) const double frame = *begin; /* 'frame' is offset by start frame, so need to cancel the offset. */ - setCurrentFrame(bmain, frame - m_settings.frame_start); + setCurrentFrame(bmain, frame); if (shape_frames.count(frame) != 0) { for (int i = 0, e = m_shapes.size(); i != e; ++i) { diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index 3831acaafab..15158a9ef51 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -53,8 +53,8 @@ struct ExportSettings { bool renderable_only; double frame_start, frame_end; - double frame_step_xform; - double frame_step_shape; + double frame_samples_xform; + double frame_samples_shape; double shutter_open; double shutter_close; float global_scale; @@ -106,13 +106,15 @@ public: void operator()(Main *bmain, float &progress, bool &was_canceled); -private: - void getShutterSamples(double step, bool time_relative, std::vector<double> &samples); +protected: + void getShutterSamples(unsigned int nr_of_samples, + bool time_relative, + std::vector<double> &samples); + void getFrameSet(unsigned int nr_of_samples, std::set<double> &frames); +private: Alembic::Abc::TimeSamplingPtr createTimeSampling(double step); - void getFrameSet(double step, std::set<double> &frames); - void createTransformWritersHierarchy(EvaluationContext *eval_ctx); AbcTransformWriter * createTransformWriter(Object *ob, Object *parent, Object *dupliObParent); void exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent); diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index e2369e80618..5392387663f 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -108,6 +108,7 @@ void AbcTransformWriter::do_write() scale_m4_fl(scale_mat, m_settings.global_scale); scale_mat[3][3] = m_settings.global_scale; /* also scale translation */ mul_m4_m4m4(yup_mat, yup_mat, scale_mat); + yup_mat[3][3] /= m_settings.global_scale; /* normalise the homogeneous component */ } m_matrix = convert_matrix(yup_mat); diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index cfff13ec77e..3cad132b7be 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -341,8 +341,8 @@ bool ABC_export( job->settings.frame_start = params->frame_start; job->settings.frame_end = params->frame_end; - job->settings.frame_step_xform = params->frame_step_xform; - job->settings.frame_step_shape = params->frame_step_shape; + job->settings.frame_samples_xform = params->frame_samples_xform; + job->settings.frame_samples_shape = params->frame_samples_shape; job->settings.shutter_open = params->shutter_open; job->settings.shutter_close = params->shutter_close; @@ -976,7 +976,9 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader, return NULL; } - ISampleSelector sample_sel(time); + /* kFloorIndex is used to be compatible with non-interpolating + * properties; they use the floor. */ + ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex); return abc_reader->read_derivedmesh(dm, sample_sel, read_flag, err_str); } diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 9a60eb29957..e353d032ee4 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -144,6 +144,8 @@ void BKE_texture_get_value( const struct Scene *scene, struct Tex *texture, float *tex_co, struct TexResult *texres, bool use_color_management); +void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 93a26082ee3..874637896cd 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2125,6 +2125,8 @@ static void mesh_calc_modifiers( DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); append_mask |= CD_MASK_PREVIEW_MLOOPCOL; } + + dm->deformedOnly = false; } isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); @@ -2465,6 +2467,8 @@ static void editbmesh_calc_modifiers( deformedVerts = NULL; } } + + dm->deformedOnly = false; } /* In case of active preview modifier, make sure preview mask remains for following modifiers. */ diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 2a34a2e9418..73e9f5d0774 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -695,4 +695,8 @@ void BKE_pose_eval_proxy_copy(struct EvaluationContext *UNUSED(eval_ctx), Object printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); } + /* Rest of operations are NO-OP in depsgraph, so can clear + * flag now. + */ + ob->recalc &= ~OB_RECALC_ALL; } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 537ff2b3c69..fb5ef403218 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1897,8 +1897,8 @@ static DerivedMesh *dynamicPaint_Modifier_apply( /* apply weights into a vertex group, if doesnt exists add a new layer */ if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) { - dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC, - NULL, sData->total_points, surface->output_name); + dvert = CustomData_add_layer(&result->vertData, CD_MDEFORMVERT, CD_CALLOC, + NULL, sData->total_points); } if (defgrp_index != -1 && dvert) { int i; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 026e8aea74f..9b28d9732e5 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -62,6 +62,7 @@ #include "BLI_blenlib.h" #include "BLI_math_vector.h" +#include "BLI_mempool.h" #include "BLI_threads.h" #include "BLI_timecode.h" /* for stamp timecode format */ #include "BLI_utildefines.h" @@ -4132,33 +4133,32 @@ typedef struct ImagePoolEntry { typedef struct ImagePool { ListBase image_buffers; + BLI_mempool *memory_pool; } ImagePool; ImagePool *BKE_image_pool_new(void) { ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool"); + pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolEntry), 0, 128, BLI_MEMPOOL_NOP); return pool; } void BKE_image_pool_free(ImagePool *pool) { - ImagePoolEntry *entry, *next_entry; - - /* use single lock to dereference all the image buffers */ + /* Use single lock to dereference all the image buffers. */ BLI_spin_lock(&image_spin); - - for (entry = pool->image_buffers.first; entry; entry = next_entry) { - next_entry = entry->next; - - if (entry->ibuf) + for (ImagePoolEntry *entry = pool->image_buffers.first; + entry != NULL; + entry = entry->next) + { + if (entry->ibuf) { IMB_freeImBuf(entry->ibuf); - - MEM_freeN(entry); + } } - BLI_spin_unlock(&image_spin); + BLI_mempool_destroy(pool->memory_pool); MEM_freeN(pool); } @@ -4210,7 +4210,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool ibuf = image_acquire_ibuf(ima, iuser, NULL); - entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry"); + entry = BLI_mempool_alloc(pool->memory_pool); entry->image = ima; entry->frame = frame; entry->index = index; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 76d1b77b3a7..2df601ee4f5 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -4192,9 +4192,10 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha if (free_imbuf) { if (ibuf_change) { - if (seq->type == SEQ_TYPE_MOVIE) + if (seq->type == SEQ_TYPE_MOVIE) { BKE_sequence_free_anim(seq); - if (seq->type == SEQ_TYPE_SPEED) { + } + else if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); } } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index ba04dd9b8f4..b62a72c7d9c 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -1519,3 +1519,33 @@ void BKE_texture_get_value( { BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management); } + +static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool) +{ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) { + Image *image = (Image *)node->id; + BKE_image_pool_acquire_ibuf(image, NULL, pool); + } + else if (node->type == NODE_GROUP && node->id != NULL) { + /* TODO(sergey): Do we need to control recursion here? */ + bNodeTree *nested_tree = (bNodeTree *)node->id; + texture_nodes_fetch_images_for_pool(nested_tree, pool); + } + } +} + +/* Make sure all images used by texture are loaded into pool. */ +void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool) +{ + if (texture->nodetree != NULL) { + texture_nodes_fetch_images_for_pool(texture->nodetree, pool); + } + else { + if (texture->type == TEX_IMAGE) { + if (texture->ima != NULL) { + BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool); + } + } + } +} diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 068c188e336..8bf5c3da90d 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -168,6 +168,8 @@ unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr); unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr); bool BLI_ghashutil_intcmp(const void *a, const void *b); +size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b); + unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]); #define BLI_ghashutil_inthash_v4(key) ( \ @@ -295,6 +297,25 @@ double BLI_ghash_calc_quality(GHash *gh); double BLI_gset_calc_quality(GSet *gs); #endif /* GHASH_INTERNAL_API */ +#define GHASH_FOREACH_BEGIN(type, var, what) \ + do { \ + GHashIterator gh_iter##var; \ + GHASH_ITER(gh_iter##var, what) { \ + type var = (type)(BLI_ghashIterator_getValue(&gh_iter##var)); \ + +#define GHASH_FOREACH_END() \ + } \ + } while(0) + +#define GSET_FOREACH_BEGIN(type, var, what) \ + do { \ + GSetIterator gh_iter##var; \ + GSET_ITER(gh_iter##var, what) { \ + type var = (type)(BLI_gsetIterator_getKey(&gh_iter##var)); + +#define GSET_FOREACH_END() \ + } \ + } while(0) #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index 5f57f46066f..c1e28d5ebc3 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -126,6 +126,11 @@ if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \ (lb_iter != lb_init)); \ } +#define LINKLIST_FOREACH(type, var, list) \ + for (type var = (type)((list)->first); \ + var != NULL; \ + var = (type)(((Link*)(var))->next)) + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index c3c587275e1..721327d26a8 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -106,6 +106,13 @@ void *BLI_task_pool_userdata(TaskPool *pool); /* optional mutex to use from run function */ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); +/* Delayed push, use that to reduce thread overhead by accumulating + * all new tasks into local queue first and pushing it to scheduler + * from within a single mutex lock. + */ +void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id); +void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id); + /* Parallel for routines */ typedef void (*TaskParallelRangeFunc)(void *userdata, const int iter); typedef void (*TaskParallelRangeFuncEx)(void *userdata, void *userdata_chunk, const int iter, const int thread_id); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 944ee18e6b2..d1fe3557801 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -1225,6 +1225,11 @@ bool BLI_ghashutil_intcmp(const void *a, const void *b) return (a != b); } +size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b) +{ + return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); +} + /** * This function implements the widely used "djb" hash apparently posted * by Daniel Bernstein to comp.lang.c some time ago. The 32 bit diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index eb4e6e91aee..a1eae8f1955 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -52,7 +52,14 @@ * * This allows thread to fetch next task without locking the whole queue. */ -#define LOCALQUEUE_SIZE 1 +#define LOCAL_QUEUE_SIZE 1 + +/* Number of tasks which are allowed to be scheduled in a delayed manner. + * + * This allows to use less locks per graph node children schedule. More details + * could be found at TaskThreadLocalStorage::do_delayed_push. + */ +#define DELAYED_QUEUE_SIZE 4096 #ifndef NDEBUG # define ASSERT_THREAD_ID(scheduler, thread_id) \ @@ -129,9 +136,28 @@ typedef struct TaskMemPoolStats { #endif typedef struct TaskThreadLocalStorage { + /* Memory pool for faster task allocation. + * The idea is to re-use memory of finished/discarded tasks by this thread. + */ TaskMemPool task_mempool; + + /* Local queue keeps thread alive by keeping small amount of tasks ready + * to be picked up without causing global thread locks for synchronization. + */ int num_local_queue; - Task *local_queue[LOCALQUEUE_SIZE]; + Task *local_queue[LOCAL_QUEUE_SIZE]; + + /* Thread can be marked for delayed tasks push. This is helpful when it's + * know that lots of subsequent task pushed will happen from the same thread + * without "interrupting" for task execution. + * + * We try to accumulate as much tasks as possible in a local queue without + * any locks first, and then we push all of them into a scheduler's queue + * from within a single mutex lock. + */ + bool do_delayed_push; + int num_delayed_queue; + Task *delayed_queue[DELAYED_QUEUE_SIZE]; } TaskThreadLocalStorage; struct TaskPool { @@ -378,6 +404,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, const int thread_id) { + BLI_assert(!tls->do_delayed_push); while (tls->num_local_queue > 0) { /* We pop task from queue before handling it so handler of the task can * push next job to the local queue. @@ -391,6 +418,7 @@ BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, local_task->run(local_pool, local_task->taskdata, thread_id); task_free(local_pool, local_task, thread_id); } + BLI_assert(!tls->do_delayed_push); } static void *task_scheduler_thread_run(void *thread_p) @@ -408,7 +436,9 @@ static void *task_scheduler_thread_run(void *thread_p) TaskPool *pool = task->pool; /* run task */ + BLI_assert(!tls->do_delayed_push); task->run(pool, task->taskdata, thread_id); + BLI_assert(!tls->do_delayed_push); /* delete task */ task_free(pool, task, thread_id); @@ -547,6 +577,27 @@ static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriori BLI_mutex_unlock(&scheduler->queue_mutex); } +static void task_scheduler_push_all(TaskScheduler *scheduler, + TaskPool *pool, + Task **tasks, + int num_tasks) +{ + if (num_tasks == 0) { + return; + } + + task_pool_num_increase(pool, num_tasks); + + BLI_mutex_lock(&scheduler->queue_mutex); + + for (int i = 0; i < num_tasks; i++) { + BLI_addhead(&scheduler->queue, tasks[i]); + } + + BLI_condition_notify_all(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); +} + static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool) { Task *task, *nexttask; @@ -714,38 +765,59 @@ void BLI_task_pool_free(TaskPool *pool) BLI_end_threaded_malloc(); } +BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id) +{ + return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work)); +} + static void task_pool_push( TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority, int thread_id) { + /* Allocate task and fill it's properties. */ Task *task = task_alloc(pool, thread_id); - task->run = run; task->taskdata = taskdata; task->free_taskdata = free_taskdata; task->freedata = freedata; task->pool = pool; - + /* For suspended pools we put everything yo a global queue first + * and exit as soon as possible. + * + * This tasks will be moved to actual execution when pool is + * activated by work_and_wait(). + */ if (pool->is_suspended) { BLI_addhead(&pool->suspended_queue, task); atomic_fetch_and_add_z(&pool->num_suspended, 1); return; } - - if (thread_id != -1 && - (thread_id != pool->thread_id || pool->do_work)) - { + /* Populate to any local queue first, this is cheapest push ever. */ + if (task_can_use_local_queues(pool, thread_id)) { ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - if (tls->num_local_queue < LOCALQUEUE_SIZE) { + /* Try to push to a local execution queue. + * These tasks will be picked up next. + */ + if (tls->num_local_queue < LOCAL_QUEUE_SIZE) { tls->local_queue[tls->num_local_queue] = task; tls->num_local_queue++; return; } + /* If we are in the delayed tasks push mode, we push tasks to a + * temporary local queue first without any locks, and then move them + * to global execution queue with a single lock. + */ + if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) { + tls->delayed_queue[tls->num_delayed_queue] = task; + tls->num_delayed_queue++; + return; + } } - + /* Do push to a global execution ppol, slowest possible method, + * causes quite reasonable amount of threading overhead. + */ task_scheduler_push(pool->scheduler, task, priority); } @@ -816,7 +888,9 @@ void BLI_task_pool_work_and_wait(TaskPool *pool) /* if found task, do it, otherwise wait until other tasks are done */ if (found_task) { /* run task */ + BLI_assert(!tls->do_delayed_push); work_task->run(pool, work_task->taskdata, pool->thread_id); + BLI_assert(!tls->do_delayed_push); /* delete task */ task_free(pool, task, pool->thread_id); @@ -871,6 +945,30 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool) return &pool->user_mutex; } +void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id) +{ + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + tls->do_delayed_push = true; + } +} + +void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id) +{ + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + BLI_assert(tls->do_delayed_push); + task_scheduler_push_all(pool->scheduler, + pool, + tls->delayed_queue, + tls->num_delayed_queue); + tls->do_delayed_push = false; + tls->num_delayed_queue = 0; + } +} + /* Parallel range routines */ /** diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 5f4ed3db261..74841dc2756 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -205,6 +205,15 @@ static int bev_debug_flags = 0; #define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2) #define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4) +/* Are d1 and d2 parallel or nearly so? */ +static bool nearly_parallel(const float d1[3], const float d2[3]) +{ + float ang; + + ang = angle_v3v3(d1, d2); + return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - M_PI) < BEVEL_EPSILON_ANG); +} + /* Make a new BoundVert of the given kind, insert it at the end of the circular linked * list with entry point bv->boundstart, and return it. */ static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3]) @@ -1059,7 +1068,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) { EdgeHalf *e; Profile *pro; - float co1[3], co2[3], co3[3], d1[3], d2[3], l; + float co1[3], co2[3], co3[3], d1[3], d2[3]; bool do_linear_interp; copy_v3_v3(co1, bndv->nv.co); @@ -1097,8 +1106,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) normalize_v3(d1); normalize_v3(d2); cross_v3_v3v3(pro->plane_no, d1, d2); - l = normalize_v3(pro->plane_no); - if (l <= BEVEL_EPSILON_BIG) { + normalize_v3(pro->plane_no); + if (nearly_parallel(d1, d2)) { /* co1 - midco -co2 are collinear. * Should be case that beveled edge is coplanar with two boundary verts. * We want to move the profile to that common plane, if possible. @@ -1130,17 +1139,24 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co); normalize_v3(d3); normalize_v3(d4); - add_v3_v3v3(co3, co1, d3); - add_v3_v3v3(co4, co2, d4); - isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2); - if (isect_kind != 0) { - copy_v3_v3(pro->midco, meetco); - } - else { + if (nearly_parallel(d3, d4)) { /* offset lines are collinear - want linear interpolation */ mid_v3_v3v3(pro->midco, co1, co2); do_linear_interp = true; } + else { + add_v3_v3v3(co3, co1, d3); + add_v3_v3v3(co4, co2, d4); + isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2); + if (isect_kind != 0) { + copy_v3_v3(pro->midco, meetco); + } + else { + /* offset lines don't intersect - want linear interpolation */ + mid_v3_v3v3(pro->midco, co1, co2); + do_linear_interp = true; + } + } } } copy_v3_v3(pro->cob, co2); @@ -1149,8 +1165,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) sub_v3_v3v3(d2, pro->midco, co2); normalize_v3(d2); cross_v3_v3v3(pro->plane_no, d1, d2); - l = normalize_v3(pro->plane_no); - if (l <= BEVEL_EPSILON_BIG) { + normalize_v3(pro->plane_no); + if (nearly_parallel(d1, d2)) { /* whole profile is collinear with edge: just interpolate */ do_linear_interp = true; } diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index a266f30fe11..d5dcb84aaf5 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -90,7 +90,6 @@ set(SRC intern/depsgraph_types.h util/deg_util_function.h - util/deg_util_hash.h ) if(WITH_CXX11) diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index f8e384bf51c..dba589ed24f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -30,9 +30,6 @@ #include "intern/builder/deg_builder.h" -// TODO(sergey): Use own wrapper over STD. -#include <stack> - #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_ID.h" @@ -40,6 +37,10 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" +extern "C" { +#include "BLI_stack.h" +} + #include "intern/depsgraph.h" #include "intern/depsgraph_types.h" #include "intern/nodes/deg_node.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc index 9b37aaa12ff..1420b5fc8a5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc @@ -32,10 +32,10 @@ // TOO(sergey): Use some wrappers over those? #include <cstdio> #include <cstdlib> -#include <stack> extern "C" { #include "BLI_utildefines.h" +#include "BLI_stack.h" } #include "util/deg_util_foreach.h" @@ -48,12 +48,6 @@ extern "C" { namespace DEG { -struct StackEntry { - OperationDepsNode *node; - StackEntry *from; - DepsRelation *via_relation; -}; - void deg_graph_detect_cycles(Depsgraph *graph) { enum { @@ -65,7 +59,15 @@ void deg_graph_detect_cycles(Depsgraph *graph) NODE_IN_STACK = 2, }; - std::stack<StackEntry> traversal_stack; + struct StackEntry { + OperationDepsNode *node; + StackEntry *from; + DepsRelation *via_relation; + }; + + BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry), + "DEG detect cycles stack"); + foreach (OperationDepsNode *node, graph->operations) { bool has_inlinks = false; foreach (DepsRelation *rel, node->inlinks) { @@ -78,7 +80,7 @@ void deg_graph_detect_cycles(Depsgraph *graph) entry.node = node; entry.from = NULL; entry.via_relation = NULL; - traversal_stack.push(entry); + BLI_stack_push(traversal_stack, &entry); node->tag = NODE_IN_STACK; } else { @@ -87,9 +89,9 @@ void deg_graph_detect_cycles(Depsgraph *graph) node->done = 0; } - while (!traversal_stack.empty()) { - StackEntry& entry = traversal_stack.top(); - OperationDepsNode *node = entry.node; + while (!BLI_stack_is_empty(traversal_stack)) { + StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack); + OperationDepsNode *node = entry->node; bool all_child_traversed = true; for (int i = node->done; i < node->outlinks.size(); ++i) { DepsRelation *rel = node->outlinks[i]; @@ -102,7 +104,7 @@ void deg_graph_detect_cycles(Depsgraph *graph) node->full_identifier().c_str(), rel->name); - StackEntry *current = &entry; + StackEntry *current = entry; while (current->node != to) { BLI_assert(current != NULL); printf(" '%s' depends on '%s' through '%s'\n", @@ -117,9 +119,9 @@ void deg_graph_detect_cycles(Depsgraph *graph) else if (to->tag == NODE_NOT_VISITED) { StackEntry new_entry; new_entry.node = to; - new_entry.from = &entry; + new_entry.from = entry; new_entry.via_relation = rel; - traversal_stack.push(new_entry); + BLI_stack_push(traversal_stack, &new_entry); to->tag = NODE_IN_STACK; all_child_traversed = false; node->done = i; @@ -129,9 +131,11 @@ void deg_graph_detect_cycles(Depsgraph *graph) } if (all_child_traversed) { node->tag = NODE_VISITED; - traversal_stack.pop(); + BLI_stack_discard(traversal_stack); } } + + BLI_stack_free(traversal_stack); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 00995ef2f31..e4b5fd6ffec 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -412,7 +412,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob) BuilderWalkUserData data; data.builder = this; data.scene = scene; - modifiers_foreachObjectLink(ob, modifier_walk, &data); BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 5a85a227453..70c430b5419 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -113,6 +113,41 @@ extern "C" { namespace DEG { +namespace { + +struct BuilderWalkUserData { + DepsgraphRelationBuilder *builder; + Main *bmain; + Scene *scene; +}; + +static void modifier_walk(void *user_data, + struct Object * /*ob*/, + struct Object **obpoin, + int /*cb_flag*/) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + if (*obpoin) { + data->builder->build_object(data->bmain, data->scene, *obpoin); + } +} + +void constraint_walk(bConstraint * /*con*/, + ID **idpoin, + bool /*is_reference*/, + void *user_data) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + if (*idpoin) { + ID *id = *idpoin; + if (GS(id->name) == ID_OB) { + data->builder->build_object(data->bmain, data->scene, (Object *)id); + } + } +} + +} /* namespace */ + /* ***************** */ /* Relations Builder */ @@ -407,6 +442,21 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o "[ObLocal -> ObParent]"); } + if (ob->modifiers.first != NULL) { + BuilderWalkUserData data; + data.builder = this; + data.bmain = bmain; + data.scene = scene; + modifiers_foreachObjectLink(ob, modifier_walk, &data); + } + if (ob->constraints.first != NULL) { + BuilderWalkUserData data; + data.builder = this; + data.bmain = bmain; + data.scene = scene; + BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data); + } + /* object constraints */ if (ob->constraints.first != NULL) { OperationKey constraint_key(&ob->id, diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 978e329136a..c3d64dc05bd 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -43,6 +43,7 @@ extern "C" { #include "DNA_windowmanager_types.h" #include "BLI_task.h" +#include "BLI_listbase.h" #include "BKE_idcode.h" #include "BKE_library.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 8bed13d0499..a2bc38a7b5e 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -123,7 +123,9 @@ static void deg_task_run_func(TaskPool *pool, #endif } + BLI_task_pool_delayed_push_begin(pool, thread_id); schedule_children(pool, state->graph, node, thread_id); + BLI_task_pool_delayed_push_end(pool, thread_id); } typedef struct CalculatePengindData { diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index e10f86f6e95..afcf6994253 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -164,14 +164,33 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) * Plus it ensures visibility changes and relations and * layers visibility update has proper flags to work with. */ - if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { - object->recalc |= OB_RECALC_TIME; - } - else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) { - object->recalc |= OB_RECALC_OB; - } - else { - object->recalc |= OB_RECALC_DATA; + switch (comp_node->type) { + case DEPSNODE_TYPE_UNDEFINED: + case DEPSNODE_TYPE_OPERATION: + case DEPSNODE_TYPE_ROOT: + case DEPSNODE_TYPE_TIMESOURCE: + case DEPSNODE_TYPE_ID_REF: + case DEPSNODE_TYPE_SUBGRAPH: + case DEPSNODE_TYPE_PARAMETERS: + case DEPSNODE_TYPE_SEQUENCER: + case DEPSNODE_TYPE_LAYER_COLLECTIONS: + /* Ignore, does not translate to object component. */ + break; + case DEPSNODE_TYPE_ANIMATION: + object->recalc |= OB_RECALC_TIME; + break; + case DEPSNODE_TYPE_TRANSFORM: + object->recalc |= OB_RECALC_OB; + break; + case DEPSNODE_TYPE_GEOMETRY: + case DEPSNODE_TYPE_EVAL_POSE: + case DEPSNODE_TYPE_BONE: + case DEPSNODE_TYPE_EVAL_PARTICLES: + case DEPSNODE_TYPE_SHADING: + case DEPSNODE_TYPE_CACHE: + case DEPSNODE_TYPE_PROXY: + object->recalc |= OB_RECALC_DATA; + break; } } } diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc index b480cad2298..855b55fd23a 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node.cc @@ -49,7 +49,6 @@ extern "C" { #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" -#include "util/deg_util_hash.h" namespace DEG { @@ -158,8 +157,8 @@ static unsigned int id_deps_node_hash_key(const void *key_v) { const IDDepsNode::ComponentIDKey *key = reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v); - return hash_combine(BLI_ghashutil_uinthash(key->type), - BLI_ghashutil_strhash_p(key->name)); + return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->type), + BLI_ghashutil_strhash_p(key->name)); } static bool id_deps_node_hash_key_cmp(const void *a, const void *b) diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc index 4a741c80086..cf6224a3d82 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc @@ -35,6 +35,7 @@ extern "C" { #include "BLI_utildefines.h" +#include "BLI_ghash.h" #include "DNA_object_types.h" @@ -44,7 +45,6 @@ extern "C" { #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" -#include "util/deg_util_hash.h" namespace DEG { @@ -95,8 +95,8 @@ static unsigned int comp_node_hash_key(const void *key_v) { const ComponentDepsNode::OperationIDKey *key = reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v); - return hash_combine(BLI_ghashutil_uinthash(key->opcode), - BLI_ghashutil_strhash_p(key->name)); + return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->opcode), + BLI_ghashutil_strhash_p(key->name)); } static bool comp_node_hash_key_cmp(const void *a, const void *b) diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc index 9eed4dfe8d8..cbf397bc7a9 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc @@ -32,13 +32,11 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_utildefines.h" -} /* extern "C" */ +#include "BLI_ghash.h" #include "intern/depsgraph.h" #include "intern/depsgraph_intern.h" -#include "util/deg_util_hash.h" namespace DEG { diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h index 8c234eae7de..e00aa5dbb5e 100644 --- a/source/blender/depsgraph/util/deg_util_foreach.h +++ b/source/blender/depsgraph/util/deg_util_foreach.h @@ -38,28 +38,3 @@ #else # error "Depsgraph requires either Boost or C++11 for range-based loops." #endif - -#define GHASH_FOREACH_BEGIN(type, var, what) \ - do { \ - GHashIterator gh_iter##var; \ - GHASH_ITER(gh_iter##var, what) { \ - type var = reinterpret_cast<type>(BLI_ghashIterator_getValue(&gh_iter##var)); \ - -#define GHASH_FOREACH_END() \ - } \ - } while(0) - -#define GSET_FOREACH_BEGIN(type, var, what) \ - do { \ - GSetIterator gh_iter##var; \ - GSET_ITER(gh_iter##var, what) { \ - type var = reinterpret_cast<type>(BLI_gsetIterator_getKey(&gh_iter##var)); \ - -#define GSET_FOREACH_END() \ - } \ - } while(0) - -#define LINKLIST_FOREACH(type, var, list) \ - for (type var = (type)((list)->first); \ - var != NULL; \ - var = (type)(((Link*)(var))->next)) diff --git a/source/blender/depsgraph/util/deg_util_hash.h b/source/blender/depsgraph/util/deg_util_hash.h deleted file mode 100644 index e490be1a7a1..00000000000 --- a/source/blender/depsgraph/util/deg_util_hash.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2014 Blender Foundation. - * All rights reserved. - * - * Original Author: Brecht van Lommel - * Contributor(s): Lukas Toenne - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/depsgraph/util/deg_util_hash.h - * \ingroup depsgraph - */ - -#pragma once - -#include "BLI_utildefines.h" - -#include "BLI_ghash.h" - -/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */ -BLI_INLINE size_t hash_combine(size_t hash_a, size_t hash_b) -{ - return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); -} diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 546f5e4208a..b4cfc1a8d87 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -748,10 +748,10 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add Blank Frame"; + ot->name = "Insert Blank Frame"; ot->idname = "GPENCIL_OT_blank_frame_add"; - ot->description = "Add a new frame with nothing in it on the current frame. " - "If there is already a frame, all existing frames are shifted one frame later"; + ot->description = "Inserts a blank frame on the current frame " + "(all subsequently existing frames, if any, are shifted right by one frame)"; /* callbacks */ ot->exec = gp_blank_frame_add_exec; diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 62c36552048..ba8792d12ff 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -102,12 +102,12 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) char filename[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filename); - const struct AlembicExportParams params = { + struct AlembicExportParams params = { .frame_start = RNA_int_get(op->ptr, "start"), .frame_end = RNA_int_get(op->ptr, "end"), - .frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"), - .frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"), + .frame_samples_xform = RNA_int_get(op->ptr, "xsamples"), + .frame_samples_shape = RNA_int_get(op->ptr, "gsamples"), .shutter_open = RNA_float_get(op->ptr, "sh_open"), .shutter_close = RNA_float_get(op->ptr, "sh_close"), @@ -133,8 +133,17 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .global_scale = RNA_float_get(op->ptr, "global_scale"), }; + /* Take some defaults from the scene, if not specified explicitly. */ + Scene *scene = CTX_data_scene(C); + if (params.frame_start == INT_MIN) { + params.frame_start = SFRA; + } + if (params.frame_end == INT_MIN) { + params.frame_end = EFRA; + } + const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job"); - bool ok = ABC_export(CTX_data_scene(C), C, filename, ¶ms, as_background_job); + bool ok = ABC_export(scene, C, filename, ¶ms, as_background_job); return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } @@ -295,11 +304,17 @@ void WM_OT_alembic_export(wmOperatorType *ot) FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX, - "Start Frame", "Start Frame", INT_MIN, INT_MAX); - - RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX, - "End Frame", "End Frame", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "start", INT_MIN, INT_MIN, INT_MAX, + "Start Frame", + "Start frame of the export, use the default value to " + "take the start frame of the current scene", + INT_MIN, INT_MAX); + + RNA_def_int(ot->srna, "end", INT_MIN, INT_MIN, INT_MAX, + "End Frame", + "End frame of the export, use the default value to " + "take the end frame of the current scene", + INT_MIN, INT_MAX); RNA_def_int(ot->srna, "xsamples", 1, 1, 128, "Transform Samples", "Number of times per frame transformations are sampled", 1, 128); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 5b204b385de..a4aff5b10f3 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -51,6 +51,7 @@ #include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_node.h" #include "BKE_report.h" #include "BKE_modifier.h" @@ -414,22 +415,18 @@ static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports) } } else { - if (ob->mat[i]) { - BKE_reportf(reports, RPT_ERROR, - "No active image found in material \"%s\" (%d) for object \"%s\"", - ob->mat[i]->id.name + 2, i, ob->id.name + 2); - } - else if (((Mesh *) ob->data)->mat[i]) { - BKE_reportf(reports, RPT_ERROR, + Material *mat = give_current_material(ob, i); + if (mat != NULL) { + BKE_reportf(reports, RPT_INFO, "No active image found in material \"%s\" (%d) for object \"%s\"", - ((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2); + mat->id.name + 2, i, ob->id.name + 2); } else { - BKE_reportf(reports, RPT_ERROR, - "No active image found in material (%d) for object \"%s\"", + BKE_reportf(reports, RPT_INFO, + "No active image found in material slot (%d) for object \"%s\"", i, ob->id.name + 2); } - return false; + continue; } image->id.tag |= LIB_TAG_DOIT; @@ -569,7 +566,11 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images) Image *image; ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); - if ((image->id.tag & LIB_TAG_DOIT)) { + /* Some materials have no image, we just ignore those cases. */ + if (image == NULL) { + bake_images->lookup[i] = -1; + } + else if (image->id.tag & LIB_TAG_DOIT) { for (j = 0; j < i; j++) { if (bake_images->data[j].image == image) { bake_images->lookup[i] = j; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 065d1b4926c..f19b5619066 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -85,6 +85,7 @@ #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_sca.h" @@ -2006,6 +2007,18 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo single_tex_users_expand(bmain); } + /* Relink nodetrees' pointers that have been duplicated. */ + FOREACH_NODETREE(bmain, ntree, id) + { + /* This is a bit convoluted, we want to root ntree of copied IDs and only those, + * so we first check that old ID has been copied and that ntree is root tree of old ID, + * then get root tree of new ID and remap its pointers to new ID... */ + if (id->newid && (&ntree->id != id)) { + ntree = ntreeFromID(id->newid); + BKE_libblock_relink_to_newid(&ntree->id); + } + } FOREACH_NODETREE_END + /* Relink datablock pointer properties */ { IDP_RelinkProperty(scene->id.properties); diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 9c73af12e3f..f497a06cb12 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -345,7 +345,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - if (ibuf == NULL) { + if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) { BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index bf004db2c84..3f1f6a9d12d 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -429,6 +429,13 @@ static void object_delete_cb( tselem->id = NULL; #endif } + else { + /* No base, means object is no more instantiated in any scene. + * Should not happen ideally, but does happens, see T51625. + * Rather than twisting in all kind of ways to address all possible cases leading to that situation, simpler + * to allow deleting such object as a mere generic data-block. */ + WM_operator_name_call(C, "OUTLINER_OT_id_delete", WM_OP_INVOKE_REGION_WIN, NULL); + } } static void id_local_cb( diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index f87a0b5e7af..35b54bfd097 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3329,6 +3329,9 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act); if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other); + BKE_sequence_invalidate_cache(scene, seq_act); + BKE_sequence_invalidate_cache(scene, seq_other); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index 6fb1bccf491..600642f5e44 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -177,19 +177,18 @@ unsigned int getRowLength(int width, LogImageElement logElement) return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4; else if (logElement.packing == 1 || logElement.packing == 2) return ((width * logElement.depth - 1) / 3 + 1) * 4; - + break; case 12: if (logElement.packing == 0) return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4; else if (logElement.packing == 1 || logElement.packing == 2) return width * logElement.depth * 2; - + break; case 16: return width * logElement.depth * 2; - default: - return 0; } + return 0; } @@ -572,20 +571,20 @@ static int logImageElementGetData(LogImageFile *logImage, LogImageElement logEle return logImageElementGetData10Packed(logImage, logElement, data); else if (logElement.packing == 1 || logElement.packing == 2) return logImageElementGetData10(logImage, logElement, data); + break; case 12: if (logElement.packing == 0) return logImageElementGetData12Packed(logImage, logElement, data); else if (logElement.packing == 1 || logElement.packing == 2) return logImageElementGetData12(logImage, logElement, data); + break; case 16: return logImageElementGetData16(logImage, logElement, data); - - default: - /* format not supported */ - return 1; } + /* format not supported */ + return 1; } static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 9d68c05dda0..de436172bfd 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3746,7 +3746,7 @@ static const char *cpp_classes = "" "template<typename T, TBeginFunc Tbegin, TNextFunc Tnext, TEndFunc Tend>\n" "class CollectionIterator {\n" "public:\n" -" CollectionIterator() : t(iter.ptr), init(false) { iter.valid = false; }\n" +" CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n" " ~CollectionIterator(void) { if (init) Tend(&iter); };\n" "\n" " operator bool(void)\n" diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 49983b0bc2b..42c0344f46e 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -71,8 +71,8 @@ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1}; if (description && (description)[0]) { \ int i = strlen(description); \ if (i > 3 && (description)[i - 1] == '.' && (description)[i - 3] != '.') { \ - fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \ - __func__, id1 ? id1 : "", id2 ? id2 : ""); \ + fprintf(stderr, "%s: '%s' description from '%s' '%s' ends with a '.' !\n", \ + __func__, description, id1 ? id1 : "", id2 ? id2 : ""); \ } \ } (void)0 diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 091950a8e66..8c3984e4b29 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -185,12 +185,16 @@ static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *v #endif } -static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *UNUSED(ptr)) +static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr) { #ifndef WITH_MOD_FLUID + UNUSED_VARS(ptr); return 0; #else - return 31; + char value[32]; + + rna_DomainFluidSettings_memory_estimate_get(ptr, value); + return strlen(value); #endif } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 8de706008ad..7bae2d64474 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -520,8 +520,9 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value) * thus causing a cycle/infinite-recursion leading to crashes on load [#25298] */ if (BKE_group_object_exists(grp, ob) == 0) { + id_us_min(&ob->dup_group->id); ob->dup_group = grp; - id_lib_extern((ID *)grp); + id_us_plus(&ob->dup_group->id); } else { BKE_report(NULL, RPT_ERROR, diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index c19da203844..f9f4e1dcdb4 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -226,8 +226,8 @@ static void rna_Scene_alembic_export( .frame_start = frame_start, .frame_end = frame_end, - .frame_step_xform = 1.0 / (double)xform_samples, - .frame_step_shape = 1.0 / (double)geom_samples, + .frame_samples_xform = xform_samples, + .frame_samples_shape = geom_samples, .shutter_open = shutter_open, .shutter_close = shutter_close, diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 3e6d8441363..84b62721999 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1095,7 +1095,7 @@ static void rna_def_strip_element(BlenderRNA *brna) prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME); RNA_def_property_string_sdna(prop, NULL, "name"); - RNA_def_property_ui_text(prop, "Filename", ""); + RNA_def_property_ui_text(prop, "Filename", "Name of the source file"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceElement_update"); prop = RNA_def_property(srna, "orig_width", PROP_INT, PROP_NONE); @@ -1120,25 +1120,25 @@ static void rna_def_strip_crop(BlenderRNA *brna) prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "top"); - RNA_def_property_ui_text(prop, "Top", ""); + RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "bottom"); - RNA_def_property_ui_text(prop, "Bottom", ""); + RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the buttom"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "left"); - RNA_def_property_ui_text(prop, "Left", ""); + RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "right"); - RNA_def_property_ui_text(prop, "Right", ""); + RNA_def_property_ui_text(prop, "Right", "Number of pixels to crop from the right side"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); @@ -1156,13 +1156,13 @@ static void rna_def_strip_transform(BlenderRNA *brna) prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "xofs"); - RNA_def_property_ui_text(prop, "Offset X", ""); + RNA_def_property_ui_text(prop, "Offset X", "Amount to move the input on the X axis within its boundaries"); RNA_def_property_ui_range(prop, -4096, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update"); prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "yofs"); - RNA_def_property_ui_text(prop, "Offset Y", ""); + RNA_def_property_ui_text(prop, "Offset Y", "Amount to move the input on the Y axis within its boundaries"); RNA_def_property_ui_range(prop, -4096, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update"); @@ -1246,7 +1246,7 @@ static void rna_def_strip_proxy(BlenderRNA *brna) prop = RNA_def_property(srna, "timecode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "tc"); RNA_def_property_enum_items(prop, seq_tc_items); - RNA_def_property_ui_text(prop, "Timecode", ""); + RNA_def_property_ui_text(prop, "Timecode", "Method for reading the inputs timecode"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update"); prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE); @@ -1289,17 +1289,17 @@ static void rna_def_color_balance(BlenderRNA *brna) prop = RNA_def_property(srna, "invert_gain", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAIN); - RNA_def_property_ui_text(prop, "Inverse Gain", ""); + RNA_def_property_ui_text(prop, "Inverse Gain", "Invert the gain color`"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update"); prop = RNA_def_property(srna, "invert_gamma", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAMMA); - RNA_def_property_ui_text(prop, "Inverse Gamma", ""); + RNA_def_property_ui_text(prop, "Inverse Gamma", "Invert the gamma color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update"); prop = RNA_def_property(srna, "invert_lift", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_LIFT); - RNA_def_property_ui_text(prop, "Inverse Lift", ""); + RNA_def_property_ui_text(prop, "Inverse Lift", "Invert the lift color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update"); /* not yet used */ @@ -1453,13 +1453,13 @@ static void rna_def_sequence(BlenderRNA *brna) prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MUTE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, true); - RNA_def_property_ui_text(prop, "Mute", ""); + RNA_def_property_ui_text(prop, "Mute", "Disable strip so that it cannot be viewed in the output"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_mute_update"); prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_LOCK); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true); - RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it can't be transformed"); + RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it cannot be transformed"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); /* strip positioning */ @@ -1481,7 +1481,7 @@ static void rna_def_sequence(BlenderRNA *brna) prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "start"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Start Frame", ""); + RNA_def_property_ui_text(prop, "Start Frame", "X position where the strip begins"); RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */ RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1552,12 +1552,12 @@ static void rna_def_sequence(BlenderRNA *brna) prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "blend_mode"); RNA_def_property_enum_items(prop, blend_mode_items); - RNA_def_property_ui_text(prop, "Blend Mode", ""); + RNA_def_property_ui_text(prop, "Blend Mode", "Method for controlling how the strip combines with other strips"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Blend Opacity", ""); + RNA_def_property_ui_text(prop, "Blend Opacity", "Percentage of how much the strip's colors affect other strips"); /* stupid 0-100 -> 0-1 */ RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1566,7 +1566,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_float_sdna(prop, NULL, "effect_fader"); - RNA_def_property_ui_text(prop, "Effect fader position", ""); + RNA_def_property_ui_text(prop, "Effect fader position", "Custom fade value"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "use_default_fade", PROP_BOOLEAN, PROP_NONE); @@ -1714,7 +1714,7 @@ static void rna_def_filter_video(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 20.0f); RNA_def_property_ui_range(prop, 0.0f, 2.0f, 3, 3); RNA_def_property_float_default(prop, 1.0f); - RNA_def_property_ui_text(prop, "Saturation", ""); + RNA_def_property_ui_text(prop, "Saturation", "Adjust the intensity of the input's color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "strobe", PROP_FLOAT, PROP_NONE); @@ -2205,13 +2205,13 @@ static void rna_def_transform(StructRNA *srna) prop = RNA_def_property(srna, "scale_start_x", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScalexIni"); - RNA_def_property_ui_text(prop, "Scale X", ""); + RNA_def_property_ui_text(prop, "Scale X", "Amount to scale the input in the X axis"); RNA_def_property_ui_range(prop, 0, 10, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScaleyIni"); - RNA_def_property_ui_text(prop, "Scale Y", ""); + RNA_def_property_ui_text(prop, "Scale Y", "Amount to scale the input in the Y axis"); RNA_def_property_ui_range(prop, 0, 10, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -2222,33 +2222,33 @@ static void rna_def_transform(StructRNA *srna) prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xIni"); - RNA_def_property_ui_text(prop, "Translate X", ""); + RNA_def_property_ui_text(prop, "Translate X", "Amount to move the input on the X axis"); RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yIni"); - RNA_def_property_ui_text(prop, "Translate Y", ""); + RNA_def_property_ui_text(prop, "Translate Y", "Amount to move the input on the Y axis"); RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rotIni"); RNA_def_property_range(prop, -360.0f, 360.0f); - RNA_def_property_ui_text(prop, "Rotation", ""); + RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "translation_unit", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "percent"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */ RNA_def_property_enum_items(prop, translation_unit_items); - RNA_def_property_ui_text(prop, "Translation Unit", ""); + RNA_def_property_ui_text(prop, "Translation Unit", "Unit of measure to translate the input"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, interpolation_items); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */ - RNA_def_property_ui_text(prop, "Interpolation", ""); + RNA_def_property_ui_text(prop, "Interpolation", "Method to determine how missing pixels are created"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } @@ -2260,7 +2260,7 @@ static void rna_def_solid_color(StructRNA *srna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "col"); - RNA_def_property_ui_text(prop, "Color", ""); + RNA_def_property_ui_text(prop, "Color", "Effect Strip color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } @@ -2333,12 +2333,12 @@ static void rna_def_text(StructRNA *srna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "color"); - RNA_def_property_ui_text(prop, "Color", ""); + RNA_def_property_ui_text(prop, "Color", "Text color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "shadow_color"); - RNA_def_property_ui_text(prop, "Shadow Color", ""); + RNA_def_property_ui_text(prop, "Shadow Color", "Shadow color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ); @@ -2358,13 +2358,13 @@ static void rna_def_text(StructRNA *srna) prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align"); RNA_def_property_enum_items(prop, text_align_x_items); - RNA_def_property_ui_text(prop, "Align X", ""); + RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align_y"); RNA_def_property_enum_items(prop, text_align_y_items); - RNA_def_property_ui_text(prop, "Align Y", ""); + RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE); @@ -2512,7 +2512,7 @@ static void rna_def_colorbalance_modifier(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "color_multiply"); RNA_def_property_range(prop, 0.0f, 20.0f); RNA_def_property_float_default(prop, 1.0f); - RNA_def_property_ui_text(prop, "Multiply Colors", ""); + RNA_def_property_ui_text(prop, "Multiply Colors", "Multiply the intensity of each pixel"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); } @@ -2576,13 +2576,13 @@ static void rna_def_brightcontrast_modifier(BlenderRNA *brna) prop = RNA_def_property(srna, "bright", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "bright"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); - RNA_def_property_ui_text(prop, "Bright", ""); + RNA_def_property_ui_text(prop, "Bright", "Adjust the luminosity of the colors"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "contrast"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); - RNA_def_property_ui_text(prop, "Contrast", ""); + RNA_def_property_ui_text(prop, "Contrast", "Adjust the difference in luminosity between pixels"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); } @@ -2599,13 +2599,12 @@ static void rna_def_tonemap_modifier(BlenderRNA *brna) srna = RNA_def_struct(brna, "SequencerTonemapModifierData", "SequenceModifier"); RNA_def_struct_sdna(srna, "SequencerTonemapModifierData"); - RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData", - "Tone mapping modifier"); + RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData", "Tone mapping modifier"); prop = RNA_def_property(srna, "tonemap_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, type_items); - RNA_def_property_ui_text(prop, "Tonemap Type", ""); + RNA_def_property_ui_text(prop, "Tonemap Type", "Tone mapping algorithm"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); prop = RNA_def_property(srna, "key", PROP_FLOAT, PROP_FACTOR); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index f2f2a8a5a49..c422aa05b12 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -358,6 +358,7 @@ static void displaceModifier_do( data.vert_clnors = vert_clnors; if (dmd->texture != NULL) { data.pool = BKE_image_pool_new(); + BKE_texture_fetch_images_for_pool(dmd->texture, data.pool); } BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512); diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index 73424a4e846..588c327ab91 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -684,6 +684,10 @@ void RE_bake_pixels_populate( int mat_nr = mp->mat_nr; int image_id = bake_images->lookup[mat_nr]; + if (image_id < 0) { + continue; + } + bd.bk_image = &bake_images->data[image_id]; bd.primitive_id = ++p_id; |