diff options
author | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-03 05:18:44 +0000 |
---|---|---|
committer | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-03 05:18:44 +0000 |
commit | 1204dbb5dc93798fffbd332f1d143b6ef98f5f18 (patch) | |
tree | 4ec13b73c528e92acf8eb8252ccef44e813d37c6 /cc | |
parent | b4685c60c5c7f4125d8c4c695585ba964bbf0fd6 (diff) | |
download | chromium_src-1204dbb5dc93798fffbd332f1d143b6ef98f5f18.zip chromium_src-1204dbb5dc93798fffbd332f1d143b6ef98f5f18.tar.gz chromium_src-1204dbb5dc93798fffbd332f1d143b6ef98f5f18.tar.bz2 |
cc: Add new RasterWorkerPool interface.
Refactor RasterWorkerPool interface such that it can be used
to implement different type of resource updates mechanisms.
The result is that the tile manager is no longer aware of
the need to perform uploads. This cleans up the tile manager
code significantly and allow zero copy resource updates to
be properly supported.
BUG=241644
TEST=cc_unittest --gtest_filter=BasicRasterWorkerPoolTest.*
Review URL: https://chromiumcodereview.appspot.com/16190002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203670 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/base/worker_pool.h | 2 | ||||
-rw-r--r-- | cc/cc.gyp | 4 | ||||
-rw-r--r-- | cc/cc_tests.gyp | 1 | ||||
-rw-r--r-- | cc/resources/image_raster_worker_pool.cc | 142 | ||||
-rw-r--r-- | cc/resources/image_raster_worker_pool.h | 44 | ||||
-rw-r--r-- | cc/resources/managed_tile_state.cc | 6 | ||||
-rw-r--r-- | cc/resources/managed_tile_state.h | 17 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling_set_unittest.cc | 4 | ||||
-rw-r--r-- | cc/resources/pixel_buffer_raster_worker_pool.cc | 313 | ||||
-rw-r--r-- | cc/resources/pixel_buffer_raster_worker_pool.h | 63 | ||||
-rw-r--r-- | cc/resources/raster_worker_pool.cc | 186 | ||||
-rw-r--r-- | cc/resources/raster_worker_pool.h | 162 | ||||
-rw-r--r-- | cc/resources/raster_worker_pool_unittest.cc | 208 | ||||
-rw-r--r-- | cc/resources/tile_manager.cc | 287 | ||||
-rw-r--r-- | cc/resources/tile_manager.h | 32 | ||||
-rw-r--r-- | cc/test/fake_tile_manager.cc | 16 | ||||
-rw-r--r-- | cc/test/test_web_graphics_context_3d.cc | 57 | ||||
-rw-r--r-- | cc/test/test_web_graphics_context_3d.h | 29 |
18 files changed, 1231 insertions, 342 deletions
diff --git a/cc/base/worker_pool.h b/cc/base/worker_pool.h index a27757a..72a4f7e 100644 --- a/cc/base/worker_pool.h +++ b/cc/base/worker_pool.h @@ -79,7 +79,7 @@ class CC_EXPORT WorkerPool { } // Force a check for completed tasks. - void CheckForCompletedTasks(); + virtual void CheckForCompletedTasks(); protected: WorkerPool(size_t num_threads, @@ -236,6 +236,8 @@ 'resources/content_layer_updater.h', 'resources/image_layer_updater.cc', 'resources/image_layer_updater.h', + 'resources/image_raster_worker_pool.cc', + 'resources/image_raster_worker_pool.h', 'resources/layer_painter.h', 'resources/layer_quad.cc', 'resources/layer_quad.h', @@ -261,6 +263,8 @@ 'resources/picture_pile_base.h', 'resources/picture_pile_impl.cc', 'resources/picture_pile_impl.h', + 'resources/pixel_buffer_raster_worker_pool.cc', + 'resources/pixel_buffer_raster_worker_pool.h', 'resources/platform_color.h', 'resources/prioritized_resource.cc', 'resources/prioritized_resource.h', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index a8c23b3..0040ae6 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -55,6 +55,7 @@ 'resources/picture_pile_unittest.cc', 'resources/picture_unittest.cc', 'resources/prioritized_resource_unittest.cc', + 'resources/raster_worker_pool_unittest.cc', 'resources/resource_provider_unittest.cc', 'resources/resource_update_controller_unittest.cc', 'resources/scoped_resource_unittest.cc', diff --git a/cc/resources/image_raster_worker_pool.cc b/cc/resources/image_raster_worker_pool.cc new file mode 100644 index 0000000..e846e91 --- /dev/null +++ b/cc/resources/image_raster_worker_pool.cc @@ -0,0 +1,142 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/image_raster_worker_pool.h" + +#include "base/debug/trace_event.h" +#include "cc/resources/resource.h" +#include "third_party/skia/include/core/SkDevice.h" + +namespace cc { + +namespace { + +class ImageWorkerPoolTaskImpl : public internal::WorkerPoolTask { + public: + typedef base::Callback<void(bool was_canceled)> Reply; + + ImageWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task, + TaskVector* dependencies, + uint8_t* buffer, + int stride, + const Reply& reply) + : internal::WorkerPoolTask(dependencies), + task_(task), + buffer_(buffer), + stride_(stride), + reply_(reply) { + } + + // Overridden from internal::WorkerPoolTask: + virtual void RunOnThread(unsigned thread_index) OVERRIDE { + DCHECK(buffer_); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + task_->resource()->size().width(), + task_->resource()->size().height(), + stride_); + bitmap.setPixels(buffer_); + SkDevice device(bitmap); + task_->RunOnThread(&device, thread_index); + } + virtual void DispatchCompletionCallback() OVERRIDE { + reply_.Run(!HasFinishedRunning()); + } + + private: + virtual ~ImageWorkerPoolTaskImpl() {} + + scoped_refptr<internal::RasterWorkerPoolTask> task_; + uint8_t* buffer_; + int stride_; + const Reply reply_; + + DISALLOW_COPY_AND_ASSIGN(ImageWorkerPoolTaskImpl); +}; + +} // namespace + +ImageRasterWorkerPool::ImageRasterWorkerPool( + ResourceProvider* resource_provider, size_t num_threads) + : RasterWorkerPool(resource_provider, num_threads) { + // TODO(reveman): Remove WorkerPool client interface. + WorkerPool::SetClient(this); +} + +ImageRasterWorkerPool::~ImageRasterWorkerPool() { + DCHECK_EQ(0u, image_tasks_.size()); +} + +void ImageRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { + TRACE_EVENT0("cc", "ImageRasterWorkerPool::ScheduleTasks"); + + internal::WorkerPoolTask::TaskVector raster_tasks; + + RasterWorkerPool::SetRasterTasks(queue); + + for (RasterTask::Queue::TaskVector::iterator it = raster_tasks_.begin(); + it != raster_tasks_.end(); ++it) { + internal::RasterWorkerPoolTask* task = *it; + + TaskMap::iterator image_it = image_tasks_.find(task); + if (image_it != image_tasks_.end()) { + internal::WorkerPoolTask* image_task = image_it->second; + raster_tasks.push_back(image_task); + continue; + } + + // Acquire image for resource. + resource_provider_->AcquireImage(task->resource()->id()); + + // Map image for raster. + uint8* buffer = resource_provider_->MapImage(task->resource()->id()); + int stride = resource_provider_->GetImageStride(task->resource()->id()); + + // TODO(reveman): Avoid having to make a copy of dependencies. + internal::WorkerPoolTask::TaskVector dependencies = task->dependencies(); + scoped_refptr<internal::WorkerPoolTask> image_task( + new ImageWorkerPoolTaskImpl( + task, + &dependencies, + buffer, + stride, + base::Bind(&ImageRasterWorkerPool::OnRasterTaskCompleted, + base::Unretained(this), + make_scoped_refptr(task)))); + + image_tasks_[task] = image_task; + raster_tasks.push_back(image_task); + } + + ScheduleRasterTasks(&raster_tasks); +} + +void ImageRasterWorkerPool::OnRasterTaskCompleted( + scoped_refptr<internal::RasterWorkerPoolTask> task, + bool was_canceled) { + TRACE_EVENT1("cc", "ImageRasterWorkerPool::OnRasterTaskCompleted", + "was_canceled", was_canceled); + + DCHECK(image_tasks_.find(task) != image_tasks_.end()); + + // Balanced with MapImage() call in ScheduleTasks(). + resource_provider_->UnmapImage(task->resource()->id()); + + // Bind image to resource. + resource_provider_->BindImage(task->resource()->id()); + + if (!was_canceled) + task->DidRun(); + + DidFinishRasterTask(task); + image_tasks_.erase(task); +} + +void ImageRasterWorkerPool::DidFinishRasterTask( + internal::RasterWorkerPoolTask* task) { + task->DidComplete(); + task->DispatchCompletionCallback(); +} + +} // namespace cc diff --git a/cc/resources/image_raster_worker_pool.h b/cc/resources/image_raster_worker_pool.h new file mode 100644 index 0000000..353c722 --- /dev/null +++ b/cc/resources/image_raster_worker_pool.h @@ -0,0 +1,44 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_IMAGE_RASTER_WORKER_POOL_H_ +#define CC_RESOURCES_IMAGE_RASTER_WORKER_POOL_H_ + +#include "cc/resources/raster_worker_pool.h" + +namespace cc { + +class CC_EXPORT ImageRasterWorkerPool : public RasterWorkerPool, + public WorkerPoolClient { + public: + virtual ~ImageRasterWorkerPool(); + + static scoped_ptr<RasterWorkerPool> Create( + ResourceProvider* resource_provider, size_t num_threads) { + return make_scoped_ptr<RasterWorkerPool>( + new ImageRasterWorkerPool(resource_provider, num_threads)); + } + + // Overridden from RasterWorkerPool: + virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE; + + private: + ImageRasterWorkerPool(ResourceProvider* resource_provider, + size_t num_threads); + + // Overridden from WorkerPoolClient: + virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE {} + + void OnRasterTaskCompleted( + scoped_refptr<internal::RasterWorkerPoolTask> task, bool was_canceled); + void DidFinishRasterTask(internal::RasterWorkerPoolTask* task); + + TaskMap image_tasks_; + + DISALLOW_COPY_AND_ASSIGN(ImageRasterWorkerPool); +}; + +} // namespace cc + +#endif // CC_RESOURCES_IMAGE_RASTER_WORKER_POOL_H_ diff --git a/cc/resources/managed_tile_state.cc b/cc/resources/managed_tile_state.cc index 2b40f7f..836dd22 100644 --- a/cc/resources/managed_tile_state.cc +++ b/cc/resources/managed_tile_state.cc @@ -49,6 +49,7 @@ ManagedTileState::ManagedTileState() ManagedTileState::TileVersion::TileVersion() : mode_(RESOURCE_MODE), + resource_id_(0), resource_format_(GL_RGBA), memory_state_(NOT_ALLOWED_TO_USE_MEMORY), forced_upload_(false) { @@ -62,10 +63,9 @@ ManagedTileState::TileVersion::~TileVersion() { bool ManagedTileState::TileVersion::IsReadyToDraw() const { switch (mode_) { case RESOURCE_MODE: - return resource_ && + return resource_id_ && (memory_state_ == USING_RELEASABLE_MEMORY || - (memory_state_ == USING_UNRELEASABLE_MEMORY && forced_upload_)) && - resource_->id(); + (memory_state_ == USING_UNRELEASABLE_MEMORY && forced_upload_)); case SOLID_COLOR_MODE: case PICTURE_PILE_MODE: return true; diff --git a/cc/resources/managed_tile_state.h b/cc/resources/managed_tile_state.h index 7d5eec7..51271ec 100644 --- a/cc/resources/managed_tile_state.h +++ b/cc/resources/managed_tile_state.h @@ -45,9 +45,9 @@ class CC_EXPORT ManagedTileState { ResourceProvider::ResourceId get_resource_id() const { DCHECK(mode_ == RESOURCE_MODE); - DCHECK(resource_); + DCHECK(resource_id_); DCHECK(memory_state_ == USING_RELEASABLE_MEMORY || forced_upload_); - return resource_->id(); + return resource_id_; } SkColor get_solid_color() const { @@ -67,6 +67,11 @@ class CC_EXPORT ManagedTileState { size_t GPUMemoryUsageInBytes() const; + void SetResourceForTesting(scoped_ptr<ResourcePool::Resource> resource) { + resource_ = resource.Pass(); + resource_id_ = resource_->id(); + } + scoped_ptr<ResourcePool::Resource>& GetResourceForTesting() { return resource_; } @@ -90,16 +95,22 @@ class CC_EXPORT ManagedTileState { mode_ = SOLID_COLOR_MODE; solid_color_ = color; memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; + resource_id_ = 0; } void set_rasterize_on_demand() { mode_ = PICTURE_PILE_MODE; memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; + resource_id_ = 0; } Mode mode_; SkColor solid_color_; + // TODO(reveman): Eliminate the need for both |resource_id_| + // and |resource| by re-factoring the "force upload" + // mechanism. crbug.com/245767 + ResourceProvider::ResourceId resource_id_; scoped_ptr<ResourcePool::Resource> resource_; GLenum resource_format_; TileVersionMemoryState memory_state_; @@ -116,7 +127,7 @@ class CC_EXPORT ManagedTileState { TileVersion tile_version; bool picture_pile_analyzed; PicturePileImpl::Analysis picture_pile_analysis; - RasterWorkerPool::Task raster_task; + RasterWorkerPool::RasterTask raster_task; // Ephemeral state, valid only during TileManager::ManageTiles. bool is_in_never_bin_on_both_trees() const { diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc index 3d035e0..50a499a 100644 --- a/cc/resources/picture_layer_tiling_set_unittest.cc +++ b/cc/resources/picture_layer_tiling_set_unittest.cc @@ -76,11 +76,11 @@ class PictureLayerTilingSetTestWithResources : public testing::Test { for (size_t i = 0; i < tiles.size(); ++i) { EXPECT_FALSE(tiles[i]->tile_version().GetResourceForTesting()); - tiles[i]->tile_version().GetResourceForTesting() = + tiles[i]->tile_version().SetResourceForTesting( make_scoped_ptr(new ResourcePool::Resource( resource_provider.get(), gfx::Size(1, 1), - resource_provider->best_texture_format())); + resource_provider->best_texture_format()))); tiles[i]->tile_version().SetMemoryStateForTesting( USING_RELEASABLE_MEMORY); } diff --git a/cc/resources/pixel_buffer_raster_worker_pool.cc b/cc/resources/pixel_buffer_raster_worker_pool.cc new file mode 100644 index 0000000..cd77b88 --- /dev/null +++ b/cc/resources/pixel_buffer_raster_worker_pool.cc @@ -0,0 +1,313 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/pixel_buffer_raster_worker_pool.h" + +#include "base/debug/trace_event.h" +#include "cc/resources/resource.h" +#include "third_party/skia/include/core/SkDevice.h" + +namespace cc { + +namespace { + +class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask { + public: + typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply; + + PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task, + TaskVector* dependencies, + uint8_t* buffer, + const Reply& reply) + : internal::WorkerPoolTask(dependencies), + task_(task), + buffer_(buffer), + reply_(reply), + needs_upload_(true) { + } + + // Overridden from internal::WorkerPoolTask: + virtual void RunOnThread(unsigned thread_index) OVERRIDE { + // |buffer_| can be NULL in lost context situations. + if (!buffer_) + return; + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + task_->resource()->size().width(), + task_->resource()->size().height()); + bitmap.setPixels(buffer_); + SkDevice device(bitmap); + needs_upload_ = task_->RunOnThread(&device, thread_index); + } + virtual void DispatchCompletionCallback() OVERRIDE { + DCHECK(HasFinishedRunning() || !buffer_ || !needs_upload_); + reply_.Run(!HasFinishedRunning(), needs_upload_); + } + + private: + virtual ~PixelBufferWorkerPoolTaskImpl() {} + + scoped_refptr<internal::RasterWorkerPoolTask> task_; + uint8_t* buffer_; + const Reply reply_; + bool needs_upload_; + + DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl); +}; + +// If we raster too fast we become upload bound, and pending +// uploads consume memory. For maximum upload throughput, we would +// want to allow for upload_throughput * pipeline_time of pending +// uploads, after which we are just wasting memory. Since we don't +// know our upload throughput yet, this just caps our memory usage. +#if defined(OS_ANDROID) +// For reference, the Nexus10 can upload 1MB in about 2.5ms. +// Assuming a three frame deep pipeline this implies ~20MB. +const size_t kMaxPendingUploadBytes = 20 * 1024 * 1024; +// TODO(epenner): We should remove this upload limit (crbug.com/176197) +const size_t kMaxPendingUploads = 72; +#else +const size_t kMaxPendingUploadBytes = 100 * 1024 * 1024; +const size_t kMaxPendingUploads = 1000; +#endif + +} // namespace + +PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( + ResourceProvider* resource_provider, + size_t num_threads) : RasterWorkerPool(resource_provider, num_threads), + bytes_pending_upload_(0), + has_performed_uploads_since_last_flush_(false) { + // TODO(reveman): Remove WorkerPool client interface. + WorkerPool::SetClient(this); +} + +PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { + DCHECK_EQ(0u, pixel_buffer_tasks_.size()); + DCHECK_EQ(0u, tasks_with_pending_upload_.size()); +} + +void PixelBufferRasterWorkerPool::Shutdown() { + RasterWorkerPool::Shutdown(); + AbortPendingUploads(); + for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); + it != pixel_buffer_tasks_.end(); ++it) { + internal::RasterWorkerPoolTask* task = it->first; + DCHECK(!it->second); + + // Everything else has been canceled. + DidFinishRasterTask(task); + } + pixel_buffer_tasks_.clear(); +} + +void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { + TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); + + RasterWorkerPool::SetRasterTasks(queue); + + // Build new pixel buffer task set. + TaskMap new_pixel_buffer_tasks; + for (RasterTask::Queue::TaskVector::iterator it = raster_tasks_.begin(); + it != raster_tasks_.end(); ++it) { + internal::RasterWorkerPoolTask* task = *it; + DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end()); + DCHECK(!task->HasCompleted()); + + // Use existing pixel buffer task if available. + TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); + if (pixel_buffer_it == pixel_buffer_tasks_.end()) { + new_pixel_buffer_tasks[task] = NULL; + continue; + } + + new_pixel_buffer_tasks[task] = pixel_buffer_it->second; + pixel_buffer_tasks_.erase(task); + } + + // Transfer active pixel buffer tasks to |new_pixel_buffer_tasks| + // and cancel any remaining tasks. + for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); + it != pixel_buffer_tasks_.end(); ++it) { + internal::RasterWorkerPoolTask* task = it->first; + + // Move task to |new_pixel_buffer_tasks| + if (it->second) { + new_pixel_buffer_tasks[task] = it->second; + continue; + } + + // Everything else can be canceled. + DidFinishRasterTask(task); + } + + pixel_buffer_tasks_.swap(new_pixel_buffer_tasks); + + ScheduleMoreTasks(); +} + +void PixelBufferRasterWorkerPool::CheckForCompletedTasks() { + TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks"); + + WorkerPool::CheckForCompletedTasks(); + + while (!tasks_with_pending_upload_.empty()) { + internal::RasterWorkerPoolTask* task = tasks_with_pending_upload_.front(); + + // Uploads complete in the order they are issued. + if (!resource_provider_->DidSetPixelsComplete(task->resource()->id())) + break; + + // It's now safe to release the pixel buffer and the shared memory. + resource_provider_->ReleasePixelBuffer(task->resource()->id()); + + bytes_pending_upload_ -= task->resource()->bytes(); + + task->DidRun(); + DidFinishRasterTask(task); + pixel_buffer_tasks_.erase(task); + + tasks_with_pending_upload_.pop_front(); + } + + ScheduleMoreTasks(); +} + +bool PixelBufferRasterWorkerPool::ForceUploadToComplete( + const RasterTask& raster_task) { + for (TaskDeque::iterator it = tasks_with_pending_upload_.begin(); + it != tasks_with_pending_upload_.end(); ++it) { + internal::RasterWorkerPoolTask* task = *it; + if (task == raster_task.internal_) { + resource_provider_->ForceSetPixelsToComplete(task->resource()->id()); + return true; + } + } + + return false; +} + +void PixelBufferRasterWorkerPool:: + DidFinishDispatchingWorkerPoolCompletionCallbacks() { + // If a flush is needed, do it now before starting to dispatch more tasks. + if (has_performed_uploads_since_last_flush_) { + resource_provider_->ShallowFlushIfSupported(); + has_performed_uploads_since_last_flush_ = false; + } +} + +bool PixelBufferRasterWorkerPool::CanScheduleRasterTask( + internal::RasterWorkerPoolTask* task) { + if (tasks_with_pending_upload_.size() >= kMaxPendingUploads) + return false; + size_t new_bytes_pending = bytes_pending_upload_; + new_bytes_pending += task->resource()->bytes(); + return new_bytes_pending <= kMaxPendingUploadBytes; +} + +void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { + TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); + + internal::WorkerPoolTask::TaskVector raster_tasks; + + for (RasterTask::Queue::TaskVector::iterator it = raster_tasks_.begin(); + it != raster_tasks_.end(); ++it) { + internal::RasterWorkerPoolTask* task = *it; + + TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); + if (pixel_buffer_it == pixel_buffer_tasks_.end()) + continue; + + scoped_refptr<internal::WorkerPoolTask> pixel_buffer_task( + pixel_buffer_it->second); + if (pixel_buffer_task) { + if (!pixel_buffer_task->HasCompleted()) + raster_tasks.push_back(pixel_buffer_task); + continue; + } + + if (!CanScheduleRasterTask(task)) + break; + + // Request a pixel buffer. This will reserve shared memory. + resource_provider_->AcquirePixelBuffer(task->resource()->id()); + + // MapPixelBuffer() returns NULL if context was lost at the time + // AcquirePixelBuffer() was called. For simplicity we still post + // a raster task that is essentially a noop in these situations. + uint8* buffer = resource_provider_->MapPixelBuffer(task->resource()->id()); + + // TODO(reveman): Avoid having to make a copy of dependencies. + internal::WorkerPoolTask::TaskVector dependencies = task->dependencies(); + pixel_buffer_task = make_scoped_refptr( + new PixelBufferWorkerPoolTaskImpl( + task, + &dependencies, + buffer, + base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted, + base::Unretained(this), + make_scoped_refptr(task)))); + + pixel_buffer_tasks_[task] = pixel_buffer_task; + raster_tasks.push_back(pixel_buffer_task); + } + + ScheduleRasterTasks(&raster_tasks); +} + +void PixelBufferRasterWorkerPool::OnRasterTaskCompleted( + scoped_refptr<internal::RasterWorkerPoolTask> task, + bool was_canceled, + bool needs_upload) { + TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted", + "was_canceled", was_canceled, + "needs_upload", needs_upload); + + DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end()); + + // Balanced with MapPixelBuffer() call in ScheduleMoreTasks(). + resource_provider_->UnmapPixelBuffer(task->resource()->id()); + + if (!needs_upload) { + resource_provider_->ReleasePixelBuffer(task->resource()->id()); + // No upload needed. Dispatch completion callback. + if (!was_canceled) + task->DidRun(); + + DidFinishRasterTask(task); + pixel_buffer_tasks_.erase(task); + return; + } + + resource_provider_->BeginSetPixels(task->resource()->id()); + has_performed_uploads_since_last_flush_ = true; + + bytes_pending_upload_ += task->resource()->bytes(); + tasks_with_pending_upload_.push_back(task); +} + +void PixelBufferRasterWorkerPool::AbortPendingUploads() { + while (!tasks_with_pending_upload_.empty()) { + internal::RasterWorkerPoolTask* task = tasks_with_pending_upload_.front(); + + resource_provider_->AbortSetPixels(task->resource()->id()); + resource_provider_->ReleasePixelBuffer(task->resource()->id()); + + bytes_pending_upload_ -= task->resource()->bytes(); + + // Need to run the reply callback even though task was aborted. + DidFinishRasterTask(task); + pixel_buffer_tasks_.erase(task); + + tasks_with_pending_upload_.pop_front(); + } +} + +void PixelBufferRasterWorkerPool::DidFinishRasterTask( + internal::RasterWorkerPoolTask* task) { + task->DidComplete(); + task->DispatchCompletionCallback(); +} + +} // namespace cc diff --git a/cc/resources/pixel_buffer_raster_worker_pool.h b/cc/resources/pixel_buffer_raster_worker_pool.h new file mode 100644 index 0000000..429bd7d --- /dev/null +++ b/cc/resources/pixel_buffer_raster_worker_pool.h @@ -0,0 +1,63 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_PIXEL_BUFFER_RASTER_WORKER_POOL_H_ +#define CC_RESOURCES_PIXEL_BUFFER_RASTER_WORKER_POOL_H_ + +#include <deque> + +#include "cc/resources/raster_worker_pool.h" + +namespace cc { + +class CC_EXPORT PixelBufferRasterWorkerPool : public RasterWorkerPool, + public WorkerPoolClient { + public: + virtual ~PixelBufferRasterWorkerPool(); + + static scoped_ptr<RasterWorkerPool> Create( + ResourceProvider* resource_provider, size_t num_threads) { + return make_scoped_ptr<RasterWorkerPool>( + new PixelBufferRasterWorkerPool(resource_provider, num_threads)); + } + + // Overridden from WorkerPool: + virtual void Shutdown() OVERRIDE; + virtual void CheckForCompletedTasks() OVERRIDE; + + // Overridden from RasterWorkerPool: + virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE; + virtual bool ForceUploadToComplete(const RasterTask& raster_task) OVERRIDE; + + private: + PixelBufferRasterWorkerPool(ResourceProvider* resource_provider, + size_t num_threads); + + // Overridden from WorkerPoolClient: + virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE; + + bool CanScheduleRasterTask(internal::RasterWorkerPoolTask* task); + void ScheduleMoreTasks(); + void OnRasterTaskCompleted( + scoped_refptr<internal::RasterWorkerPoolTask> task, + bool was_canceled, + bool needs_upload); + void AbortPendingUploads(); + void DidFinishRasterTask(internal::RasterWorkerPoolTask* task); + + TaskMap pixel_buffer_tasks_; + + typedef std::deque<scoped_refptr<internal::RasterWorkerPoolTask> > TaskDeque; + TaskDeque tasks_with_pending_upload_; + + size_t bytes_pending_upload_; + bool has_performed_uploads_since_last_flush_; + bool did_dispatch_completion_callback_; + + DISALLOW_COPY_AND_ASSIGN(PixelBufferRasterWorkerPool); +}; + +} // namespace cc + +#endif // CC_RESOURCES_PIXEL_BUFFER_RASTER_WORKER_POOL_H_ diff --git a/cc/resources/raster_worker_pool.cc b/cc/resources/raster_worker_pool.cc index dcfb6471..9748958 100644 --- a/cc/resources/raster_worker_pool.cc +++ b/cc/resources/raster_worker_pool.cc @@ -1,4 +1,4 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,72 +10,70 @@ namespace cc { namespace { -class RasterWorkerPoolContainerTaskImpl : public internal::WorkerPoolTask { - public: - RasterWorkerPoolContainerTaskImpl( - internal::WorkerPoolTask::TaskVector* dependencies) - : internal::WorkerPoolTask(dependencies) { - } - - // Overridden from internal::WorkerPoolTask: - virtual void RunOnThread(unsigned thread_index) OVERRIDE {} - virtual void DispatchCompletionCallback() OVERRIDE {} - - private: - virtual ~RasterWorkerPoolContainerTaskImpl() {} -}; +void Noop() {} -class RasterWorkerPoolTaskImpl : public internal::WorkerPoolTask { +class WorkerPoolTaskImpl : public internal::WorkerPoolTask { public: - RasterWorkerPoolTaskImpl(const base::Closure& callback, - const RasterWorkerPool::Task::Reply& reply) + WorkerPoolTaskImpl(const base::Closure& callback, + const base::Closure& reply) : callback_(callback), reply_(reply) { } + explicit WorkerPoolTaskImpl( + internal::WorkerPoolTask::TaskVector* dependencies) + : internal::WorkerPoolTask(dependencies), + callback_(base::Bind(&Noop)), + reply_(base::Bind(&Noop)) { + } // Overridden from internal::WorkerPoolTask: virtual void RunOnThread(unsigned thread_index) OVERRIDE { callback_.Run(); } virtual void DispatchCompletionCallback() OVERRIDE { - reply_.Run(!HasFinishedRunning()); + reply_.Run(); } private: - virtual ~RasterWorkerPoolTaskImpl() {} + virtual ~WorkerPoolTaskImpl() {} const base::Closure callback_; - const RasterWorkerPool::Task::Reply reply_; + const base::Closure reply_; + + DISALLOW_COPY_AND_ASSIGN(WorkerPoolTaskImpl); }; -class RasterWorkerPoolPictureTaskImpl : public internal::WorkerPoolTask { +class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask { public: - RasterWorkerPoolPictureTaskImpl( + RasterWorkerPoolTaskImpl( PicturePileImpl* picture_pile, - const RasterWorkerPool::PictureTask::Callback& callback, - const RasterWorkerPool::Task::Reply& reply, + const Resource* resource, + const RasterWorkerPool::RasterTask::Callback& callback, + const RasterWorkerPool::RasterTask::Reply& reply, internal::WorkerPoolTask::TaskVector* dependencies) - : internal::WorkerPoolTask(dependencies), + : internal::RasterWorkerPoolTask(resource, dependencies), picture_pile_(picture_pile), callback_(callback), reply_(reply) { - DCHECK(picture_pile_.get()); } - // Overridden from internal::WorkerPoolTask: - virtual void RunOnThread(unsigned thread_index) OVERRIDE { - callback_.Run(picture_pile_->GetCloneForDrawingOnThread(thread_index)); + // Overridden from internal::RasterWorkerPoolTask: + virtual bool RunOnThread(SkDevice* device, unsigned thread_index) OVERRIDE { + return callback_.Run( + device, picture_pile_->GetCloneForDrawingOnThread(thread_index)); } virtual void DispatchCompletionCallback() OVERRIDE { reply_.Run(!HasFinishedRunning()); } private: - virtual ~RasterWorkerPoolPictureTaskImpl() {} + virtual ~RasterWorkerPoolTaskImpl() {} scoped_refptr<PicturePileImpl> picture_pile_; - const RasterWorkerPool::PictureTask::Callback callback_; - const RasterWorkerPool::Task::Reply reply_; + const RasterWorkerPool::RasterTask::Callback callback_; + const RasterWorkerPool::RasterTask::Reply reply_; + + DISALLOW_COPY_AND_ASSIGN(RasterWorkerPoolTaskImpl); }; const char* kWorkerThreadNamePrefix = "CompositorRaster"; @@ -84,13 +82,47 @@ const int kCheckForCompletedTasksDelayMs = 6; } // namespace -RasterWorkerPool::Task::Queue::Queue() { +namespace internal { + +RasterWorkerPoolTask::RasterWorkerPoolTask( + const Resource* resource, + WorkerPoolTask::TaskVector* dependencies) + : did_run_(false), + did_complete_(false), + resource_(resource) { + dependencies_.swap(*dependencies); +} + +RasterWorkerPoolTask::~RasterWorkerPoolTask() { +} + +void RasterWorkerPoolTask::DidRun() { + DCHECK(!did_run_); + did_run_ = true; +} + +bool RasterWorkerPoolTask::HasFinishedRunning() const { + return did_run_; +} + +void RasterWorkerPoolTask::DidComplete() { + DCHECK(!did_complete_); + did_complete_ = true; } -RasterWorkerPool::Task::Queue::~Queue() { +bool RasterWorkerPoolTask::HasCompleted() const { + return did_complete_; } -void RasterWorkerPool::Task::Queue::Append(const Task& task) { +} // namespace internal + +RasterWorkerPool::Task::Set::Set() { +} + +RasterWorkerPool::Task::Set::~Set() { +} + +void RasterWorkerPool::Task::Set::Insert(const Task& task) { DCHECK(!task.is_null()); tasks_.push_back(task.internal_); } @@ -99,54 +131,84 @@ RasterWorkerPool::Task::Task() { } RasterWorkerPool::Task::Task(const base::Closure& callback, - const Reply& reply) - : internal_(new RasterWorkerPoolTaskImpl(callback, reply)) { + const base::Closure& reply) + : internal_(new WorkerPoolTaskImpl(callback, reply)) { +} + +RasterWorkerPool::Task::~Task() { } -RasterWorkerPool::Task::Task(Queue* dependencies) - : internal_(new RasterWorkerPoolContainerTaskImpl(&dependencies->tasks_)) { +void RasterWorkerPool::Task::Reset() { + internal_ = NULL; } -RasterWorkerPool::Task::Task(scoped_refptr<internal::WorkerPoolTask> internal) - : internal_(internal) { +RasterWorkerPool::RasterTask::Queue::Queue() { } -RasterWorkerPool::Task::~Task() { +RasterWorkerPool::RasterTask::Queue::~Queue() { } -void RasterWorkerPool::Task::Reset() { +void RasterWorkerPool::RasterTask::Queue::Append(const RasterTask& task) { + DCHECK(!task.is_null()); + tasks_.push_back(task.internal_); +} + +RasterWorkerPool::RasterTask::RasterTask() { +} + +RasterWorkerPool::RasterTask::RasterTask(PicturePileImpl* picture_pile, + const Resource* resource, + const Callback& callback, + const Reply& reply, + Task::Set* dependencies) + : internal_(new RasterWorkerPoolTaskImpl(picture_pile, + resource, + callback, + reply, + &dependencies->tasks_)) { +} + +void RasterWorkerPool::RasterTask::Reset() { internal_ = NULL; } -RasterWorkerPool::PictureTask::PictureTask(PicturePileImpl* picture_pile, - const Callback& callback, - const Reply& reply, - Task::Queue* dependencies) - : RasterWorkerPool::Task( - new RasterWorkerPoolPictureTaskImpl(picture_pile, - callback, - reply, - &dependencies->tasks_)) { +RasterWorkerPool::RasterTask::~RasterTask() { } -RasterWorkerPool::RasterWorkerPool(size_t num_threads) : WorkerPool( - num_threads, - base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs), - kWorkerThreadNamePrefix) { +RasterWorkerPool::RasterWorkerPool(ResourceProvider* resource_provider, + size_t num_threads) + : WorkerPool( + num_threads, + base::TimeDelta::FromMilliseconds(kCheckForCompletedTasksDelayMs), + kWorkerThreadNamePrefix), + resource_provider_(resource_provider) { } RasterWorkerPool::~RasterWorkerPool() { } void RasterWorkerPool::Shutdown() { - // Cancel all previously scheduled tasks. - WorkerPool::ScheduleTasks(NULL); - + raster_tasks_.clear(); WorkerPool::Shutdown(); } -void RasterWorkerPool::ScheduleTasks(Task* task) { - WorkerPool::ScheduleTasks(task ? task->internal_ : NULL); +bool RasterWorkerPool::ForceUploadToComplete(const RasterTask& raster_task) { + return false; +} + +void RasterWorkerPool::SetRasterTasks(RasterTask::Queue* queue) { + raster_tasks_.swap(queue->tasks_); +} + +void RasterWorkerPool::ScheduleRasterTasks( + internal::WorkerPoolTask::TaskVector* raster_tasks) { + if (raster_tasks->empty()) { + WorkerPool::ScheduleTasks(NULL); + return; + } + + scoped_refptr<WorkerPoolTaskImpl> root(new WorkerPoolTaskImpl(raster_tasks)); + WorkerPool::ScheduleTasks(root); } } // namespace cc diff --git a/cc/resources/raster_worker_pool.h b/cc/resources/raster_worker_pool.h index 1a20c5c..ed42a76 100644 --- a/cc/resources/raster_worker_pool.h +++ b/cc/resources/raster_worker_pool.h @@ -5,38 +5,90 @@ #ifndef CC_RESOURCES_RASTER_WORKER_POOL_H_ #define CC_RESOURCES_RASTER_WORKER_POOL_H_ +#include <vector> + +#include "base/hash_tables.h" #include "cc/base/worker_pool.h" +#include "cc/resources/resource_provider.h" + +class SkDevice; namespace cc { class PicturePileImpl; +class PixelBufferRasterWorkerPool; +class Resource; + +namespace internal { + +class CC_EXPORT RasterWorkerPoolTask + : public base::RefCounted<RasterWorkerPoolTask> { + public: + typedef std::vector<scoped_refptr<RasterWorkerPoolTask> > TaskVector; + + virtual bool RunOnThread(SkDevice* device, unsigned thread_index) = 0; + virtual void DispatchCompletionCallback() = 0; + + void DidRun(); + bool HasFinishedRunning() const; + void DidComplete(); + bool HasCompleted() const; + + const Resource* resource() const { return resource_; } + const WorkerPoolTask::TaskVector& dependencies() const { + return dependencies_; + } + + protected: + friend class base::RefCounted<RasterWorkerPoolTask>; + + RasterWorkerPoolTask(const Resource* resource, + WorkerPoolTask::TaskVector* dependencies); + virtual ~RasterWorkerPoolTask(); + + private: + bool did_run_; + bool did_complete_; + const Resource* resource_; + WorkerPoolTask::TaskVector dependencies_; +}; + +} // namespace internal +} // namespace cc + +#if defined(COMPILER_GCC) +namespace BASE_HASH_NAMESPACE { +template <> struct hash<cc::internal::RasterWorkerPoolTask*> { + size_t operator()(cc::internal::RasterWorkerPoolTask* ptr) const { + return hash<size_t>()(reinterpret_cast<size_t>(ptr)); + } +}; +} // namespace BASE_HASH_NAMESPACE +#endif // COMPILER + +namespace cc { // A worker thread pool that runs raster tasks. class CC_EXPORT RasterWorkerPool : public WorkerPool { public: - class Task { + class CC_EXPORT Task { public: - typedef base::Callback<void(bool)> Reply; - - // Highest priority task first. Order of execution is not guaranteed. - class Queue { + class CC_EXPORT Set { public: - Queue(); - ~Queue(); + typedef internal::WorkerPoolTask::TaskVector TaskVector; - bool empty() const { return tasks_.empty(); } + Set(); + ~Set(); - // Add task to the back of the queue. - void Append(const Task& task); + void Insert(const Task& task); private: friend class RasterWorkerPool; - internal::WorkerPoolTask::TaskVector tasks_; + TaskVector tasks_; }; Task(); - Task(const base::Closure& callback, const Reply& reply); - explicit Task(Queue* dependencies); + Task(const base::Closure& callback, const base::Closure& reply); ~Task(); // Returns true if Task is null (doesn't refer to anything). @@ -48,42 +100,84 @@ class CC_EXPORT RasterWorkerPool : public WorkerPool { protected: friend class RasterWorkerPool; - explicit Task(scoped_refptr<internal::WorkerPoolTask> internal); - scoped_refptr<internal::WorkerPoolTask> internal_; }; - class PictureTask : public Task { + class CC_EXPORT RasterTask { public: - typedef base::Callback<void(PicturePileImpl*)> Callback; + // Returns true if |device| was written to. False indicate that + // the content of |device| is undefined and the resource doesn't + // need to be initialized. + typedef base::Callback<bool(SkDevice* device, + PicturePileImpl* picture_pile)> Callback; + + typedef base::Callback<void(bool was_canceled)> Reply; - PictureTask(PicturePileImpl* picture_pile, - const Callback& callback, - const Reply& reply, - Queue* dependencies); + class CC_EXPORT Queue { + public: + typedef internal::RasterWorkerPoolTask::TaskVector TaskVector; + + Queue(); + ~Queue(); + + void Append(const RasterTask& task); + + private: + friend class RasterWorkerPool; + + TaskVector tasks_; + }; + + RasterTask(); + RasterTask(PicturePileImpl* picture_pile, + const Resource* resource, + const Callback& callback, + const Reply& reply, + Task::Set* dependencies); + ~RasterTask(); + + // Returns true if Task is null (doesn't refer to anything). + bool is_null() const { return !internal_; } + + // Returns the Task into an uninitialized state. + void Reset(); + + protected: + friend class PixelBufferRasterWorkerPool; + friend class RasterWorkerPool; + + scoped_refptr<internal::RasterWorkerPoolTask> internal_; }; virtual ~RasterWorkerPool(); - static scoped_ptr<RasterWorkerPool> Create(size_t num_threads) { - return make_scoped_ptr(new RasterWorkerPool(num_threads)); - } - // Tells the worker pool to shutdown after canceling all previously // scheduled tasks. Reply callbacks are still guaranteed to run. virtual void Shutdown() OVERRIDE; - // Schedule running of |root| task and all its dependencies. Tasks - // previously scheduled but no longer needed to run |root| will be - // canceled unless already running. Once scheduled, reply callbacks - // are guaranteed to run for all tasks even if they later get - // canceled by another call to ScheduleTasks(). - void ScheduleTasks(Task* root); + // Schedule running of raster tasks in |queue| and all dependencies. + // Previously scheduled tasks that are no longer needed to run + // raster tasks in |queue| will be canceled unless already running. + // Once scheduled, reply callbacks are guaranteed to run for all tasks + // even if they later get canceled by another call to ScheduleTasks(). + virtual void ScheduleTasks(RasterTask::Queue* queue) = 0; - private: - explicit RasterWorkerPool(size_t num_threads); + // Tells the raster worker pool to force any pending uploads for + // |raster_task| to complete. Returns true when successful. + virtual bool ForceUploadToComplete(const RasterTask& raster_task); + + protected: + typedef internal::RasterWorkerPoolTask* TaskMapKey; + typedef base::hash_map<TaskMapKey, + scoped_refptr<internal::WorkerPoolTask> > TaskMap; + + RasterWorkerPool(ResourceProvider* resource_provider, size_t num_threads); + + void SetRasterTasks(RasterTask::Queue* queue); + void ScheduleRasterTasks(internal::WorkerPoolTask::TaskVector* raster_tasks); - DISALLOW_COPY_AND_ASSIGN(RasterWorkerPool); + ResourceProvider* resource_provider_; + RasterTask::Queue::TaskVector raster_tasks_; }; } // namespace cc diff --git a/cc/resources/raster_worker_pool_unittest.cc b/cc/resources/raster_worker_pool_unittest.cc new file mode 100644 index 0000000..d3fdaed --- /dev/null +++ b/cc/resources/raster_worker_pool_unittest.cc @@ -0,0 +1,208 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/raster_worker_pool.h" + +#include <vector> + +#include "cc/resources/image_raster_worker_pool.h" +#include "cc/resources/picture_pile.h" +#include "cc/resources/picture_pile_impl.h" +#include "cc/resources/pixel_buffer_raster_worker_pool.h" +#include "cc/resources/resource_provider.h" +#include "cc/resources/scoped_resource.h" +#include "cc/test/fake_output_surface.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { + +namespace { + +class RasterWorkerPoolTest : public testing::Test { + public: + RasterWorkerPoolTest() + : output_surface_(FakeOutputSurface::Create3d()), + resource_provider_( + ResourceProvider::Create(output_surface_.get(), 0)), + check_interval_milliseconds_(1), + timeout_seconds_(5), + timed_out_(false) { + } + virtual ~RasterWorkerPoolTest() { + resource_provider_.reset(); + } + + // Overridden from testing::Test: + virtual void TearDown() OVERRIDE { + if (!raster_worker_pool_) + return; + raster_worker_pool_->Shutdown(); + raster_worker_pool_->CheckForCompletedTasks(); + } + + virtual void BeginTest() = 0; + virtual void AfterTest() = 0; + + ResourceProvider* resource_provider() const { + return resource_provider_.get(); + } + + RasterWorkerPool* worker_pool() { + return raster_worker_pool_.get(); + } + + void RunTest(bool use_map_image) { + if (use_map_image) { + raster_worker_pool_ = ImageRasterWorkerPool::Create( + resource_provider(), 1); + } else { + raster_worker_pool_ = PixelBufferRasterWorkerPool::Create( + resource_provider(), 1); + } + + BeginTest(); + + ScheduleCheckForCompletedTasks(); + + if (timeout_seconds_) { + timeout_.Reset(base::Bind(&RasterWorkerPoolTest::OnTimeout, + base::Unretained(this))); + base::MessageLoopProxy::current()->PostDelayedTask( + FROM_HERE, + timeout_.callback(), + base::TimeDelta::FromSeconds(timeout_seconds_)); + } + + base::MessageLoop::current()->Run(); + + check_.Cancel(); + timeout_.Cancel(); + + if (timed_out_) { + FAIL() << "Test timed out"; + return; + } + AfterTest(); + } + + void EndTest() { + base::MessageLoop::current()->Quit(); + } + + private: + void ScheduleCheckForCompletedTasks() { + check_.Reset(base::Bind(&RasterWorkerPoolTest::OnCheckForCompletedTasks, + base::Unretained(this))); + base::MessageLoopProxy::current()->PostDelayedTask( + FROM_HERE, + check_.callback(), + base::TimeDelta::FromMilliseconds(check_interval_milliseconds_)); + } + + void OnCheckForCompletedTasks() { + raster_worker_pool_->CheckForCompletedTasks(); + ScheduleCheckForCompletedTasks(); + } + + void OnTimeout() { + timed_out_ = true; + base::MessageLoop::current()->Quit(); + } + + scoped_ptr<FakeOutputSurface> output_surface_; + scoped_ptr<ResourceProvider> resource_provider_; + scoped_ptr<RasterWorkerPool> raster_worker_pool_; + base::CancelableClosure check_; + int check_interval_milliseconds_; + base::CancelableClosure timeout_; + int timeout_seconds_; + bool timed_out_; +}; + +#define PIXEL_BUFFER_TEST_F(TEST_FIXTURE_NAME) \ + TEST_F(TEST_FIXTURE_NAME, RunPixelBuffer) { \ + RunTest(false); \ + } + +#define IMAGE_TEST_F(TEST_FIXTURE_NAME) \ + TEST_F(TEST_FIXTURE_NAME, RunImage) { \ + RunTest(true); \ + } + +#define PIXEL_BUFFER_AND_IMAGE_TEST_F(TEST_FIXTURE_NAME) \ + PIXEL_BUFFER_TEST_F(TEST_FIXTURE_NAME); \ + IMAGE_TEST_F(TEST_FIXTURE_NAME) + +class BasicRasterWorkerPoolTest : public RasterWorkerPoolTest { + public: + bool RunRasterTask(SkDevice* device, PicturePileImpl* picture_pile) { + return true; + } + + void OnTaskCompleted(scoped_ptr<ScopedResource> resource, + unsigned id, + bool was_canceled) { + on_task_completed_ids_.push_back(id); + if (on_task_completed_ids_.size() == 2) + EndTest(); + } + + void AppendTask(unsigned id) { + const gfx::Size size(1, 1); + + scoped_refptr<PicturePile> picture_pile(new PicturePile); + picture_pile->set_num_raster_threads(1); + scoped_refptr<PicturePileImpl> picture_pile_impl( + PicturePileImpl::CreateFromOther(picture_pile.get(), false)); + + scoped_ptr<ScopedResource> resource( + ScopedResource::create(resource_provider())); + resource->Allocate(size, GL_RGBA, ResourceProvider::TextureUsageAny); + const Resource* const_resource = resource.get(); + + RasterWorkerPool::Task::Set empty; + tasks_.push_back( + RasterWorkerPool::RasterTask( + picture_pile_impl, + const_resource, + base::Bind(&BasicRasterWorkerPoolTest::RunRasterTask, + base::Unretained(this)), + base::Bind(&BasicRasterWorkerPoolTest::OnTaskCompleted, + base::Unretained(this), + base::Passed(&resource), + id), + &empty)); + } + + void ScheduleTasks() { + RasterWorkerPool::RasterTask::Queue tasks; + + for (std::vector<RasterWorkerPool::RasterTask>::iterator it = + tasks_.begin(); + it != tasks_.end(); ++it) + tasks.Append(*it); + + worker_pool()->ScheduleTasks(&tasks); + } + + // Overridden from RasterWorkerPoolTest: + virtual void BeginTest() OVERRIDE { + AppendTask(0u); + AppendTask(1u); + ScheduleTasks(); + } + virtual void AfterTest() OVERRIDE { + EXPECT_EQ(2u, on_task_completed_ids_.size()); + tasks_.clear(); + } + + std::vector<RasterWorkerPool::RasterTask> tasks_; + std::vector<unsigned> on_task_completed_ids_; +}; + +PIXEL_BUFFER_AND_IMAGE_TEST_F(BasicRasterWorkerPoolTest); + +} // namespace + +} // namespace cc diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc index 0a1f2e0..14012a9 100644 --- a/cc/resources/tile_manager.cc +++ b/cc/resources/tile_manager.cc @@ -13,38 +13,16 @@ #include "base/metrics/histogram.h" #include "cc/debug/devtools_instrumentation.h" #include "cc/debug/traced_value.h" -#include "cc/resources/raster_worker_pool.h" -#include "cc/resources/resource_pool.h" +#include "cc/resources/image_raster_worker_pool.h" +#include "cc/resources/pixel_buffer_raster_worker_pool.h" #include "cc/resources/tile.h" -#include "third_party/skia/include/core/SkDevice.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/rect_conversions.h" namespace cc { namespace { -// If we raster too fast we become upload bound, and pending -// uploads consume memory. For maximum upload throughput, we would -// want to allow for upload_throughput * pipeline_time of pending -// uploads, after which we are just wasting memory. Since we don't -// know our upload throughput yet, this just caps our memory usage. -#if defined(OS_ANDROID) -// For reference, the Nexus10 can upload 1MB in about 2.5ms. -// Assuming a three frame deep pipeline this implies ~20MB. -const size_t kMaxPendingUploadBytes = 20 * 1024 * 1024; -// TODO(epenner): We should remove this upload limit (crbug.com/176197) -const size_t kMaxPendingUploads = 72; -#else -const size_t kMaxPendingUploadBytes = 100 * 1024 * 1024; -const size_t kMaxPendingUploads = 1000; -#endif - -#if defined(OS_ANDROID) -const int kMaxNumPendingTasksPerThread = 8; -#else -const int kMaxNumPendingTasksPerThread = 40; -#endif - // Determine bin based on three categories of tiles: things we need now, // things we need soon, and eventually. inline TileManagerBin BinFromTilePriority(const TilePriority& prio) { @@ -112,15 +90,17 @@ scoped_ptr<TileManager> TileManager::Create( bool use_color_estimator, RenderingStatsInstrumentation* rendering_stats_instrumentation, bool use_map_image) { - scoped_ptr<RasterWorkerPool> raster_worker_pool = - RasterWorkerPool::Create(num_raster_threads); - return make_scoped_ptr(new TileManager(client, - resource_provider, - raster_worker_pool.Pass(), - num_raster_threads, - use_color_estimator, - rendering_stats_instrumentation, - use_map_image)); + return make_scoped_ptr( + new TileManager(client, + resource_provider, + use_map_image ? + ImageRasterWorkerPool::Create( + resource_provider, num_raster_threads) : + PixelBufferRasterWorkerPool::Create( + resource_provider, num_raster_threads), + num_raster_threads, + use_color_estimator, + rendering_stats_instrumentation)); } TileManager::TileManager( @@ -129,20 +109,15 @@ TileManager::TileManager( scoped_ptr<RasterWorkerPool> raster_worker_pool, size_t num_raster_threads, bool use_color_estimator, - RenderingStatsInstrumentation* rendering_stats_instrumentation, - bool use_map_image) + RenderingStatsInstrumentation* rendering_stats_instrumentation) : client_(client), resource_pool_(ResourcePool::Create(resource_provider)), raster_worker_pool_(raster_worker_pool.Pass()), manage_tiles_pending_(false), - bytes_pending_upload_(0), - has_performed_uploads_since_last_flush_(false), ever_exceeded_memory_budget_(false), rendering_stats_instrumentation_(rendering_stats_instrumentation), use_color_estimator_(use_color_estimator), - did_initialize_visible_tile_(false), - max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { - raster_worker_pool_->SetClient(this); + did_initialize_visible_tile_(false) { } TileManager::~TileManager() { @@ -153,8 +128,7 @@ TileManager::~TileManager() { // This should finish all pending tasks and release any uninitialized // resources. raster_worker_pool_->Shutdown(); - AbortPendingTileUploads(); - DCHECK_EQ(0u, tiles_with_pending_upload_.size()); + raster_worker_pool_->CheckForCompletedTasks(); DCHECK_EQ(0u, tiles_.size()); } @@ -321,66 +295,34 @@ void TileManager::ManageTiles() { } void TileManager::CheckForCompletedTileUploads() { - while (!tiles_with_pending_upload_.empty()) { - Tile* tile = tiles_with_pending_upload_.front().get(); - DCHECK(tile->tile_version().resource_); - - // Set pixel tasks complete in the order they are posted. - if (!resource_pool_->resource_provider()->DidSetPixelsComplete( - tile->tile_version().resource_->id())) { - break; - } - - // It's now safe to release the pixel buffer. - resource_pool_->resource_provider()->ReleasePixelBuffer( - tile->tile_version().resource_->id()); - - bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); - bool was_forced = tile->tile_version().forced_upload_; - // Reset forced_upload_ since we now got the upload completed notification. - tile->tile_version().forced_upload_ = false; - tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; - if (!was_forced) - DidFinishTileInitialization(tile); - - tiles_with_pending_upload_.pop(); - } - - ScheduleTasks(); -} + raster_worker_pool_->CheckForCompletedTasks(); -void TileManager::AbortPendingTileUploads() { - while (!tiles_with_pending_upload_.empty()) { - Tile* tile = tiles_with_pending_upload_.front().get(); - DCHECK(tile->tile_version().resource_); - - resource_pool_->resource_provider()->AbortSetPixels( - tile->tile_version().resource_->id()); - resource_pool_->resource_provider()->ReleasePixelBuffer( - tile->tile_version().resource_->id()); - tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; + if (!client_->ShouldForceTileUploadsRequiredForActivationToComplete()) + return; - FreeResourcesForTile(tile); + TileSet initialized_tiles; + for (TileSet::iterator it = + tiles_that_need_to_be_initialized_for_activation_.begin(); + it != tiles_that_need_to_be_initialized_for_activation_.end(); + ++it) { + Tile* tile = *it; + if (!tile->managed_state().raster_task.is_null() && + tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY && + !tile->tile_version().forced_upload_) { + if (!raster_worker_pool_->ForceUploadToComplete( + tile->managed_state().raster_task)) + continue; - bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); - tiles_with_pending_upload_.pop(); + // Setting |forced_upload_| to true makes this tile ready to draw. + tile->tile_version().forced_upload_ = true; + initialized_tiles.insert(tile); + } } -} -void TileManager::ForceTileUploadToComplete(Tile* tile) { - DCHECK(tile); - if (tile->tile_version().resource_ && - tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY && - !tile->tile_version().forced_upload_) { - resource_pool_->resource_provider()-> - ForceSetPixelsToComplete(tile->tile_version().resource_->id()); - - // We have to set the memory state to be unreleasable, to ensure - // that the tile will not be freed until we get the upload finished - // notification. However, setting |forced_upload_| to true makes - // this tile ready to draw. - tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY; - tile->tile_version().forced_upload_ = true; + for (TileSet::iterator it = initialized_tiles.begin(); + it != initialized_tiles.end(); + ++it) { + Tile* tile = *it; DidFinishTileInitialization(tile); DCHECK(tile->tile_version().IsReadyToDraw()); } @@ -454,16 +396,6 @@ void TileManager::AddRequiredTileForActivation(Tile* tile) { tiles_that_need_to_be_initialized_for_activation_.insert(tile); } -void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() { - // If a flush is needed, do it now before starting to dispatch more tasks. - if (has_performed_uploads_since_last_flush_) { - resource_pool_->resource_provider()->ShallowFlushIfSupported(); - has_performed_uploads_since_last_flush_ = false; - } - - ScheduleTasks(); -} - void TileManager::AssignGpuMemoryToTiles() { TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); size_t unreleasable_bytes = 0; @@ -552,16 +484,6 @@ void TileManager::AssignGpuMemoryToTiles() { if (!tile_version.resource_ && tile->required_for_activation()) AddRequiredTileForActivation(tile); - - if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY && - tile->required_for_activation()) { - // If after rasterizing, this tile has become required or the client has - // changed its mind about forcing tiles, do that now. - if (!tile->tile_version().forced_upload_ && - client_->ShouldForceTileUploadsRequiredForActivationToComplete()) { - ForceTileUploadToComplete(tile); - } - } } // In OOM situation, we iterate tiles_, remove the memory for active tree @@ -633,10 +555,7 @@ void TileManager::FreeResourcesForTile(Tile* tile) { void TileManager::ScheduleTasks() { TRACE_EVENT0("cc", "TileManager::ScheduleTasks"); - RasterWorkerPool::Task::Queue tasks; - - size_t bytes_pending_upload = bytes_pending_upload_; - unsigned pending_tasks = 0; + RasterWorkerPool::RasterTask::Queue tasks; // Build a new task queue containing all task currently needed. Tasks // are added in order of priority, highest priority task first. @@ -646,29 +565,8 @@ void TileManager::ScheduleTasks() { Tile* tile = *it; ManagedTileState& mts = tile->managed_state(); - // Skip tile if determined to not require resource. - if (!tile->tile_version().requires_resource()) - continue; - - // Skip tile if already rasterized. - if (tile->tile_version().resource_) - continue; - - // TODO(reveman): Remove throttling based on max pending tasks. - if (pending_tasks >= max_pending_tasks_) - break; - - // TODO(reveman): Remove throttling based on max pending uploads. - if (tiles_with_pending_upload_.size() >= kMaxPendingUploads) - break; - - // TODO(reveman): Throttle based on shared memory usage rather - // than bytes pending upload. - size_t new_bytes_pending = bytes_pending_upload; - new_bytes_pending += tile->bytes_consumed_if_allocated(); - if (new_bytes_pending > kMaxPendingUploadBytes) - break; - bytes_pending_upload = new_bytes_pending; + DCHECK(tile->tile_version().requires_resource()); + DCHECK(!tile->tile_version().resource_); // Create raster task for this tile if necessary. if (mts.raster_task.is_null()) @@ -676,24 +574,12 @@ void TileManager::ScheduleTasks() { // Finally append raster task. tasks.Append(mts.raster_task); - pending_tasks++; - } - - if (!tasks.empty()) { - RasterWorkerPool::Task root(&tasks); - - // Schedule running of |tasks|. This replaces any previously - // scheduled tasks and effectively cancels all tasks not present - // in |tasks|. - raster_worker_pool_->ScheduleTasks(&root); - } else { - raster_worker_pool_->ScheduleTasks(NULL); } - if (did_initialize_visible_tile_) { - did_initialize_visible_tile_ = false; - client_->DidInitializeVisibleTile(); - } + // Schedule running of |tasks|. This replaces any previously + // scheduled tasks and effectively cancels all tasks not present + // in |tasks|. + raster_worker_pool_->ScheduleTasks(&tasks); } RasterWorkerPool::Task TileManager::CreateImageDecodeTask( @@ -712,8 +598,7 @@ RasterWorkerPool::Task TileManager::CreateImageDecodeTask( } void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile, - uint32_t pixel_ref_id, - bool was_canceled) { + uint32_t pixel_ref_id) { TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); DCHECK(pending_decode_tasks_.find(pixel_ref_id) != pending_decode_tasks_.end()); @@ -733,28 +618,23 @@ TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( return metadata; } -RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) { +RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) { TRACE_EVENT0("cc", "TileManager::CreateRasterTask"); scoped_ptr<ResourcePool::Resource> resource = resource_pool_->AcquireResource( tile->tile_size_.size(), tile->tile_version().resource_format_); - resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id()); + const Resource* const_resource = resource.get(); DCHECK_EQ(CAN_USE_MEMORY, tile->tile_version().memory_state_); tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY; + tile->tile_version().resource_id_ = resource->id(); PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis; - // MapPixelBuffer() returns NULL if context was lost at the time - // AcquirePixelBuffer() was called. For simplicity we still create - // a raster task that is essentially a noop in these situations. - uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer( - resource->id()); - // Create and queue all image decode tasks that this tile depends on. - RasterWorkerPool::Task::Queue decode_tasks; + RasterWorkerPool::Task::Set decode_tasks; for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), tile->contents_scale(), tile->picture_pile()); @@ -765,7 +645,7 @@ RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) { // Append existing image decode task if available. PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id); if (decode_task_it != pending_decode_tasks_.end()) { - decode_tasks.Append(decode_task_it->second); + decode_tasks.Insert(decode_task_it->second); continue; } @@ -778,12 +658,13 @@ RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) { // Create and append new image decode task for this pixel ref. RasterWorkerPool::Task decode_task = CreateImageDecodeTask( tile, pixel_ref); - decode_tasks.Append(decode_task); + decode_tasks.Insert(decode_task); pending_decode_tasks_[id] = decode_task; } - return RasterWorkerPool::PictureTask( + return RasterWorkerPool::RasterTask( tile->picture_pile(), + const_resource, base::Bind(&TileManager::RunAnalyzeAndRasterTask, base::Bind(&TileManager::RunAnalyzeTask, analysis, @@ -793,7 +674,6 @@ RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) { GetRasterTaskMetadata(*tile), rendering_stats_instrumentation_), base::Bind(&TileManager::RunRasterTask, - buffer, analysis, tile->content_rect(), tile->contents_scale(), @@ -812,21 +692,18 @@ void TileManager::OnRasterTaskCompleted( scoped_ptr<ResourcePool::Resource> resource, PicturePileImpl::Analysis* analysis, bool was_canceled) { - TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); + TRACE_EVENT1("cc", "TileManager::OnRasterTaskCompleted", + "was_canceled", was_canceled); ManagedTileState& mts = tile->managed_state(); DCHECK(!mts.raster_task.is_null()); mts.raster_task.Reset(); - // Tile resources can't be freed until upload has completed. + // Tile resources can't be freed until task has completed. DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_); - // Release raster resources. - resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); - if (was_canceled) { tile->tile_version().memory_state_ = CAN_USE_MEMORY; - resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); resource_pool_->ReleaseResource(resource.Pass()); return; } @@ -836,23 +713,13 @@ void TileManager::OnRasterTaskCompleted( if (analysis->is_solid_color) { tile->tile_version().set_solid_color(analysis->solid_color); - resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); resource_pool_->ReleaseResource(resource.Pass()); - DidFinishTileInitialization(tile.get()); - return; + } else { + tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; + tile->tile_version().resource_ = resource.Pass(); } - resource_pool_->resource_provider()->BeginSetPixels(resource->id()); - has_performed_uploads_since_last_flush_ = true; - - tile->tile_version().resource_ = resource.Pass(); - - bytes_pending_upload_ += tile->bytes_consumed_if_allocated(); - tiles_with_pending_upload_.push(tile); - - if (tile->required_for_activation() && - client_->ShouldForceTileUploadsRequiredForActivationToComplete()) - ForceTileUploadToComplete(tile.get()); + DidFinishTileInitialization(tile.get()); } void TileManager::DidFinishTileInitialization(Tile* tile) { @@ -888,12 +755,13 @@ void TileManager::RunImageDecodeTask( } // static -void TileManager::RunAnalyzeAndRasterTask( - const RasterWorkerPool::PictureTask::Callback& analyze_task, - const RasterWorkerPool::PictureTask::Callback& raster_task, +bool TileManager::RunAnalyzeAndRasterTask( + const base::Callback<void(PicturePileImpl* picture_pile)>& analyze_task, + const RasterWorkerPool::RasterTask::Callback& raster_task, + SkDevice* device, PicturePileImpl* picture_pile) { analyze_task.Run(picture_pile); - raster_task.Run(picture_pile); + return raster_task.Run(device, picture_pile); } // static @@ -938,13 +806,13 @@ scoped_ptr<base::Value> TileManager::RasterTaskMetadata::AsValue() const { } // static -void TileManager::RunRasterTask( - uint8* buffer, +bool TileManager::RunRasterTask( PicturePileImpl::Analysis* analysis, gfx::Rect rect, float contents_scale, const RasterTaskMetadata& metadata, RenderingStatsInstrumentation* stats_instrumentation, + SkDevice* device, PicturePileImpl* picture_pile) { TRACE_EVENT1( "cc", "TileManager::RunRasterTask", @@ -954,19 +822,12 @@ void TileManager::RunRasterTask( DCHECK(picture_pile); DCHECK(analysis); - - // |buffer| can be NULL in lost context situations. - if (!buffer) - return; + DCHECK(device); if (analysis->is_solid_color) - return; + return false; - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); - bitmap.setPixels(buffer); - SkDevice device(bitmap); - SkCanvas canvas(&device); + SkCanvas canvas(device); if (stats_instrumentation->record_rendering_stats()) { PicturePileImpl::RasterStats raster_stats; @@ -986,6 +847,8 @@ void TileManager::RunRasterTask( } else { picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL); } + + return true; } } // namespace cc diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h index c43b857..057ae92 100644 --- a/cc/resources/tile_manager.h +++ b/cc/resources/tile_manager.h @@ -60,7 +60,7 @@ scoped_ptr<base::Value> TileManagerBinPriorityAsValue( // should no longer have any memory assigned to them. Tile objects are "owned" // by layers; they automatically register with the manager when they are // created, and unregister from the manager when they are deleted. -class CC_EXPORT TileManager : public WorkerPoolClient { +class CC_EXPORT TileManager { public: typedef base::hash_set<uint32_t> PixelRefSet; @@ -80,7 +80,6 @@ class CC_EXPORT TileManager : public WorkerPoolClient { void ManageTiles(); void CheckForCompletedTileUploads(); - void AbortPendingTileUploads(); scoped_ptr<base::Value> BasicStateAsValue() const; scoped_ptr<base::Value> AllTilesAsValue() const; @@ -92,9 +91,6 @@ class CC_EXPORT TileManager : public WorkerPoolClient { return memory_stats_from_last_assign_; } - // Overridden from WorkerPoolClient: - virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE; - void WillModifyTilePriorities() { ScheduleManageTiles(); } @@ -109,8 +105,7 @@ class CC_EXPORT TileManager : public WorkerPoolClient { scoped_ptr<RasterWorkerPool> raster_worker_pool, size_t num_raster_threads, bool use_color_estimator, - RenderingStatsInstrumentation* rendering_stats_instrumentation, - bool use_map_image); + RenderingStatsInstrumentation* rendering_stats_instrumentation); // Methods called by Tile friend class Tile; @@ -135,7 +130,6 @@ class CC_EXPORT TileManager : public WorkerPoolClient { void SortTiles(); void AssignGpuMemoryToTiles(); void FreeResourcesForTile(Tile* tile); - void ForceTileUploadToComplete(Tile* tile); void ScheduleManageTiles() { if (manage_tiles_pending_) return; @@ -146,10 +140,9 @@ class CC_EXPORT TileManager : public WorkerPoolClient { Tile* tile, skia::LazyPixelRef* pixel_ref); void OnImageDecodeTaskCompleted( scoped_refptr<Tile> tile, - uint32_t pixel_ref_id, - bool was_canceled); + uint32_t pixel_ref_id); RasterTaskMetadata GetRasterTaskMetadata(const Tile& tile) const; - RasterWorkerPool::Task CreateRasterTask(Tile* tile); + RasterWorkerPool::RasterTask CreateRasterTask(Tile* tile); void OnRasterTaskCompleted( scoped_refptr<Tile> tile, scoped_ptr<ResourcePool::Resource> resource, @@ -166,9 +159,10 @@ class CC_EXPORT TileManager : public WorkerPoolClient { skia::LazyPixelRef* pixel_ref, int layer_id, RenderingStatsInstrumentation* stats_instrumentation); - static void RunAnalyzeAndRasterTask( - const RasterWorkerPool::PictureTask::Callback& analyze_task, - const RasterWorkerPool::PictureTask::Callback& raster_task, + static bool RunAnalyzeAndRasterTask( + const base::Callback<void(PicturePileImpl* picture_pile)>& analyze_task, + const RasterWorkerPool::RasterTask::Callback& raster_task, + SkDevice* device, PicturePileImpl* picture_pile); static void RunAnalyzeTask( PicturePileImpl::Analysis* analysis, @@ -178,13 +172,13 @@ class CC_EXPORT TileManager : public WorkerPoolClient { const RasterTaskMetadata& metadata, RenderingStatsInstrumentation* stats_instrumentation, PicturePileImpl* picture_pile); - static void RunRasterTask( - uint8* buffer, + static bool RunRasterTask( PicturePileImpl::Analysis* analysis, gfx::Rect rect, float contents_scale, const RasterTaskMetadata& metadata, RenderingStatsInstrumentation* stats_instrumentation, + SkDevice* device, PicturePileImpl* picture_pile); TileManagerClient* client_; @@ -203,10 +197,6 @@ class CC_EXPORT TileManager : public WorkerPoolClient { typedef base::hash_map<uint32_t, RasterWorkerPool::Task> PixelRefMap; PixelRefMap pending_decode_tasks_; - typedef std::queue<scoped_refptr<Tile> > TileQueue; - TileQueue tiles_with_pending_upload_; - size_t bytes_pending_upload_; - bool has_performed_uploads_since_last_flush_; bool ever_exceeded_memory_budget_; MemoryHistory::Entry memory_stats_from_last_assign_; @@ -215,8 +205,6 @@ class CC_EXPORT TileManager : public WorkerPoolClient { bool use_color_estimator_; bool did_initialize_visible_tile_; - size_t max_pending_tasks_; - DISALLOW_COPY_AND_ASSIGN(TileManager); }; diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc index f40dbaa..c3af876 100644 --- a/cc/test/fake_tile_manager.cc +++ b/cc/test/fake_tile_manager.cc @@ -8,12 +8,22 @@ namespace cc { +namespace { + +class FakeRasterWorkerPool : public RasterWorkerPool { + public: + FakeRasterWorkerPool() : RasterWorkerPool(NULL, 1) {} + + virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE {} +}; + +} // namespace + FakeTileManager::FakeTileManager(TileManagerClient* client) : TileManager(client, NULL, - RasterWorkerPool::Create(1), + make_scoped_ptr<RasterWorkerPool>(new FakeRasterWorkerPool), 1, false, - NULL, - false) {} + NULL) {} } diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index 11c8a90..aaeff68 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc @@ -39,6 +39,7 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D() : FakeWebGraphicsContext3D(), context_id_(s_context_id++), next_buffer_id_(1), + next_image_id_(1), next_texture_id_(1), have_extension_io_surface_(false), have_extension_egl_image_(false), @@ -60,6 +61,7 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D( : FakeWebGraphicsContext3D(), context_id_(s_context_id++), next_buffer_id_(1), + next_image_id_(1), next_texture_id_(1), attributes_(attributes), have_extension_io_surface_(false), @@ -442,6 +444,50 @@ WebKit::WGC3Dboolean TestWebGraphicsContext3D::unmapBufferCHROMIUM( return true; } +void TestWebGraphicsContext3D::bindTexImage2DCHROMIUM( + WebKit::WGC3Denum target, + WebKit::WGC3Dint image_id) { + DCHECK_GT(images_.count(image_id), 0u); +} + +WebKit::WGC3Duint TestWebGraphicsContext3D::createImageCHROMIUM( + WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height, + WebKit::WGC3Denum internalformat) { + DCHECK_EQ(GL_RGBA8_OES, static_cast<int>(internalformat)); + WebKit::WGC3Duint image_id = NextImageId(); + images_.set(image_id, make_scoped_ptr(new Image).Pass()); + images_.get(image_id)->pixels.reset(new uint8[width * height * 4]); + return image_id; +} + +void TestWebGraphicsContext3D::destroyImageCHROMIUM( + WebKit::WGC3Duint id) { + unsigned context_id = id >> 17; + unsigned image_id = id & 0x1ffff; + DCHECK(image_id && image_id < next_image_id_); + DCHECK_EQ(context_id, context_id_); +} + +void TestWebGraphicsContext3D::getImageParameterivCHROMIUM( + WebKit::WGC3Duint image_id, + WebKit::WGC3Denum pname, + WebKit::WGC3Dint* params) { + DCHECK_GT(images_.count(image_id), 0u); + DCHECK_EQ(GL_IMAGE_ROWBYTES_CHROMIUM, static_cast<int>(pname)); + *params = 0; +} + +void* TestWebGraphicsContext3D::mapImageCHROMIUM(WebKit::WGC3Duint image_id, + WebKit::WGC3Denum access) { + DCHECK_GT(images_.count(image_id), 0u); + return images_.get(image_id)->pixels.get(); +} + +void TestWebGraphicsContext3D::unmapImageCHROMIUM( + WebKit::WGC3Duint image_id) { + DCHECK_GT(images_.count(image_id), 0u); +} + WebGLId TestWebGraphicsContext3D::NextTextureId() { WebGLId texture_id = next_texture_id_++; DCHECK(texture_id < (1 << 16)); @@ -456,8 +502,19 @@ WebGLId TestWebGraphicsContext3D::NextBufferId() { return buffer_id; } +WebKit::WGC3Duint TestWebGraphicsContext3D::NextImageId() { + WebKit::WGC3Duint image_id = next_image_id_++; + DCHECK(image_id < (1 << 17)); + image_id |= context_id_ << 17; + return image_id; +} + TestWebGraphicsContext3D::Buffer::Buffer() : target(0) {} TestWebGraphicsContext3D::Buffer::~Buffer() {} +TestWebGraphicsContext3D::Image::Image() {} + +TestWebGraphicsContext3D::Image::~Image() {} + } // namespace cc diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index 5780980..ffd847d 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h @@ -127,6 +127,22 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { WebKit::WGC3Denum access); virtual WebKit::WGC3Dboolean unmapBufferCHROMIUM(WebKit::WGC3Denum target); + virtual void bindTexImage2DCHROMIUM(WebKit::WGC3Denum target, + WebKit::WGC3Dint image_id); + virtual WebKit::WGC3Duint createImageCHROMIUM( + WebKit::WGC3Dsizei width, + WebKit::WGC3Dsizei height, + WebKit::WGC3Denum internalformat); + virtual void destroyImageCHROMIUM(WebKit::WGC3Duint image_id); + virtual void getImageParameterivCHROMIUM( + WebKit::WGC3Duint image_id, + WebKit::WGC3Denum pname, + WebKit::WGC3Dint* params); + virtual void* mapImageCHROMIUM( + WebKit::WGC3Duint image_id, + WebKit::WGC3Denum access); + virtual void unmapImageCHROMIUM(WebKit::WGC3Duint image_id); + // When set, MakeCurrent() will fail after this many times. void set_times_make_current_succeeds(int times) { times_make_current_succeeds_ = times; @@ -166,6 +182,8 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { virtual WebKit::WebGLId NextBufferId(); + virtual WebKit::WebGLId NextImageId(); + protected: TestWebGraphicsContext3D(); TestWebGraphicsContext3D( @@ -176,6 +194,7 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { unsigned context_id_; unsigned next_buffer_id_; + unsigned next_image_id_; unsigned next_texture_id_; Attributes attributes_; bool have_extension_io_surface_; @@ -206,6 +225,16 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { }; ScopedPtrHashMap<unsigned, Buffer> buffers_; unsigned bound_buffer_; + struct Image { + Image(); + ~Image(); + + scoped_ptr<uint8[]> pixels; + + private: + DISALLOW_COPY_AND_ASSIGN(Image); + }; + ScopedPtrHashMap<unsigned, Image> images_; base::WeakPtrFactory<TestWebGraphicsContext3D> weak_ptr_factory_; }; |