Chromium Code Reviews| 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 |