[M108 Migration][VD] Avoid pending frame counter becoming negative
[platform/framework/web/chromium-efl.git] / cc / tiles / mipmap_util.cc
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/tiles/mipmap_util.h"
6
7 #include "base/numerics/safe_math.h"
8
9 namespace cc {
10 namespace {
11 // Calculates the size of |axis_base_size| at the given |mip_level|. Note that
12 // the calculation here rounds up for consistency with size calculations in the
13 // JPEG decoder. This allows us to decode images to the mip size directly.
14 int ScaleAxisToMipLevel(int axis_base_size, int mip_level) {
15   DCHECK_GE(mip_level, 0);
16   DCHECK_LT(mip_level, 32);
17
18   if (mip_level == 0)
19     return axis_base_size;
20
21   // Increment the size by (2^mip_level - 1) so we round on when dividing it
22   // below.
23   base::CheckedNumeric<int> base_size = axis_base_size;
24   base_size += (1 << mip_level) - 1;
25   axis_base_size = base_size.ValueOrDefault(std::numeric_limits<int>::max());
26   return std::max(1, axis_base_size >> mip_level);
27 }
28
29 }  // namespace
30
31 int MipMapUtil::GetLevelForSize(const gfx::Size& src_size,
32                                 const gfx::Size& target_size) {
33   int src_height = src_size.height();
34   int src_width = src_size.width();
35   int target_height = target_size.height();
36   int target_width = target_size.width();
37   DCHECK_GT(target_height, 0);
38   DCHECK_GT(target_width, 0);
39   DCHECK_GT(src_width, 0);
40   DCHECK_GT(src_height, 0);
41
42   int next_mip_height = src_height;
43   int next_mip_width = src_width;
44   for (int current_mip_level = 0;; current_mip_level++) {
45     int mip_height = next_mip_height;
46     int mip_width = next_mip_width;
47
48     next_mip_height = ScaleAxisToMipLevel(src_height, current_mip_level + 1);
49     next_mip_width = ScaleAxisToMipLevel(src_width, current_mip_level + 1);
50
51     // Check if an axis on the next mip level would be smaller than the target.
52     // If so, use the current mip level.
53     // This effectively always uses the larger image and always scales down.
54     if (next_mip_height < target_height || next_mip_width < target_width) {
55       return current_mip_level;
56     }
57
58     if (mip_height == 1 && mip_width == 1) {
59       // We have reached the final mip level
60       return current_mip_level;
61     }
62   }
63 }
64
65 SkSize MipMapUtil::GetScaleAdjustmentForLevel(const gfx::Size& src_size,
66                                               int mip_level) {
67   DCHECK_GT(src_size.width(), 0);
68   DCHECK_GT(src_size.height(), 0);
69   DCHECK_GE(mip_level, 0);
70
71   gfx::Size target_size = GetSizeForLevel(src_size, mip_level);
72
73   return SkSize::Make(
74       static_cast<float>(target_size.width()) / src_size.width(),
75       static_cast<float>(target_size.height()) / src_size.height());
76 }
77
78 gfx::Size MipMapUtil::GetSizeForLevel(const gfx::Size& src_size,
79                                       int mip_level) {
80   DCHECK_GT(src_size.width(), 0);
81   DCHECK_GT(src_size.height(), 0);
82   DCHECK_GE(mip_level, 0);
83
84   return gfx::Size(ScaleAxisToMipLevel(src_size.width(), mip_level),
85                    ScaleAxisToMipLevel(src_size.height(), mip_level));
86 }
87
88 SkSize MipMapUtil::GetScaleAdjustmentForSize(const gfx::Size& src_size,
89                                              const gfx::Size& target_size) {
90   int target_mip_level = GetLevelForSize(src_size, target_size);
91   return GetScaleAdjustmentForLevel(src_size, target_mip_level);
92 }
93
94 }  // namespace cc