diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-01-25 11:39:07 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2016-01-25 15:20:42 +0000 |
commit | 6c91641271e536ffaa88a1dff5127e42ee99a91e (patch) | |
tree | 703d9dd49602377ddc90cbf886aad37913f2496b /chromium/cc/tiles/tile_manager.cc | |
parent | b145b7fafd36f0c260d6a768c81fc14e32578099 (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.cc | 523 |
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())); } |