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/picture_layer_tiling.h" | 5 #include "cc/picture_layer_tiling.h" |
6 | 6 |
7 #include <cmath> | |
8 | |
7 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
8 #include "cc/math_util.h" | 10 #include "cc/math_util.h" |
9 #include "ui/gfx/point_conversions.h" | 11 #include "ui/gfx/point_conversions.h" |
10 #include "ui/gfx/rect_conversions.h" | 12 #include "ui/gfx/rect_conversions.h" |
11 #include "ui/gfx/safe_integer_conversions.h" | 13 #include "ui/gfx/safe_integer_conversions.h" |
12 #include "ui/gfx/size_conversions.h" | 14 #include "ui/gfx/size_conversions.h" |
13 | 15 |
14 namespace cc { | 16 namespace cc { |
15 | 17 |
16 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( | 18 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 if (last_impl_frame_time_ != 0 && | 386 if (last_impl_frame_time_ != 0 && |
385 last_layer_bounds == current_layer_bounds && | 387 last_layer_bounds == current_layer_bounds && |
386 last_layer_content_bounds == current_layer_content_bounds && | 388 last_layer_content_bounds == current_layer_content_bounds && |
387 last_layer_contents_scale == current_layer_contents_scale) { | 389 last_layer_contents_scale == current_layer_contents_scale) { |
388 time_delta = current_frame_time - last_impl_frame_time_; | 390 time_delta = current_frame_time - last_impl_frame_time_; |
389 } | 391 } |
390 | 392 |
391 gfx::Rect viewport_in_content_space = | 393 gfx::Rect viewport_in_content_space = |
392 gfx::ToEnclosingRect(gfx::ScaleRect(viewport_in_layer_space, | 394 gfx::ToEnclosingRect(gfx::ScaleRect(viewport_in_layer_space, |
393 contents_scale_)); | 395 contents_scale_)); |
394 gfx::Rect inflated_rect = viewport_in_content_space; | 396 |
395 float adjusted_inset = TilePriority::kMaxDistanceInContentSpace / | 397 static const int64 kMaxTilesForPrioritizedRect = 80; |
nduca
2013/02/16 22:30:59
Should we put this by where the old constant lived
danakj
2013/02/18 19:26:20
Right, I feel like asking 3 people would get you 3
| |
396 std::max(contents_scale_, 1.f); | 398 |
397 inflated_rect.Inset( | 399 gfx::Size tile_size = tiling_data_.max_texture_size(); |
398 -adjusted_inset, | 400 int64 prioritized_rect_area = kMaxTilesForPrioritizedRect * |
399 -adjusted_inset, | 401 tile_size.width() * tile_size.height(); |
400 -adjusted_inset, | 402 |
401 -adjusted_inset); | 403 gfx::Rect prioritized_rect = ExpandRectEquallyToAreaBoundedBy( |
402 inflated_rect.Intersect(ContentRect()); | 404 viewport_in_content_space, |
405 prioritized_rect_area, | |
406 ContentRect()); | |
407 DCHECK(ContentRect().Contains(prioritized_rect)); | |
403 | 408 |
404 // Iterate through all of the tiles that were live last frame but will | 409 // Iterate through all of the tiles that were live last frame but will |
405 // not be live this frame, and mark them as being dead. | 410 // not be live this frame, and mark them as being dead. |
406 for (TilingData::DifferenceIterator iter(&tiling_data_, | 411 for (TilingData::DifferenceIterator iter(&tiling_data_, |
407 last_prioritized_rect_, | 412 last_prioritized_rect_, |
408 inflated_rect); | 413 prioritized_rect); |
409 iter; | 414 iter; |
410 ++iter) { | 415 ++iter) { |
411 TileMap::iterator find = tiles_.find(iter.index()); | 416 TileMap::iterator find = tiles_.find(iter.index()); |
412 if (find == tiles_.end()) | 417 if (find == tiles_.end()) |
413 continue; | 418 continue; |
414 | 419 |
415 TilePriority priority; | 420 TilePriority priority; |
416 DCHECK(!priority.is_live); | 421 DCHECK(!priority.is_live); |
417 Tile* tile = find->second.get(); | 422 Tile* tile = find->second.get(); |
418 tile->set_priority(tree, priority); | 423 tile->set_priority(tree, priority); |
419 } | 424 } |
420 last_prioritized_rect_ = inflated_rect; | 425 last_prioritized_rect_ = prioritized_rect; |
421 | 426 |
422 gfx::Rect view_rect(device_viewport); | 427 gfx::Rect view_rect(device_viewport); |
423 float current_scale = current_layer_contents_scale / contents_scale_; | 428 float current_scale = current_layer_contents_scale / contents_scale_; |
424 float last_scale = last_layer_contents_scale / contents_scale_; | 429 float last_scale = last_layer_contents_scale / contents_scale_; |
425 | 430 |
426 // Fast path tile priority calculation when both transforms are translations. | 431 // Fast path tile priority calculation when both transforms are translations. |
427 if (last_screen_transform.IsIdentityOrTranslation() && | 432 if (last_screen_transform.IsIdentityOrTranslation() && |
428 current_screen_transform.IsIdentityOrTranslation()) | 433 current_screen_transform.IsIdentityOrTranslation()) |
429 { | 434 { |
430 gfx::Vector2dF current_offset( | 435 gfx::Vector2dF current_offset( |
431 current_screen_transform.matrix().get(0, 3), | 436 current_screen_transform.matrix().get(0, 3), |
432 current_screen_transform.matrix().get(1, 3)); | 437 current_screen_transform.matrix().get(1, 3)); |
433 gfx::Vector2dF last_offset( | 438 gfx::Vector2dF last_offset( |
434 last_screen_transform.matrix().get(0, 3), | 439 last_screen_transform.matrix().get(0, 3), |
435 last_screen_transform.matrix().get(1, 3)); | 440 last_screen_transform.matrix().get(1, 3)); |
436 | 441 |
437 for (TilingData::Iterator iter(&tiling_data_, inflated_rect); | 442 for (TilingData::Iterator iter(&tiling_data_, prioritized_rect); |
438 iter; ++iter) { | 443 iter; ++iter) { |
439 TileMap::iterator find = tiles_.find(iter.index()); | 444 TileMap::iterator find = tiles_.find(iter.index()); |
440 if (find == tiles_.end()) | 445 if (find == tiles_.end()) |
441 continue; | 446 continue; |
442 Tile* tile = find->second.get(); | 447 Tile* tile = find->second.get(); |
443 | 448 |
444 gfx::Rect tile_bounds = | 449 gfx::Rect tile_bounds = |
445 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); | 450 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
446 gfx::RectF current_screen_rect = gfx::ScaleRect( | 451 gfx::RectF current_screen_rect = gfx::ScaleRect( |
447 tile_bounds, | 452 tile_bounds, |
(...skipping 12 matching lines...) Expand all Loading... | |
460 last_screen_rect, current_screen_rect, time_delta, view_rect); | 465 last_screen_rect, current_screen_rect, time_delta, view_rect); |
461 TilePriority priority( | 466 TilePriority priority( |
462 resolution_, | 467 resolution_, |
463 time_to_visible_in_seconds, | 468 time_to_visible_in_seconds, |
464 distance_to_visible_in_pixels); | 469 distance_to_visible_in_pixels); |
465 if (store_screen_space_quads_on_tiles) | 470 if (store_screen_space_quads_on_tiles) |
466 priority.set_current_screen_quad(gfx::QuadF(current_screen_rect)); | 471 priority.set_current_screen_quad(gfx::QuadF(current_screen_rect)); |
467 tile->set_priority(tree, priority); | 472 tile->set_priority(tree, priority); |
468 } | 473 } |
469 } else { | 474 } else { |
470 for (TilingData::Iterator iter(&tiling_data_, inflated_rect); | 475 for (TilingData::Iterator iter(&tiling_data_, prioritized_rect); |
471 iter; ++iter) { | 476 iter; ++iter) { |
472 TileMap::iterator find = tiles_.find(iter.index()); | 477 TileMap::iterator find = tiles_.find(iter.index()); |
473 if (find == tiles_.end()) | 478 if (find == tiles_.end()) |
474 continue; | 479 continue; |
475 Tile* tile = find->second.get(); | 480 Tile* tile = find->second.get(); |
476 | 481 |
477 gfx::Rect tile_bounds = | 482 gfx::Rect tile_bounds = |
478 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); | 483 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
479 gfx::RectF current_layer_content_rect = gfx::ScaleRect( | 484 gfx::RectF current_layer_content_rect = gfx::ScaleRect( |
480 tile_bounds, | 485 tile_bounds, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 | 537 |
533 scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { | 538 scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { |
534 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | 539 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
535 state->SetInteger("num_tiles", tiles_.size()); | 540 state->SetInteger("num_tiles", tiles_.size()); |
536 state->SetDouble("content_scale", contents_scale_); | 541 state->SetDouble("content_scale", contents_scale_); |
537 state->Set("content_bounds", | 542 state->Set("content_bounds", |
538 MathUtil::asValue(ContentRect().size()).release()); | 543 MathUtil::asValue(ContentRect().size()).release()); |
539 return state.PassAs<base::Value>(); | 544 return state.PassAs<base::Value>(); |
540 } | 545 } |
541 | 546 |
547 namespace { | |
548 | |
549 int ComputeOffsetToExpand4EdgesEqually(int old_width, | |
550 int old_height, | |
551 int64 target_area) { | |
552 // We need to expand the rect in 4 directions, we can compute the | |
553 // amount to expand along each axis with a quadratic equation: | |
554 // (old_w + add) * (old_h + add) = target_area | |
555 // old_w * old_h + old_w * add + add * old_h + add * add = target_area | |
556 // add^2 + add * (old_w + old_h) - target_area + old_w * old_h = 0 | |
557 // Therefore, we solve the quadratic equation with: | |
558 // a = 1 | |
559 // b = old_w + old_h | |
560 // c = -target_area + old_w * old_h | |
561 int a = 1; | |
562 int64 b = old_width + old_height; | |
563 int64 c = -target_area + old_width * old_height; | |
564 int sqrt_part = std::sqrt(b * b - 4.0 * a * c); | |
565 int add_each_axis = (-b + sqrt_part) / 2 / a; | |
566 return add_each_axis / 2; | |
567 } | |
568 | |
569 int ComputeOffsetToExpand3EdgesEqually(int old_width, | |
570 int old_height, | |
571 int64 target_area, | |
572 bool left_complete, | |
573 bool top_complete, | |
574 bool right_complete, | |
575 bool bottom_complete) { | |
576 // We need to expand the rect in three directions, so we will have to | |
577 // expand along one axis twice as much as the other. Otherwise, this | |
578 // is very similar to the case where we expand in all 4 directions. | |
579 | |
580 if (left_complete || right_complete) { | |
581 // Expanding twice as much vertically as horizontally. | |
582 // (old_w + add) * (old_h + add*2) = target_area | |
583 // old_w * old_h + old_w * add*2 + add * old_h + add * add*2 = target_area | |
584 // (add^2)*2 + add * (old_w*2 + old_h) - target_area + old_w * old_h = 0 | |
585 // Therefore, we solve the quadratic equation with: | |
586 // a = 2 | |
587 // b = old_w*2 + old_h | |
588 // c = -target_area + old_w * old_h | |
589 int a = 2; | |
590 int64 b = old_width * 2 + old_height; | |
591 int64 c = -target_area + old_width * old_height; | |
592 int sqrt_part = std::sqrt(b * b - 4.0 * a * c); | |
593 int add_each_direction = (-b + sqrt_part) / 2 / a; | |
594 return add_each_direction; | |
595 } else { | |
596 // Expanding twice as much horizontally as vertically. | |
597 // (old_w + add*2) * (old_h + add) = target_area | |
598 // old_w * old_h + old_w * add + add*2 * old_h + add*2 * add = target_area | |
599 // (add^2)*2 + add * (old_w + old_h*2) - target_area + old_w * old_h = 0 | |
600 // Therefore, we solve the quadratic equation with: | |
601 // a = 2 | |
602 // b = old_w + old_h*2 | |
603 // c = -target_area + old_w * old_h | |
604 int a = 2; | |
605 int64 b = old_width + old_height * 2; | |
606 int64 c = -target_area + old_width * old_height; | |
607 int sqrt_part = std::sqrt(b * b - 4.0 * a * c); | |
608 int add_each_direction = (-b + sqrt_part) / 2 / a; | |
609 return add_each_direction; | |
610 } | |
611 } | |
612 | |
613 int ComputeOffsetToExpand2EdgesEqually(int old_width, | |
614 int old_height, | |
615 int64 target_area, | |
616 bool left_complete, | |
617 bool top_complete, | |
618 bool right_complete, | |
619 bool bottom_complete) { | |
620 // We need to expand the rect along two directions. If the two directions | |
621 // are opposite from each other then we only need to compute a distance | |
622 // along a single axis. | |
623 if (left_complete && right_complete) { | |
624 // Expanding along the vertical axis only: | |
625 // old_w * (old_h + add) = target_area | |
626 // old_w * old_h + old_w * add = target_area | |
627 // add_vertically = (target_area - old_w * old_h) / old_w | |
628 int add_vertically = target_area / old_width - old_height; | |
629 return add_vertically / 2; | |
630 } else if (top_complete && bottom_complete) { | |
631 // Expanding along the horizontal axis only: | |
632 // (old_w + add) * old_h = target_area | |
633 // old_w * old_h + add * old_h = target_area | |
634 // add_horizontally = (target_area - old_w * old_h) / old_h | |
635 int add_horizontally = target_area / old_height - old_width; | |
636 return add_horizontally / 2; | |
637 } else { | |
638 // If we need to expand along both horizontal and vertical axes, we can use | |
639 // the same result as if we were expanding all four edges. But we apply the | |
640 // offset computed for opposing edges to a single edge. | |
641 int add_each_direction = ComputeOffsetToExpand4EdgesEqually( | |
642 old_width, old_height, target_area); | |
643 return add_each_direction * 2; | |
644 } | |
645 } | |
646 | |
647 int ComputeOffsetToExpand1Edge(int old_width, | |
648 int old_height, | |
649 int64 target_area, | |
650 bool left_complete, | |
651 bool top_complete, | |
652 bool right_complete, | |
653 bool bottom_complete) { | |
654 // We need to expand the rect in a single direction, so we are either | |
655 // moving just a verical edge, or just a horizontal edge. | |
656 if (!top_complete || !bottom_complete) { | |
657 // Moving a vertical edge: | |
658 // old_w * (old_h + add) = target_area | |
659 // old_w * old_h + old_w * add = target_area | |
660 // add_vertically = (target_area - old_w * old_h) / old_w | |
661 int add_vertically = target_area / old_width - old_height; | |
662 return add_vertically; | |
663 } else { | |
664 // Moving a horizontal edge: | |
665 // (old_w + add) * old_h = target_area | |
666 // old_w * old_h + add * old_h = target_area | |
667 // add_horizontally = (target_area - old_w * old_h) / old_h | |
668 int add_horizontally = target_area / old_height - old_width; | |
669 return add_horizontally; | |
670 } | |
671 } | |
672 | |
673 } // namespace | |
674 | |
675 // static | |
676 gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy( | |
677 gfx::Rect starting_rect, | |
678 int64 target_area, | |
679 gfx::Rect bounding_rect) { | |
680 | |
681 bool left_complete = false; | |
682 bool top_complete = false; | |
683 bool right_complete = false; | |
684 bool bottom_complete = false; | |
685 int num_edges_complete = 0; | |
686 | |
687 gfx::Rect working_rect = starting_rect; | |
688 for (int i = 0; i < 4; ++i) { | |
689 if (num_edges_complete != i) | |
690 continue; | |
691 int offset_for_each_edge = 0; | |
692 switch (num_edges_complete) { | |
693 case 0: | |
694 offset_for_each_edge = ComputeOffsetToExpand4EdgesEqually( | |
695 working_rect.width(), | |
696 working_rect.height(), | |
697 target_area); | |
698 break; | |
699 case 1: | |
700 offset_for_each_edge = ComputeOffsetToExpand3EdgesEqually( | |
701 working_rect.width(), | |
702 working_rect.height(), | |
703 target_area, | |
704 left_complete, | |
705 top_complete, | |
706 right_complete, | |
707 bottom_complete); | |
708 break; | |
709 case 2: | |
710 offset_for_each_edge = ComputeOffsetToExpand2EdgesEqually( | |
711 working_rect.width(), | |
712 working_rect.height(), | |
713 target_area, | |
714 left_complete, | |
715 top_complete, | |
716 right_complete, | |
717 bottom_complete); | |
718 break; | |
719 case 3: | |
720 offset_for_each_edge = ComputeOffsetToExpand1Edge( | |
721 working_rect.width(), | |
722 working_rect.height(), | |
723 target_area, | |
724 left_complete, | |
725 top_complete, | |
726 right_complete, | |
727 bottom_complete); | |
728 } | |
729 | |
730 working_rect.Inset((left_complete ? 0 : -offset_for_each_edge), | |
731 (top_complete ? 0 : -offset_for_each_edge), | |
732 (right_complete ? 0 : -offset_for_each_edge), | |
733 (bottom_complete ? 0 : -offset_for_each_edge)); | |
734 | |
735 if (bounding_rect.Contains(working_rect)) | |
736 return working_rect; | |
737 working_rect.Intersect(bounding_rect); | |
738 | |
739 if (working_rect.x() == bounding_rect.x()) left_complete = true; | |
740 if (working_rect.y() == bounding_rect.y()) top_complete = true; | |
741 if (working_rect.right() == bounding_rect.right()) right_complete = true; | |
742 if (working_rect.bottom() == bounding_rect.bottom()) bottom_complete = true; | |
743 | |
744 num_edges_complete = (left_complete ? 1 : 0) + | |
745 (top_complete ? 1 : 0) + | |
746 (right_complete ? 1 : 0) + | |
747 (bottom_complete ? 1 : 0); | |
748 if (num_edges_complete == 4) | |
749 return working_rect; | |
750 } | |
751 | |
752 NOTREACHED(); | |
753 return starting_rect; | |
754 } | |
755 | |
542 } // namespace cc | 756 } // namespace cc |
OLD | NEW |