summaryrefslogtreecommitdiffstats
path: root/chromium/cc/tiles/tile_manager.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-01-25 11:39:07 +0100
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2016-01-25 15:20:42 +0000
commit6c91641271e536ffaa88a1dff5127e42ee99a91e (patch)
tree703d9dd49602377ddc90cbf886aad37913f2496b /chromium/cc/tiles/tile_manager.cc
parentb145b7fafd36f0c260d6a768c81fc14e32578099 (diff)
BASELINE: Update Chromium to 49.0.2623.23
Also adds missing printing sources. Change-Id: I3726b8f0c7d6751c9fc846096c571fadca7108cd Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/cc/tiles/tile_manager.cc')
-rw-r--r--chromium/cc/tiles/tile_manager.cc523
1 files changed, 351 insertions, 172 deletions
diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc
index b9d3ab7fd15..ebb1d3fd636 100644
--- a/chromium/cc/tiles/tile_manager.cc
+++ b/chromium/cc/tiles/tile_manager.cc
@@ -4,6 +4,9 @@
#include "cc/tiles/tile_manager.h"
+#include <stddef.h>
+#include <stdint.h>
+
#include <algorithm>
#include <limits>
#include <string>
@@ -11,6 +14,7 @@
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/numerics/safe_conversions.h"
#include "base/trace_event/trace_event_argument.h"
@@ -20,6 +24,7 @@
#include "cc/debug/traced_value.h"
#include "cc/layers/picture_layer_impl.h"
#include "cc/raster/raster_buffer.h"
+#include "cc/raster/task_category.h"
#include "cc/raster/tile_task_runner.h"
#include "cc/tiles/tile.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -38,24 +43,21 @@ DEFINE_SCOPED_UMA_HISTOGRAM_AREA_TIMER(
class RasterTaskImpl : public RasterTask {
public:
- RasterTaskImpl(
- const Resource* resource,
- RasterSource* raster_source,
- const gfx::Rect& content_rect,
- const gfx::Rect& invalid_content_rect,
- float contents_scale,
- TileResolution tile_resolution,
- int layer_id,
- uint64_t source_prepare_tiles_id,
- const void* tile,
- uint64_t new_content_id,
- uint64_t previous_content_id,
- uint64_t resource_content_id,
- int source_frame_number,
- bool analyze_picture,
- const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>&
- reply,
- ImageDecodeTask::Vector* dependencies)
+ RasterTaskImpl(const Resource* resource,
+ DisplayListRasterSource* raster_source,
+ const gfx::Rect& content_rect,
+ const gfx::Rect& invalid_content_rect,
+ float contents_scale,
+ TileResolution tile_resolution,
+ int layer_id,
+ uint64_t source_prepare_tiles_id,
+ const void* tile,
+ uint64_t new_content_id,
+ uint64_t previous_content_id,
+ uint64_t resource_content_id,
+ int source_frame_number,
+ const base::Callback<void(bool)>& reply,
+ ImageDecodeTask::Vector* dependencies)
: RasterTask(dependencies),
resource_(resource),
raster_source_(raster_source),
@@ -70,7 +72,6 @@ class RasterTaskImpl : public RasterTask {
previous_content_id_(previous_content_id),
resource_content_id_(resource_content_id),
source_frame_number_(source_frame_number),
- analyze_picture_(analyze_picture),
reply_(reply) {}
// Overridden from Task:
@@ -81,12 +82,6 @@ class RasterTaskImpl : public RasterTask {
DCHECK(raster_source_.get());
DCHECK(raster_buffer_);
- if (analyze_picture_) {
- Analyze(raster_source_.get());
- if (analysis_.is_solid_color)
- return;
- }
-
Raster(raster_source_.get());
}
@@ -97,27 +92,15 @@ class RasterTaskImpl : public RasterTask {
resource_, resource_content_id_, previous_content_id_);
}
void CompleteOnOriginThread(TileTaskClient* client) override {
- client->ReleaseBufferForRaster(raster_buffer_.Pass());
- reply_.Run(analysis_, !HasFinishedRunning());
+ client->ReleaseBufferForRaster(std::move(raster_buffer_));
+ reply_.Run(!HasFinishedRunning());
}
protected:
~RasterTaskImpl() override { DCHECK(!raster_buffer_); }
private:
- void Analyze(const RasterSource* raster_source) {
- frame_viewer_instrumentation::ScopedAnalyzeTask analyze_task(
- tile_, tile_resolution_, source_frame_number_, layer_id_);
-
- DCHECK(raster_source);
-
- raster_source->PerformSolidColorAnalysis(content_rect_, contents_scale_,
- &analysis_);
- // Clear the flag if we're not using the estimator.
- analysis_.is_solid_color &= kUseColorEstimator;
- }
-
- void Raster(const RasterSource* raster_source) {
+ void Raster(const DisplayListRasterSource* raster_source) {
frame_viewer_instrumentation::ScopedRasterTask raster_task(
tile_, tile_resolution_, source_frame_number_, layer_id_);
ScopedRasterTaskTimer timer;
@@ -132,8 +115,7 @@ class RasterTaskImpl : public RasterTask {
}
const Resource* resource_;
- RasterSource::SolidColorAnalysis analysis_;
- scoped_refptr<RasterSource> raster_source_;
+ scoped_refptr<DisplayListRasterSource> raster_source_;
gfx::Rect content_rect_;
gfx::Rect invalid_content_rect_;
float contents_scale_;
@@ -145,28 +127,127 @@ class RasterTaskImpl : public RasterTask {
uint64_t previous_content_id_;
uint64_t resource_content_id_;
int source_frame_number_;
- bool analyze_picture_;
- const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>
- reply_;
+ const base::Callback<void(bool)> reply_;
scoped_ptr<RasterBuffer> raster_buffer_;
DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl);
};
-const char* TaskSetName(TaskSet task_set) {
- switch (task_set) {
- case TileManager::ALL:
- return "ALL";
- case TileManager::REQUIRED_FOR_ACTIVATION:
- return "REQUIRED_FOR_ACTIVATION";
- case TileManager::REQUIRED_FOR_DRAW:
- return "REQUIRED_FOR_DRAW";
+// Task priorities that make sure that the task set done tasks run before any
+// other remaining tasks.
+const size_t kRequiredForActivationDoneTaskPriority = 1u;
+const size_t kRequiredForDrawDoneTaskPriority = 2u;
+const size_t kAllDoneTaskPriority = 3u;
+
+// For correctness, |kTileTaskPriorityBase| must be greater than
+// all task set done task priorities.
+size_t kTileTaskPriorityBase = 10u;
+
+void InsertNodeForTask(TaskGraph* graph,
+ TileTask* task,
+ uint16_t category,
+ uint16_t priority,
+ size_t dependencies) {
+ DCHECK(std::find_if(graph->nodes.begin(), graph->nodes.end(),
+ [task](const TaskGraph::Node& node) {
+ return node.task == task;
+ }) == graph->nodes.end());
+ graph->nodes.push_back(
+ TaskGraph::Node(task, category, priority, dependencies));
+}
+
+void InsertNodesForRasterTask(TaskGraph* graph,
+ RasterTask* raster_task,
+ const ImageDecodeTask::Vector& decode_tasks,
+ size_t priority,
+ bool use_gpu_rasterization,
+ bool high_priority) {
+ size_t dependencies = 0u;
+
+ // Determine the TaskCategory for raster tasks - if a task uses GPU, it
+ // cannot run concurrently and is assigned
+ // TASK_CATEGORY_NONCONCURRENT_FOREGROUND, regardless of its priority.
+ // Otherwise its category is based on its priority.
+ TaskCategory raster_task_category;
+ if (use_gpu_rasterization) {
+ raster_task_category = TASK_CATEGORY_NONCONCURRENT_FOREGROUND;
+ } else {
+ raster_task_category =
+ high_priority ? TASK_CATEGORY_FOREGROUND : TASK_CATEGORY_BACKGROUND;
}
- NOTREACHED();
- return "Invalid TaskSet";
+ // Determine the TaskCategory for decode tasks. This category is based on
+ // the priority of the raster task which depends on it.
+ TaskCategory decode_task_category =
+ high_priority ? TASK_CATEGORY_FOREGROUND : TASK_CATEGORY_BACKGROUND;
+
+ // Insert image decode tasks.
+ for (ImageDecodeTask::Vector::const_iterator it = decode_tasks.begin();
+ it != decode_tasks.end(); ++it) {
+ ImageDecodeTask* decode_task = it->get();
+
+ // Skip if already decoded.
+ if (decode_task->HasCompleted())
+ continue;
+
+ dependencies++;
+
+ // Add decode task if it doesn't already exists in graph.
+ TaskGraph::Node::Vector::iterator decode_it =
+ std::find_if(graph->nodes.begin(), graph->nodes.end(),
+ [decode_task](const TaskGraph::Node& node) {
+ return node.task == decode_task;
+ });
+
+ // Tasks are inserted in priority order, so existing decode tasks should
+ // already be FOREGROUND if this is a high priority task.
+ DCHECK(decode_it == graph->nodes.end() || !high_priority ||
+ static_cast<uint16_t>(TASK_CATEGORY_FOREGROUND) ==
+ decode_it->category);
+
+ if (decode_it == graph->nodes.end()) {
+ InsertNodeForTask(graph, decode_task, decode_task_category, priority, 0u);
+ }
+
+ graph->edges.push_back(TaskGraph::Edge(decode_task, raster_task));
+ }
+
+ InsertNodeForTask(graph, raster_task, raster_task_category, priority,
+ dependencies);
}
+class TaskSetFinishedTaskImpl : public TileTask {
+ public:
+ explicit TaskSetFinishedTaskImpl(
+ base::SequencedTaskRunner* task_runner,
+ const base::Closure& on_task_set_finished_callback)
+ : task_runner_(task_runner),
+ on_task_set_finished_callback_(on_task_set_finished_callback) {}
+
+ // Overridden from Task:
+ void RunOnWorkerThread() override {
+ TRACE_EVENT0("cc", "TaskSetFinishedTaskImpl::RunOnWorkerThread");
+ TaskSetFinished();
+ }
+
+ // Overridden from TileTask:
+ void ScheduleOnOriginThread(TileTaskClient* client) override {}
+ void CompleteOnOriginThread(TileTaskClient* client) override {}
+
+ protected:
+ ~TaskSetFinishedTaskImpl() override {}
+
+ void TaskSetFinished() {
+ task_runner_->PostTask(FROM_HERE, on_task_set_finished_callback_);
+ }
+
+ private:
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ const base::Closure on_task_set_finished_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskSetFinishedTaskImpl);
+};
+
} // namespace
RasterTaskCompletionStats::RasterTaskCompletionStats()
@@ -187,20 +268,24 @@ RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
scoped_ptr<TileManager> TileManager::Create(
TileManagerClient* client,
base::SequencedTaskRunner* task_runner,
- size_t scheduled_raster_task_limit) {
- return make_scoped_ptr(
- new TileManager(client, task_runner, scheduled_raster_task_limit));
+ size_t scheduled_raster_task_limit,
+ bool use_partial_raster) {
+ return make_scoped_ptr(new TileManager(
+ client, task_runner, scheduled_raster_task_limit, use_partial_raster));
}
TileManager::TileManager(
TileManagerClient* client,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- size_t scheduled_raster_task_limit)
+ size_t scheduled_raster_task_limit,
+ bool use_partial_raster)
: client_(client),
task_runner_(task_runner),
resource_pool_(nullptr),
tile_task_runner_(nullptr),
scheduled_raster_task_limit_(scheduled_raster_task_limit),
+ use_partial_raster_(use_partial_raster),
+ use_gpu_rasterization_(false),
all_tiles_that_need_to_be_rasterized_are_scheduled_(true),
did_check_for_completed_tasks_since_last_schedule_tasks_(true),
did_oom_on_last_assign_(false),
@@ -213,7 +298,8 @@ TileManager::TileManager(
base::Unretained(this))),
has_scheduled_tile_tasks_(false),
prepare_tiles_count_(0u),
- next_tile_id_(0u) {}
+ next_tile_id_(0u),
+ task_set_finished_weak_ptr_factory_(this) {}
TileManager::~TileManager() {
FinishTasksAndCleanUp();
@@ -225,13 +311,14 @@ void TileManager::FinishTasksAndCleanUp() {
global_state_ = GlobalStateThatImpactsTilePriority();
- TileTaskQueue empty;
- tile_task_runner_->ScheduleTasks(&empty);
- orphan_raster_tasks_.clear();
-
- // This should finish all pending tasks and release any uninitialized
- // resources.
+ // This cancels tasks if possible, finishes pending tasks, and release any
+ // uninitialized resources.
tile_task_runner_->Shutdown();
+
+ // Now that all tasks have been finished, we can clear any
+ // |orphan_tasks_|.
+ orphan_tasks_.clear();
+
tile_task_runner_->CheckForCompletedTasks();
FreeResourcesForReleasedTiles();
@@ -241,18 +328,20 @@ void TileManager::FinishTasksAndCleanUp() {
resource_pool_ = nullptr;
more_tiles_need_prepare_check_notifier_.Cancel();
signals_check_notifier_.Cancel();
+ task_set_finished_weak_ptr_factory_.InvalidateWeakPtrs();
}
void TileManager::SetResources(ResourcePool* resource_pool,
TileTaskRunner* tile_task_runner,
- size_t scheduled_raster_task_limit) {
+ size_t scheduled_raster_task_limit,
+ bool use_gpu_rasterization) {
DCHECK(!tile_task_runner_);
DCHECK(tile_task_runner);
+ use_gpu_rasterization_ = use_gpu_rasterization;
scheduled_raster_task_limit_ = scheduled_raster_task_limit;
resource_pool_ = resource_pool;
tile_task_runner_ = tile_task_runner;
- tile_task_runner_->SetClient(this);
}
void TileManager::Release(Tile* tile) {
@@ -282,44 +371,45 @@ void TileManager::CleanUpReleasedTiles() {
released_tiles_.swap(tiles_to_retain);
}
-void TileManager::DidFinishRunningTileTasks(TaskSet task_set) {
- TRACE_EVENT1("cc", "TileManager::DidFinishRunningTileTasks", "task_set",
- TaskSetName(task_set));
+void TileManager::DidFinishRunningTileTasksRequiredForActivation() {
+ TRACE_EVENT0("cc",
+ "TileManager::DidFinishRunningTileTasksRequiredForActivation");
+ TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", "state",
+ ScheduledTasksStateAsValue());
+ signals_.ready_to_activate = true;
+ signals_check_notifier_.Schedule();
+}
+
+void TileManager::DidFinishRunningTileTasksRequiredForDraw() {
+ TRACE_EVENT0("cc", "TileManager::DidFinishRunningTileTasksRequiredForDraw");
+ TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", "state",
+ ScheduledTasksStateAsValue());
+ signals_.ready_to_draw = true;
+ signals_check_notifier_.Schedule();
+}
+
+void TileManager::DidFinishRunningAllTileTasks() {
+ TRACE_EVENT0("cc", "TileManager::DidFinishRunningAllTileTasks");
+ TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
DCHECK(resource_pool_);
DCHECK(tile_task_runner_);
- switch (task_set) {
- case ALL: {
- has_scheduled_tile_tasks_ = false;
-
- bool memory_usage_above_limit = resource_pool_->memory_usage_bytes() >
- global_state_.soft_memory_limit_in_bytes;
-
- if (all_tiles_that_need_to_be_rasterized_are_scheduled_ &&
- !memory_usage_above_limit) {
- // TODO(ericrk): We should find a better way to safely handle re-entrant
- // notifications than always having to schedule a new task.
- // http://crbug.com/498439
- signals_.all_tile_tasks_completed = true;
- signals_check_notifier_.Schedule();
- return;
- }
+ has_scheduled_tile_tasks_ = false;
- more_tiles_need_prepare_check_notifier_.Schedule();
- return;
- }
- case REQUIRED_FOR_ACTIVATION:
- signals_.ready_to_activate = true;
- signals_check_notifier_.Schedule();
- return;
+ bool memory_usage_above_limit = resource_pool_->memory_usage_bytes() >
+ global_state_.soft_memory_limit_in_bytes;
- case REQUIRED_FOR_DRAW:
- signals_.ready_to_draw = true;
- signals_check_notifier_.Schedule();
- return;
+ if (all_tiles_that_need_to_be_rasterized_are_scheduled_ &&
+ !memory_usage_above_limit) {
+ // TODO(ericrk): We should find a better way to safely handle re-entrant
+ // notifications than always having to schedule a new task.
+ // http://crbug.com/498439
+ signals_.all_tile_tasks_completed = true;
+ signals_check_notifier_.Schedule();
+ return;
}
- NOTREACHED();
+ more_tiles_need_prepare_check_notifier_.Schedule();
}
bool TileManager::PrepareTiles(
@@ -509,6 +599,23 @@ void TileManager::AssignGpuMemoryToTiles(
break;
}
+ if (tile->use_picture_analysis() && kUseColorEstimator) {
+ // We analyze for solid color here, to decide to continue
+ // or drop the tile for scheduling and raster.
+ // TODO(sohanjg): Check if we could use a shared analysis
+ // canvas which is reset between tiles.
+ SkColor color = SK_ColorTRANSPARENT;
+ bool is_solid_color =
+ prioritized_tile.raster_source()->PerformSolidColorAnalysis(
+ tile->content_rect(), tile->contents_scale(), &color);
+ if (is_solid_color) {
+ tile->draw_info().set_solid_color(color);
+ tile->draw_info().set_was_ever_ready_to_draw();
+ client_->NotifyTileStateChanged(tile);
+ continue;
+ }
+ }
+
// We won't be able to schedule this tile, so break out early.
if (tiles_that_need_to_be_rasterized->size() >=
scheduled_raster_task_limit) {
@@ -518,8 +625,8 @@ void TileManager::AssignGpuMemoryToTiles(
tile->scheduled_priority_ = schedule_priority++;
- DCHECK_IMPLIES(tile->draw_info().mode() != TileDrawInfo::OOM_MODE,
- !tile->draw_info().IsReadyToDraw());
+ DCHECK(tile->draw_info().mode() == TileDrawInfo::OOM_MODE ||
+ !tile->draw_info().IsReadyToDraw());
// If the tile already has a raster_task, then the memory used by it is
// already accounted for in memory_usage. Otherwise, we'll have to acquire
@@ -542,7 +649,7 @@ void TileManager::AssignGpuMemoryToTiles(
tile_memory_limit - memory_required_by_tile_to_be_scheduled;
eviction_priority_queue =
FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
- eviction_priority_queue.Pass(), scheduled_tile_memory_limit,
+ std::move(eviction_priority_queue), scheduled_tile_memory_limit,
priority, &memory_usage);
bool memory_usage_is_within_limit =
!memory_usage.Exceeds(scheduled_tile_memory_limit);
@@ -564,7 +671,7 @@ void TileManager::AssignGpuMemoryToTiles(
// didn't reduce memory. This ensures that we always release as many resources
// as possible to stay within the memory limit.
eviction_priority_queue = FreeTileResourcesUntilUsageIsWithinLimit(
- eviction_priority_queue.Pass(), hard_memory_limit, &memory_usage);
+ std::move(eviction_priority_queue), hard_memory_limit, &memory_usage);
UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget",
!had_enough_memory_to_schedule_tiles_needed_now);
@@ -602,20 +709,41 @@ void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(
void TileManager::ScheduleTasks(
const PrioritizedTileVector& tiles_that_need_to_be_rasterized) {
- TRACE_EVENT1("cc",
- "TileManager::ScheduleTasks",
- "count",
+ TRACE_EVENT1("cc", "TileManager::ScheduleTasks", "count",
tiles_that_need_to_be_rasterized.size());
DCHECK(did_check_for_completed_tasks_since_last_schedule_tasks_);
- raster_queue_.Reset();
+ if (!has_scheduled_tile_tasks_) {
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
+ }
+
+ // Cancel existing OnTaskSetFinished callbacks.
+ task_set_finished_weak_ptr_factory_.InvalidateWeakPtrs();
// Even when scheduling an empty set of tiles, the TTWP does some work, and
// will always trigger a DidFinishRunningTileTasks notification. Because of
// this we unconditionally set |has_scheduled_tile_tasks_| to true.
has_scheduled_tile_tasks_ = true;
+ // Track the number of dependents for each *_done task.
+ size_t required_for_activate_count = 0;
+ size_t required_for_draw_count = 0;
+ size_t all_count = 0;
+
+ size_t priority = kTileTaskPriorityBase;
+
+ graph_.Reset();
+
+ scoped_refptr<TileTask> required_for_activation_done_task =
+ CreateTaskSetFinishedTask(
+ &TileManager::DidFinishRunningTileTasksRequiredForActivation);
+ scoped_refptr<TileTask> required_for_draw_done_task =
+ CreateTaskSetFinishedTask(
+ &TileManager::DidFinishRunningTileTasksRequiredForDraw);
+ scoped_refptr<TileTask> all_done_task =
+ CreateTaskSetFinishedTask(&TileManager::DidFinishRunningAllTileTasks);
+
// Build a new task queue containing all task currently needed. Tasks
// are added in order of priority, highest priority task first.
for (auto& prioritized_tile : tiles_that_need_to_be_rasterized) {
@@ -624,19 +752,48 @@ void TileManager::ScheduleTasks(
DCHECK(tile->draw_info().requires_resource());
DCHECK(!tile->draw_info().resource_);
+ if (!tile->raster_task_) {
+ tile->raster_task_ = CreateRasterTask(prioritized_tile);
+ }
+
+ RasterTask* task = tile->raster_task_.get();
+ DCHECK(!task->HasCompleted());
+
if (!tile->raster_task_.get())
tile->raster_task_ = CreateRasterTask(prioritized_tile);
- TaskSetCollection task_sets;
- if (tile->required_for_activation())
- task_sets.set(REQUIRED_FOR_ACTIVATION);
- if (tile->required_for_draw())
- task_sets.set(REQUIRED_FOR_DRAW);
- task_sets.set(ALL);
- raster_queue_.items.push_back(
- TileTaskQueue::Item(tile->raster_task_.get(), task_sets));
+ if (tile->required_for_activation()) {
+ required_for_activate_count++;
+ graph_.edges.push_back(
+ TaskGraph::Edge(task, required_for_activation_done_task.get()));
+ }
+ if (tile->required_for_draw()) {
+ required_for_draw_count++;
+ graph_.edges.push_back(
+ TaskGraph::Edge(task, required_for_draw_done_task.get()));
+ }
+ all_count++;
+ graph_.edges.push_back(TaskGraph::Edge(task, all_done_task.get()));
+
+ bool high_priority =
+ tile->required_for_draw() || tile->required_for_activation();
+ InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++,
+ use_gpu_rasterization_, high_priority);
}
+ // Insert nodes for our task completion tasks. We enqueue these using
+ // FOREGROUND priority as they are relatively quick tasks and we'd like
+ // to trigger our callbacks quickly to aid in scheduling.
+ InsertNodeForTask(&graph_, required_for_activation_done_task.get(),
+ TASK_CATEGORY_FOREGROUND,
+ kRequiredForActivationDoneTaskPriority,
+ required_for_activate_count);
+ InsertNodeForTask(&graph_, required_for_draw_done_task.get(),
+ TASK_CATEGORY_FOREGROUND, kRequiredForDrawDoneTaskPriority,
+ required_for_draw_count);
+ InsertNodeForTask(&graph_, all_done_task.get(), TASK_CATEGORY_FOREGROUND,
+ kAllDoneTaskPriority, all_count);
+
// We must reduce the amount of unused resoruces before calling
// ScheduleTasks to prevent usage from rising above limits.
resource_pool_->ReduceResourceUsage();
@@ -644,14 +801,23 @@ void TileManager::ScheduleTasks(
// Schedule running of |raster_queue_|. This replaces any previously
// scheduled tasks and effectively cancels all tasks not present
// in |raster_queue_|.
- tile_task_runner_->ScheduleTasks(&raster_queue_);
+ tile_task_runner_->ScheduleTasks(&graph_);
// It's now safe to clean up orphan tasks as raster worker pool is not
// allowed to keep around unreferenced raster tasks after ScheduleTasks() has
// been called.
- orphan_raster_tasks_.clear();
+ orphan_tasks_.clear();
+
+ // It's also now safe to replace our *_done_task_ tasks.
+ required_for_activation_done_task_ =
+ std::move(required_for_activation_done_task);
+ required_for_draw_done_task_ = std::move(required_for_draw_done_task);
+ all_done_task_ = std::move(all_done_task);
did_check_for_completed_tasks_since_last_schedule_tasks_ = false;
+
+ TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", "state",
+ ScheduledTasksStateAsValue());
}
scoped_refptr<RasterTask> TileManager::CreateRasterTask(
@@ -659,7 +825,7 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(
Tile* tile = prioritized_tile.tile();
uint64_t resource_content_id = 0;
Resource* resource = nullptr;
- if (tile->invalidated_id()) {
+ if (use_partial_raster_ && tile->invalidated_id()) {
// TODO(danakj): For resources that are in use, we should still grab them
// and copy from them instead of rastering everything. crbug.com/492754
resource =
@@ -677,9 +843,9 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(
// Create and queue all image decode tasks that this tile depends on.
ImageDecodeTask::Vector decode_tasks;
- std::vector<PositionImage> images;
+ std::vector<DrawImage> images;
prioritized_tile.raster_source()->GetDiscardableImagesInRect(
- tile->enclosing_layer_rect(), &images);
+ tile->enclosing_layer_rect(), tile->contents_scale(), &images);
for (const auto& image : images) {
decode_tasks.push_back(image_decode_controller_.GetTaskForImage(
image, tile->layer_id(), prepare_tiles_count_));
@@ -691,7 +857,6 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(
prioritized_tile.priority().resolution, tile->layer_id(),
prepare_tiles_count_, static_cast<const void*>(tile), tile->id(),
tile->invalidated_id(), resource_content_id, tile->source_frame_number(),
- tile->use_picture_analysis(),
base::Bind(&TileManager::OnRasterTaskCompleted, base::Unretained(this),
tile->id(), resource),
&decode_tasks));
@@ -700,13 +865,13 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(
void TileManager::OnRasterTaskCompleted(
Tile::Id tile_id,
Resource* resource,
- const RasterSource::SolidColorAnalysis& analysis,
bool was_canceled) {
DCHECK(tiles_.find(tile_id) != tiles_.end());
Tile* tile = tiles_[tile_id];
+ TileDrawInfo& draw_info = tile->draw_info();
DCHECK(tile->raster_task_.get());
- orphan_raster_tasks_.push_back(tile->raster_task_);
+ orphan_tasks_.push_back(tile->raster_task_);
tile->raster_task_ = nullptr;
if (was_canceled) {
@@ -719,32 +884,12 @@ void TileManager::OnRasterTaskCompleted(
return;
}
- UpdateTileDrawInfo(tile, resource, analysis);
-}
-
-void TileManager::UpdateTileDrawInfo(
- Tile* tile,
- Resource* resource,
- const RasterSource::SolidColorAnalysis& analysis) {
- TileDrawInfo& draw_info = tile->draw_info();
-
++flush_stats_.completed_count;
- if (analysis.is_solid_color) {
- draw_info.set_solid_color(analysis.solid_color);
- if (resource) {
- // TODO(ericrk): If more partial raster work is done in the future, it may
- // be worth returning the resource to the pool with its previous ID (not
- // currently tracked). crrev.com/1370333002/#ps40001 has a possible method
- // of achieving this.
- resource_pool_->ReleaseResource(resource, 0 /* content_id */);
- }
- } else {
- DCHECK(resource);
- draw_info.set_use_resource();
- draw_info.resource_ = resource;
- draw_info.contents_swizzled_ = DetermineResourceRequiresSwizzle(tile);
- }
+ draw_info.set_use_resource();
+ draw_info.resource_ = resource;
+ draw_info.contents_swizzled_ = DetermineResourceRequiresSwizzle(tile);
+
DCHECK(draw_info.IsReadyToDraw());
draw_info.set_was_ever_ready_to_draw();
@@ -770,7 +915,6 @@ ScopedTilePtr TileManager::CreateTile(const Tile::CreateInfo& info,
void TileManager::SetTileTaskRunnerForTesting(
TileTaskRunner* tile_task_runner) {
tile_task_runner_ = tile_task_runner;
- tile_task_runner_->SetClient(this);
}
bool TileManager::AreRequiredTilesReadyToDraw(
@@ -792,8 +936,8 @@ bool TileManager::AreRequiredTilesReadyToDraw(
client_->BuildRasterQueue(global_state_.tree_priority, type));
for (; !all_queue->IsEmpty(); all_queue->Pop()) {
Tile* tile = all_queue->Top().tile();
- DCHECK_IMPLIES(tile->required_for_activation(),
- tile->draw_info().IsReadyToDraw());
+ DCHECK(!tile->required_for_activation() ||
+ tile->draw_info().IsReadyToDraw());
}
#endif
return true;
@@ -894,36 +1038,48 @@ void TileManager::CheckIfMoreTilesNeedToBePrepared() {
global_state_.tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
global_state_.memory_limit_policy == ALLOW_NOTHING;
- // Mark any required-for-activation tiles that have not been been assigned
- // memory after reaching a steady memory state as OOM. This ensures that we
- // activate even when OOM. Note that we can't reuse the queue we used for
- // AssignGpuMemoryToTiles, since the AssignGpuMemoryToTiles call could have
- // evicted some tiles that would not be picked up by the old raster queue.
- scoped_ptr<RasterTilePriorityQueue> required_for_activation_queue(
- client_->BuildRasterQueue(
- global_state_.tree_priority,
- RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
-
// If we have tiles left to raster for activation, and we don't allow
// activating without them, then skip activation and return early.
- if (!required_for_activation_queue->IsEmpty() && wait_for_all_required_tiles)
+ if (wait_for_all_required_tiles)
return;
- // Mark required tiles as OOM so that we can activate without them.
- for (; !required_for_activation_queue->IsEmpty();
- required_for_activation_queue->Pop()) {
- Tile* tile = required_for_activation_queue->Top().tile();
- tile->draw_info().set_oom();
- client_->NotifyTileStateChanged(tile);
- }
+ // Mark any required tiles that have not been been assigned memory after
+ // reaching a steady memory state as OOM. This ensures that we activate/draw
+ // even when OOM. Note that we can't reuse the queue we used for
+ // AssignGpuMemoryToTiles, since the AssignGpuMemoryToTiles call could have
+ // evicted some tiles that would not be picked up by the old raster queue.
+ bool need_to_signal_activate = MarkTilesOutOfMemory(client_->BuildRasterQueue(
+ global_state_.tree_priority,
+ RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
+ bool need_to_signal_draw = MarkTilesOutOfMemory(client_->BuildRasterQueue(
+ global_state_.tree_priority,
+ RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW));
DCHECK(IsReadyToActivate());
+ DCHECK(IsReadyToDraw());
+ signals_.ready_to_activate = need_to_signal_activate;
+ signals_.ready_to_draw = need_to_signal_draw;
// TODO(ericrk): Investigate why we need to schedule this (not just call it
// inline). http://crbug.com/498439
- signals_.ready_to_activate = true;
signals_check_notifier_.Schedule();
}
+bool TileManager::MarkTilesOutOfMemory(
+ scoped_ptr<RasterTilePriorityQueue> queue) const {
+ // Mark required tiles as OOM so that we can activate/draw without them.
+ if (queue->IsEmpty())
+ return false;
+
+ for (; !queue->IsEmpty(); queue->Pop()) {
+ Tile* tile = queue->Top().tile();
+ if (tile->draw_info().IsReadyToDraw())
+ continue;
+ tile->draw_info().set_oom();
+ client_->NotifyTileStateChanged(tile);
+ }
+ return true;
+}
+
ResourceFormat TileManager::DetermineResourceFormat(const Tile* tile) const {
return tile_task_runner_->GetResourceFormat(!tile->is_opaque());
}
@@ -932,19 +1088,42 @@ bool TileManager::DetermineResourceRequiresSwizzle(const Tile* tile) const {
return tile_task_runner_->GetResourceRequiresSwizzle(!tile->is_opaque());
}
-TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) {
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+TileManager::ScheduledTasksStateAsValue() const {
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
+
+ state->BeginDictionary("tasks_pending");
+ state->SetBoolean("ready_to_activate", signals_.ready_to_activate);
+ state->SetBoolean("ready_to_draw", signals_.ready_to_draw);
+ state->SetBoolean("all_tile_tasks_completed",
+ signals_.all_tile_tasks_completed);
+ state->EndDictionary();
+ return state;
+}
+
+// Utility function that can be used to create a "Task set finished" task that
+// posts |callback| to |task_runner| when run.
+scoped_refptr<TileTask> TileManager::CreateTaskSetFinishedTask(
+ void (TileManager::*callback)()) {
+ return make_scoped_refptr(new TaskSetFinishedTaskImpl(
+ task_runner_.get(),
+ base::Bind(callback, task_set_finished_weak_ptr_factory_.GetWeakPtr())));
}
+TileManager::MemoryUsage::MemoryUsage()
+ : memory_bytes_(0), resource_count_(0) {}
+
TileManager::MemoryUsage::MemoryUsage(size_t memory_bytes,
size_t resource_count)
- : memory_bytes_(static_cast<int64>(memory_bytes)),
+ : memory_bytes_(static_cast<int64_t>(memory_bytes)),
resource_count_(static_cast<int>(resource_count)) {
// MemoryUsage is constructed using size_ts, since it deals with memory and
// the inputs are typically size_t. However, during the course of usage (in
// particular operator-=) can cause internal values to become negative. Thus,
// member variables are signed.
DCHECK_LE(memory_bytes,
- static_cast<size_t>(std::numeric_limits<int64>::max()));
+ static_cast<size_t>(std::numeric_limits<int64_t>::max()));
DCHECK_LE(resource_count,
static_cast<size_t>(std::numeric_limits<int>::max()));
}