Commit 0c01026d authored by Lei Zhang's avatar Lei Zhang Committed by Commit Bot

Add base::bits::AlignDown().

Like base::bits::Align(), but rounds down instead. Replace duplicate
implementations.

Change-Id: I7ad74d021feba26a34f2c80bc025e9ab9fe6660a
Reviewed-on: https://chromium-review.googlesource.com/c/1369047Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarAlbert J. Wong <ajwong@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#615610}
parent 3e224595
......@@ -42,6 +42,12 @@ inline size_t Align(size_t size, size_t alignment) {
return (size + alignment - 1) & ~(alignment - 1);
}
// Round down |size| to a multiple of alignment, which must be a power of two.
inline size_t AlignDown(size_t size, size_t alignment) {
DCHECK(IsPowerOfTwo(alignment));
return size & ~(alignment - 1);
}
// CountLeadingZeroBits(value) returns the number of zero bits following the
// most significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns {sizeof(T) * 8}.
......
......@@ -51,7 +51,7 @@ TEST(BitsTest, Log2Ceiling) {
}
TEST(BitsTest, Align) {
const size_t kSizeTMax = std::numeric_limits<size_t>::max();
static constexpr size_t kSizeTMax = std::numeric_limits<size_t>::max();
EXPECT_EQ(0ul, Align(0, 4));
EXPECT_EQ(4ul, Align(1, 4));
EXPECT_EQ(4096ul, Align(1, 4096));
......@@ -62,6 +62,19 @@ TEST(BitsTest, Align) {
EXPECT_EQ(kSizeTMax / 2 + 1, Align(1, kSizeTMax / 2 + 1));
}
TEST(BitsTest, AlignDown) {
static constexpr size_t kSizeTMax = std::numeric_limits<size_t>::max();
EXPECT_EQ(0ul, AlignDown(0, 4));
EXPECT_EQ(0ul, AlignDown(1, 4));
EXPECT_EQ(0ul, AlignDown(1, 4096));
EXPECT_EQ(4096ul, AlignDown(4096, 4096));
EXPECT_EQ(0ul, AlignDown(4095, 4096));
EXPECT_EQ(4096ul, AlignDown(4097, 4096));
EXPECT_EQ(kSizeTMax - 63, AlignDown(kSizeTMax - 62, 32));
EXPECT_EQ(kSizeTMax - 31, AlignDown(kSizeTMax, 32));
EXPECT_EQ(0ul, AlignDown(1, kSizeTMax / 2 + 1));
}
TEST(BitsTest, CountLeadingZeroBits8) {
EXPECT_EQ(8u, CountLeadingZeroBits(uint8_t{0}));
EXPECT_EQ(7u, CountLeadingZeroBits(uint8_t{1}));
......
......@@ -9,6 +9,7 @@
#include <utility>
#include "base/atomic_sequence_num.h"
#include "base/bits.h"
#include "base/debug/stack_trace.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
......@@ -55,8 +56,8 @@ AtomicSequenceNumber g_next_id;
// Gets the next non-zero identifier. It is only unique within a process.
uint32_t GetNextDataId() {
uint32_t id;
while ((id = g_next_id.GetNext()) == 0)
;
while ((id = g_next_id.GetNext()) == 0) {
}
return id;
}
......@@ -91,12 +92,12 @@ PersistentMemoryAllocator::Reference AllocateFrom(
// Determines the previous aligned index.
size_t RoundDownToAlignment(size_t index, size_t alignment) {
return index & (0 - alignment);
return bits::AlignDown(index, alignment);
}
// Determines the next aligned index.
size_t RoundUpToAlignment(size_t index, size_t alignment) {
return (index + (alignment - 1)) & (0 - alignment);
return bits::Align(index, alignment);
}
// Converts "tick" timing into wall time.
......@@ -692,7 +693,6 @@ ThreadActivityTracker::ThreadActivityTracker(void* base, size_t size)
#endif
stack_slots_(
static_cast<uint32_t>((size - sizeof(Header)) / sizeof(Activity))) {
// Verify the parameters but fail gracefully if they're not valid so that
// production code based on external inputs will not crash. IsValid() will
// return false in this case.
......
......@@ -24,7 +24,7 @@ namespace {
const size_t kSkiaAlignment = 4u;
size_t RoundDownToAlignment(size_t bytes, size_t alignment) {
return bytes - (bytes & (alignment - 1));
return base::bits::AlignDown(bytes, alignment);
}
SkIRect MakeSrcRect(const PaintImage& image) {
......
......@@ -11,6 +11,7 @@
#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/bits.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
......@@ -39,20 +40,6 @@ gfx::Rect Intersection(gfx::Rect a, const gfx::Rect& b) {
// Static constexpr class for generating unique identifiers for each VideoFrame.
static base::AtomicSequenceNumber g_unique_id_generator;
static bool IsPowerOfTwo(size_t x) {
return x != 0 && (x & (x - 1)) == 0;
}
static inline size_t RoundUp(size_t value, size_t alignment) {
DCHECK(IsPowerOfTwo(alignment));
return ((value + (alignment - 1)) & ~(alignment - 1));
}
static inline size_t RoundDown(size_t value, size_t alignment) {
DCHECK(IsPowerOfTwo(alignment));
return value & ~(alignment - 1);
}
static std::string StorageTypeToString(
const VideoFrame::StorageType storage_type) {
switch (storage_type) {
......@@ -706,8 +693,8 @@ gfx::Size VideoFrame::PlaneSize(VideoPixelFormat format,
// Align to multiple-of-two size overall. This ensures that non-subsampled
// planes can be addressed by pixel with the same scaling as the subsampled
// planes.
width = RoundUp(width, 2);
height = RoundUp(height, 2);
width = base::bits::Align(width, 2);
height = base::bits::Align(height, 2);
}
const gfx::Size subsample = SampleSize(format, plane);
......@@ -791,14 +778,14 @@ int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) {
size_t VideoFrame::Rows(size_t plane, VideoPixelFormat format, int height) {
DCHECK(IsValidPlane(plane, format));
const int sample_height = SampleSize(format, plane).height();
return RoundUp(height, sample_height) / sample_height;
return base::bits::Align(height, sample_height) / sample_height;
}
// static
size_t VideoFrame::Columns(size_t plane, VideoPixelFormat format, int width) {
DCHECK(IsValidPlane(plane, format));
const int sample_width = SampleSize(format, plane).width();
return RoundUp(width, sample_width) / sample_width;
return base::bits::Align(width, sample_width) / sample_width;
}
// static
......@@ -855,8 +842,9 @@ const uint8_t* VideoFrame::visible_data(size_t plane) const {
// Calculate an offset that is properly aligned for all planes.
const gfx::Size alignment = CommonAlignment(format());
const gfx::Point offset(RoundDown(visible_rect_.x(), alignment.width()),
RoundDown(visible_rect_.y(), alignment.height()));
const gfx::Point offset(
base::bits::AlignDown(visible_rect_.x(), alignment.width()),
base::bits::AlignDown(visible_rect_.y(), alignment.height()));
const gfx::Size subsample = SampleSize(format(), plane);
DCHECK(offset.x() % subsample.width() == 0);
......@@ -1108,8 +1096,8 @@ gfx::Size VideoFrame::DetermineAlignedSize(VideoPixelFormat format,
const gfx::Size& dimensions) {
const gfx::Size alignment = CommonAlignment(format);
const gfx::Size adjusted =
gfx::Size(RoundUp(dimensions.width(), alignment.width()),
RoundUp(dimensions.height(), alignment.height()));
gfx::Size(base::bits::Align(dimensions.width(), alignment.width()),
base::bits::Align(dimensions.height(), alignment.height()));
DCHECK((adjusted.width() % alignment.width() == 0) &&
(adjusted.height() % alignment.height() == 0));
return adjusted;
......@@ -1266,8 +1254,8 @@ std::vector<int32_t> VideoFrame::ComputeStrides(VideoPixelFormat format,
strides.push_back(RowBytes(0, format, coded_size.width()));
} else {
for (size_t plane = 0; plane < num_planes; ++plane) {
strides.push_back(RoundUp(RowBytes(plane, format, coded_size.width()),
kFrameAddressAlignment));
strides.push_back(base::bits::Align(
RowBytes(plane, format, coded_size.width()), kFrameAddressAlignment));
}
}
return strides;
......@@ -1307,7 +1295,8 @@ std::vector<size_t> VideoFrame::CalculatePlaneSize() const {
// These values were chosen to mirror ffmpeg's get_video_buffer().
// TODO(dalecurtis): This should be configurable; eventually ffmpeg wants
// us to use av_cpu_max_align(), but... for now, they just hard-code 32.
const size_t height = RoundUp(rows(plane), kFrameAddressAlignment);
const size_t height =
base::bits::Align(rows(plane), kFrameAddressAlignment);
const size_t width = std::abs(stride(plane));
plane_size.push_back(width * height);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment