| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/tiles/picture_layer_tiling.h" | 5 #include "cc/tiles/picture_layer_tiling.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 const float kSoonBorderDistanceViewportPercentage = 0.15f; | 31 const float kSoonBorderDistanceViewportPercentage = 0.15f; |
| 32 const float kMaxSoonBorderDistanceInScreenPixels = 312.f; | 32 const float kMaxSoonBorderDistanceInScreenPixels = 312.f; |
| 33 | 33 |
| 34 } // namespace | 34 } // namespace |
| 35 | 35 |
| 36 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( | 36 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
| 37 WhichTree tree, | 37 WhichTree tree, |
| 38 float contents_scale, | 38 float contents_scale, |
| 39 scoped_refptr<RasterSource> raster_source, | 39 scoped_refptr<RasterSource> raster_source, |
| 40 PictureLayerTilingClient* client, | 40 PictureLayerTilingClient* client, |
| 41 size_t max_tiles_for_interest_area, | 41 size_t tiling_interest_area_padding, |
| 42 float skewport_target_time_in_seconds, | 42 float skewport_target_time_in_seconds, |
| 43 int skewport_extrapolation_limit_in_content_pixels) { | 43 int skewport_extrapolation_limit_in_content_pixels) { |
| 44 return make_scoped_ptr(new PictureLayerTiling( | 44 return make_scoped_ptr(new PictureLayerTiling( |
| 45 tree, contents_scale, raster_source, client, max_tiles_for_interest_area, | 45 tree, contents_scale, raster_source, client, tiling_interest_area_padding, |
| 46 skewport_target_time_in_seconds, | 46 skewport_target_time_in_seconds, |
| 47 skewport_extrapolation_limit_in_content_pixels)); | 47 skewport_extrapolation_limit_in_content_pixels)); |
| 48 } | 48 } |
| 49 | 49 |
| 50 PictureLayerTiling::PictureLayerTiling( | 50 PictureLayerTiling::PictureLayerTiling( |
| 51 WhichTree tree, | 51 WhichTree tree, |
| 52 float contents_scale, | 52 float contents_scale, |
| 53 scoped_refptr<RasterSource> raster_source, | 53 scoped_refptr<RasterSource> raster_source, |
| 54 PictureLayerTilingClient* client, | 54 PictureLayerTilingClient* client, |
| 55 size_t max_tiles_for_interest_area, | 55 size_t tiling_interest_area_padding, |
| 56 float skewport_target_time_in_seconds, | 56 float skewport_target_time_in_seconds, |
| 57 int skewport_extrapolation_limit_in_content_pixels) | 57 int skewport_extrapolation_limit_in_content_pixels) |
| 58 : max_tiles_for_interest_area_(max_tiles_for_interest_area), | 58 : tiling_interest_area_padding_(tiling_interest_area_padding), |
| 59 skewport_target_time_in_seconds_(skewport_target_time_in_seconds), | 59 skewport_target_time_in_seconds_(skewport_target_time_in_seconds), |
| 60 skewport_extrapolation_limit_in_content_pixels_( | 60 skewport_extrapolation_limit_in_content_pixels_( |
| 61 skewport_extrapolation_limit_in_content_pixels), | 61 skewport_extrapolation_limit_in_content_pixels), |
| 62 contents_scale_(contents_scale), | 62 contents_scale_(contents_scale), |
| 63 client_(client), | 63 client_(client), |
| 64 tree_(tree), | 64 tree_(tree), |
| 65 raster_source_(raster_source), | 65 raster_source_(raster_source), |
| 66 resolution_(NON_IDEAL_RESOLUTION), | 66 resolution_(NON_IDEAL_RESOLUTION), |
| 67 tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), | 67 tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), |
| 68 can_require_tiles_for_activation_(false), | 68 can_require_tiles_for_activation_(false), |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 return false; | 619 return false; |
| 620 } | 620 } |
| 621 | 621 |
| 622 // Calculate the skewport. | 622 // Calculate the skewport. |
| 623 gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds, | 623 gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds, |
| 624 visible_rect_in_content_space); | 624 visible_rect_in_content_space); |
| 625 DCHECK(skewport.Contains(visible_rect_in_content_space)); | 625 DCHECK(skewport.Contains(visible_rect_in_content_space)); |
| 626 | 626 |
| 627 // Calculate the eventually/live tiles rect. | 627 // Calculate the eventually/live tiles rect. |
| 628 gfx::Size tile_size = tiling_data_.max_texture_size(); | 628 gfx::Size tile_size = tiling_data_.max_texture_size(); |
| 629 int64 eventually_rect_area = | |
| 630 max_tiles_for_interest_area_ * tile_size.width() * tile_size.height(); | |
| 631 | 629 |
| 632 gfx::Rect eventually_rect = | 630 float content_to_screen_scale = ideal_contents_scale / contents_scale_; |
| 633 ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space, | 631 int pad_in_content_space = |
| 634 eventually_rect_area, | 632 static_cast<int>(tiling_interest_area_padding_ / content_to_screen_scale); |
| 635 gfx::Rect(tiling_size()), | 633 gfx::Rect eventually_rect = visible_rect_in_content_space; |
| 636 &expansion_cache_); | 634 // If the visible rect is empty, keep the eventually rect as empty. |
| 635 if (!eventually_rect.IsEmpty()) { |
| 636 eventually_rect.Inset(-pad_in_content_space, -pad_in_content_space); |
| 637 eventually_rect = |
| 638 tiling_data_.ExpandRectIgnoringBordersToTileBounds(eventually_rect); |
| 639 } |
| 637 | 640 |
| 638 DCHECK(eventually_rect.IsEmpty() || | 641 DCHECK_IMPLIES(!eventually_rect.IsEmpty(), |
| 639 gfx::Rect(tiling_size()).Contains(eventually_rect)) | 642 gfx::Rect(tiling_size()).Contains(eventually_rect)) |
| 640 << "tiling_size: " << tiling_size().ToString() | 643 << "tiling_size: " << tiling_size().ToString() |
| 641 << " eventually_rect: " << eventually_rect.ToString(); | 644 << " eventually_rect: " << eventually_rect.ToString(); |
| 642 | 645 |
| 643 // Calculate the soon border rect. | 646 // Calculate the soon border rect. |
| 644 float content_to_screen_scale = ideal_contents_scale / contents_scale_; | |
| 645 gfx::Rect soon_border_rect = visible_rect_in_content_space; | 647 gfx::Rect soon_border_rect = visible_rect_in_content_space; |
| 646 float border = CalculateSoonBorderDistance(visible_rect_in_content_space, | 648 float border = CalculateSoonBorderDistance(visible_rect_in_content_space, |
| 647 content_to_screen_scale); | 649 content_to_screen_scale); |
| 648 soon_border_rect.Inset(-border, -border, -border, -border); | 650 soon_border_rect.Inset(-border, -border, -border, -border); |
| 649 | 651 |
| 650 UpdateVisibleRectHistory(current_frame_time_in_seconds, | 652 UpdateVisibleRectHistory(current_frame_time_in_seconds, |
| 651 visible_rect_in_content_space); | 653 visible_rect_in_content_space); |
| 652 last_viewport_in_layer_space_ = viewport_in_layer_space; | 654 last_viewport_in_layer_space_ = viewport_in_layer_space; |
| 653 | 655 |
| 654 SetTilePriorityRects(content_to_screen_scale, visible_rect_in_content_space, | 656 SetTilePriorityRects(content_to_screen_scale, visible_rect_in_content_space, |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 | 961 |
| 960 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { | 962 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { |
| 961 size_t amount = 0; | 963 size_t amount = 0; |
| 962 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 964 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 963 const Tile* tile = it->second; | 965 const Tile* tile = it->second; |
| 964 amount += tile->GPUMemoryUsageInBytes(); | 966 amount += tile->GPUMemoryUsageInBytes(); |
| 965 } | 967 } |
| 966 return amount; | 968 return amount; |
| 967 } | 969 } |
| 968 | 970 |
| 969 PictureLayerTiling::RectExpansionCache::RectExpansionCache() | |
| 970 : previous_target(0) { | |
| 971 } | |
| 972 | |
| 973 namespace { | |
| 974 | |
| 975 // This struct represents an event at which the expending rect intersects | |
| 976 // one of its boundaries. 4 intersection events will occur during expansion. | |
| 977 struct EdgeEvent { | |
| 978 enum { BOTTOM, TOP, LEFT, RIGHT } edge; | |
| 979 int* num_edges; | |
| 980 int distance; | |
| 981 }; | |
| 982 | |
| 983 // Compute the delta to expand from edges to cover target_area. | |
| 984 int ComputeExpansionDelta(int num_x_edges, int num_y_edges, | |
| 985 int width, int height, | |
| 986 int64 target_area) { | |
| 987 // Compute coefficients for the quadratic equation: | |
| 988 // a*x^2 + b*x + c = 0 | |
| 989 int a = num_y_edges * num_x_edges; | |
| 990 int b = num_y_edges * width + num_x_edges * height; | |
| 991 int64 c = static_cast<int64>(width) * height - target_area; | |
| 992 | |
| 993 // Compute the delta for our edges using the quadratic equation. | |
| 994 int delta = | |
| 995 (a == 0) ? -c / b : (-b + static_cast<int>(std::sqrt( | |
| 996 static_cast<int64>(b) * b - 4.0 * a * c))) / | |
| 997 (2 * a); | |
| 998 return std::max(0, delta); | |
| 999 } | |
| 1000 | |
| 1001 } // namespace | |
| 1002 | |
| 1003 gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy( | |
| 1004 const gfx::Rect& starting_rect, | |
| 1005 int64 target_area, | |
| 1006 const gfx::Rect& bounding_rect, | |
| 1007 RectExpansionCache* cache) { | |
| 1008 if (starting_rect.IsEmpty()) | |
| 1009 return starting_rect; | |
| 1010 | |
| 1011 if (cache && | |
| 1012 cache->previous_start == starting_rect && | |
| 1013 cache->previous_bounds == bounding_rect && | |
| 1014 cache->previous_target == target_area) | |
| 1015 return cache->previous_result; | |
| 1016 | |
| 1017 if (cache) { | |
| 1018 cache->previous_start = starting_rect; | |
| 1019 cache->previous_bounds = bounding_rect; | |
| 1020 cache->previous_target = target_area; | |
| 1021 } | |
| 1022 | |
| 1023 DCHECK(!bounding_rect.IsEmpty()); | |
| 1024 DCHECK_GT(target_area, 0); | |
| 1025 | |
| 1026 // Expand the starting rect to cover target_area, if it is smaller than it. | |
| 1027 int delta = ComputeExpansionDelta( | |
| 1028 2, 2, starting_rect.width(), starting_rect.height(), target_area); | |
| 1029 gfx::Rect expanded_starting_rect = starting_rect; | |
| 1030 if (delta > 0) | |
| 1031 expanded_starting_rect.Inset(-delta, -delta); | |
| 1032 | |
| 1033 gfx::Rect rect = IntersectRects(expanded_starting_rect, bounding_rect); | |
| 1034 if (rect.IsEmpty()) { | |
| 1035 // The starting_rect and bounding_rect are far away. | |
| 1036 if (cache) | |
| 1037 cache->previous_result = rect; | |
| 1038 return rect; | |
| 1039 } | |
| 1040 if (delta >= 0 && rect == expanded_starting_rect) { | |
| 1041 // The starting rect already covers the entire bounding_rect and isn't too | |
| 1042 // large for the target_area. | |
| 1043 if (cache) | |
| 1044 cache->previous_result = rect; | |
| 1045 return rect; | |
| 1046 } | |
| 1047 | |
| 1048 // Continue to expand/shrink rect to let it cover target_area. | |
| 1049 | |
| 1050 // These values will be updated by the loop and uses as the output. | |
| 1051 int origin_x = rect.x(); | |
| 1052 int origin_y = rect.y(); | |
| 1053 int width = rect.width(); | |
| 1054 int height = rect.height(); | |
| 1055 | |
| 1056 // In the beginning we will consider 2 edges in each dimension. | |
| 1057 int num_y_edges = 2; | |
| 1058 int num_x_edges = 2; | |
| 1059 | |
| 1060 // Create an event list. | |
| 1061 EdgeEvent events[] = { | |
| 1062 { EdgeEvent::BOTTOM, &num_y_edges, rect.y() - bounding_rect.y() }, | |
| 1063 { EdgeEvent::TOP, &num_y_edges, bounding_rect.bottom() - rect.bottom() }, | |
| 1064 { EdgeEvent::LEFT, &num_x_edges, rect.x() - bounding_rect.x() }, | |
| 1065 { EdgeEvent::RIGHT, &num_x_edges, bounding_rect.right() - rect.right() } | |
| 1066 }; | |
| 1067 | |
| 1068 // Sort the events by distance (closest first). | |
| 1069 if (events[0].distance > events[1].distance) std::swap(events[0], events[1]); | |
| 1070 if (events[2].distance > events[3].distance) std::swap(events[2], events[3]); | |
| 1071 if (events[0].distance > events[2].distance) std::swap(events[0], events[2]); | |
| 1072 if (events[1].distance > events[3].distance) std::swap(events[1], events[3]); | |
| 1073 if (events[1].distance > events[2].distance) std::swap(events[1], events[2]); | |
| 1074 | |
| 1075 for (int event_index = 0; event_index < 4; event_index++) { | |
| 1076 const EdgeEvent& event = events[event_index]; | |
| 1077 | |
| 1078 int delta = ComputeExpansionDelta( | |
| 1079 num_x_edges, num_y_edges, width, height, target_area); | |
| 1080 | |
| 1081 // Clamp delta to our event distance. | |
| 1082 if (delta > event.distance) | |
| 1083 delta = event.distance; | |
| 1084 | |
| 1085 // Adjust the edge count for this kind of edge. | |
| 1086 --*event.num_edges; | |
| 1087 | |
| 1088 // Apply the delta to the edges and edge events. | |
| 1089 for (int i = event_index; i < 4; i++) { | |
| 1090 switch (events[i].edge) { | |
| 1091 case EdgeEvent::BOTTOM: | |
| 1092 origin_y -= delta; | |
| 1093 height += delta; | |
| 1094 break; | |
| 1095 case EdgeEvent::TOP: | |
| 1096 height += delta; | |
| 1097 break; | |
| 1098 case EdgeEvent::LEFT: | |
| 1099 origin_x -= delta; | |
| 1100 width += delta; | |
| 1101 break; | |
| 1102 case EdgeEvent::RIGHT: | |
| 1103 width += delta; | |
| 1104 break; | |
| 1105 } | |
| 1106 events[i].distance -= delta; | |
| 1107 } | |
| 1108 | |
| 1109 // If our delta is less then our event distance, we're done. | |
| 1110 if (delta < event.distance) | |
| 1111 break; | |
| 1112 } | |
| 1113 | |
| 1114 gfx::Rect result(origin_x, origin_y, width, height); | |
| 1115 if (cache) | |
| 1116 cache->previous_result = result; | |
| 1117 return result; | |
| 1118 } | |
| 1119 | |
| 1120 } // namespace cc | 971 } // namespace cc |
| OLD | NEW |