Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: cc/picture_layer_tiling.cc

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

Powered by Google App Engine
This is Rietveld 408576698