From 4cc0f09881174467f63f33ed16a5c6d6dfadeed3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 12:23:35 +0100 Subject: [PATCH 01/10] Tracking: Cleanup, use more const qualifiers when appropriate --- source/blender/blenkernel/BKE_movieclip.h | 4 ++-- source/blender/blenkernel/intern/movieclip.c | 4 ++-- source/blender/blenkernel/intern/tracking_auto.c | 10 ++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 0bdff3eb795..bd193b82b9e 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -74,8 +74,8 @@ void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, stru void BKE_movieclip_build_proxy_frame_for_ibuf(struct MovieClip *clip, struct ImBuf *ibuf, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, bool undistorted); -float BKE_movieclip_remap_scene_to_clip_frame(struct MovieClip *clip, float framenr); -float BKE_movieclip_remap_clip_to_scene_frame(struct MovieClip *clip, float framenr); +float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr); +float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr); void BKE_movieclip_filename_for_frame(struct MovieClip *clip, struct MovieClipUser *user, char *name); struct ImBuf *BKE_movieclip_anim_ibuf_for_frame(struct MovieClip *clip, struct MovieClipUser *user); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index db05939b1cc..08df976941b 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1524,12 +1524,12 @@ void BKE_movieclip_make_local(Main *bmain, MovieClip *clip, const bool lib_local BKE_id_make_local_generic(bmain, &clip->id, true, lib_local); } -float BKE_movieclip_remap_scene_to_clip_frame(MovieClip *clip, float framenr) +float BKE_movieclip_remap_scene_to_clip_frame(const MovieClip *clip, float framenr) { return framenr - (float) clip->start_frame + 1.0f; } -float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr) +float BKE_movieclip_remap_clip_to_scene_frame(const MovieClip *clip, float framenr) { return framenr + (float) clip->start_frame - 1.0f; } diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 4ff4a129768..2120e730eab 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -236,17 +236,15 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker, } } -static bool check_track_trackable(MovieClip *clip, +static bool check_track_trackable(const MovieClip *clip, MovieTrackingTrack *track, - MovieClipUser *user) + const MovieClipUser *user) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) { - MovieTrackingMarker *marker; - int frame; - frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - marker = BKE_tracking_marker_get(track, frame); + int frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); + const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, frame); return (marker->flag & MARKER_DISABLED) == 0; } return false; From e50442418adf4377a86a102f213e836c6d155445 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 12:35:41 +0100 Subject: [PATCH 02/10] Tracking: Cleanup, make autotrack context creation code more granular --- .../blender/blenkernel/intern/tracking_auto.c | 156 ++++++++++-------- 1 file changed, 90 insertions(+), 66 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 2120e730eab..28e2882a37f 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -281,6 +281,81 @@ static bool tracking_check_marker_margin(libmv_Marker *libmv_marker, return true; } +/* Provide Libmv side of auto track all information about given tracks. */ +static void fill_autotrack_tracks(const int frame_width, + const int frame_height, + const ListBase *tracksbase, + const bool backwards, + struct libmv_AutoTrack *autotrack) +{ + int track_index = 0; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + for (int i = 0; i < track->markersnr; ++i) { + MovieTrackingMarker *marker = track->markers + i; + if ((marker->flag & MARKER_DISABLED) != 0) { + continue; + } + libmv_Marker libmv_marker; + dna_marker_to_libmv_marker(track, + marker, + 0, + track_index, + frame_width, + frame_height, + backwards, + &libmv_marker); + libmv_autoTrackAddMarker(autotrack, &libmv_marker); + } + track_index++; + } +} + +static void create_per_track_tracking_options(const MovieClip *clip, + const MovieClipUser *user, + const ListBase *tracksbase, + AutoTrackContext *context) +{ + /* Count number of trackable tracks. */ + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (check_track_trackable(clip, track, user)) { + context->num_tracks++; + } + } + /* Allocate required memory. */ + context->options = + MEM_callocN(sizeof(AutoTrackOptions) * context->num_tracks, + "auto track options"); + /* Fill in all the settings. */ + int i = 0, track_index = 0; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (!check_track_trackable(clip, track, user)) { + ++track_index; + continue; + } + AutoTrackOptions *options = &context->options[i++]; + /* TODO(sergey): Single clip only for now. */ + options->clip_index = 0; + options->track_index = track_index; + options->track = track; + tracking_configure_tracker(track, + NULL, + &options->track_region_options); + options->use_keyframe_match = + track->pattern_match == TRACK_MATCH_KEYFRAME; + context->tracks[track_index] = track; + ++track_index; + } +} + AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, MovieClipUser *user, const bool backwards, @@ -289,16 +364,13 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext), "autotrack context"); MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *track; ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); - int i, track_index, frame_width, frame_height; - + int frame_width, frame_height; + /* get size of frame to convert normalized coordinates to a picture ones. */ BKE_movieclip_get_size(clip, user, &frame_width, &frame_height); - /* TODO(sergey): Currently using only a single clip. */ context->clips[0] = clip; context->num_clips = 1; - context->user = *user; context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; context->user.render_flag = 0; @@ -309,75 +381,27 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, context->first_frame = user->framenr; context->sync_frame = user->framenr; context->first_sync = true; - BLI_spin_init(&context->spin_lock); - - int num_total_tracks = BLI_listbase_count(tracksbase); + const int num_total_tracks = BLI_listbase_count(tracksbase); context->tracks = - MEM_callocN(sizeof(MovieTrackingTrack *) * num_total_tracks, - "auto track pointers"); - + MEM_callocN(sizeof(MovieTrackingTrack *) * num_total_tracks, + "auto track pointers"); + /* Initialize image accessor. */ context->image_accessor = tracking_image_accessor_new(context->clips, 1, context->tracks, num_total_tracks, user->framenr); + /* Initialize auto track context and provide all information about currently + * tracked markers. + */ context->autotrack = - libmv_autoTrackNew(context->image_accessor->libmv_accessor); - - /* Fill in Autotrack with all markers we know. */ - track_index = 0; - for (track = tracksbase->first; - track; - track = track->next) - { - if (check_track_trackable(clip, track, user)) { - context->num_tracks++; - } - - for (i = 0; i < track->markersnr; ++i) { - MovieTrackingMarker *marker = track->markers + i; - if ((marker->flag & MARKER_DISABLED) == 0) { - libmv_Marker libmv_marker; - dna_marker_to_libmv_marker(track, - marker, - 0, - track_index, - frame_width, - frame_height, - backwards, - &libmv_marker); - libmv_autoTrackAddMarker(context->autotrack, - &libmv_marker); - } - } - track_index++; - } - + libmv_autoTrackNew(context->image_accessor->libmv_accessor); + fill_autotrack_tracks(frame_width, frame_height, + tracksbase, + backwards, + context->autotrack); /* Create per-track tracking options. */ - context->options = - MEM_callocN(sizeof(AutoTrackOptions) * context->num_tracks, - "auto track options"); - i = track_index = 0; - for (track = tracksbase->first; - track; - track = track->next) - { - if (check_track_trackable(clip, track, user)) { - AutoTrackOptions *options = &context->options[i++]; - /* TODO(sergey): Single clip only for now. */ - options->clip_index = 0; - options->track_index = track_index; - options->track = track; - tracking_configure_tracker(track, - NULL, - &options->track_region_options); - options->use_keyframe_match = - track->pattern_match == TRACK_MATCH_KEYFRAME; - } - context->tracks[track_index] = track; - ++track_index; - } - + create_per_track_tracking_options(clip, user, tracksbase, context); return context; } From 4895bd6aceec57a08b471b6be9a0cabef30f7aa7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 12:51:17 +0100 Subject: [PATCH 03/10] Libmv: Add C-API function to set all markers within AutoTrack structure --- intern/libmv/intern/autotrack.cc | 15 +++++++++++++++ intern/libmv/intern/autotrack.h | 4 ++++ intern/libmv/intern/stub.cc | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/intern/libmv/intern/autotrack.cc b/intern/libmv/intern/autotrack.cc index 3b7c9c5a010..980504ed163 100644 --- a/intern/libmv/intern/autotrack.cc +++ b/intern/libmv/intern/autotrack.cc @@ -82,6 +82,21 @@ void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack, ((AutoTrack*) libmv_autotrack)->AddMarker(marker); } +void libmv_autoTrackSetMarkers(libmv_AutoTrack* libmv_autotrack, + const libmv_Marker* libmv_marker, + size_t num_markers) { + if (num_markers == 0) { + // Early output. + return; + } + libmv::vector markers; + markers.resize(num_markers); + for (size_t i = 0; i < num_markers; ++i) { + libmv_apiMarkerToMarker(libmv_marker[i], &markers[i]); + } + ((AutoTrack*) libmv_autotrack)->SetMarkers(&markers); +} + int libmv_autoTrackGetMarker(libmv_AutoTrack* libmv_autotrack, int clip, int frame, diff --git a/intern/libmv/intern/autotrack.h b/intern/libmv/intern/autotrack.h index 2a4a8f3c97f..9a073ff249b 100644 --- a/intern/libmv/intern/autotrack.h +++ b/intern/libmv/intern/autotrack.h @@ -58,6 +58,10 @@ int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack, void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack, const libmv_Marker* libmv_marker); +void libmv_autoTrackSetMarkers(libmv_AutoTrack* libmv_autotrack, + const libmv_Marker* libmv_marker, + size_t num_markers); + int libmv_autoTrackGetMarker(libmv_AutoTrack* libmv_autotrack, int clip, int frame, diff --git a/intern/libmv/intern/stub.cc b/intern/libmv/intern/stub.cc index 8603cc03153..fa2509ffcf6 100644 --- a/intern/libmv/intern/stub.cc +++ b/intern/libmv/intern/stub.cc @@ -361,6 +361,12 @@ void libmv_autoTrackAddMarker(libmv_AutoTrack* /*libmv_autotrack*/, { } +void libmv_autoTrackSetMarkers(libmv_AutoTrack* /*libmv_autotrack*/, + const libmv_Marker* /*libmv_marker-*/, + size_t /*num_markers*/) +{ +} + int libmv_autoTrackGetMarker(libmv_AutoTrack* /*libmv_autotrack*/, int /*clip*/, int /*frame*/, From 6b62f1dcb93d1a4a4ec2b7ed29afc6c0be6d3c21 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 12:51:53 +0100 Subject: [PATCH 04/10] Tracking: Pass all markers to autotrack at once This solves delay before tracking actually starts. The issue is reported by Sebastian over IRC, thanks! --- .../blender/blenkernel/intern/tracking_auto.c | 49 ++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 28e2882a37f..ccff86e4258 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -288,7 +288,29 @@ static void fill_autotrack_tracks(const int frame_width, const bool backwards, struct libmv_AutoTrack *autotrack) { - int track_index = 0; + /* Count number of markers to be put to a context. */ + size_t num_trackable_marekrs = 0; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + for (int i = 0; i < track->markersnr; ++i) { + const MovieTrackingMarker *marker = track->markers + i; + if ((marker->flag & MARKER_DISABLED) == 0) { + num_trackable_marekrs++; + } + } + } + /* Early output if we don't have any markers. */ + if (num_trackable_marekrs == 0) { + return; + } + /* Allocate memory for all the markers. */ + libmv_Marker *libmv_markers = MEM_mallocN( + sizeof(libmv_Marker) * num_trackable_marekrs, + "libmv markers array"); + /* Fill in markers array. */ + int track_index = 0, num_filled_libmv_markers = 0; for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) @@ -298,19 +320,24 @@ static void fill_autotrack_tracks(const int frame_width, if ((marker->flag & MARKER_DISABLED) != 0) { continue; } - libmv_Marker libmv_marker; - dna_marker_to_libmv_marker(track, - marker, - 0, - track_index, - frame_width, - frame_height, - backwards, - &libmv_marker); - libmv_autoTrackAddMarker(autotrack, &libmv_marker); + dna_marker_to_libmv_marker( + track, + marker, + 0, + track_index, + frame_width, frame_height, + backwards, + &libmv_markers[num_filled_libmv_markers++]); } + /* Put all markers to autotrack at once. */ track_index++; } + /* Add all markers to autotrack. */ + libmv_autoTrackSetMarkers(autotrack, + libmv_markers, + num_trackable_marekrs); + /* Free temporary memory. */ + MEM_freeN(libmv_markers); } static void create_per_track_tracking_options(const MovieClip *clip, From ff0d3c520ff94434f0cc86a13cccd479622d74b8 Mon Sep 17 00:00:00 2001 From: Sebastian Koenig Date: Fri, 15 Dec 2017 13:53:44 +0100 Subject: [PATCH 05/10] Tracking: Cleanup, fix typo in variable name --- source/blender/blenkernel/intern/tracking_auto.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index ccff86e4258..40234bacdfe 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -289,7 +289,7 @@ static void fill_autotrack_tracks(const int frame_width, struct libmv_AutoTrack *autotrack) { /* Count number of markers to be put to a context. */ - size_t num_trackable_marekrs = 0; + size_t num_trackable_markers = 0; for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) @@ -297,17 +297,17 @@ static void fill_autotrack_tracks(const int frame_width, for (int i = 0; i < track->markersnr; ++i) { const MovieTrackingMarker *marker = track->markers + i; if ((marker->flag & MARKER_DISABLED) == 0) { - num_trackable_marekrs++; + num_trackable_markers++; } } } /* Early output if we don't have any markers. */ - if (num_trackable_marekrs == 0) { + if (num_trackable_markers == 0) { return; } /* Allocate memory for all the markers. */ libmv_Marker *libmv_markers = MEM_mallocN( - sizeof(libmv_Marker) * num_trackable_marekrs, + sizeof(libmv_Marker) * num_trackable_markers, "libmv markers array"); /* Fill in markers array. */ int track_index = 0, num_filled_libmv_markers = 0; @@ -335,7 +335,7 @@ static void fill_autotrack_tracks(const int frame_width, /* Add all markers to autotrack. */ libmv_autoTrackSetMarkers(autotrack, libmv_markers, - num_trackable_marekrs); + num_trackable_markers); /* Free temporary memory. */ MEM_freeN(libmv_markers); } From 2aa0f8a41bba64933db19ad4231f9392a8445cd7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 16:16:22 +0100 Subject: [PATCH 06/10] Math utils: Cleanup, use _uint suffix for function which operates on uint --- source/blender/blenlib/BLI_math_bits.h | 2 +- source/blender/blenlib/intern/math_bits_inline.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 1ac98a682d1..1d0ee77feed 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -31,7 +31,7 @@ extern "C" { #include "BLI_math_inline.h" -MINLINE unsigned int highest_order_bit_i(unsigned int n); +MINLINE unsigned int highest_order_bit_uint(unsigned int n); MINLINE unsigned short highest_order_bit_s(unsigned short n); #ifdef __GNUC__ diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index 82d7e2114c2..9f502d367cb 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -27,7 +27,7 @@ #include "BLI_math_bits.h" -MINLINE unsigned int highest_order_bit_i(unsigned int n) +MINLINE unsigned int highest_order_bit_uint(unsigned int n) { n |= (n >> 1); n |= (n >> 2); From 02ec0b53df0a966048500e659389dbb987847c49 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 16:17:37 +0100 Subject: [PATCH 07/10] Math utils: Make it more clear what the functions are returning --- source/blender/blenlib/BLI_math_bits.h | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 1d0ee77feed..40a1d84b0e1 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -31,6 +31,7 @@ extern "C" { #include "BLI_math_inline.h" +/* NOTE: Those functions returns 2 to the power of index of highest order bit. */ MINLINE unsigned int highest_order_bit_uint(unsigned int n); MINLINE unsigned short highest_order_bit_s(unsigned short n); From 412de222f8711893f7ed66630b6b8a1473810ab2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 16:22:54 +0100 Subject: [PATCH 08/10] Math utils: Add bit scan operations --- source/blender/blenlib/BLI_math_bits.h | 8 +++++ .../blender/blenlib/intern/math_bits_inline.c | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 40a1d84b0e1..248b615e3f8 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -31,6 +31,14 @@ extern "C" { #include "BLI_math_inline.h" +/* Search the value from LSB to MSB for a set bit. Returns index of this bit. */ +MINLINE int bitscan_forward_i(int a); +MINLINE unsigned int bitscan_forward_uint(unsigned int a); + +/* Search the value from MSB to LSB for a set bit. Returns index of this bit. */ +MINLINE int bitscan_reverse_i(int a); +MINLINE unsigned int bitscan_reverse_uint(unsigned int a); + /* NOTE: Those functions returns 2 to the power of index of highest order bit. */ MINLINE unsigned int highest_order_bit_uint(unsigned int n); MINLINE unsigned short highest_order_bit_s(unsigned short n); diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index 9f502d367cb..fdef0f9c9c6 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -27,6 +27,40 @@ #include "BLI_math_bits.h" +MINLINE int bitscan_forward_i(int a) +{ + BLI_assert(a != 0); +# ifdef _MSC_VER + unsigned long ctz; + _BitScanForward(&ctz, a); + return ctz; +#else + return __builtin_ctz((unsigned int)a); +#endif +} + +MINLINE unsigned int bitscan_forward_uint(unsigned int a) +{ + return (unsigned int)bitscan_forward_i((int)a); +} + +MINLINE int bitscan_reverse_i(int a) +{ + BLI_assert(a != 0); +# ifdef _MSC_VER + unsigned long clz; + _BitScanReverse(&clz, a); + return clz; +#else + return __builtin_clz((unsigned int)a); +#endif +} + +MINLINE unsigned int bitscan_reverse_uint(unsigned int a) +{ + return (unsigned int)bitscan_reverse_i((int)a); +} + MINLINE unsigned int highest_order_bit_uint(unsigned int n) { n |= (n >> 1); From de9e5a092659cf2424b55dca4ac6f149966fe427 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 16:28:53 +0100 Subject: [PATCH 09/10] Math utils: Go away form naive code for highest_order_bit_uint --- source/blender/blenlib/intern/math_bits_inline.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index fdef0f9c9c6..e967ecbb3a3 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -63,12 +63,10 @@ MINLINE unsigned int bitscan_reverse_uint(unsigned int a) MINLINE unsigned int highest_order_bit_uint(unsigned int n) { - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - n |= (n >> 16); - return n - (n >> 1); + if (n == 0) { + return 0; + } + return 1 << (sizeof(unsigned int) * 8 - bitscan_reverse_uint(n)); } MINLINE unsigned short highest_order_bit_s(unsigned short n) From 5e28b71457e8c8ce20e19a28ce44c9d9b5f47844 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Dec 2017 16:41:31 +0100 Subject: [PATCH 10/10] math utils: Add utilities to scan bit and clear it --- source/blender/blenlib/BLI_math_bits.h | 8 ++++++ .../blender/blenlib/intern/math_bits_inline.c | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 248b615e3f8..86213dc271f 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -35,10 +35,18 @@ extern "C" { MINLINE int bitscan_forward_i(int a); MINLINE unsigned int bitscan_forward_uint(unsigned int a); +/* Similar to above, but also clears the bit. */ +MINLINE int bitscan_forward_clear_i(int *a); +MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a); + /* Search the value from MSB to LSB for a set bit. Returns index of this bit. */ MINLINE int bitscan_reverse_i(int a); MINLINE unsigned int bitscan_reverse_uint(unsigned int a); +/* Similar to above, but also clears the bit. */ +MINLINE int bitscan_reverse_clear_i(int *a); +MINLINE unsigned int bitscan_reverse_clear_uint(unsigned int *a); + /* NOTE: Those functions returns 2 to the power of index of highest order bit. */ MINLINE unsigned int highest_order_bit_uint(unsigned int n); MINLINE unsigned short highest_order_bit_s(unsigned short n); diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index e967ecbb3a3..d96cf969dae 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -44,6 +44,18 @@ MINLINE unsigned int bitscan_forward_uint(unsigned int a) return (unsigned int)bitscan_forward_i((int)a); } +MINLINE int bitscan_forward_clear_i(int *a) +{ + int i = bitscan_forward_i(*a); + *a &= (*a) - 1; + return i; +} + +MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a) +{ + return (unsigned int)bitscan_forward_clear_i((int *)a); +} + MINLINE int bitscan_reverse_i(int a) { BLI_assert(a != 0); @@ -61,6 +73,19 @@ MINLINE unsigned int bitscan_reverse_uint(unsigned int a) return (unsigned int)bitscan_reverse_i((int)a); } +MINLINE int bitscan_reverse_clear_i(int *a) +{ + int i = bitscan_reverse_i(*a); + /* TODO(sergey): This could probably be optimized. */ + *a &= ~(1 << (sizeof(int) * 8 - i - 1)); + return i; +} + +MINLINE unsigned int bitscan_reverse_clear_uint(unsigned int *a) +{ + return (unsigned int)bitscan_reverse_clear_i((int *)a); +} + MINLINE unsigned int highest_order_bit_uint(unsigned int n) { if (n == 0) {