summaryrefslogtreecommitdiff
path: root/chromium/cc/resources
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@theqtcompany.com>2014-12-05 15:04:29 +0100
committerAndras Becsi <andras.becsi@theqtcompany.com>2014-12-09 10:49:28 +0100
commitaf6588f8d723931a298c995fa97259bb7f7deb55 (patch)
tree060ca707847ba1735f01af2372e0d5e494dc0366 /chromium/cc/resources
parent2fff84d821cc7b1c785f6404e0f8091333283e74 (diff)
downloadqtwebengine-chromium-af6588f8d723931a298c995fa97259bb7f7deb55.tar.gz
BASELINE: Update chromium to 40.0.2214.28 and ninja to 1.5.3.
Change-Id: I759465284fd64d59ad120219cbe257f7402c4181 Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/cc/resources')
-rw-r--r--chromium/cc/resources/bitmap_content_layer_updater.cc40
-rw-r--r--chromium/cc/resources/bitmap_content_layer_updater.h30
-rw-r--r--chromium/cc/resources/bitmap_raster_worker_pool.cc203
-rw-r--r--chromium/cc/resources/bitmap_raster_worker_pool.h79
-rw-r--r--chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc15
-rw-r--r--chromium/cc/resources/bitmap_skpicture_content_layer_updater.h14
-rw-r--r--chromium/cc/resources/content_layer_updater.cc82
-rw-r--r--chromium/cc/resources/content_layer_updater.h25
-rw-r--r--chromium/cc/resources/direct_raster_worker_pool.cc215
-rw-r--r--chromium/cc/resources/direct_raster_worker_pool.h81
-rw-r--r--chromium/cc/resources/eviction_tile_priority_queue.cc221
-rw-r--r--chromium/cc/resources/eviction_tile_priority_queue.h61
-rw-r--r--chromium/cc/resources/gpu_raster_worker_pool.cc252
-rw-r--r--chromium/cc/resources/gpu_raster_worker_pool.h83
-rw-r--r--chromium/cc/resources/image_copy_raster_worker_pool.cc260
-rw-r--r--chromium/cc/resources/image_copy_raster_worker_pool.h110
-rw-r--r--chromium/cc/resources/image_layer_updater.cc2
-rw-r--r--chromium/cc/resources/image_layer_updater.h16
-rw-r--r--chromium/cc/resources/image_raster_worker_pool.cc194
-rw-r--r--chromium/cc/resources/image_raster_worker_pool.h74
-rw-r--r--chromium/cc/resources/layer_painter.h4
-rw-r--r--chromium/cc/resources/layer_quad.cc2
-rw-r--r--chromium/cc/resources/layer_quad.h2
-rw-r--r--chromium/cc/resources/layer_quad_unittest.cc2
-rw-r--r--chromium/cc/resources/layer_tiling_data.cc35
-rw-r--r--chromium/cc/resources/layer_tiling_data.h15
-rw-r--r--chromium/cc/resources/layer_updater.h15
-rw-r--r--chromium/cc/resources/managed_tile_state.cc88
-rw-r--r--chromium/cc/resources/managed_tile_state.h17
-rw-r--r--chromium/cc/resources/memory_history.cc2
-rw-r--r--chromium/cc/resources/memory_history.h13
-rw-r--r--chromium/cc/resources/one_copy_raster_worker_pool.cc506
-rw-r--r--chromium/cc/resources/one_copy_raster_worker_pool.h141
-rw-r--r--chromium/cc/resources/picture.cc168
-rw-r--r--chromium/cc/resources/picture.h30
-rw-r--r--chromium/cc/resources/picture_layer_tiling.cc818
-rw-r--r--chromium/cc/resources/picture_layer_tiling.h226
-rw-r--r--chromium/cc/resources/picture_layer_tiling_perftest.cc256
-rw-r--r--chromium/cc/resources/picture_layer_tiling_set.cc120
-rw-r--r--chromium/cc/resources/picture_layer_tiling_set.h45
-rw-r--r--chromium/cc/resources/picture_layer_tiling_set_unittest.cc224
-rw-r--r--chromium/cc/resources/picture_layer_tiling_unittest.cc746
-rw-r--r--chromium/cc/resources/picture_pile.cc395
-rw-r--r--chromium/cc/resources/picture_pile.h16
-rw-r--r--chromium/cc/resources/picture_pile_base.cc146
-rw-r--r--chromium/cc/resources/picture_pile_base.h49
-rw-r--r--chromium/cc/resources/picture_pile_impl.cc239
-rw-r--r--chromium/cc/resources/picture_pile_impl.h150
-rw-r--r--chromium/cc/resources/picture_pile_impl_perftest.cc14
-rw-r--r--chromium/cc/resources/picture_pile_impl_unittest.cc64
-rw-r--r--chromium/cc/resources/picture_pile_unittest.cc1446
-rw-r--r--chromium/cc/resources/picture_unittest.cc133
-rw-r--r--chromium/cc/resources/pixel_buffer_raster_worker_pool.cc449
-rw-r--r--chromium/cc/resources/pixel_buffer_raster_worker_pool.h64
-rw-r--r--chromium/cc/resources/platform_color.h2
-rw-r--r--chromium/cc/resources/prioritized_resource.h7
-rw-r--r--chromium/cc/resources/prioritized_resource_manager.cc3
-rw-r--r--chromium/cc/resources/prioritized_resource_manager.h14
-rw-r--r--chromium/cc/resources/prioritized_resource_unittest.cc24
-rw-r--r--chromium/cc/resources/prioritized_tile_set.cc140
-rw-r--r--chromium/cc/resources/prioritized_tile_set.h59
-rw-r--r--chromium/cc/resources/prioritized_tile_set_unittest.cc732
-rw-r--r--chromium/cc/resources/priority_calculator.cc2
-rw-r--r--chromium/cc/resources/raster_buffer.cc15
-rw-r--r--chromium/cc/resources/raster_buffer.h26
-rw-r--r--chromium/cc/resources/raster_mode.cc28
-rw-r--r--chromium/cc/resources/raster_mode.h28
-rw-r--r--chromium/cc/resources/raster_source.h71
-rw-r--r--chromium/cc/resources/raster_tile_priority_queue.cc310
-rw-r--r--chromium/cc/resources/raster_tile_priority_queue.h66
-rw-r--r--chromium/cc/resources/raster_worker_pool.cc187
-rw-r--r--chromium/cc/resources/raster_worker_pool.h28
-rw-r--r--chromium/cc/resources/raster_worker_pool_perftest.cc259
-rw-r--r--chromium/cc/resources/raster_worker_pool_unittest.cc211
-rw-r--r--chromium/cc/resources/rasterizer.cc13
-rw-r--r--chromium/cc/resources/rasterizer.h43
-rw-r--r--chromium/cc/resources/release_callback_impl.h20
-rw-r--r--chromium/cc/resources/resource.h2
-rw-r--r--chromium/cc/resources/resource_format.cc5
-rw-r--r--chromium/cc/resources/resource_format.h1
-rw-r--r--chromium/cc/resources/resource_pool.cc5
-rw-r--r--chromium/cc/resources/resource_pool.h6
-rw-r--r--chromium/cc/resources/resource_provider.cc825
-rw-r--r--chromium/cc/resources/resource_provider.h300
-rw-r--r--chromium/cc/resources/resource_provider_unittest.cc1203
-rw-r--r--chromium/cc/resources/resource_update.h4
-rw-r--r--chromium/cc/resources/resource_update_controller_unittest.cc43
-rw-r--r--chromium/cc/resources/return_callback.h5
-rw-r--r--chromium/cc/resources/scoped_gpu_raster.cc52
-rw-r--r--chromium/cc/resources/scoped_gpu_raster.h34
-rw-r--r--chromium/cc/resources/scoped_resource.cc8
-rw-r--r--chromium/cc/resources/scoped_resource.h3
-rw-r--r--chromium/cc/resources/scoped_resource_unittest.cc77
-rw-r--r--chromium/cc/resources/scoped_ui_resource.h6
-rw-r--r--chromium/cc/resources/shared_bitmap.h2
-rw-r--r--chromium/cc/resources/shared_bitmap_manager.h2
-rw-r--r--chromium/cc/resources/single_release_callback_impl.cc34
-rw-r--r--chromium/cc/resources/single_release_callback_impl.h36
-rw-r--r--chromium/cc/resources/skpicture_content_layer_updater.cc24
-rw-r--r--chromium/cc/resources/skpicture_content_layer_updater.h12
-rw-r--r--chromium/cc/resources/task_graph_runner.cc5
-rw-r--r--chromium/cc/resources/task_graph_runner.h2
-rw-r--r--chromium/cc/resources/task_graph_runner_perftest.cc10
-rw-r--r--chromium/cc/resources/task_graph_runner_unittest.cc20
-rw-r--r--chromium/cc/resources/texture_mailbox.cc1
-rw-r--r--chromium/cc/resources/texture_mailbox.h3
-rw-r--r--chromium/cc/resources/texture_mailbox_deleter_unittest.cc2
-rw-r--r--chromium/cc/resources/texture_uploader.cc11
-rw-r--r--chromium/cc/resources/texture_uploader_unittest.cc33
-rw-r--r--chromium/cc/resources/tile.cc86
-rw-r--r--chromium/cc/resources/tile.h131
-rw-r--r--chromium/cc/resources/tile_manager.cc1480
-rw-r--r--chromium/cc/resources/tile_manager.h266
-rw-r--r--chromium/cc/resources/tile_manager_perftest.cc262
-rw-r--r--chromium/cc/resources/tile_manager_unittest.cc976
-rw-r--r--chromium/cc/resources/tile_priority.cc92
-rw-r--r--chromium/cc/resources/tile_priority.h47
-rw-r--r--chromium/cc/resources/transferable_resource.cc4
-rw-r--r--chromium/cc/resources/transferable_resource.h3
-rw-r--r--chromium/cc/resources/ui_resource_bitmap.cc26
-rw-r--r--chromium/cc/resources/ui_resource_bitmap.h6
-rw-r--r--chromium/cc/resources/ui_resource_request.cc2
-rw-r--r--chromium/cc/resources/video_resource_updater.cc70
-rw-r--r--chromium/cc/resources/video_resource_updater.h17
-rw-r--r--chromium/cc/resources/video_resource_updater_unittest.cc14
-rw-r--r--chromium/cc/resources/zero_copy_raster_worker_pool.cc211
-rw-r--r--chromium/cc/resources/zero_copy_raster_worker_pool.h79
127 files changed, 9989 insertions, 7544 deletions
diff --git a/chromium/cc/resources/bitmap_content_layer_updater.cc b/chromium/cc/resources/bitmap_content_layer_updater.cc
index fff62cf0aca..63ba336a152 100644
--- a/chromium/cc/resources/bitmap_content_layer_updater.cc
+++ b/chromium/cc/resources/bitmap_content_layer_updater.cc
@@ -50,41 +50,38 @@ BitmapContentLayerUpdater::~BitmapContentLayerUpdater() {}
scoped_ptr<LayerUpdater::Resource> BitmapContentLayerUpdater::CreateResource(
PrioritizedResourceManager* manager) {
- return scoped_ptr<LayerUpdater::Resource>(
+ return make_scoped_ptr(
new Resource(this, PrioritizedResource::Create(manager)));
}
-void BitmapContentLayerUpdater::PrepareToUpdate(
- const gfx::Rect& content_rect,
- const gfx::Size& tile_size,
- float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect) {
- if (canvas_size_ != content_rect.size()) {
+void BitmapContentLayerUpdater::PrepareToUpdate(const gfx::Size& content_size,
+ const gfx::Rect& paint_rect,
+ const gfx::Size& tile_size,
+ float contents_width_scale,
+ float contents_height_scale) {
+ if (canvas_size_ != paint_rect.size()) {
devtools_instrumentation::ScopedLayerTask paint_setup(
devtools_instrumentation::kPaintSetup, layer_id_);
- canvas_size_ = content_rect.size();
- bool alloc = bitmap_backing_.allocN32Pixels(
+ canvas_size_ = paint_rect.size();
+ bitmap_backing_.allocN32Pixels(
canvas_size_.width(), canvas_size_.height(), layer_is_opaque_);
// TODO(danak): Remove when skia does the check for us: crbug.com/360384
- CHECK(alloc);
canvas_ = skia::AdoptRef(new SkCanvas(bitmap_backing_));
- DCHECK_EQ(content_rect.width(), canvas_->getBaseLayerSize().width());
- DCHECK_EQ(content_rect.height(), canvas_->getBaseLayerSize().height());
+ DCHECK_EQ(paint_rect.width(), canvas_->getBaseLayerSize().width());
+ DCHECK_EQ(paint_rect.height(), canvas_->getBaseLayerSize().height());
}
base::TimeTicks start_time =
rendering_stats_instrumentation_->StartRecording();
PaintContents(canvas_.get(),
- content_rect,
+ content_size,
+ paint_rect,
contents_width_scale,
- contents_height_scale,
- resulting_opaque_rect);
+ contents_height_scale);
base::TimeDelta duration =
rendering_stats_instrumentation_->EndRecording(start_time);
rendering_stats_instrumentation_->AddPaint(
- duration,
- content_rect.width() * content_rect.height());
+ duration, paint_rect.width() * paint_rect.height());
}
void BitmapContentLayerUpdater::UpdateTexture(ResourceUpdateQueue* queue,
@@ -93,11 +90,8 @@ void BitmapContentLayerUpdater::UpdateTexture(ResourceUpdateQueue* queue,
const gfx::Vector2d& dest_offset,
bool partial_update) {
CHECK(canvas_);
- ResourceUpdate upload = ResourceUpdate::Create(texture,
- &bitmap_backing_,
- content_rect(),
- source_rect,
- dest_offset);
+ ResourceUpdate upload = ResourceUpdate::Create(
+ texture, &bitmap_backing_, paint_rect(), source_rect, dest_offset);
if (partial_update)
queue->AppendPartialUpload(upload);
else
diff --git a/chromium/cc/resources/bitmap_content_layer_updater.h b/chromium/cc/resources/bitmap_content_layer_updater.h
index 781fc0baa73..5ddc35f48a7 100644
--- a/chromium/cc/resources/bitmap_content_layer_updater.h
+++ b/chromium/cc/resources/bitmap_content_layer_updater.h
@@ -27,12 +27,12 @@ class CC_EXPORT BitmapContentLayerUpdater : public ContentLayerUpdater {
public:
Resource(BitmapContentLayerUpdater* updater,
scoped_ptr<PrioritizedResource> resource);
- virtual ~Resource();
+ ~Resource() override;
- virtual void Update(ResourceUpdateQueue* queue,
- const gfx::Rect& source_rect,
- const gfx::Vector2d& dest_offset,
- bool partial_update) OVERRIDE;
+ void Update(ResourceUpdateQueue* queue,
+ const gfx::Rect& source_rect,
+ const gfx::Vector2d& dest_offset,
+ bool partial_update) override;
private:
BitmapContentLayerUpdater* updater_;
@@ -45,27 +45,27 @@ class CC_EXPORT BitmapContentLayerUpdater : public ContentLayerUpdater {
RenderingStatsInstrumentation* stats_instrumenation,
int layer_id);
- virtual scoped_ptr<LayerUpdater::Resource> CreateResource(
- PrioritizedResourceManager* manager) OVERRIDE;
- virtual void PrepareToUpdate(const gfx::Rect& content_rect,
- const gfx::Size& tile_size,
- float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect) OVERRIDE;
+ scoped_ptr<LayerUpdater::Resource> CreateResource(
+ PrioritizedResourceManager* manager) override;
+ void PrepareToUpdate(const gfx::Size& content_size,
+ const gfx::Rect& paint_rect,
+ const gfx::Size& tile_size,
+ float contents_width_scale,
+ float contents_height_scale) override;
void UpdateTexture(ResourceUpdateQueue* queue,
PrioritizedResource* resource,
const gfx::Rect& source_rect,
const gfx::Vector2d& dest_offset,
bool partial_update);
- virtual void SetOpaque(bool opaque) OVERRIDE;
- virtual void ReduceMemoryUsage() OVERRIDE;
+ void SetOpaque(bool opaque) override;
+ void ReduceMemoryUsage() override;
protected:
BitmapContentLayerUpdater(
scoped_ptr<LayerPainter> painter,
RenderingStatsInstrumentation* stats_instrumenation,
int layer_id);
- virtual ~BitmapContentLayerUpdater();
+ ~BitmapContentLayerUpdater() override;
SkBitmap bitmap_backing_;
skia::RefPtr<SkCanvas> canvas_;
diff --git a/chromium/cc/resources/bitmap_raster_worker_pool.cc b/chromium/cc/resources/bitmap_raster_worker_pool.cc
new file mode 100644
index 00000000000..3b3739a3ccc
--- /dev/null
+++ b/chromium/cc/resources/bitmap_raster_worker_pool.cc
@@ -0,0 +1,203 @@
+// Copyright 2014 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/bitmap_raster_worker_pool.h"
+
+#include <algorithm>
+
+#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
+#include "base/strings/stringprintf.h"
+#include "cc/debug/traced_value.h"
+#include "cc/resources/raster_buffer.h"
+#include "cc/resources/raster_source.h"
+#include "cc/resources/resource.h"
+
+namespace cc {
+namespace {
+
+class RasterBufferImpl : public RasterBuffer {
+ public:
+ RasterBufferImpl(ResourceProvider* resource_provider,
+ const Resource* resource)
+ : lock_(resource_provider, resource->id()) {}
+
+ // Overridden from RasterBuffer:
+ void Playback(const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) override {
+ raster_source->PlaybackToCanvas(lock_.sk_canvas(), rect, scale);
+ }
+
+ private:
+ ResourceProvider::ScopedWriteLockSoftware lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+};
+
+} // namespace
+
+// static
+scoped_ptr<RasterWorkerPool> BitmapRasterWorkerPool::Create(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider) {
+ return make_scoped_ptr<RasterWorkerPool>(new BitmapRasterWorkerPool(
+ task_runner, task_graph_runner, resource_provider));
+}
+
+BitmapRasterWorkerPool::BitmapRasterWorkerPool(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider)
+ : task_runner_(task_runner),
+ task_graph_runner_(task_graph_runner),
+ namespace_token_(task_graph_runner->GetNamespaceToken()),
+ resource_provider_(resource_provider),
+ raster_finished_weak_ptr_factory_(this) {
+}
+
+BitmapRasterWorkerPool::~BitmapRasterWorkerPool() {
+}
+
+Rasterizer* BitmapRasterWorkerPool::AsRasterizer() {
+ return this;
+}
+
+void BitmapRasterWorkerPool::SetClient(RasterizerClient* client) {
+ client_ = client;
+}
+
+void BitmapRasterWorkerPool::Shutdown() {
+ TRACE_EVENT0("cc", "BitmapRasterWorkerPool::Shutdown");
+
+ TaskGraph empty;
+ task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
+ task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
+}
+
+void BitmapRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
+ TRACE_EVENT0("cc", "BitmapRasterWorkerPool::ScheduleTasks");
+
+ if (raster_pending_.none())
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
+
+ // Mark all task sets as pending.
+ raster_pending_.set();
+
+ unsigned priority = kRasterTaskPriorityBase;
+
+ graph_.Reset();
+
+ // Cancel existing OnRasterFinished callbacks.
+ raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
+
+ scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
+
+ size_t task_count[kNumberOfTaskSets] = {0};
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
+ task_runner_.get(),
+ base::Bind(&BitmapRasterWorkerPool::OnRasterFinished,
+ raster_finished_weak_ptr_factory_.GetWeakPtr(),
+ task_set));
+ }
+
+ for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
+ it != queue->items.end();
+ ++it) {
+ const RasterTaskQueue::Item& item = *it;
+ RasterTask* task = item.task;
+ DCHECK(!task->HasCompleted());
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (!item.task_sets[task_set])
+ continue;
+
+ ++task_count[task_set];
+
+ graph_.edges.push_back(
+ TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get()));
+ }
+
+ InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
+ }
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ InsertNodeForTask(&graph_,
+ new_raster_finished_tasks[task_set].get(),
+ kRasterFinishedTaskPriority,
+ task_count[task_set]);
+ }
+
+ ScheduleTasksOnOriginThread(this, &graph_);
+ task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
+
+ std::copy(new_raster_finished_tasks,
+ new_raster_finished_tasks + kNumberOfTaskSets,
+ raster_finished_tasks_);
+
+ TRACE_EVENT_ASYNC_STEP_INTO1(
+ "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
+}
+
+void BitmapRasterWorkerPool::CheckForCompletedTasks() {
+ TRACE_EVENT0("cc", "BitmapRasterWorkerPool::CheckForCompletedTasks");
+
+ task_graph_runner_->CollectCompletedTasks(namespace_token_,
+ &completed_tasks_);
+ for (Task::Vector::const_iterator it = completed_tasks_.begin();
+ it != completed_tasks_.end();
+ ++it) {
+ RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
+
+ task->WillComplete();
+ task->CompleteOnOriginThread(this);
+ task->DidComplete();
+
+ task->RunReplyOnOriginThread();
+ }
+ completed_tasks_.clear();
+}
+
+scoped_ptr<RasterBuffer> BitmapRasterWorkerPool::AcquireBufferForRaster(
+ const Resource* resource) {
+ return make_scoped_ptr<RasterBuffer>(
+ new RasterBufferImpl(resource_provider_, resource));
+}
+
+void BitmapRasterWorkerPool::ReleaseBufferForRaster(
+ scoped_ptr<RasterBuffer> buffer) {
+ // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
+}
+
+void BitmapRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
+ TRACE_EVENT1(
+ "cc", "BitmapRasterWorkerPool::OnRasterFinished", "task_set", task_set);
+
+ DCHECK(raster_pending_[task_set]);
+ raster_pending_[task_set] = false;
+ if (raster_pending_.any()) {
+ TRACE_EVENT_ASYNC_STEP_INTO1(
+ "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
+ } else {
+ TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
+ }
+ client_->DidFinishRunningTasks(task_set);
+}
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+BitmapRasterWorkerPool::StateAsValue() const {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
+
+ state->BeginArray("tasks_pending");
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
+ state->AppendBoolean(raster_pending_[task_set]);
+ state->EndArray();
+ return state;
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/bitmap_raster_worker_pool.h b/chromium/cc/resources/bitmap_raster_worker_pool.h
new file mode 100644
index 00000000000..624318b5e74
--- /dev/null
+++ b/chromium/cc/resources/bitmap_raster_worker_pool.h
@@ -0,0 +1,79 @@
+// Copyright 2014 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_BITMAP_RASTER_WORKER_POOL_H_
+#define CC_RESOURCES_BITMAP_RASTER_WORKER_POOL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "cc/resources/raster_worker_pool.h"
+#include "cc/resources/rasterizer.h"
+
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+}
+
+namespace cc {
+class ResourceProvider;
+
+class CC_EXPORT BitmapRasterWorkerPool : public RasterWorkerPool,
+ public Rasterizer,
+ public RasterizerTaskClient {
+ public:
+ ~BitmapRasterWorkerPool() override;
+
+ static scoped_ptr<RasterWorkerPool> Create(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider);
+
+ // Overridden from RasterWorkerPool:
+ Rasterizer* AsRasterizer() override;
+
+ // Overridden from Rasterizer:
+ void SetClient(RasterizerClient* client) override;
+ void Shutdown() override;
+ void ScheduleTasks(RasterTaskQueue* queue) override;
+ void CheckForCompletedTasks() override;
+
+ // Overridden from RasterizerTaskClient:
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) override;
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
+
+ protected:
+ BitmapRasterWorkerPool(base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider);
+
+ private:
+ void OnRasterFinished(TaskSet task_set);
+ scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ TaskGraphRunner* task_graph_runner_;
+ const NamespaceToken namespace_token_;
+ RasterizerClient* client_;
+ ResourceProvider* resource_provider_;
+
+ TaskSetCollection raster_pending_;
+
+ scoped_refptr<RasterizerTask> raster_finished_tasks_[kNumberOfTaskSets];
+
+ // Task graph used when scheduling tasks and vector used to gather
+ // completed tasks.
+ TaskGraph graph_;
+ Task::Vector completed_tasks_;
+
+ base::WeakPtrFactory<BitmapRasterWorkerPool>
+ raster_finished_weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BitmapRasterWorkerPool);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_BITMAP_RASTER_WORKER_POOL_H_
diff --git a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc
index 21fdbbb72bc..5b8e5e43f2e 100644
--- a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc
+++ b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.cc
@@ -26,7 +26,7 @@ void BitmapSkPictureContentLayerUpdater::Resource::Update(
SkAlphaType at =
updater_->layer_is_opaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
bitmap_.allocPixels(SkImageInfo::Make(
- source_rect.width(), source_rect.height(), kPMColor_SkColorType, at));
+ source_rect.width(), source_rect.height(), kN32_SkColorType, at));
SkCanvas canvas(bitmap_);
updater_->PaintContentsRect(&canvas, source_rect);
@@ -62,7 +62,7 @@ BitmapSkPictureContentLayerUpdater::~BitmapSkPictureContentLayerUpdater() {}
scoped_ptr<LayerUpdater::Resource>
BitmapSkPictureContentLayerUpdater::CreateResource(
PrioritizedResourceManager* manager) {
- return scoped_ptr<LayerUpdater::Resource>(
+ return make_scoped_ptr(
new Resource(this, PrioritizedResource::Create(manager)));
}
@@ -72,16 +72,9 @@ void BitmapSkPictureContentLayerUpdater::PaintContentsRect(
if (!canvas)
return;
// Translate the origin of content_rect to that of source_rect.
- canvas->translate(content_rect().x() - source_rect.x(),
- content_rect().y() - source_rect.y());
- base::TimeTicks start_time =
- rendering_stats_instrumentation_->StartRecording();
+ canvas->translate(paint_rect().x() - source_rect.x(),
+ paint_rect().y() - source_rect.y());
DrawPicture(canvas);
- base::TimeDelta duration =
- rendering_stats_instrumentation_->EndRecording(start_time);
- rendering_stats_instrumentation_->AddRaster(
- duration,
- source_rect.width() * source_rect.height());
}
} // namespace cc
diff --git a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h
index e20e3c35c5e..ba22b2e5908 100644
--- a/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h
+++ b/chromium/cc/resources/bitmap_skpicture_content_layer_updater.h
@@ -20,10 +20,10 @@ class BitmapSkPictureContentLayerUpdater : public SkPictureContentLayerUpdater {
Resource(BitmapSkPictureContentLayerUpdater* updater,
scoped_ptr<PrioritizedResource> texture);
- virtual void Update(ResourceUpdateQueue* queue,
- const gfx::Rect& source_rect,
- const gfx::Vector2d& dest_offset,
- bool partial_update) OVERRIDE;
+ void Update(ResourceUpdateQueue* queue,
+ const gfx::Rect& source_rect,
+ const gfx::Vector2d& dest_offset,
+ bool partial_update) override;
private:
SkBitmap bitmap_;
@@ -37,8 +37,8 @@ class BitmapSkPictureContentLayerUpdater : public SkPictureContentLayerUpdater {
RenderingStatsInstrumentation* stats_instrumentation,
int layer_id);
- virtual scoped_ptr<LayerUpdater::Resource> CreateResource(
- PrioritizedResourceManager* manager) OVERRIDE;
+ scoped_ptr<LayerUpdater::Resource> CreateResource(
+ PrioritizedResourceManager* manager) override;
void PaintContentsRect(SkCanvas* canvas,
const gfx::Rect& source_rect);
@@ -47,7 +47,7 @@ class BitmapSkPictureContentLayerUpdater : public SkPictureContentLayerUpdater {
scoped_ptr<LayerPainter> painter,
RenderingStatsInstrumentation* stats_instrumentation,
int layer_id);
- virtual ~BitmapSkPictureContentLayerUpdater();
+ ~BitmapSkPictureContentLayerUpdater() override;
DISALLOW_COPY_AND_ASSIGN(BitmapSkPictureContentLayerUpdater);
};
diff --git a/chromium/cc/resources/content_layer_updater.cc b/chromium/cc/resources/content_layer_updater.cc
index 249a6e92cd8..971362fb8b8 100644
--- a/chromium/cc/resources/content_layer_updater.cc
+++ b/chromium/cc/resources/content_layer_updater.cc
@@ -5,15 +5,14 @@
#include "cc/resources/content_layer_updater.h"
#include "base/debug/trace_event.h"
-#include "base/time/time.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/resources/layer_painter.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkScalar.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/rect_f.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/skia_util.h"
namespace cc {
@@ -25,7 +24,9 @@ ContentLayerUpdater::ContentLayerUpdater(
layer_id_(layer_id),
layer_is_opaque_(false),
layer_fills_bounds_completely_(false),
- painter_(painter.Pass()) {}
+ painter_(painter.Pass()),
+ background_color_(SK_ColorTRANSPARENT) {
+}
ContentLayerUpdater::~ContentLayerUpdater() {}
@@ -35,28 +36,62 @@ void ContentLayerUpdater::set_rendering_stats_instrumentation(
}
void ContentLayerUpdater::PaintContents(SkCanvas* canvas,
- const gfx::Rect& content_rect,
+ const gfx::Size& layer_content_size,
+ const gfx::Rect& paint_rect,
float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect) {
+ float contents_height_scale) {
TRACE_EVENT0("cc", "ContentLayerUpdater::PaintContents");
if (!canvas)
return;
canvas->save();
- canvas->translate(SkFloatToScalar(-content_rect.x()),
- SkFloatToScalar(-content_rect.y()));
-
- // The |canvas| backing should be sized to hold the |content_rect|.
- DCHECK_EQ(content_rect.width(), canvas->getBaseLayerSize().width());
- DCHECK_EQ(content_rect.height(), canvas->getBaseLayerSize().height());
+ canvas->translate(SkIntToScalar(-paint_rect.x()),
+ SkIntToScalar(-paint_rect.y()));
+
+ // The |canvas| backing should be sized to hold the |paint_rect|.
+ DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width());
+ DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height());
+
+ const bool is_scaled =
+ contents_width_scale != 1.f || contents_height_scale != 1.f;
+
+ if (is_scaled && (layer_is_opaque_ || layer_fills_bounds_completely_)) {
+ // Even if completely covered, for rasterizations that touch the edge of the
+ // layer, we also need to raster the background color underneath the last
+ // texel (since the paint won't cover it).
+ //
+ // The final texel of content may only be partially covered by a
+ // rasterization; this rect represents the content rect that is fully
+ // covered by content.
+ const gfx::Rect layer_content_rect = gfx::Rect(layer_content_size);
+ gfx::Rect deflated_layer_content_rect = layer_content_rect;
+ deflated_layer_content_rect.Inset(0, 0, 1, 1);
+
+ if (!layer_content_rect.Contains(deflated_layer_content_rect)) {
+ // Drawing at most 1 x 1 x (canvas width + canvas height) texels is 2-3X
+ // faster than clearing, so special case this.
+ DCHECK_LE(paint_rect.right(), layer_content_rect.right());
+ DCHECK_LE(paint_rect.bottom(), layer_content_rect.bottom());
+ canvas->save();
+ canvas->clipRect(gfx::RectToSkRect(layer_content_rect),
+ SkRegion::kReplace_Op);
+ canvas->clipRect(gfx::RectToSkRect(deflated_layer_content_rect),
+ SkRegion::kDifference_Op);
+ canvas->drawColor(background_color_, SkXfermode::kSrc_Mode);
+ canvas->restore();
+ }
+ }
- gfx::Rect layer_rect = content_rect;
- if (contents_width_scale != 1.f || contents_height_scale != 1.f) {
+ gfx::Rect layer_rect;
+ if (is_scaled) {
canvas->scale(SkFloatToScalar(contents_width_scale),
SkFloatToScalar(contents_height_scale));
+ // NOTE: this may go beyond the bounds of the layer, but that shouldn't
+ // cause problems (anything beyond the layer is clipped out).
layer_rect = gfx::ScaleToEnclosingRect(
- content_rect, 1.f / contents_width_scale, 1.f / contents_height_scale);
+ paint_rect, 1.f / contents_width_scale, 1.f / contents_height_scale);
+ } else {
+ layer_rect = paint_rect;
}
SkRect layer_sk_rect = SkRect::MakeXYWH(
@@ -71,15 +106,10 @@ void ContentLayerUpdater::PaintContents(SkCanvas* canvas,
canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode);
}
- gfx::RectF opaque_layer_rect;
- painter_->Paint(canvas, layer_rect, &opaque_layer_rect);
+ painter_->Paint(canvas, layer_rect);
canvas->restore();
- gfx::Rect opaque_content_rect = gfx::ToEnclosedRect(gfx::ScaleRect(
- opaque_layer_rect, contents_width_scale, contents_height_scale));
- *resulting_opaque_rect = opaque_content_rect;
-
- content_rect_ = content_rect;
+ paint_rect_ = paint_rect;
}
void ContentLayerUpdater::SetOpaque(bool opaque) {
@@ -90,4 +120,8 @@ void ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds) {
layer_fills_bounds_completely_ = fills_bounds;
}
+void ContentLayerUpdater::SetBackgroundColor(SkColor background_color) {
+ background_color_ = background_color;
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/content_layer_updater.h b/chromium/cc/resources/content_layer_updater.h
index 7dfcb6a794f..4ba18ba9e40 100644
--- a/chromium/cc/resources/content_layer_updater.h
+++ b/chromium/cc/resources/content_layer_updater.h
@@ -7,7 +7,7 @@
#include "cc/base/cc_export.h"
#include "cc/resources/layer_updater.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
class SkCanvas;
@@ -22,27 +22,33 @@ class RenderingStatsInstrumentation;
class CC_EXPORT ContentLayerUpdater : public LayerUpdater {
public:
void set_rendering_stats_instrumentation(RenderingStatsInstrumentation* rsi);
- virtual void SetOpaque(bool opaque) OVERRIDE;
- virtual void SetFillsBoundsCompletely(bool fills_bounds) OVERRIDE;
+ void SetOpaque(bool opaque) override;
+ void SetFillsBoundsCompletely(bool fills_bounds) override;
+ void SetBackgroundColor(SkColor background_color) override;
protected:
ContentLayerUpdater(scoped_ptr<LayerPainter> painter,
RenderingStatsInstrumentation* stats_instrumentation,
int layer_id);
- virtual ~ContentLayerUpdater();
+ ~ContentLayerUpdater() override;
+ // Paints the contents. |content_size| size of the underlying layer in
+ // layer's content space. |paint_rect| bounds to paint in content space of the
+ // layer. Both |content_size| and |paint_rect| are in pixels.
void PaintContents(SkCanvas* canvas,
- const gfx::Rect& content_rect,
+ const gfx::Size& layer_content_size,
+ const gfx::Rect& paint_rect,
float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect);
- gfx::Rect content_rect() const { return content_rect_; }
+ float contents_height_scale);
+ gfx::Rect paint_rect() const { return paint_rect_; }
bool layer_is_opaque() const { return layer_is_opaque_; }
bool layer_fills_bounds_completely() const {
return layer_fills_bounds_completely_;
}
+ SkColor background_color() const { return background_color_; }
+
RenderingStatsInstrumentation* rendering_stats_instrumentation_;
int layer_id_;
@@ -52,8 +58,9 @@ class CC_EXPORT ContentLayerUpdater : public LayerUpdater {
bool layer_fills_bounds_completely_;
private:
- gfx::Rect content_rect_;
+ gfx::Rect paint_rect_;
scoped_ptr<LayerPainter> painter_;
+ SkColor background_color_;
DISALLOW_COPY_AND_ASSIGN(ContentLayerUpdater);
};
diff --git a/chromium/cc/resources/direct_raster_worker_pool.cc b/chromium/cc/resources/direct_raster_worker_pool.cc
deleted file mode 100644
index 4bd0c55c739..00000000000
--- a/chromium/cc/resources/direct_raster_worker_pool.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2014 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/direct_raster_worker_pool.h"
-
-#include "base/debug/trace_event.h"
-#include "cc/output/context_provider.h"
-#include "cc/resources/resource.h"
-#include "cc/resources/resource_provider.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-
-namespace cc {
-
-// static
-scoped_ptr<RasterWorkerPool> DirectRasterWorkerPool::Create(
- base::SequencedTaskRunner* task_runner,
- ResourceProvider* resource_provider,
- ContextProvider* context_provider) {
- return make_scoped_ptr<RasterWorkerPool>(new DirectRasterWorkerPool(
- task_runner, resource_provider, context_provider));
-}
-
-DirectRasterWorkerPool::DirectRasterWorkerPool(
- base::SequencedTaskRunner* task_runner,
- ResourceProvider* resource_provider,
- ContextProvider* context_provider)
- : task_runner_(task_runner),
- task_graph_runner_(new TaskGraphRunner),
- namespace_token_(task_graph_runner_->GetNamespaceToken()),
- resource_provider_(resource_provider),
- context_provider_(context_provider),
- run_tasks_on_origin_thread_pending_(false),
- raster_tasks_pending_(false),
- raster_tasks_required_for_activation_pending_(false),
- raster_finished_weak_ptr_factory_(this),
- weak_ptr_factory_(this) {}
-
-DirectRasterWorkerPool::~DirectRasterWorkerPool() {
- DCHECK_EQ(0u, completed_tasks_.size());
-}
-
-Rasterizer* DirectRasterWorkerPool::AsRasterizer() { return this; }
-
-void DirectRasterWorkerPool::SetClient(RasterizerClient* client) {
- client_ = client;
-}
-
-void DirectRasterWorkerPool::Shutdown() {
- TRACE_EVENT0("cc", "DirectRasterWorkerPool::Shutdown");
-
- TaskGraph empty;
- task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
- task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-}
-
-void DirectRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
- TRACE_EVENT0("cc", "DirectRasterWorkerPool::ScheduleTasks");
-
- DCHECK_EQ(queue->required_for_activation_count,
- static_cast<size_t>(
- std::count_if(queue->items.begin(),
- queue->items.end(),
- RasterTaskQueue::Item::IsRequiredForActivation)));
-
- raster_tasks_pending_ = true;
- raster_tasks_required_for_activation_pending_ = true;
-
- unsigned priority = kRasterTaskPriorityBase;
-
- graph_.Reset();
-
- // Cancel existing OnRasterFinished callbacks.
- raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
-
- scoped_refptr<RasterizerTask>
- new_raster_required_for_activation_finished_task(
- CreateRasterRequiredForActivationFinishedTask(
- queue->required_for_activation_count,
- task_runner_.get(),
- base::Bind(&DirectRasterWorkerPool::
- OnRasterRequiredForActivationFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr())));
- scoped_refptr<RasterizerTask> new_raster_finished_task(
- CreateRasterFinishedTask(
- task_runner_.get(),
- base::Bind(&DirectRasterWorkerPool::OnRasterFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr())));
-
- for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
- it != queue->items.end();
- ++it) {
- const RasterTaskQueue::Item& item = *it;
- RasterTask* task = item.task;
- DCHECK(!task->HasCompleted());
-
- if (item.required_for_activation) {
- graph_.edges.push_back(TaskGraph::Edge(
- task, new_raster_required_for_activation_finished_task.get()));
- }
-
- InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
-
- graph_.edges.push_back(
- TaskGraph::Edge(task, new_raster_finished_task.get()));
- }
-
- InsertNodeForTask(&graph_,
- new_raster_required_for_activation_finished_task.get(),
- kRasterRequiredForActivationFinishedTaskPriority,
- queue->required_for_activation_count);
- InsertNodeForTask(&graph_,
- new_raster_finished_task.get(),
- kRasterFinishedTaskPriority,
- queue->items.size());
-
- ScheduleTasksOnOriginThread(this, &graph_);
- task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
-
- ScheduleRunTasksOnOriginThread();
-
- raster_finished_task_ = new_raster_finished_task;
- raster_required_for_activation_finished_task_ =
- new_raster_required_for_activation_finished_task;
-}
-
-void DirectRasterWorkerPool::CheckForCompletedTasks() {
- TRACE_EVENT0("cc", "DirectRasterWorkerPool::CheckForCompletedTasks");
-
- task_graph_runner_->CollectCompletedTasks(namespace_token_,
- &completed_tasks_);
- for (Task::Vector::const_iterator it = completed_tasks_.begin();
- it != completed_tasks_.end();
- ++it) {
- RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
-
- task->WillComplete();
- task->CompleteOnOriginThread(this);
- task->DidComplete();
-
- task->RunReplyOnOriginThread();
- }
- completed_tasks_.clear();
-}
-
-SkCanvas* DirectRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) {
- return resource_provider_->MapDirectRasterBuffer(task->resource()->id());
-}
-
-void DirectRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) {
- resource_provider_->UnmapDirectRasterBuffer(task->resource()->id());
-}
-
-void DirectRasterWorkerPool::OnRasterFinished() {
- TRACE_EVENT0("cc", "DirectRasterWorkerPool::OnRasterFinished");
-
- DCHECK(raster_tasks_pending_);
- raster_tasks_pending_ = false;
- client_->DidFinishRunningTasks();
-}
-
-void DirectRasterWorkerPool::OnRasterRequiredForActivationFinished() {
- TRACE_EVENT0("cc",
- "DirectRasterWorkerPool::OnRasterRequiredForActivationFinished");
-
- DCHECK(raster_tasks_required_for_activation_pending_);
- raster_tasks_required_for_activation_pending_ = false;
- client_->DidFinishRunningTasksRequiredForActivation();
-}
-
-void DirectRasterWorkerPool::ScheduleRunTasksOnOriginThread() {
- if (run_tasks_on_origin_thread_pending_)
- return;
-
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&DirectRasterWorkerPool::RunTasksOnOriginThread,
- weak_ptr_factory_.GetWeakPtr()));
- run_tasks_on_origin_thread_pending_ = true;
-}
-
-void DirectRasterWorkerPool::RunTasksOnOriginThread() {
- TRACE_EVENT0("cc", "DirectRasterWorkerPool::RunTasksOnOriginThread");
-
- DCHECK(run_tasks_on_origin_thread_pending_);
- run_tasks_on_origin_thread_pending_ = false;
-
- if (context_provider_) {
- DCHECK(context_provider_->ContextGL());
- // TODO(alokp): Use a trace macro to push/pop markers.
- // Using push/pop functions directly incurs cost to evaluate function
- // arguments even when tracing is disabled.
- context_provider_->ContextGL()->PushGroupMarkerEXT(
- 0, "DirectRasterWorkerPool::RunTasksOnOriginThread");
-
- GrContext* gr_context = context_provider_->GrContext();
- // TODO(alokp): Implement TestContextProvider::GrContext().
- if (gr_context)
- gr_context->resetContext();
- }
-
- task_graph_runner_->RunUntilIdle();
-
- if (context_provider_) {
- GrContext* gr_context = context_provider_->GrContext();
- // TODO(alokp): Implement TestContextProvider::GrContext().
- if (gr_context)
- gr_context->flush();
-
- context_provider_->ContextGL()->PopGroupMarkerEXT();
- }
-}
-
-} // namespace cc
diff --git a/chromium/cc/resources/direct_raster_worker_pool.h b/chromium/cc/resources/direct_raster_worker_pool.h
deleted file mode 100644
index 8194b4f2d6c..00000000000
--- a/chromium/cc/resources/direct_raster_worker_pool.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 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_DIRECT_RASTER_WORKER_POOL_H_
-#define CC_RESOURCES_DIRECT_RASTER_WORKER_POOL_H_
-
-#include "base/memory/weak_ptr.h"
-#include "cc/resources/raster_worker_pool.h"
-#include "cc/resources/rasterizer.h"
-
-namespace cc {
-class ContextProvider;
-class ResourceProvider;
-
-class CC_EXPORT DirectRasterWorkerPool : public RasterWorkerPool,
- public Rasterizer,
- public RasterizerTaskClient {
- public:
- virtual ~DirectRasterWorkerPool();
-
- static scoped_ptr<RasterWorkerPool> Create(
- base::SequencedTaskRunner* task_runner,
- ResourceProvider* resource_provider,
- ContextProvider* context_provider);
-
- // Overridden from RasterWorkerPool:
- virtual Rasterizer* AsRasterizer() OVERRIDE;
-
- // Overridden from Rasterizer:
- virtual void SetClient(RasterizerClient* client) OVERRIDE;
- virtual void Shutdown() OVERRIDE;
- virtual void ScheduleTasks(RasterTaskQueue* queue) OVERRIDE;
- virtual void CheckForCompletedTasks() OVERRIDE;
-
- // Overridden from RasterizerTaskClient:
- virtual SkCanvas* AcquireCanvasForRaster(RasterTask* task) OVERRIDE;
- virtual void ReleaseCanvasForRaster(RasterTask* task) OVERRIDE;
-
- private:
- DirectRasterWorkerPool(base::SequencedTaskRunner* task_runner,
- ResourceProvider* resource_provider,
- ContextProvider* context_provider);
-
- void OnRasterFinished();
- void OnRasterRequiredForActivationFinished();
- void ScheduleRunTasksOnOriginThread();
- void RunTasksOnOriginThread();
- void RunTaskOnOriginThread(RasterizerTask* task);
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- scoped_ptr<TaskGraphRunner> task_graph_runner_;
- const NamespaceToken namespace_token_;
- RasterizerClient* client_;
- ResourceProvider* resource_provider_;
- ContextProvider* context_provider_;
-
- bool run_tasks_on_origin_thread_pending_;
-
- bool raster_tasks_pending_;
- bool raster_tasks_required_for_activation_pending_;
-
- base::WeakPtrFactory<DirectRasterWorkerPool>
- raster_finished_weak_ptr_factory_;
-
- scoped_refptr<RasterizerTask> raster_finished_task_;
- scoped_refptr<RasterizerTask> raster_required_for_activation_finished_task_;
-
- // Task graph used when scheduling tasks and vector used to gather
- // completed tasks.
- TaskGraph graph_;
- Task::Vector completed_tasks_;
-
- base::WeakPtrFactory<DirectRasterWorkerPool> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectRasterWorkerPool);
-};
-
-} // namespace cc
-
-#endif // CC_RESOURCES_DIRECT_RASTER_WORKER_POOL_H_
diff --git a/chromium/cc/resources/eviction_tile_priority_queue.cc b/chromium/cc/resources/eviction_tile_priority_queue.cc
new file mode 100644
index 00000000000..9f05e816764
--- /dev/null
+++ b/chromium/cc/resources/eviction_tile_priority_queue.cc
@@ -0,0 +1,221 @@
+// Copyright 2014 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/eviction_tile_priority_queue.h"
+
+namespace cc {
+
+namespace {
+
+class EvictionOrderComparator {
+ public:
+ explicit EvictionOrderComparator(TreePriority tree_priority)
+ : tree_priority_(tree_priority) {}
+
+ bool operator()(
+ const EvictionTilePriorityQueue::PairedPictureLayerQueue* a,
+ const EvictionTilePriorityQueue::PairedPictureLayerQueue* b) const {
+ // Note that in this function, we have to return true if and only if
+ // b is strictly lower priority than a. Note that for the sake of
+ // completeness, empty queue is considered to have lowest priority.
+ if (a->IsEmpty() || b->IsEmpty())
+ return b->IsEmpty() < a->IsEmpty();
+
+ WhichTree a_tree = a->NextTileIteratorTree(tree_priority_);
+ const PictureLayerImpl::LayerEvictionTileIterator* a_iterator =
+ a_tree == ACTIVE_TREE ? &a->active_iterator : &a->pending_iterator;
+
+ WhichTree b_tree = b->NextTileIteratorTree(tree_priority_);
+ const PictureLayerImpl::LayerEvictionTileIterator* b_iterator =
+ b_tree == ACTIVE_TREE ? &b->active_iterator : &b->pending_iterator;
+
+ const Tile* a_tile = **a_iterator;
+ const Tile* b_tile = **b_iterator;
+
+ const TilePriority& a_priority =
+ a_tile->priority_for_tree_priority(tree_priority_);
+ const TilePriority& b_priority =
+ b_tile->priority_for_tree_priority(tree_priority_);
+ bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
+
+ // If the priority bin differs, b is lower priority if it has the higher
+ // priority bin.
+ if (a_priority.priority_bin != b_priority.priority_bin)
+ return b_priority.priority_bin > a_priority.priority_bin;
+
+ // Otherwise if the resolution differs, then the order will be determined by
+ // whether we prioritize low res or not.
+ // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile
+ // class but instead produced by the iterators.
+ if (b_priority.resolution != a_priority.resolution) {
+ // Non ideal resolution should be sorted higher than other resolutions.
+ if (a_priority.resolution == NON_IDEAL_RESOLUTION)
+ return false;
+
+ if (b_priority.resolution == NON_IDEAL_RESOLUTION)
+ return true;
+
+ if (prioritize_low_res)
+ return a_priority.resolution == LOW_RESOLUTION;
+ return a_priority.resolution == HIGH_RESOLUTION;
+ }
+
+ // Otherwise if the occlusion differs, b is lower priority if it is
+ // occluded.
+ bool a_is_occluded = a_tile->is_occluded_for_tree_priority(tree_priority_);
+ bool b_is_occluded = b_tile->is_occluded_for_tree_priority(tree_priority_);
+ if (a_is_occluded != b_is_occluded)
+ return b_is_occluded;
+
+ // b is lower priorty if it is farther from visible.
+ return b_priority.distance_to_visible > a_priority.distance_to_visible;
+ }
+
+ private:
+ TreePriority tree_priority_;
+};
+
+} // namespace
+
+EvictionTilePriorityQueue::EvictionTilePriorityQueue() {
+}
+
+EvictionTilePriorityQueue::~EvictionTilePriorityQueue() {
+}
+
+void EvictionTilePriorityQueue::Build(
+ const std::vector<PictureLayerImpl::Pair>& paired_layers,
+ TreePriority tree_priority) {
+ tree_priority_ = tree_priority;
+
+ for (std::vector<PictureLayerImpl::Pair>::const_iterator it =
+ paired_layers.begin();
+ it != paired_layers.end();
+ ++it) {
+ paired_queues_.push_back(
+ make_scoped_ptr(new PairedPictureLayerQueue(*it, tree_priority_)));
+ }
+
+ paired_queues_.make_heap(EvictionOrderComparator(tree_priority_));
+}
+
+void EvictionTilePriorityQueue::Reset() {
+ paired_queues_.clear();
+}
+
+bool EvictionTilePriorityQueue::IsEmpty() const {
+ return paired_queues_.empty() || paired_queues_.front()->IsEmpty();
+}
+
+Tile* EvictionTilePriorityQueue::Top() {
+ DCHECK(!IsEmpty());
+ return paired_queues_.front()->Top(tree_priority_);
+}
+
+void EvictionTilePriorityQueue::Pop() {
+ DCHECK(!IsEmpty());
+
+ paired_queues_.pop_heap(EvictionOrderComparator(tree_priority_));
+ PairedPictureLayerQueue* paired_queue = paired_queues_.back();
+ paired_queue->Pop(tree_priority_);
+ paired_queues_.push_heap(EvictionOrderComparator(tree_priority_));
+}
+
+EvictionTilePriorityQueue::PairedPictureLayerQueue::PairedPictureLayerQueue() {
+}
+
+EvictionTilePriorityQueue::PairedPictureLayerQueue::PairedPictureLayerQueue(
+ const PictureLayerImpl::Pair& layer_pair,
+ TreePriority tree_priority)
+ : active_iterator(
+ layer_pair.active
+ ? PictureLayerImpl::LayerEvictionTileIterator(layer_pair.active,
+ tree_priority)
+ : PictureLayerImpl::LayerEvictionTileIterator()),
+ pending_iterator(
+ layer_pair.pending
+ ? PictureLayerImpl::LayerEvictionTileIterator(layer_pair.pending,
+ tree_priority)
+ : PictureLayerImpl::LayerEvictionTileIterator()) {
+}
+
+EvictionTilePriorityQueue::PairedPictureLayerQueue::~PairedPictureLayerQueue() {
+}
+
+bool EvictionTilePriorityQueue::PairedPictureLayerQueue::IsEmpty() const {
+ return !active_iterator && !pending_iterator;
+}
+
+Tile* EvictionTilePriorityQueue::PairedPictureLayerQueue::Top(
+ TreePriority tree_priority) {
+ DCHECK(!IsEmpty());
+
+ WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ PictureLayerImpl::LayerEvictionTileIterator* next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+ DCHECK(*next_iterator);
+
+ Tile* tile = **next_iterator;
+ DCHECK(std::find(returned_shared_tiles.begin(),
+ returned_shared_tiles.end(),
+ tile) == returned_shared_tiles.end());
+ return tile;
+}
+
+void EvictionTilePriorityQueue::PairedPictureLayerQueue::Pop(
+ TreePriority tree_priority) {
+ DCHECK(!IsEmpty());
+
+ WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ PictureLayerImpl::LayerEvictionTileIterator* next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+ DCHECK(*next_iterator);
+ returned_shared_tiles.push_back(**next_iterator);
+ ++(*next_iterator);
+
+ if (IsEmpty())
+ return;
+
+ next_tree = NextTileIteratorTree(tree_priority);
+ next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+ while (std::find(returned_shared_tiles.begin(),
+ returned_shared_tiles.end(),
+ **next_iterator) != returned_shared_tiles.end()) {
+ ++(*next_iterator);
+ if (IsEmpty())
+ break;
+ next_tree = NextTileIteratorTree(tree_priority);
+ next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+ }
+}
+
+WhichTree
+EvictionTilePriorityQueue::PairedPictureLayerQueue::NextTileIteratorTree(
+ TreePriority tree_priority) const {
+ DCHECK(!IsEmpty());
+
+ // If we only have one iterator with tiles, return it.
+ if (!active_iterator)
+ return PENDING_TREE;
+ if (!pending_iterator)
+ return ACTIVE_TREE;
+
+ const Tile* active_tile = *active_iterator;
+ const Tile* pending_tile = *pending_iterator;
+ if (active_tile == pending_tile)
+ return ACTIVE_TREE;
+
+ const TilePriority& active_priority =
+ active_tile->priority_for_tree_priority(tree_priority);
+ const TilePriority& pending_priority =
+ pending_tile->priority_for_tree_priority(tree_priority);
+
+ if (pending_priority.IsHigherPriorityThan(active_priority))
+ return ACTIVE_TREE;
+ return PENDING_TREE;
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/eviction_tile_priority_queue.h b/chromium/cc/resources/eviction_tile_priority_queue.h
new file mode 100644
index 00000000000..e91f0d2a682
--- /dev/null
+++ b/chromium/cc/resources/eviction_tile_priority_queue.h
@@ -0,0 +1,61 @@
+// Copyright 2014 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_EVICTION_TILE_PRIORITY_QUEUE_H_
+#define CC_RESOURCES_EVICTION_TILE_PRIORITY_QUEUE_H_
+
+#include <utility>
+#include <vector>
+
+#include "cc/base/cc_export.h"
+#include "cc/layers/picture_layer_impl.h"
+#include "cc/resources/tile_priority.h"
+
+namespace cc {
+
+class CC_EXPORT EvictionTilePriorityQueue {
+ public:
+ struct PairedPictureLayerQueue {
+ PairedPictureLayerQueue();
+ PairedPictureLayerQueue(const PictureLayerImpl::Pair& layer_pair,
+ TreePriority tree_priority);
+ ~PairedPictureLayerQueue();
+
+ bool IsEmpty() const;
+ Tile* Top(TreePriority tree_priority);
+ void Pop(TreePriority tree_priority);
+
+ WhichTree NextTileIteratorTree(TreePriority tree_priority) const;
+
+ PictureLayerImpl::LayerEvictionTileIterator active_iterator;
+ PictureLayerImpl::LayerEvictionTileIterator pending_iterator;
+
+ // TODO(vmpstr): Investigate removing this.
+ std::vector<Tile*> returned_shared_tiles;
+ };
+
+ EvictionTilePriorityQueue();
+ ~EvictionTilePriorityQueue();
+
+ void Build(const std::vector<PictureLayerImpl::Pair>& paired_layers,
+ TreePriority tree_priority);
+ void Reset();
+
+ bool IsEmpty() const;
+ Tile* Top();
+ void Pop();
+
+ private:
+ // TODO(vmpstr): This is potentially unnecessary if it becomes the case that
+ // PairedPictureLayerQueue is fast enough to copy. In that case, we can use
+ // objects directly (ie std::vector<PairedPictureLayerQueue>).
+ ScopedPtrVector<PairedPictureLayerQueue> paired_queues_;
+ TreePriority tree_priority_;
+
+ DISALLOW_COPY_AND_ASSIGN(EvictionTilePriorityQueue);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_EVICTION_TILE_PRIORITY_QUEUE_H_
diff --git a/chromium/cc/resources/gpu_raster_worker_pool.cc b/chromium/cc/resources/gpu_raster_worker_pool.cc
new file mode 100644
index 00000000000..04724f120f0
--- /dev/null
+++ b/chromium/cc/resources/gpu_raster_worker_pool.cc
@@ -0,0 +1,252 @@
+// Copyright 2014 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/gpu_raster_worker_pool.h"
+
+#include <algorithm>
+
+#include "base/debug/trace_event.h"
+#include "cc/output/context_provider.h"
+#include "cc/resources/raster_buffer.h"
+#include "cc/resources/raster_source.h"
+#include "cc/resources/resource.h"
+#include "cc/resources/resource_provider.h"
+#include "cc/resources/scoped_gpu_raster.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/skia/include/core/SkMultiPictureDraw.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+
+namespace cc {
+namespace {
+
+class RasterBufferImpl : public RasterBuffer {
+ public:
+ RasterBufferImpl(ResourceProvider* resource_provider,
+ const Resource* resource,
+ SkMultiPictureDraw* multi_picture_draw,
+ bool use_distance_field_text)
+ : lock_(resource_provider, resource->id()),
+ resource_(resource),
+ multi_picture_draw_(multi_picture_draw),
+ use_distance_field_text_(use_distance_field_text) {}
+
+ // Overridden from RasterBuffer:
+ void Playback(const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) override {
+ // Turn on distance fields for layers that have ever animated.
+ bool use_distance_field_text =
+ use_distance_field_text_ ||
+ raster_source->SuitableForDistanceFieldText();
+ SkSurface* sk_surface = lock_.GetSkSurface(use_distance_field_text);
+
+ if (!sk_surface)
+ return;
+
+ SkPictureRecorder recorder;
+ gfx::Size size = resource_->size();
+ skia::RefPtr<SkCanvas> canvas =
+ skia::SharePtr(recorder.beginRecording(size.width(), size.height()));
+
+ canvas->save();
+ raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
+ canvas->restore();
+
+ // Add the canvas and recorded picture to |multi_picture_draw_|.
+ skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
+ multi_picture_draw_->add(sk_surface->getCanvas(), picture.get());
+ }
+
+ private:
+ ResourceProvider::ScopedWriteLockGr lock_;
+ const Resource* resource_;
+ SkMultiPictureDraw* multi_picture_draw_;
+ bool use_distance_field_text_;
+
+ DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+};
+
+} // namespace
+
+// static
+scoped_ptr<RasterWorkerPool> GpuRasterWorkerPool::Create(
+ base::SequencedTaskRunner* task_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ bool use_distance_field_text) {
+ return make_scoped_ptr<RasterWorkerPool>(
+ new GpuRasterWorkerPool(task_runner,
+ context_provider,
+ resource_provider,
+ use_distance_field_text));
+}
+
+GpuRasterWorkerPool::GpuRasterWorkerPool(base::SequencedTaskRunner* task_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ bool use_distance_field_text)
+ : task_runner_(task_runner),
+ task_graph_runner_(new TaskGraphRunner),
+ namespace_token_(task_graph_runner_->GetNamespaceToken()),
+ context_provider_(context_provider),
+ resource_provider_(resource_provider),
+ run_tasks_on_origin_thread_pending_(false),
+ use_distance_field_text_(use_distance_field_text),
+ raster_finished_weak_ptr_factory_(this),
+ weak_ptr_factory_(this) {
+ DCHECK(context_provider_);
+}
+
+GpuRasterWorkerPool::~GpuRasterWorkerPool() {
+ DCHECK_EQ(0u, completed_tasks_.size());
+}
+
+Rasterizer* GpuRasterWorkerPool::AsRasterizer() {
+ return this;
+}
+
+void GpuRasterWorkerPool::SetClient(RasterizerClient* client) {
+ client_ = client;
+}
+
+void GpuRasterWorkerPool::Shutdown() {
+ TRACE_EVENT0("cc", "GpuRasterWorkerPool::Shutdown");
+
+ TaskGraph empty;
+ task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
+ task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
+}
+
+void GpuRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
+ TRACE_EVENT0("cc", "GpuRasterWorkerPool::ScheduleTasks");
+
+ // Mark all task sets as pending.
+ raster_pending_.set();
+
+ unsigned priority = kRasterTaskPriorityBase;
+
+ graph_.Reset();
+
+ // Cancel existing OnRasterFinished callbacks.
+ raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
+
+ scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
+
+ size_t task_count[kNumberOfTaskSets] = {0};
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
+ task_runner_.get(),
+ base::Bind(&GpuRasterWorkerPool::OnRasterFinished,
+ raster_finished_weak_ptr_factory_.GetWeakPtr(),
+ task_set));
+ }
+
+ for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
+ it != queue->items.end();
+ ++it) {
+ const RasterTaskQueue::Item& item = *it;
+ RasterTask* task = item.task;
+ DCHECK(!task->HasCompleted());
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (!item.task_sets[task_set])
+ continue;
+
+ ++task_count[task_set];
+
+ graph_.edges.push_back(
+ TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get()));
+ }
+
+ InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
+ }
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ InsertNodeForTask(&graph_,
+ new_raster_finished_tasks[task_set].get(),
+ kRasterFinishedTaskPriority,
+ task_count[task_set]);
+ }
+
+ ScheduleTasksOnOriginThread(this, &graph_);
+ task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
+
+ ScheduleRunTasksOnOriginThread();
+
+ std::copy(new_raster_finished_tasks,
+ new_raster_finished_tasks + kNumberOfTaskSets,
+ raster_finished_tasks_);
+}
+
+void GpuRasterWorkerPool::CheckForCompletedTasks() {
+ TRACE_EVENT0("cc", "GpuRasterWorkerPool::CheckForCompletedTasks");
+
+ task_graph_runner_->CollectCompletedTasks(namespace_token_,
+ &completed_tasks_);
+ for (Task::Vector::const_iterator it = completed_tasks_.begin();
+ it != completed_tasks_.end();
+ ++it) {
+ RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
+
+ task->WillComplete();
+ task->CompleteOnOriginThread(this);
+ task->DidComplete();
+
+ task->RunReplyOnOriginThread();
+ }
+ completed_tasks_.clear();
+}
+
+scoped_ptr<RasterBuffer> GpuRasterWorkerPool::AcquireBufferForRaster(
+ const Resource* resource) {
+ return make_scoped_ptr<RasterBuffer>(
+ new RasterBufferImpl(resource_provider_,
+ resource,
+ &multi_picture_draw_,
+ use_distance_field_text_));
+}
+
+void GpuRasterWorkerPool::ReleaseBufferForRaster(
+ scoped_ptr<RasterBuffer> buffer) {
+ // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
+}
+
+void GpuRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
+ TRACE_EVENT1(
+ "cc", "GpuRasterWorkerPool::OnRasterFinished", "task_set", task_set);
+
+ DCHECK(raster_pending_[task_set]);
+ raster_pending_[task_set] = false;
+ client_->DidFinishRunningTasks(task_set);
+}
+
+void GpuRasterWorkerPool::ScheduleRunTasksOnOriginThread() {
+ if (run_tasks_on_origin_thread_pending_)
+ return;
+
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&GpuRasterWorkerPool::RunTasksOnOriginThread,
+ weak_ptr_factory_.GetWeakPtr()));
+ run_tasks_on_origin_thread_pending_ = true;
+}
+
+void GpuRasterWorkerPool::RunTasksOnOriginThread() {
+ TRACE_EVENT0("cc", "GpuRasterWorkerPool::RunTasksOnOriginThread");
+
+ DCHECK(run_tasks_on_origin_thread_pending_);
+ run_tasks_on_origin_thread_pending_ = false;
+
+ ScopedGpuRaster gpu_raster(context_provider_);
+ task_graph_runner_->RunUntilIdle();
+
+ // Draw each all of the pictures that were collected. This will also clear
+ // the pictures and canvases added to |multi_picture_draw_|
+ multi_picture_draw_.draw();
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/gpu_raster_worker_pool.h b/chromium/cc/resources/gpu_raster_worker_pool.h
new file mode 100644
index 00000000000..c5ff13f1361
--- /dev/null
+++ b/chromium/cc/resources/gpu_raster_worker_pool.h
@@ -0,0 +1,83 @@
+// Copyright 2014 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_GPU_RASTER_WORKER_POOL_H_
+#define CC_RESOURCES_GPU_RASTER_WORKER_POOL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cc/resources/raster_worker_pool.h"
+#include "cc/resources/rasterizer.h"
+#include "third_party/skia/include/core/SkMultiPictureDraw.h"
+
+namespace cc {
+class ContextProvider;
+class ResourceProvider;
+
+class CC_EXPORT GpuRasterWorkerPool : public RasterWorkerPool,
+ public Rasterizer,
+ public RasterizerTaskClient {
+ public:
+ ~GpuRasterWorkerPool() override;
+
+ static scoped_ptr<RasterWorkerPool> Create(
+ base::SequencedTaskRunner* task_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ bool use_distance_field_text);
+
+ // Overridden from RasterWorkerPool:
+ Rasterizer* AsRasterizer() override;
+
+ // Overridden from Rasterizer:
+ void SetClient(RasterizerClient* client) override;
+ void Shutdown() override;
+ void ScheduleTasks(RasterTaskQueue* queue) override;
+ void CheckForCompletedTasks() override;
+
+ // Overridden from RasterizerTaskClient:
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) override;
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
+
+ private:
+ GpuRasterWorkerPool(base::SequencedTaskRunner* task_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ bool use_distance_field_text);
+
+ void OnRasterFinished(TaskSet task_set);
+ void ScheduleRunTasksOnOriginThread();
+ void RunTasksOnOriginThread();
+ void RunTaskOnOriginThread(RasterizerTask* task);
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ scoped_ptr<TaskGraphRunner> task_graph_runner_;
+ const NamespaceToken namespace_token_;
+ RasterizerClient* client_;
+ ContextProvider* context_provider_;
+ ResourceProvider* resource_provider_;
+ SkMultiPictureDraw multi_picture_draw_;
+
+ bool run_tasks_on_origin_thread_pending_;
+ bool use_distance_field_text_;
+
+ TaskSetCollection raster_pending_;
+
+ scoped_refptr<RasterizerTask> raster_finished_tasks_[kNumberOfTaskSets];
+
+ // Task graph used when scheduling tasks and vector used to gather
+ // completed tasks.
+ TaskGraph graph_;
+ Task::Vector completed_tasks_;
+
+ base::WeakPtrFactory<GpuRasterWorkerPool> raster_finished_weak_ptr_factory_;
+
+ base::WeakPtrFactory<GpuRasterWorkerPool> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuRasterWorkerPool);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_GPU_RASTER_WORKER_POOL_H_
diff --git a/chromium/cc/resources/image_copy_raster_worker_pool.cc b/chromium/cc/resources/image_copy_raster_worker_pool.cc
deleted file mode 100644
index 0d4f7441e52..00000000000
--- a/chromium/cc/resources/image_copy_raster_worker_pool.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2014 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_copy_raster_worker_pool.h"
-
-#include <algorithm>
-
-#include "base/debug/trace_event.h"
-#include "cc/debug/traced_value.h"
-#include "cc/resources/resource_pool.h"
-#include "cc/resources/scoped_resource.h"
-
-namespace cc {
-
-// static
-scoped_ptr<RasterWorkerPool> ImageCopyRasterWorkerPool::Create(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider,
- ResourcePool* resource_pool) {
- return make_scoped_ptr<RasterWorkerPool>(new ImageCopyRasterWorkerPool(
- task_runner, task_graph_runner, resource_provider, resource_pool));
-}
-
-ImageCopyRasterWorkerPool::ImageCopyRasterWorkerPool(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider,
- ResourcePool* resource_pool)
- : task_runner_(task_runner),
- task_graph_runner_(task_graph_runner),
- namespace_token_(task_graph_runner->GetNamespaceToken()),
- resource_provider_(resource_provider),
- resource_pool_(resource_pool),
- has_performed_copy_since_last_flush_(false),
- raster_tasks_pending_(false),
- raster_tasks_required_for_activation_pending_(false),
- raster_finished_weak_ptr_factory_(this) {}
-
-ImageCopyRasterWorkerPool::~ImageCopyRasterWorkerPool() {
- DCHECK_EQ(0u, raster_task_states_.size());
-}
-
-Rasterizer* ImageCopyRasterWorkerPool::AsRasterizer() { return this; }
-
-void ImageCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
- client_ = client;
-}
-
-void ImageCopyRasterWorkerPool::Shutdown() {
- TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::Shutdown");
-
- TaskGraph empty;
- task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
- task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-}
-
-void ImageCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
- TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::ScheduleTasks");
-
- DCHECK_EQ(queue->required_for_activation_count,
- static_cast<size_t>(
- std::count_if(queue->items.begin(),
- queue->items.end(),
- RasterTaskQueue::Item::IsRequiredForActivation)));
-
- if (!raster_tasks_pending_)
- TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
-
- raster_tasks_pending_ = true;
- raster_tasks_required_for_activation_pending_ = true;
-
- unsigned priority = kRasterTaskPriorityBase;
-
- graph_.Reset();
-
- // Cancel existing OnRasterFinished callbacks.
- raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
-
- scoped_refptr<RasterizerTask>
- new_raster_required_for_activation_finished_task(
- CreateRasterRequiredForActivationFinishedTask(
- queue->required_for_activation_count,
- task_runner_.get(),
- base::Bind(&ImageCopyRasterWorkerPool::
- OnRasterRequiredForActivationFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr())));
- scoped_refptr<RasterizerTask> new_raster_finished_task(
- CreateRasterFinishedTask(
- task_runner_.get(),
- base::Bind(&ImageCopyRasterWorkerPool::OnRasterFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr())));
-
- resource_pool_->CheckBusyResources();
-
- for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
- it != queue->items.end();
- ++it) {
- const RasterTaskQueue::Item& item = *it;
- RasterTask* task = item.task;
- DCHECK(!task->HasCompleted());
-
- if (item.required_for_activation) {
- graph_.edges.push_back(TaskGraph::Edge(
- task, new_raster_required_for_activation_finished_task.get()));
- }
-
- InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
-
- graph_.edges.push_back(
- TaskGraph::Edge(task, new_raster_finished_task.get()));
- }
-
- InsertNodeForTask(&graph_,
- new_raster_required_for_activation_finished_task.get(),
- kRasterRequiredForActivationFinishedTaskPriority,
- queue->required_for_activation_count);
- InsertNodeForTask(&graph_,
- new_raster_finished_task.get(),
- kRasterFinishedTaskPriority,
- queue->items.size());
-
- ScheduleTasksOnOriginThread(this, &graph_);
- task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
-
- raster_finished_task_ = new_raster_finished_task;
- raster_required_for_activation_finished_task_ =
- new_raster_required_for_activation_finished_task;
-
- resource_pool_->ReduceResourceUsage();
-
- TRACE_EVENT_ASYNC_STEP_INTO1(
- "cc",
- "ScheduledTasks",
- this,
- "rasterizing",
- "state",
- TracedValue::FromValue(StateAsValue().release()));
-}
-
-void ImageCopyRasterWorkerPool::CheckForCompletedTasks() {
- TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::CheckForCompletedTasks");
-
- task_graph_runner_->CollectCompletedTasks(namespace_token_,
- &completed_tasks_);
- for (Task::Vector::const_iterator it = completed_tasks_.begin();
- it != completed_tasks_.end();
- ++it) {
- RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
-
- task->WillComplete();
- task->CompleteOnOriginThread(this);
- task->DidComplete();
-
- task->RunReplyOnOriginThread();
- }
- completed_tasks_.clear();
-
- FlushCopies();
-}
-
-SkCanvas* ImageCopyRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) {
- DCHECK_EQ(task->resource()->format(), resource_pool_->resource_format());
- scoped_ptr<ScopedResource> resource(
- resource_pool_->AcquireResource(task->resource()->size()));
- SkCanvas* canvas = resource_provider_->MapImageRasterBuffer(resource->id());
- DCHECK(std::find_if(raster_task_states_.begin(),
- raster_task_states_.end(),
- RasterTaskState::TaskComparator(task)) ==
- raster_task_states_.end());
- raster_task_states_.push_back(RasterTaskState(task, resource.release()));
- return canvas;
-}
-
-void ImageCopyRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) {
- RasterTaskState::Vector::iterator it =
- std::find_if(raster_task_states_.begin(),
- raster_task_states_.end(),
- RasterTaskState::TaskComparator(task));
- DCHECK(it != raster_task_states_.end());
- scoped_ptr<ScopedResource> resource(it->resource);
- std::swap(*it, raster_task_states_.back());
- raster_task_states_.pop_back();
-
- bool content_has_changed =
- resource_provider_->UnmapImageRasterBuffer(resource->id());
-
- // |content_has_changed| can be false as result of task being canceled or
- // task implementation deciding not to modify bitmap (ie. analysis of raster
- // commands detected content as a solid color).
- if (content_has_changed) {
- resource_provider_->CopyResource(resource->id(), task->resource()->id());
- has_performed_copy_since_last_flush_ = true;
- }
-
- resource_pool_->ReleaseResource(resource.Pass());
-}
-
-void ImageCopyRasterWorkerPool::OnRasterFinished() {
- TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::OnRasterFinished");
-
- DCHECK(raster_tasks_pending_);
- raster_tasks_pending_ = false;
- TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
- client_->DidFinishRunningTasks();
-}
-
-void ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished() {
- TRACE_EVENT0(
- "cc", "ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished");
-
- DCHECK(raster_tasks_required_for_activation_pending_);
- raster_tasks_required_for_activation_pending_ = false;
- TRACE_EVENT_ASYNC_STEP_INTO1(
- "cc",
- "ScheduledTasks",
- this,
- "rasterizing",
- "state",
- TracedValue::FromValue(StateAsValue().release()));
- client_->DidFinishRunningTasksRequiredForActivation();
-}
-
-void ImageCopyRasterWorkerPool::FlushCopies() {
- if (!has_performed_copy_since_last_flush_)
- return;
-
- resource_provider_->ShallowFlushIfSupported();
- has_performed_copy_since_last_flush_ = false;
-}
-
-scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StateAsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
-
- state->SetInteger("pending_count", raster_task_states_.size());
- state->SetBoolean("tasks_required_for_activation_pending",
- raster_tasks_required_for_activation_pending_);
- state->Set("staging_state", StagingStateAsValue().release());
-
- return state.PassAs<base::Value>();
-}
-scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StagingStateAsValue() const {
- scoped_ptr<base::DictionaryValue> staging_state(new base::DictionaryValue);
-
- staging_state->SetInteger("staging_resource_count",
- resource_pool_->total_resource_count());
- staging_state->SetInteger("bytes_used_for_staging_resources",
- resource_pool_->total_memory_usage_bytes());
- staging_state->SetInteger("pending_copy_count",
- resource_pool_->total_resource_count() -
- resource_pool_->acquired_resource_count());
- staging_state->SetInteger("bytes_pending_copy",
- resource_pool_->total_memory_usage_bytes() -
- resource_pool_->acquired_memory_usage_bytes());
-
- return staging_state.PassAs<base::Value>();
-}
-
-} // namespace cc
diff --git a/chromium/cc/resources/image_copy_raster_worker_pool.h b/chromium/cc/resources/image_copy_raster_worker_pool.h
deleted file mode 100644
index cb243daca38..00000000000
--- a/chromium/cc/resources/image_copy_raster_worker_pool.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 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_COPY_RASTER_WORKER_POOL_H_
-#define CC_RESOURCES_IMAGE_COPY_RASTER_WORKER_POOL_H_
-
-#include <vector>
-
-#include "base/memory/weak_ptr.h"
-#include "base/values.h"
-#include "cc/resources/raster_worker_pool.h"
-#include "cc/resources/rasterizer.h"
-
-namespace cc {
-class ResourcePool;
-class ResourceProvider;
-class ScopedResource;
-
-class CC_EXPORT ImageCopyRasterWorkerPool : public RasterWorkerPool,
- public Rasterizer,
- public RasterizerTaskClient {
- public:
- virtual ~ImageCopyRasterWorkerPool();
-
- static scoped_ptr<RasterWorkerPool> Create(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider,
- ResourcePool* resource_pool);
-
- // Overridden from RasterWorkerPool:
- virtual Rasterizer* AsRasterizer() OVERRIDE;
-
- // Overridden from Rasterizer:
- virtual void SetClient(RasterizerClient* client) OVERRIDE;
- virtual void Shutdown() OVERRIDE;
- virtual void ScheduleTasks(RasterTaskQueue* queue) OVERRIDE;
- virtual void CheckForCompletedTasks() OVERRIDE;
-
- // Overridden from RasterizerTaskClient:
- virtual SkCanvas* AcquireCanvasForRaster(RasterTask* task) OVERRIDE;
- virtual void ReleaseCanvasForRaster(RasterTask* task) OVERRIDE;
-
- protected:
- ImageCopyRasterWorkerPool(base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider,
- ResourcePool* resource_pool);
-
- private:
- struct RasterTaskState {
- class TaskComparator {
- public:
- explicit TaskComparator(const RasterTask* task) : task_(task) {}
-
- bool operator()(const RasterTaskState& state) const {
- return state.task == task_;
- }
-
- private:
- const RasterTask* task_;
- };
-
- typedef std::vector<RasterTaskState> Vector;
-
- RasterTaskState(const RasterTask* task, ScopedResource* resource)
- : task(task), resource(resource) {}
-
- const RasterTask* task;
- ScopedResource* resource;
- };
-
- void OnRasterFinished();
- void OnRasterRequiredForActivationFinished();
- void FlushCopies();
- scoped_ptr<base::Value> StateAsValue() const;
- scoped_ptr<base::Value> StagingStateAsValue() const;
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- TaskGraphRunner* task_graph_runner_;
- const NamespaceToken namespace_token_;
- RasterizerClient* client_;
- ResourceProvider* resource_provider_;
- ResourcePool* resource_pool_;
-
- RasterTaskState::Vector raster_task_states_;
-
- bool has_performed_copy_since_last_flush_;
-
- bool raster_tasks_pending_;
- bool raster_tasks_required_for_activation_pending_;
-
- base::WeakPtrFactory<ImageCopyRasterWorkerPool>
- raster_finished_weak_ptr_factory_;
-
- scoped_refptr<RasterizerTask> raster_finished_task_;
- scoped_refptr<RasterizerTask> raster_required_for_activation_finished_task_;
-
- // Task graph used when scheduling tasks and vector used to gather
- // completed tasks.
- TaskGraph graph_;
- Task::Vector completed_tasks_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageCopyRasterWorkerPool);
-};
-
-} // namespace cc
-
-#endif // CC_RESOURCES_IMAGE_COPY_RASTER_WORKER_POOL_H_
diff --git a/chromium/cc/resources/image_layer_updater.cc b/chromium/cc/resources/image_layer_updater.cc
index d5d62ed5e97..0538d96ea36 100644
--- a/chromium/cc/resources/image_layer_updater.cc
+++ b/chromium/cc/resources/image_layer_updater.cc
@@ -29,7 +29,7 @@ scoped_refptr<ImageLayerUpdater> ImageLayerUpdater::Create() {
scoped_ptr<LayerUpdater::Resource> ImageLayerUpdater::CreateResource(
PrioritizedResourceManager* manager) {
- return scoped_ptr<LayerUpdater::Resource>(
+ return make_scoped_ptr(
new Resource(this, PrioritizedResource::Create(manager)));
}
diff --git a/chromium/cc/resources/image_layer_updater.h b/chromium/cc/resources/image_layer_updater.h
index b2235b18031..81225ba7b5e 100644
--- a/chromium/cc/resources/image_layer_updater.h
+++ b/chromium/cc/resources/image_layer_updater.h
@@ -19,12 +19,12 @@ class CC_EXPORT ImageLayerUpdater : public LayerUpdater {
public:
Resource(ImageLayerUpdater* updater,
scoped_ptr<PrioritizedResource> texture);
- virtual ~Resource();
+ ~Resource() override;
- virtual void Update(ResourceUpdateQueue* queue,
- const gfx::Rect& source_rect,
- const gfx::Vector2d& dest_offset,
- bool partial_update) OVERRIDE;
+ void Update(ResourceUpdateQueue* queue,
+ const gfx::Rect& source_rect,
+ const gfx::Vector2d& dest_offset,
+ bool partial_update) override;
private:
ImageLayerUpdater* updater_;
@@ -34,8 +34,8 @@ class CC_EXPORT ImageLayerUpdater : public LayerUpdater {
static scoped_refptr<ImageLayerUpdater> Create();
- virtual scoped_ptr<LayerUpdater::Resource> CreateResource(
- PrioritizedResourceManager*) OVERRIDE;
+ scoped_ptr<LayerUpdater::Resource> CreateResource(
+ PrioritizedResourceManager*) override;
void UpdateTexture(ResourceUpdateQueue* queue,
PrioritizedResource* texture,
@@ -48,7 +48,7 @@ class CC_EXPORT ImageLayerUpdater : public LayerUpdater {
private:
ImageLayerUpdater() {}
- virtual ~ImageLayerUpdater() {}
+ ~ImageLayerUpdater() override {}
SkBitmap bitmap_;
diff --git a/chromium/cc/resources/image_raster_worker_pool.cc b/chromium/cc/resources/image_raster_worker_pool.cc
deleted file mode 100644
index 007c1ed83f3..00000000000
--- a/chromium/cc/resources/image_raster_worker_pool.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// 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/debug/traced_value.h"
-#include "cc/resources/resource.h"
-
-namespace cc {
-
-// static
-scoped_ptr<RasterWorkerPool> ImageRasterWorkerPool::Create(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider) {
- return make_scoped_ptr<RasterWorkerPool>(new ImageRasterWorkerPool(
- task_runner, task_graph_runner, resource_provider));
-}
-
-ImageRasterWorkerPool::ImageRasterWorkerPool(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider)
- : task_runner_(task_runner),
- task_graph_runner_(task_graph_runner),
- namespace_token_(task_graph_runner->GetNamespaceToken()),
- resource_provider_(resource_provider),
- raster_tasks_pending_(false),
- raster_tasks_required_for_activation_pending_(false),
- raster_finished_weak_ptr_factory_(this) {}
-
-ImageRasterWorkerPool::~ImageRasterWorkerPool() {}
-
-Rasterizer* ImageRasterWorkerPool::AsRasterizer() { return this; }
-
-void ImageRasterWorkerPool::SetClient(RasterizerClient* client) {
- client_ = client;
-}
-
-void ImageRasterWorkerPool::Shutdown() {
- TRACE_EVENT0("cc", "ImageRasterWorkerPool::Shutdown");
-
- TaskGraph empty;
- task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
- task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-}
-
-void ImageRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
- TRACE_EVENT0("cc", "ImageRasterWorkerPool::ScheduleTasks");
-
- DCHECK_EQ(queue->required_for_activation_count,
- static_cast<size_t>(
- std::count_if(queue->items.begin(),
- queue->items.end(),
- RasterTaskQueue::Item::IsRequiredForActivation)));
-
- if (!raster_tasks_pending_)
- TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
-
- raster_tasks_pending_ = true;
- raster_tasks_required_for_activation_pending_ = true;
-
- unsigned priority = kRasterTaskPriorityBase;
-
- graph_.Reset();
-
- // Cancel existing OnRasterFinished callbacks.
- raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
-
- scoped_refptr<RasterizerTask>
- new_raster_required_for_activation_finished_task(
- CreateRasterRequiredForActivationFinishedTask(
- queue->required_for_activation_count,
- task_runner_.get(),
- base::Bind(
- &ImageRasterWorkerPool::OnRasterRequiredForActivationFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr())));
- scoped_refptr<RasterizerTask> new_raster_finished_task(
- CreateRasterFinishedTask(
- task_runner_.get(),
- base::Bind(&ImageRasterWorkerPool::OnRasterFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr())));
-
- for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
- it != queue->items.end();
- ++it) {
- const RasterTaskQueue::Item& item = *it;
- RasterTask* task = item.task;
- DCHECK(!task->HasCompleted());
-
- if (item.required_for_activation) {
- graph_.edges.push_back(TaskGraph::Edge(
- task, new_raster_required_for_activation_finished_task.get()));
- }
-
- InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
-
- graph_.edges.push_back(
- TaskGraph::Edge(task, new_raster_finished_task.get()));
- }
-
- InsertNodeForTask(&graph_,
- new_raster_required_for_activation_finished_task.get(),
- kRasterRequiredForActivationFinishedTaskPriority,
- queue->required_for_activation_count);
- InsertNodeForTask(&graph_,
- new_raster_finished_task.get(),
- kRasterFinishedTaskPriority,
- queue->items.size());
-
- ScheduleTasksOnOriginThread(this, &graph_);
- task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
-
- raster_finished_task_ = new_raster_finished_task;
- raster_required_for_activation_finished_task_ =
- new_raster_required_for_activation_finished_task;
-
- TRACE_EVENT_ASYNC_STEP_INTO1(
- "cc",
- "ScheduledTasks",
- this,
- "rasterizing",
- "state",
- TracedValue::FromValue(StateAsValue().release()));
-}
-
-void ImageRasterWorkerPool::CheckForCompletedTasks() {
- TRACE_EVENT0("cc", "ImageRasterWorkerPool::CheckForCompletedTasks");
-
- task_graph_runner_->CollectCompletedTasks(namespace_token_,
- &completed_tasks_);
- for (Task::Vector::const_iterator it = completed_tasks_.begin();
- it != completed_tasks_.end();
- ++it) {
- RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
-
- task->WillComplete();
- task->CompleteOnOriginThread(this);
- task->DidComplete();
-
- task->RunReplyOnOriginThread();
- }
- completed_tasks_.clear();
-}
-
-SkCanvas* ImageRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) {
- return resource_provider_->MapImageRasterBuffer(task->resource()->id());
-}
-
-void ImageRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) {
- resource_provider_->UnmapImageRasterBuffer(task->resource()->id());
-
- // Map/UnmapImageRasterBuffer provides direct access to the memory used by the
- // GPU. Read lock fences are required to ensure that we're not trying to map a
- // resource that is currently in-use by the GPU.
- resource_provider_->EnableReadLockFences(task->resource()->id(), true);
-}
-
-void ImageRasterWorkerPool::OnRasterFinished() {
- TRACE_EVENT0("cc", "ImageRasterWorkerPool::OnRasterFinished");
-
- DCHECK(raster_tasks_pending_);
- raster_tasks_pending_ = false;
- TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
- client_->DidFinishRunningTasks();
-}
-
-void ImageRasterWorkerPool::OnRasterRequiredForActivationFinished() {
- TRACE_EVENT0("cc",
- "ImageRasterWorkerPool::OnRasterRequiredForActivationFinished");
-
- DCHECK(raster_tasks_required_for_activation_pending_);
- raster_tasks_required_for_activation_pending_ = false;
- TRACE_EVENT_ASYNC_STEP_INTO1(
- "cc",
- "ScheduledTasks",
- this,
- "rasterizing",
- "state",
- TracedValue::FromValue(StateAsValue().release()));
- client_->DidFinishRunningTasksRequiredForActivation();
-}
-
-scoped_ptr<base::Value> ImageRasterWorkerPool::StateAsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
-
- state->SetBoolean("tasks_required_for_activation_pending",
- raster_tasks_required_for_activation_pending_);
- return state.PassAs<base::Value>();
-}
-
-} // namespace cc
diff --git a/chromium/cc/resources/image_raster_worker_pool.h b/chromium/cc/resources/image_raster_worker_pool.h
deleted file mode 100644
index 2e11a220f41..00000000000
--- a/chromium/cc/resources/image_raster_worker_pool.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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 "base/memory/weak_ptr.h"
-#include "base/values.h"
-#include "cc/resources/raster_worker_pool.h"
-#include "cc/resources/rasterizer.h"
-
-namespace cc {
-class ResourceProvider;
-
-class CC_EXPORT ImageRasterWorkerPool : public RasterWorkerPool,
- public Rasterizer,
- public RasterizerTaskClient {
- public:
- virtual ~ImageRasterWorkerPool();
-
- static scoped_ptr<RasterWorkerPool> Create(
- base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider);
-
- // Overridden from RasterWorkerPool:
- virtual Rasterizer* AsRasterizer() OVERRIDE;
-
- // Overridden from Rasterizer:
- virtual void SetClient(RasterizerClient* client) OVERRIDE;
- virtual void Shutdown() OVERRIDE;
- virtual void ScheduleTasks(RasterTaskQueue* queue) OVERRIDE;
- virtual void CheckForCompletedTasks() OVERRIDE;
-
- // Overridden from RasterizerTaskClient:
- virtual SkCanvas* AcquireCanvasForRaster(RasterTask* task) OVERRIDE;
- virtual void ReleaseCanvasForRaster(RasterTask* task) OVERRIDE;
-
- protected:
- ImageRasterWorkerPool(base::SequencedTaskRunner* task_runner,
- TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider);
-
- private:
- void OnRasterFinished();
- void OnRasterRequiredForActivationFinished();
- scoped_ptr<base::Value> StateAsValue() const;
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- TaskGraphRunner* task_graph_runner_;
- const NamespaceToken namespace_token_;
- RasterizerClient* client_;
- ResourceProvider* resource_provider_;
-
- bool raster_tasks_pending_;
- bool raster_tasks_required_for_activation_pending_;
-
- base::WeakPtrFactory<ImageRasterWorkerPool> raster_finished_weak_ptr_factory_;
-
- scoped_refptr<RasterizerTask> raster_finished_task_;
- scoped_refptr<RasterizerTask> raster_required_for_activation_finished_task_;
-
- // Task graph used when scheduling tasks and vector used to gather
- // completed tasks.
- TaskGraph graph_;
- Task::Vector completed_tasks_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageRasterWorkerPool);
-};
-
-} // namespace cc
-
-#endif // CC_RESOURCES_IMAGE_RASTER_WORKER_POOL_H_
diff --git a/chromium/cc/resources/layer_painter.h b/chromium/cc/resources/layer_painter.h
index 4cb2527c42f..54dc434671d 100644
--- a/chromium/cc/resources/layer_painter.h
+++ b/chromium/cc/resources/layer_painter.h
@@ -19,9 +19,7 @@ namespace cc {
class CC_EXPORT LayerPainter {
public:
virtual ~LayerPainter() {}
- virtual void Paint(SkCanvas* canvas,
- const gfx::Rect& content_rect,
- gfx::RectF* opaque) = 0;
+ virtual void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) = 0;
};
} // namespace cc
diff --git a/chromium/cc/resources/layer_quad.cc b/chromium/cc/resources/layer_quad.cc
index fdd68662e35..38ec7b32b01 100644
--- a/chromium/cc/resources/layer_quad.cc
+++ b/chromium/cc/resources/layer_quad.cc
@@ -5,7 +5,7 @@
#include "cc/resources/layer_quad.h"
#include "base/logging.h"
-#include "ui/gfx/quad_f.h"
+#include "ui/gfx/geometry/quad_f.h"
namespace cc {
diff --git a/chromium/cc/resources/layer_quad.h b/chromium/cc/resources/layer_quad.h
index 1d711931b20..ed1db101a97 100644
--- a/chromium/cc/resources/layer_quad.h
+++ b/chromium/cc/resources/layer_quad.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
-#include "ui/gfx/point_f.h"
+#include "ui/gfx/geometry/point_f.h"
namespace gfx {
class QuadF;
diff --git a/chromium/cc/resources/layer_quad_unittest.cc b/chromium/cc/resources/layer_quad_unittest.cc
index 8d3909cb586..3560b8d379e 100644
--- a/chromium/cc/resources/layer_quad_unittest.cc
+++ b/chromium/cc/resources/layer_quad_unittest.cc
@@ -5,7 +5,7 @@
#include "cc/resources/layer_quad.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/quad_f.h"
+#include "ui/gfx/geometry/quad_f.h"
namespace cc {
namespace {
diff --git a/chromium/cc/resources/layer_tiling_data.cc b/chromium/cc/resources/layer_tiling_data.cc
index b8d80bc3760..63b003628c3 100644
--- a/chromium/cc/resources/layer_tiling_data.cc
+++ b/chromium/cc/resources/layer_tiling_data.cc
@@ -7,6 +7,8 @@
#include <vector>
#include "base/logging.h"
+#include "cc/base/region.h"
+#include "cc/base/simple_enclosed_region.h"
namespace cc {
@@ -17,7 +19,7 @@ scoped_ptr<LayerTilingData> LayerTilingData::Create(const gfx::Size& tile_size,
LayerTilingData::LayerTilingData(const gfx::Size& tile_size,
BorderTexelOption border)
- : tiling_data_(tile_size, gfx::Rect(), border == HAS_BORDER_TEXELS) {
+ : tiling_data_(tile_size, gfx::Size(), border == HAS_BORDER_TEXELS) {
SetTileSize(tile_size);
}
@@ -90,31 +92,9 @@ gfx::Rect LayerTilingData::TileRect(const Tile* tile) const {
return tile_rect;
}
-Region LayerTilingData::OpaqueRegionInContentRect(
- const gfx::Rect& content_rect) const {
- if (content_rect.IsEmpty())
- return Region();
-
- Region opaque_region;
- int left, top, right, bottom;
- ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom);
- for (int j = top; j <= bottom; ++j) {
- for (int i = left; i <= right; ++i) {
- Tile* tile = TileAt(i, j);
- if (!tile)
- continue;
-
- gfx::Rect tile_opaque_rect =
- gfx::IntersectRects(content_rect, tile->opaque_rect());
- opaque_region.Union(tile_opaque_rect);
- }
- }
- return opaque_region;
-}
-
-void LayerTilingData::SetTilingRect(const gfx::Rect& tiling_rect) {
- tiling_data_.SetTilingRect(tiling_rect);
- if (tiling_rect.IsEmpty()) {
+void LayerTilingData::SetTilingSize(const gfx::Size& tiling_size) {
+ tiling_data_.SetTilingSize(tiling_size);
+ if (tiling_size.IsEmpty()) {
tiles_.clear();
return;
}
@@ -122,7 +102,8 @@ void LayerTilingData::SetTilingRect(const gfx::Rect& tiling_rect) {
// Any tiles completely outside our new bounds are invalid and should be
// dropped.
int left, top, right, bottom;
- ContentRectToTileIndices(tiling_rect, &left, &top, &right, &bottom);
+ ContentRectToTileIndices(
+ gfx::Rect(tiling_size), &left, &top, &right, &bottom);
std::vector<TileMapKey> invalid_tile_keys;
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
if (it->first.first > right || it->first.second > bottom)
diff --git a/chromium/cc/resources/layer_tiling_data.h b/chromium/cc/resources/layer_tiling_data.h
index b145e38ffab..51681184bbd 100644
--- a/chromium/cc/resources/layer_tiling_data.h
+++ b/chromium/cc/resources/layer_tiling_data.h
@@ -12,9 +12,9 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
-#include "cc/base/region.h"
+#include "cc/base/simple_enclosed_region.h"
#include "cc/base/tiling_data.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
namespace cc {
@@ -63,14 +63,9 @@ class CC_EXPORT LayerTilingData {
j_ = j;
}
- gfx::Rect opaque_rect() const { return opaque_rect_; }
- void set_opaque_rect(const gfx::Rect& opaque_rect) {
- opaque_rect_ = opaque_rect;
- }
private:
int i_;
int j_;
- gfx::Rect opaque_rect_;
DISALLOW_COPY_AND_ASSIGN(Tile);
};
typedef std::pair<int, int> TileMapKey;
@@ -81,8 +76,8 @@ class CC_EXPORT LayerTilingData {
Tile* TileAt(int i, int j) const;
const TileMap& tiles() const { return tiles_; }
- void SetTilingRect(const gfx::Rect& tiling_rect);
- gfx::Rect tiling_rect() const { return tiling_data_.tiling_rect(); }
+ void SetTilingSize(const gfx::Size& tiling_size);
+ gfx::Size tiling_size() const { return tiling_data_.tiling_size(); }
void ContentRectToTileIndices(const gfx::Rect& rect,
int* left,
@@ -91,8 +86,6 @@ class CC_EXPORT LayerTilingData {
int* bottom) const;
gfx::Rect TileRect(const Tile* tile) const;
- Region OpaqueRegionInContentRect(const gfx::Rect& rect) const;
-
void reset() { tiles_.clear(); }
protected:
diff --git a/chromium/cc/resources/layer_updater.h b/chromium/cc/resources/layer_updater.h
index 47f44106e40..a5eb0a11da7 100644
--- a/chromium/cc/resources/layer_updater.h
+++ b/chromium/cc/resources/layer_updater.h
@@ -8,8 +8,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/vector2d.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
namespace cc {
@@ -46,14 +47,11 @@ class CC_EXPORT LayerUpdater : public base::RefCounted<LayerUpdater> {
virtual scoped_ptr<Resource> CreateResource(
PrioritizedResourceManager* manager) = 0;
- // The |resulting_opaque_rect| gives back a region of the layer that was
- // painted opaque. If the layer is marked opaque in the updater, then this
- // region should be ignored in preference for the entire layer's area.
- virtual void PrepareToUpdate(const gfx::Rect& content_rect,
+ virtual void PrepareToUpdate(const gfx::Size& content_size,
+ const gfx::Rect& paint_rect,
const gfx::Size& tile_size,
float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect) {}
+ float contents_height_scale) {}
virtual void ReduceMemoryUsage() {}
// Set true by the layer when it is known that the entire output is going to
@@ -62,6 +60,7 @@ class CC_EXPORT LayerUpdater : public base::RefCounted<LayerUpdater> {
// Set true by the layer when it is known that the entire output bounds will
// be rasterized.
virtual void SetFillsBoundsCompletely(bool fills_bounds) {}
+ virtual void SetBackgroundColor(SkColor background_color) {}
protected:
virtual ~LayerUpdater() {}
diff --git a/chromium/cc/resources/managed_tile_state.cc b/chromium/cc/resources/managed_tile_state.cc
index 037432764bd..2841711dd81 100644
--- a/chromium/cc/resources/managed_tile_state.cc
+++ b/chromium/cc/resources/managed_tile_state.cc
@@ -5,61 +5,57 @@
#include "cc/resources/managed_tile_state.h"
#include <limits>
+#include <string>
+#include "base/debug/trace_event_argument.h"
#include "cc/base/math_util.h"
namespace cc {
-scoped_ptr<base::Value> ManagedTileBinAsValue(ManagedTileBin bin) {
+std::string ManagedTileBinToString(ManagedTileBin bin) {
switch (bin) {
case NOW_AND_READY_TO_DRAW_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("NOW_AND_READY_TO_DRAW_BIN"));
+ return "NOW_AND_READY_TO_DRAW_BIN";
case NOW_BIN:
- return scoped_ptr<base::Value>(new base::StringValue("NOW_BIN"));
+ return "NOW_BIN";
case SOON_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("SOON_BIN"));
+ return "SOON_BIN";
case EVENTUALLY_AND_ACTIVE_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("EVENTUALLY_AND_ACTIVE_BIN"));
+ return "EVENTUALLY_AND_ACTIVE_BIN";
case EVENTUALLY_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("EVENTUALLY_BIN"));
+ return "EVENTUALLY_BIN";
case AT_LAST_AND_ACTIVE_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("AT_LAST_AND_ACTIVE_BIN"));
+ return "AT_LAST_AND_ACTIVE_BIN";
case AT_LAST_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("AT_LAST_BIN"));
+ return "AT_LAST_BIN";
case NEVER_BIN:
- return scoped_ptr<base::Value>(
- new base::StringValue("NEVER_BIN"));
+ return "NEVER_BIN";
case NUM_BINS:
NOTREACHED();
- return scoped_ptr<base::Value>(
- new base::StringValue("Invalid Bin (NUM_BINS)"));
+ return "Invalid Bin (NUM_BINS)";
}
- return scoped_ptr<base::Value>(
- new base::StringValue("Invalid Bin (UNKNOWN)"));
+ return "Invalid Bin (UNKNOWN)";
}
ManagedTileState::ManagedTileState()
- : raster_mode(LOW_QUALITY_RASTER_MODE),
- bin(NEVER_BIN),
+ : bin(NEVER_BIN),
resolution(NON_IDEAL_RESOLUTION),
required_for_activation(false),
priority_bin(TilePriority::EVENTUALLY),
distance_to_visible(std::numeric_limits<float>::infinity()),
visible_and_ready_to_draw(false),
- scheduled_priority(0) {}
+ scheduled_priority(0) {
+}
-ManagedTileState::TileVersion::TileVersion() : mode_(RESOURCE_MODE) {
+ManagedTileState::DrawInfo::DrawInfo()
+ : mode_(RESOURCE_MODE), solid_color_(SK_ColorWHITE) {
}
-ManagedTileState::TileVersion::~TileVersion() { DCHECK(!resource_); }
+ManagedTileState::DrawInfo::~DrawInfo() {
+ DCHECK(!resource_);
+}
-bool ManagedTileState::TileVersion::IsReadyToDraw() const {
+bool ManagedTileState::DrawInfo::IsReadyToDraw() const {
switch (mode_) {
case RESOURCE_MODE:
return !!resource_;
@@ -71,42 +67,28 @@ bool ManagedTileState::TileVersion::IsReadyToDraw() const {
return false;
}
-size_t ManagedTileState::TileVersion::GPUMemoryUsageInBytes() const {
- if (!resource_)
- return 0;
- return resource_->bytes();
-}
-
ManagedTileState::~ManagedTileState() {}
-scoped_ptr<base::Value> ManagedTileState::AsValue() const {
- bool has_resource = false;
- bool has_active_task = false;
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- has_resource |= (tile_versions[mode].resource_.get() != 0);
- has_active_task |= (tile_versions[mode].raster_task_.get() != 0);
- }
+void ManagedTileState::AsValueInto(base::debug::TracedValue* state) const {
+ bool has_resource = (draw_info.resource_.get() != 0);
+ bool has_active_task = (raster_task.get() != 0);
bool is_using_gpu_memory = has_resource || has_active_task;
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
state->SetBoolean("has_resource", has_resource);
state->SetBoolean("is_using_gpu_memory", is_using_gpu_memory);
- state->Set("bin", ManagedTileBinAsValue(bin).release());
- state->Set("resolution", TileResolutionAsValue(resolution).release());
- state->Set("priority_bin", TilePriorityBinAsValue(priority_bin).release());
- state->Set("distance_to_visible",
- MathUtil::AsValueSafely(distance_to_visible).release());
+ state->SetString("bin", ManagedTileBinToString(bin));
+ state->SetString("resolution", TileResolutionToString(resolution));
+ state->SetString("priority_bin", TilePriorityBinToString(priority_bin));
+ state->SetDouble("distance_to_visible",
+ MathUtil::AsFloatSafely(distance_to_visible));
state->SetBoolean("required_for_activation", required_for_activation);
- state->SetBoolean(
- "is_solid_color",
- tile_versions[raster_mode].mode_ == TileVersion::SOLID_COLOR_MODE);
- state->SetBoolean(
- "is_transparent",
- tile_versions[raster_mode].mode_ == TileVersion::SOLID_COLOR_MODE &&
- !SkColorGetA(tile_versions[raster_mode].solid_color_));
+ state->SetBoolean("is_solid_color",
+ draw_info.mode_ == DrawInfo::SOLID_COLOR_MODE);
+ state->SetBoolean("is_transparent",
+ draw_info.mode_ == DrawInfo::SOLID_COLOR_MODE &&
+ !SkColorGetA(draw_info.solid_color_));
state->SetInteger("scheduled_priority", scheduled_priority);
- return state.PassAs<base::Value>();
}
} // namespace cc
diff --git a/chromium/cc/resources/managed_tile_state.h b/chromium/cc/resources/managed_tile_state.h
index 7224dd64b41..58b77c60fc3 100644
--- a/chromium/cc/resources/managed_tile_state.h
+++ b/chromium/cc/resources/managed_tile_state.h
@@ -7,7 +7,6 @@
#include "base/memory/scoped_ptr.h"
#include "cc/resources/platform_color.h"
-#include "cc/resources/raster_mode.h"
#include "cc/resources/rasterizer.h"
#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
@@ -38,12 +37,13 @@ scoped_ptr<base::Value> ManagedTileBinAsValue(ManagedTileBin bin);
// managed by the TileManager.
class CC_EXPORT ManagedTileState {
public:
- class CC_EXPORT TileVersion {
+ // This class holds all the state relevant to drawing a tile.
+ class CC_EXPORT DrawInfo {
public:
enum Mode { RESOURCE_MODE, SOLID_COLOR_MODE, PICTURE_PILE_MODE };
- TileVersion();
- ~TileVersion();
+ DrawInfo();
+ ~DrawInfo();
Mode mode() const { return mode_; }
@@ -73,8 +73,6 @@ class CC_EXPORT ManagedTileState {
inline bool has_resource() const { return !!resource_; }
- size_t GPUMemoryUsageInBytes() const;
-
void SetSolidColorForTesting(SkColor color) { set_solid_color(color); }
void SetResourceForTesting(scoped_ptr<ScopedResource> resource) {
resource_ = resource.Pass();
@@ -98,17 +96,16 @@ class CC_EXPORT ManagedTileState {
Mode mode_;
SkColor solid_color_;
scoped_ptr<ScopedResource> resource_;
- scoped_refptr<RasterTask> raster_task_;
};
ManagedTileState();
~ManagedTileState();
- scoped_ptr<base::Value> AsValue() const;
+ void AsValueInto(base::debug::TracedValue* dict) const;
// Persisted state: valid all the time.
- TileVersion tile_versions[NUM_RASTER_MODES];
- RasterMode raster_mode;
+ DrawInfo draw_info;
+ scoped_refptr<RasterTask> raster_task;
ManagedTileBin bin;
diff --git a/chromium/cc/resources/memory_history.cc b/chromium/cc/resources/memory_history.cc
index a2f8b6ee113..4dc49c881a6 100644
--- a/chromium/cc/resources/memory_history.cc
+++ b/chromium/cc/resources/memory_history.cc
@@ -24,7 +24,7 @@ void MemoryHistory::GetMinAndMax(size_t* min, size_t* max) const {
*max = 0;
for (RingBufferType::Iterator it = ring_buffer_.Begin(); it; ++it) {
- size_t bytes_total = it->bytes_total();
+ size_t bytes_total = it->total_bytes_used;
if (bytes_total < *min)
*min = bytes_total;
diff --git a/chromium/cc/resources/memory_history.h b/chromium/cc/resources/memory_history.h
index daca10f35a0..570a3d0ca43 100644
--- a/chromium/cc/resources/memory_history.h
+++ b/chromium/cc/resources/memory_history.h
@@ -22,17 +22,12 @@ class MemoryHistory {
struct Entry {
Entry()
: total_budget_in_bytes(0),
- bytes_allocated(0),
- bytes_unreleasable(0),
- bytes_over(0) {}
+ total_bytes_used(0),
+ had_enough_memory(false) {}
size_t total_budget_in_bytes;
- size_t bytes_allocated;
- size_t bytes_unreleasable;
- size_t bytes_over;
- size_t bytes_total() const {
- return bytes_allocated + bytes_unreleasable + bytes_over;
- }
+ size_t total_bytes_used;
+ bool had_enough_memory;
};
void SaveEntry(const Entry& entry);
diff --git a/chromium/cc/resources/one_copy_raster_worker_pool.cc b/chromium/cc/resources/one_copy_raster_worker_pool.cc
new file mode 100644
index 00000000000..a8b838e8390
--- /dev/null
+++ b/chromium/cc/resources/one_copy_raster_worker_pool.cc
@@ -0,0 +1,506 @@
+// Copyright 2014 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/one_copy_raster_worker_pool.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
+#include "base/strings/stringprintf.h"
+#include "cc/debug/traced_value.h"
+#include "cc/resources/raster_buffer.h"
+#include "cc/resources/resource_pool.h"
+#include "cc/resources/scoped_resource.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+namespace cc {
+namespace {
+
+class RasterBufferImpl : public RasterBuffer {
+ public:
+ RasterBufferImpl(OneCopyRasterWorkerPool* worker_pool,
+ ResourceProvider* resource_provider,
+ ResourcePool* resource_pool,
+ const Resource* resource)
+ : worker_pool_(worker_pool),
+ resource_provider_(resource_provider),
+ resource_pool_(resource_pool),
+ resource_(resource),
+ raster_resource_(resource_pool->AcquireResource(resource->size())),
+ lock_(new ResourceProvider::ScopedWriteLockGpuMemoryBuffer(
+ resource_provider_,
+ raster_resource_->id())),
+ sequence_(0) {}
+
+ ~RasterBufferImpl() override {
+ // Release write lock in case a copy was never scheduled.
+ lock_.reset();
+
+ // Make sure any scheduled copy operations are issued before we release the
+ // raster resource.
+ if (sequence_)
+ worker_pool_->AdvanceLastIssuedCopyTo(sequence_);
+
+ // Return raster resource to pool so it can be used by another RasterBuffer
+ // instance.
+ if (raster_resource_)
+ resource_pool_->ReleaseResource(raster_resource_.Pass());
+ }
+
+ // Overridden from RasterBuffer:
+ void Playback(const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) override {
+ sequence_ = worker_pool_->PlaybackAndScheduleCopyOnWorkerThread(
+ lock_.Pass(), raster_resource_.Pass(), resource_, raster_source, rect,
+ scale);
+ }
+
+ private:
+ OneCopyRasterWorkerPool* worker_pool_;
+ ResourceProvider* resource_provider_;
+ ResourcePool* resource_pool_;
+ const Resource* resource_;
+ scoped_ptr<ScopedResource> raster_resource_;
+ scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> lock_;
+ CopySequenceNumber sequence_;
+
+ DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+};
+
+// Flush interval when performing copy operations.
+const int kCopyFlushPeriod = 4;
+
+// Number of in-flight copy operations to allow.
+const int kMaxCopyOperations = 16;
+
+// Delay been checking for copy operations to complete.
+const int kCheckForCompletedCopyOperationsTickRateMs = 1;
+
+// Number of failed attempts to allow before we perform a check that will
+// wait for copy operations to complete if needed.
+const int kFailedAttemptsBeforeWaitIfNeeded = 256;
+
+} // namespace
+
+OneCopyRasterWorkerPool::CopyOperation::CopyOperation(
+ scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock,
+ scoped_ptr<ScopedResource> src,
+ const Resource* dst)
+ : write_lock(write_lock.Pass()), src(src.Pass()), dst(dst) {
+}
+
+OneCopyRasterWorkerPool::CopyOperation::~CopyOperation() {
+}
+
+// static
+scoped_ptr<RasterWorkerPool> OneCopyRasterWorkerPool::Create(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ ResourcePool* resource_pool) {
+ return make_scoped_ptr<RasterWorkerPool>(
+ new OneCopyRasterWorkerPool(task_runner,
+ task_graph_runner,
+ context_provider,
+ resource_provider,
+ resource_pool));
+}
+
+OneCopyRasterWorkerPool::OneCopyRasterWorkerPool(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ ResourcePool* resource_pool)
+ : task_runner_(task_runner),
+ task_graph_runner_(task_graph_runner),
+ namespace_token_(task_graph_runner->GetNamespaceToken()),
+ context_provider_(context_provider),
+ resource_provider_(resource_provider),
+ resource_pool_(resource_pool),
+ last_issued_copy_operation_(0),
+ last_flushed_copy_operation_(0),
+ lock_(),
+ copy_operation_count_cv_(&lock_),
+ scheduled_copy_operation_count_(0),
+ issued_copy_operation_count_(0),
+ next_copy_operation_sequence_(1),
+ check_for_completed_copy_operations_pending_(false),
+ shutdown_(false),
+ weak_ptr_factory_(this),
+ raster_finished_weak_ptr_factory_(this) {
+ DCHECK(context_provider_);
+}
+
+OneCopyRasterWorkerPool::~OneCopyRasterWorkerPool() {
+ DCHECK_EQ(scheduled_copy_operation_count_, 0u);
+}
+
+Rasterizer* OneCopyRasterWorkerPool::AsRasterizer() {
+ return this;
+}
+
+void OneCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
+ client_ = client;
+}
+
+void OneCopyRasterWorkerPool::Shutdown() {
+ TRACE_EVENT0("cc", "OneCopyRasterWorkerPool::Shutdown");
+
+ {
+ base::AutoLock lock(lock_);
+
+ shutdown_ = true;
+ copy_operation_count_cv_.Signal();
+ }
+
+ TaskGraph empty;
+ task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
+ task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
+}
+
+void OneCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
+ TRACE_EVENT0("cc", "OneCopyRasterWorkerPool::ScheduleTasks");
+
+ if (raster_pending_.none())
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
+
+ // Mark all task sets as pending.
+ raster_pending_.set();
+
+ unsigned priority = kRasterTaskPriorityBase;
+
+ graph_.Reset();
+
+ // Cancel existing OnRasterFinished callbacks.
+ raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
+
+ scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
+
+ size_t task_count[kNumberOfTaskSets] = {0};
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
+ task_runner_.get(),
+ base::Bind(&OneCopyRasterWorkerPool::OnRasterFinished,
+ raster_finished_weak_ptr_factory_.GetWeakPtr(),
+ task_set));
+ }
+
+ resource_pool_->CheckBusyResources(false);
+
+ for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
+ it != queue->items.end();
+ ++it) {
+ const RasterTaskQueue::Item& item = *it;
+ RasterTask* task = item.task;
+ DCHECK(!task->HasCompleted());
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (!item.task_sets[task_set])
+ continue;
+
+ ++task_count[task_set];
+
+ graph_.edges.push_back(
+ TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get()));
+ }
+
+ InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
+ }
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ InsertNodeForTask(&graph_,
+ new_raster_finished_tasks[task_set].get(),
+ kRasterFinishedTaskPriority,
+ task_count[task_set]);
+ }
+
+ ScheduleTasksOnOriginThread(this, &graph_);
+ task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
+
+ std::copy(new_raster_finished_tasks,
+ new_raster_finished_tasks + kNumberOfTaskSets,
+ raster_finished_tasks_);
+
+ resource_pool_->ReduceResourceUsage();
+
+ TRACE_EVENT_ASYNC_STEP_INTO1(
+ "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
+}
+
+void OneCopyRasterWorkerPool::CheckForCompletedTasks() {
+ TRACE_EVENT0("cc", "OneCopyRasterWorkerPool::CheckForCompletedTasks");
+
+ task_graph_runner_->CollectCompletedTasks(namespace_token_,
+ &completed_tasks_);
+
+ for (Task::Vector::const_iterator it = completed_tasks_.begin();
+ it != completed_tasks_.end();
+ ++it) {
+ RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
+
+ task->WillComplete();
+ task->CompleteOnOriginThread(this);
+ task->DidComplete();
+
+ task->RunReplyOnOriginThread();
+ }
+ completed_tasks_.clear();
+}
+
+scoped_ptr<RasterBuffer> OneCopyRasterWorkerPool::AcquireBufferForRaster(
+ const Resource* resource) {
+ DCHECK_EQ(resource->format(), resource_pool_->resource_format());
+ return make_scoped_ptr<RasterBuffer>(
+ new RasterBufferImpl(this, resource_provider_, resource_pool_, resource));
+}
+
+void OneCopyRasterWorkerPool::ReleaseBufferForRaster(
+ scoped_ptr<RasterBuffer> buffer) {
+ // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
+}
+
+CopySequenceNumber
+OneCopyRasterWorkerPool::PlaybackAndScheduleCopyOnWorkerThread(
+ scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock,
+ scoped_ptr<ScopedResource> src,
+ const Resource* dst,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) {
+ base::AutoLock lock(lock_);
+
+ int failed_attempts = 0;
+ while ((scheduled_copy_operation_count_ + issued_copy_operation_count_) >=
+ kMaxCopyOperations) {
+ // Ignore limit when shutdown is set.
+ if (shutdown_)
+ break;
+
+ ++failed_attempts;
+
+ // Schedule a check that will also wait for operations to complete
+ // after too many failed attempts.
+ bool wait_if_needed = failed_attempts > kFailedAttemptsBeforeWaitIfNeeded;
+
+ // Schedule a check for completed copy operations if too many operations
+ // are currently in-flight.
+ ScheduleCheckForCompletedCopyOperationsWithLockAcquired(wait_if_needed);
+
+ {
+ TRACE_EVENT0("cc", "WaitingForCopyOperationsToComplete");
+
+ // Wait for in-flight copy operations to drop below limit.
+ copy_operation_count_cv_.Wait();
+ }
+ }
+
+ // Increment |scheduled_copy_operation_count_| before releasing |lock_|.
+ ++scheduled_copy_operation_count_;
+
+ // There may be more work available, so wake up another worker thread.
+ copy_operation_count_cv_.Signal();
+
+ {
+ base::AutoUnlock unlock(lock_);
+
+ gfx::GpuMemoryBuffer* gpu_memory_buffer = write_lock->GetGpuMemoryBuffer();
+ if (gpu_memory_buffer) {
+ RasterWorkerPool::PlaybackToMemory(gpu_memory_buffer->Map(),
+ src->format(),
+ src->size(),
+ gpu_memory_buffer->GetStride(),
+ raster_source,
+ rect,
+ scale);
+ gpu_memory_buffer->Unmap();
+ }
+ }
+
+ pending_copy_operations_.push_back(
+ make_scoped_ptr(new CopyOperation(write_lock.Pass(), src.Pass(), dst)));
+
+ // Acquire a sequence number for this copy operation.
+ CopySequenceNumber sequence = next_copy_operation_sequence_++;
+
+ // Post task that will advance last flushed copy operation to |sequence|
+ // if we have reached the flush period.
+ if ((sequence % kCopyFlushPeriod) == 0) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&OneCopyRasterWorkerPool::AdvanceLastFlushedCopyTo,
+ weak_ptr_factory_.GetWeakPtr(),
+ sequence));
+ }
+
+ return sequence;
+}
+
+void OneCopyRasterWorkerPool::AdvanceLastIssuedCopyTo(
+ CopySequenceNumber sequence) {
+ if (last_issued_copy_operation_ >= sequence)
+ return;
+
+ IssueCopyOperations(sequence - last_issued_copy_operation_);
+ last_issued_copy_operation_ = sequence;
+}
+
+void OneCopyRasterWorkerPool::AdvanceLastFlushedCopyTo(
+ CopySequenceNumber sequence) {
+ if (last_flushed_copy_operation_ >= sequence)
+ return;
+
+ AdvanceLastIssuedCopyTo(sequence);
+
+ // Flush all issued copy operations.
+ context_provider_->ContextGL()->ShallowFlushCHROMIUM();
+ last_flushed_copy_operation_ = last_issued_copy_operation_;
+}
+
+void OneCopyRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
+ TRACE_EVENT1(
+ "cc", "OneCopyRasterWorkerPool::OnRasterFinished", "task_set", task_set);
+
+ DCHECK(raster_pending_[task_set]);
+ raster_pending_[task_set] = false;
+ if (raster_pending_.any()) {
+ TRACE_EVENT_ASYNC_STEP_INTO1(
+ "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
+ } else {
+ TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
+ }
+ client_->DidFinishRunningTasks(task_set);
+}
+
+void OneCopyRasterWorkerPool::IssueCopyOperations(int64 count) {
+ TRACE_EVENT1(
+ "cc", "OneCopyRasterWorkerPool::IssueCopyOperations", "count", count);
+
+ CopyOperation::Deque copy_operations;
+
+ {
+ base::AutoLock lock(lock_);
+
+ for (int64 i = 0; i < count; ++i) {
+ DCHECK(!pending_copy_operations_.empty());
+ copy_operations.push_back(pending_copy_operations_.take_front());
+ }
+
+ // Decrement |scheduled_copy_operation_count_| and increment
+ // |issued_copy_operation_count_| to reflect the transition of copy
+ // operations from "pending" to "issued" state.
+ DCHECK_GE(scheduled_copy_operation_count_, copy_operations.size());
+ scheduled_copy_operation_count_ -= copy_operations.size();
+ issued_copy_operation_count_ += copy_operations.size();
+ }
+
+ while (!copy_operations.empty()) {
+ scoped_ptr<CopyOperation> copy_operation = copy_operations.take_front();
+
+ // Remove the write lock.
+ copy_operation->write_lock.reset();
+
+ // Copy contents of source resource to destination resource.
+ resource_provider_->CopyResource(copy_operation->src->id(),
+ copy_operation->dst->id());
+
+ // Return source resource to pool where it can be reused once copy
+ // operation has completed and resource is no longer busy.
+ resource_pool_->ReleaseResource(copy_operation->src.Pass());
+ }
+}
+
+void OneCopyRasterWorkerPool::
+ ScheduleCheckForCompletedCopyOperationsWithLockAcquired(
+ bool wait_if_needed) {
+ lock_.AssertAcquired();
+
+ if (check_for_completed_copy_operations_pending_)
+ return;
+
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ // Schedule a check for completed copy operations as soon as possible but
+ // don't allow two consecutive checks to be scheduled to run less than the
+ // tick rate apart.
+ base::TimeTicks next_check_for_completed_copy_operations_time =
+ std::max(last_check_for_completed_copy_operations_time_ +
+ base::TimeDelta::FromMilliseconds(
+ kCheckForCompletedCopyOperationsTickRateMs),
+ now);
+
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&OneCopyRasterWorkerPool::CheckForCompletedCopyOperations,
+ weak_ptr_factory_.GetWeakPtr(),
+ wait_if_needed),
+ next_check_for_completed_copy_operations_time - now);
+
+ last_check_for_completed_copy_operations_time_ =
+ next_check_for_completed_copy_operations_time;
+ check_for_completed_copy_operations_pending_ = true;
+}
+
+void OneCopyRasterWorkerPool::CheckForCompletedCopyOperations(
+ bool wait_if_needed) {
+ TRACE_EVENT1("cc",
+ "OneCopyRasterWorkerPool::CheckForCompletedCopyOperations",
+ "wait_if_needed",
+ wait_if_needed);
+
+ resource_pool_->CheckBusyResources(wait_if_needed);
+
+ {
+ base::AutoLock lock(lock_);
+
+ DCHECK(check_for_completed_copy_operations_pending_);
+ check_for_completed_copy_operations_pending_ = false;
+
+ // The number of busy resources in the pool reflects the number of issued
+ // copy operations that have not yet completed.
+ issued_copy_operation_count_ = resource_pool_->busy_resource_count();
+
+ // There may be work blocked on too many in-flight copy operations, so wake
+ // up a worker thread.
+ copy_operation_count_cv_.Signal();
+ }
+}
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+OneCopyRasterWorkerPool::StateAsValue() const {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
+
+ state->BeginArray("tasks_pending");
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
+ state->AppendBoolean(raster_pending_[task_set]);
+ state->EndArray();
+ state->BeginDictionary("staging_state");
+ StagingStateAsValueInto(state.get());
+ state->EndDictionary();
+
+ return state;
+}
+
+void OneCopyRasterWorkerPool::StagingStateAsValueInto(
+ base::debug::TracedValue* staging_state) const {
+ staging_state->SetInteger("staging_resource_count",
+ resource_pool_->total_resource_count());
+ staging_state->SetInteger("bytes_used_for_staging_resources",
+ resource_pool_->total_memory_usage_bytes());
+ staging_state->SetInteger("pending_copy_count",
+ resource_pool_->total_resource_count() -
+ resource_pool_->acquired_resource_count());
+ staging_state->SetInteger("bytes_pending_copy",
+ resource_pool_->total_memory_usage_bytes() -
+ resource_pool_->acquired_memory_usage_bytes());
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/one_copy_raster_worker_pool.h b/chromium/cc/resources/one_copy_raster_worker_pool.h
new file mode 100644
index 00000000000..b209da274bf
--- /dev/null
+++ b/chromium/cc/resources/one_copy_raster_worker_pool.h
@@ -0,0 +1,141 @@
+// Copyright 2014 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_ONE_COPY_RASTER_WORKER_POOL_H_
+#define CC_RESOURCES_ONE_COPY_RASTER_WORKER_POOL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/values.h"
+#include "cc/base/scoped_ptr_deque.h"
+#include "cc/output/context_provider.h"
+#include "cc/resources/raster_worker_pool.h"
+#include "cc/resources/rasterizer.h"
+#include "cc/resources/resource_provider.h"
+
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
+namespace cc {
+class ResourcePool;
+class ScopedResource;
+
+typedef int64 CopySequenceNumber;
+
+class CC_EXPORT OneCopyRasterWorkerPool : public RasterWorkerPool,
+ public Rasterizer,
+ public RasterizerTaskClient {
+ public:
+ ~OneCopyRasterWorkerPool() override;
+
+ static scoped_ptr<RasterWorkerPool> Create(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ ResourcePool* resource_pool);
+
+ // Overridden from RasterWorkerPool:
+ Rasterizer* AsRasterizer() override;
+
+ // Overridden from Rasterizer:
+ void SetClient(RasterizerClient* client) override;
+ void Shutdown() override;
+ void ScheduleTasks(RasterTaskQueue* queue) override;
+ void CheckForCompletedTasks() override;
+
+ // Overridden from RasterizerTaskClient:
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) override;
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
+
+ // Playback raster source and schedule copy of |src| resource to |dst|
+ // resource. Returns a non-zero sequence number for this copy operation.
+ CopySequenceNumber PlaybackAndScheduleCopyOnWorkerThread(
+ scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock,
+ scoped_ptr<ScopedResource> src,
+ const Resource* dst,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale);
+
+ // Issues copy operations until |sequence| has been processed. This will
+ // return immediately if |sequence| has already been processed.
+ void AdvanceLastIssuedCopyTo(CopySequenceNumber sequence);
+
+ protected:
+ OneCopyRasterWorkerPool(base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ ResourcePool* resource_pool);
+
+ private:
+ struct CopyOperation {
+ typedef ScopedPtrDeque<CopyOperation> Deque;
+
+ CopyOperation(
+ scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock,
+ scoped_ptr<ScopedResource> src,
+ const Resource* dst);
+ ~CopyOperation();
+
+ scoped_ptr<ResourceProvider::ScopedWriteLockGpuMemoryBuffer> write_lock;
+ scoped_ptr<ScopedResource> src;
+ const Resource* dst;
+ };
+
+ void OnRasterFinished(TaskSet task_set);
+ void AdvanceLastFlushedCopyTo(CopySequenceNumber sequence);
+ void IssueCopyOperations(int64 count);
+ void ScheduleCheckForCompletedCopyOperationsWithLockAcquired(
+ bool wait_if_needed);
+ void CheckForCompletedCopyOperations(bool wait_if_needed);
+ scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+ void StagingStateAsValueInto(base::debug::TracedValue* staging_state) const;
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ TaskGraphRunner* task_graph_runner_;
+ const NamespaceToken namespace_token_;
+ RasterizerClient* client_;
+ ContextProvider* context_provider_;
+ ResourceProvider* resource_provider_;
+ ResourcePool* resource_pool_;
+ TaskSetCollection raster_pending_;
+ scoped_refptr<RasterizerTask> raster_finished_tasks_[kNumberOfTaskSets];
+ CopySequenceNumber last_issued_copy_operation_;
+ CopySequenceNumber last_flushed_copy_operation_;
+
+ // Task graph used when scheduling tasks and vector used to gather
+ // completed tasks.
+ TaskGraph graph_;
+ Task::Vector completed_tasks_;
+
+ base::Lock lock_;
+ // |lock_| must be acquired when accessing the following members.
+ base::ConditionVariable copy_operation_count_cv_;
+ size_t scheduled_copy_operation_count_;
+ size_t issued_copy_operation_count_;
+ CopyOperation::Deque pending_copy_operations_;
+ CopySequenceNumber next_copy_operation_sequence_;
+ bool check_for_completed_copy_operations_pending_;
+ base::TimeTicks last_check_for_completed_copy_operations_time_;
+ bool shutdown_;
+
+ base::WeakPtrFactory<OneCopyRasterWorkerPool> weak_ptr_factory_;
+ // "raster finished" tasks need their own factory as they need to be
+ // canceled when ScheduleTasks() is called.
+ base::WeakPtrFactory<OneCopyRasterWorkerPool>
+ raster_finished_weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OneCopyRasterWorkerPool);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_ONE_COPY_RASTER_WORKER_POOL_H_
diff --git a/chromium/cc/resources/picture.cc b/chromium/cc/resources/picture.cc
index a19fd33f3a0..c35da96848e 100644
--- a/chromium/cc/resources/picture.cc
+++ b/chromium/cc/resources/picture.cc
@@ -10,6 +10,7 @@
#include "base/base64.h"
#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
#include "base/values.h"
#include "cc/base/math_util.h"
#include "cc/base/util.h"
@@ -17,17 +18,16 @@
#include "cc/debug/traced_value.h"
#include "cc/layers/content_layer_client.h"
#include "skia/ext/pixel_ref_utils.h"
+#include "third_party/skia/include/core/SkBBHFactory.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkData.h"
-#include "third_party/skia/include/core/SkDrawFilter.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/utils/SkNullCanvas.h"
-#include "third_party/skia/include/utils/SkPictureUtils.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
namespace cc {
@@ -88,14 +88,12 @@ scoped_refptr<Picture> Picture::Create(
ContentLayerClient* client,
const SkTileGridFactory::TileGridInfo& tile_grid_info,
bool gather_pixel_refs,
- int num_raster_threads,
RecordingMode recording_mode) {
scoped_refptr<Picture> picture = make_scoped_refptr(new Picture(layer_rect));
picture->Record(client, tile_grid_info, recording_mode);
if (gather_pixel_refs)
picture->GatherPixelRefs(tile_grid_info);
- picture->CloneForDrawing(num_raster_threads);
return picture;
}
@@ -123,9 +121,7 @@ scoped_refptr<Picture> Picture::CreateFromSkpValue(const base::Value* value) {
return NULL;
gfx::Rect layer_rect(skpicture->width(), skpicture->height());
- gfx::Rect opaque_rect(skpicture->width(), skpicture->height());
-
- return make_scoped_refptr(new Picture(skpicture, layer_rect, opaque_rect));
+ return make_scoped_refptr(new Picture(skpicture, layer_rect));
}
scoped_refptr<Picture> Picture::CreateFromValue(const base::Value* raw_value) {
@@ -150,37 +146,24 @@ scoped_refptr<Picture> Picture::CreateFromValue(const base::Value* raw_value) {
if (!MathUtil::FromValue(layer_rect_value, &layer_rect))
return NULL;
- const base::Value* opaque_rect_value = NULL;
- if (!value->Get("params.opaque_rect", &opaque_rect_value))
- return NULL;
-
- gfx::Rect opaque_rect;
- if (!MathUtil::FromValue(opaque_rect_value, &opaque_rect))
- return NULL;
-
// Read the picture. This creates an empty picture on failure.
SkPicture* skpicture = SkPicture::CreateFromStream(&stream, &DecodeBitmap);
if (skpicture == NULL)
return NULL;
- return make_scoped_refptr(new Picture(skpicture, layer_rect, opaque_rect));
+ return make_scoped_refptr(new Picture(skpicture, layer_rect));
}
-Picture::Picture(SkPicture* picture,
- const gfx::Rect& layer_rect,
- const gfx::Rect& opaque_rect) :
- layer_rect_(layer_rect),
- opaque_rect_(opaque_rect),
- picture_(skia::AdoptRef(picture)),
- cell_size_(layer_rect.size()) {
+Picture::Picture(SkPicture* picture, const gfx::Rect& layer_rect)
+ : layer_rect_(layer_rect),
+ picture_(skia::AdoptRef(picture)),
+ cell_size_(layer_rect.size()) {
}
Picture::Picture(const skia::RefPtr<SkPicture>& picture,
const gfx::Rect& layer_rect,
- const gfx::Rect& opaque_rect,
const PixelRefMap& pixel_refs) :
layer_rect_(layer_rect),
- opaque_rect_(opaque_rect),
picture_(picture),
pixel_refs_(pixel_refs),
cell_size_(layer_rect.size()) {
@@ -191,18 +174,6 @@ Picture::~Picture() {
TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::Picture", this);
}
-Picture* Picture::GetCloneForDrawingOnThread(unsigned thread_index) {
- // We don't need clones to draw from multiple threads with SkRecord.
- if (playback_) {
- return this;
- }
-
- // SkPicture is not thread-safe to rasterize with, this returns a clone
- // to rasterize with on a specific thread.
- CHECK_GE(clones_.size(), thread_index);
- return thread_index == clones_.size() ? this : clones_[thread_index].get();
-}
-
bool Picture::IsSuitableForGpuRasterization() const {
DCHECK(picture_);
@@ -216,36 +187,14 @@ bool Picture::IsSuitableForGpuRasterization() const {
return picture_->suitableForGpuRasterization(NULL);
}
-void Picture::CloneForDrawing(int num_threads) {
- TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads);
-
- // We don't need clones to draw from multiple threads with SkRecord.
- if (playback_) {
- return;
- }
-
+int Picture::ApproximateOpCount() const {
DCHECK(picture_);
- DCHECK(clones_.empty());
-
- // We can re-use this picture for one raster worker thread.
- raster_thread_checker_.DetachFromThread();
-
- if (num_threads > 1) {
- scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads - 1]);
- picture_->clone(&clones[0], num_threads - 1);
-
- for (int i = 0; i < num_threads - 1; i++) {
- scoped_refptr<Picture> clone = make_scoped_refptr(
- new Picture(skia::AdoptRef(new SkPicture(clones[i])),
- layer_rect_,
- opaque_rect_,
- pixel_refs_));
- clones_.push_back(clone);
+ return picture_->approximateOpCount();
+}
- clone->EmitTraceSnapshotAlias(this);
- clone->raster_thread_checker_.DetachFromThread();
- }
- }
+bool Picture::HasText() const {
+ DCHECK(picture_);
+ return picture_->hasText();
}
void Picture::Record(ContentLayerClient* painter,
@@ -264,8 +213,6 @@ void Picture::Record(ContentLayerClient* painter,
SkTileGridFactory factory(tile_grid_info);
SkPictureRecorder recorder;
- scoped_ptr<EXPERIMENTAL::SkRecording> recording;
-
skia::RefPtr<SkCanvas> canvas;
canvas = skia::SharePtr(recorder.beginRecording(
layer_rect_.width(), layer_rect_.height(), &factory));
@@ -288,11 +235,6 @@ void Picture::Record(ContentLayerClient* painter,
canvas = skia::AdoptRef(SkCreateNullCanvas());
graphics_context_status = ContentLayerClient::GRAPHICS_CONTEXT_DISABLED;
break;
- case RECORD_WITH_SKRECORD:
- recording.reset(new EXPERIMENTAL::SkRecording(layer_rect_.width(),
- layer_rect_.height()));
- canvas = skia::SharePtr(recording->canvas());
- break;
default:
NOTREACHED();
}
@@ -307,23 +249,12 @@ void Picture::Record(ContentLayerClient* painter,
layer_rect_.height());
canvas->clipRect(layer_skrect);
- gfx::RectF opaque_layer_rect;
- painter->PaintContents(
- canvas.get(), layer_rect_, &opaque_layer_rect, graphics_context_status);
+ painter->PaintContents(canvas.get(), layer_rect_, graphics_context_status);
canvas->restore();
picture_ = skia::AdoptRef(recorder.endRecording());
DCHECK(picture_);
- if (recording) {
- // SkRecording requires it's the only one holding onto canvas before we
- // may call releasePlayback(). (This helps enforce thread-safety.)
- canvas.clear();
- playback_.reset(recording->releasePlayback());
- }
-
- opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect);
-
EmitTraceSnapshot();
}
@@ -383,13 +314,10 @@ void Picture::GatherPixelRefs(
max_pixel_cell_ = gfx::Point(max_x, max_y);
}
-int Picture::Raster(
- SkCanvas* canvas,
- SkDrawPictureCallback* callback,
- const Region& negated_content_region,
- float contents_scale) {
- if (!playback_)
- DCHECK(raster_thread_checker_.CalledOnValidThread());
+int Picture::Raster(SkCanvas* canvas,
+ SkDrawPictureCallback* callback,
+ const Region& negated_content_region,
+ float contents_scale) const {
TRACE_EVENT_BEGIN1(
"cc",
"Picture::Raster",
@@ -405,10 +333,14 @@ int Picture::Raster(
canvas->scale(contents_scale, contents_scale);
canvas->translate(layer_rect_.x(), layer_rect_.y());
- if (playback_) {
- playback_->draw(canvas);
- } else {
+ if (callback) {
+ // If we have a callback, we need to call |draw()|, |drawPicture()| doesn't
+ // take a callback. This is used by |AnalysisCanvas| to early out.
picture_->draw(canvas, callback);
+ } else {
+ // Prefer to call |drawPicture()| on the canvas since it could place the
+ // entire picture on the canvas instead of parsing the skia operations.
+ canvas->drawPicture(picture_.get());
}
SkIRect bounds;
canvas->getClipDeviceBounds(&bounds);
@@ -420,16 +352,9 @@ int Picture::Raster(
}
void Picture::Replay(SkCanvas* canvas) {
- if (!playback_)
- DCHECK(raster_thread_checker_.CalledOnValidThread());
TRACE_EVENT_BEGIN0("cc", "Picture::Replay");
DCHECK(picture_);
-
- if (playback_) {
- playback_->draw(canvas);
- } else {
- picture_->draw(canvas);
- }
+ picture_->draw(canvas);
SkIRect bounds;
canvas->getClipDeviceBounds(&bounds);
TRACE_EVENT_END1("cc", "Picture::Replay",
@@ -438,26 +363,11 @@ void Picture::Replay(SkCanvas* canvas) {
scoped_ptr<base::Value> Picture::AsValue() const {
SkDynamicMemoryWStream stream;
-
- if (playback_) {
- // SkPlayback can't serialize itself, so re-record into an SkPicture.
- SkPictureRecorder recorder;
- skia::RefPtr<SkCanvas> canvas(skia::SharePtr(recorder.beginRecording(
- layer_rect_.width(),
- layer_rect_.height(),
- NULL))); // Default (no) bounding-box hierarchy is fastest.
- playback_->draw(canvas.get());
- skia::RefPtr<SkPicture> picture(skia::AdoptRef(recorder.endRecording()));
- picture->serialize(&stream, &EncodeBitmap);
- } else {
- // Serialize the picture.
- picture_->serialize(&stream, &EncodeBitmap);
- }
+ picture_->serialize(&stream, &EncodeBitmap);
// Encode the picture as base64.
scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
res->Set("params.layer_rect", MathUtil::AsValue(layer_rect_).release());
- res->Set("params.opaque_rect", MathUtil::AsValue(opaque_rect_).release());
size_t serialized_size = stream.bytesWritten();
scoped_ptr<char[]> serialized_picture(new char[serialized_size]);
@@ -466,7 +376,7 @@ scoped_ptr<base::Value> Picture::AsValue() const {
base::Base64Encode(std::string(serialized_picture.get(), serialized_size),
&b64_picture);
res->SetString("skp64", b64_picture);
- return res.PassAs<base::Value>();
+ return res.Pass();
}
void Picture::EmitTraceSnapshot() const {
@@ -589,18 +499,22 @@ Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() {
scoped_refptr<base::debug::ConvertableToTraceFormat>
Picture::AsTraceableRasterData(float scale) const {
- scoped_ptr<base::DictionaryValue> raster_data(new base::DictionaryValue());
- raster_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
+ scoped_refptr<base::debug::TracedValue> raster_data =
+ new base::debug::TracedValue();
+ TracedValue::SetIDRef(this, raster_data.get(), "picture_id");
raster_data->SetDouble("scale", scale);
- return TracedValue::FromValue(raster_data.release());
+ return raster_data;
}
scoped_refptr<base::debug::ConvertableToTraceFormat>
Picture::AsTraceableRecordData() const {
- scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
- record_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
- record_data->Set("layer_rect", MathUtil::AsValue(layer_rect_).release());
- return TracedValue::FromValue(record_data.release());
+ scoped_refptr<base::debug::TracedValue> record_data =
+ new base::debug::TracedValue();
+ TracedValue::SetIDRef(this, record_data.get(), "picture_id");
+ record_data->BeginArray("layer_rect");
+ MathUtil::AddToTracedValue(layer_rect_, record_data.get());
+ record_data->EndArray();
+ return record_data;
}
} // namespace cc
diff --git a/chromium/cc/resources/picture.h b/chromium/cc/resources/picture.h
index 78833d17e91..1677309a6e2 100644
--- a/chromium/cc/resources/picture.h
+++ b/chromium/cc/resources/picture.h
@@ -16,14 +16,12 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/threading/thread_checker.h"
#include "cc/base/cc_export.h"
#include "cc/base/region.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkBBHFactory.h"
#include "third_party/skia/include/core/SkPicture.h"
-#include "third_party/skia/include/record/SkRecording.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
class SkPixelRef;
@@ -50,7 +48,6 @@ class CC_EXPORT Picture
RECORD_NORMALLY,
RECORD_WITH_SK_NULL_CANVAS,
RECORD_WITH_PAINTING_DISABLED,
- RECORD_WITH_SKRECORD,
RECORDING_MODE_COUNT, // Must be the last entry.
};
@@ -59,21 +56,19 @@ class CC_EXPORT Picture
ContentLayerClient* client,
const SkTileGridFactory::TileGridInfo& tile_grid_info,
bool gather_pixels_refs,
- int num_raster_threads,
RecordingMode recording_mode);
static scoped_refptr<Picture> CreateFromValue(const base::Value* value);
static scoped_refptr<Picture> CreateFromSkpValue(const base::Value* value);
gfx::Rect LayerRect() const { return layer_rect_; }
- gfx::Rect OpaqueRect() const { return opaque_rect_; }
-
- // Get thread-safe clone for rasterizing with on a specific thread.
- Picture* GetCloneForDrawingOnThread(unsigned thread_index);
// Has Record() been called yet?
bool HasRecording() const { return picture_.get() != NULL; }
bool IsSuitableForGpuRasterization() const;
+ int ApproximateOpCount() const;
+
+ bool HasText() const;
// Apply this scale and raster the negated region into the canvas.
// |negated_content_region| specifies the region to be clipped out of the
@@ -82,7 +77,7 @@ class CC_EXPORT Picture
int Raster(SkCanvas* canvas,
SkDrawPictureCallback* callback,
const Region& negated_content_region,
- float contents_scale);
+ float contents_scale) const;
// Draw the picture directly into the given canvas, without applying any
// clip/scale/layer transformations.
@@ -137,17 +132,11 @@ class CC_EXPORT Picture
// ownership to this picture.
Picture(const skia::RefPtr<SkPicture>&,
const gfx::Rect& layer_rect,
- const gfx::Rect& opaque_rect,
const PixelRefMap& pixel_refs);
// This constructor will call AdoptRef on the SkPicture.
- Picture(SkPicture*,
- const gfx::Rect& layer_rect,
- const gfx::Rect& opaque_rect);
+ Picture(SkPicture*, const gfx::Rect& layer_rect);
~Picture();
- // Make thread-safe clones for rasterizing with.
- void CloneForDrawing(int num_threads);
-
// Record a paint operation. To be able to safely use this SkPicture for
// playback on a different thread this can only be called once.
void Record(ContentLayerClient* client,
@@ -158,12 +147,7 @@ class CC_EXPORT Picture
void GatherPixelRefs(const SkTileGridFactory::TileGridInfo& tile_grid_info);
gfx::Rect layer_rect_;
- gfx::Rect opaque_rect_;
skia::RefPtr<SkPicture> picture_;
- scoped_ptr<const EXPERIMENTAL::SkPlayback> playback_;
-
- typedef std::vector<scoped_refptr<Picture> > PictureVector;
- PictureVector clones_;
PixelRefMap pixel_refs_;
gfx::Point min_pixel_cell_;
@@ -175,8 +159,6 @@ class CC_EXPORT Picture
scoped_refptr<base::debug::ConvertableToTraceFormat>
AsTraceableRecordData() const;
- base::ThreadChecker raster_thread_checker_;
-
friend class base::RefCountedThreadSafe<Picture>;
friend class PixelRefIterator;
DISALLOW_COPY_AND_ASSIGN(Picture);
diff --git a/chromium/cc/resources/picture_layer_tiling.cc b/chromium/cc/resources/picture_layer_tiling.cc
index 5a419516e63..d8885e7bc13 100644
--- a/chromium/cc/resources/picture_layer_tiling.cc
+++ b/chromium/cc/resources/picture_layer_tiling.cc
@@ -7,15 +7,18 @@
#include <algorithm>
#include <cmath>
#include <limits>
+#include <set>
#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
+#include "base/logging.h"
#include "cc/base/math_util.h"
#include "cc/resources/tile.h"
#include "cc/resources/tile_priority.h"
-#include "ui/gfx/point_conversions.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/safe_integer_conversions.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
namespace cc {
namespace {
@@ -34,16 +37,23 @@ class TileEvictionOrder {
const TilePriority& b_priority =
b->priority_for_tree_priority(tree_priority_);
- if (a_priority.priority_bin == b_priority.priority_bin &&
- a->required_for_activation() != b->required_for_activation()) {
- return b->required_for_activation();
- }
- return b_priority.IsHigherPriorityThan(a_priority);
+ DCHECK(a_priority.priority_bin == b_priority.priority_bin);
+ DCHECK(a->required_for_activation() == b->required_for_activation());
+
+ // Or if a is occluded and b is unoccluded.
+ bool a_is_occluded = a->is_occluded_for_tree_priority(tree_priority_);
+ bool b_is_occluded = b->is_occluded_for_tree_priority(tree_priority_);
+ if (a_is_occluded != b_is_occluded)
+ return a_is_occluded;
+
+ // Or if a is farther away from visible.
+ return a_priority.distance_to_visible > b_priority.distance_to_visible;
}
private:
TreePriority tree_priority_;
};
+
} // namespace
scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create(
@@ -62,13 +72,23 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale,
layer_bounds_(layer_bounds),
resolution_(NON_IDEAL_RESOLUTION),
client_(client),
- tiling_data_(gfx::Size(), gfx::Rect(), true),
+ tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels),
last_impl_frame_time_in_seconds_(0.0),
+ content_to_screen_scale_(0.f),
+ can_require_tiles_for_activation_(false),
+ has_visible_rect_tiles_(false),
+ has_skewport_rect_tiles_(false),
+ has_soon_border_rect_tiles_(false),
+ has_eventually_rect_tiles_(false),
eviction_tiles_cache_valid_(false),
eviction_cache_tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES) {
gfx::Size content_bounds =
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale));
gfx::Size tile_size = client_->CalculateTileSize(content_bounds);
+ if (tile_size.IsEmpty()) {
+ layer_bounds_ = gfx::Size();
+ content_bounds = gfx::Size();
+ }
DCHECK(!gfx::ToFlooredSize(
gfx::ScaleSize(layer_bounds, contents_scale)).IsEmpty()) <<
@@ -76,21 +96,19 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale,
" Layer bounds: " << layer_bounds.ToString() <<
" Contents scale: " << contents_scale;
- tiling_data_.SetTilingRect(gfx::Rect(content_bounds));
+ tiling_data_.SetTilingSize(content_bounds);
tiling_data_.SetMaxTextureSize(tile_size);
}
PictureLayerTiling::~PictureLayerTiling() {
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
+ it->second->set_shared(false);
}
void PictureLayerTiling::SetClient(PictureLayerTilingClient* client) {
client_ = client;
}
-gfx::Rect PictureLayerTiling::TilingRect() const {
- return tiling_data_.tiling_rect();
-}
-
Tile* PictureLayerTiling::CreateTile(int i,
int j,
const PictureLayerTiling* twin_tiling) {
@@ -108,7 +126,12 @@ Tile* PictureLayerTiling::CreateTile(int i,
if (Tile* candidate_tile = twin_tiling->TileAt(i, j)) {
gfx::Rect rect =
gfx::ScaleToEnclosingRect(paint_rect, 1.0f / contents_scale_);
- if (!client_->GetInvalidation()->Intersects(rect)) {
+ const Region* invalidation = client_->GetPendingInvalidation();
+ if (!invalidation || !invalidation->Intersects(rect)) {
+ DCHECK(!candidate_tile->is_shared());
+ DCHECK_EQ(i, candidate_tile->tiling_i_index());
+ DCHECK_EQ(j, candidate_tile->tiling_j_index());
+ candidate_tile->set_shared(true);
tiles_[key] = candidate_tile;
return candidate_tile;
}
@@ -117,14 +140,19 @@ Tile* PictureLayerTiling::CreateTile(int i,
// Create a new tile because our twin didn't have a valid one.
scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect);
- if (tile.get())
+ if (tile.get()) {
+ DCHECK(!tile->is_shared());
+ tile->set_tiling_index(i, j);
tiles_[key] = tile;
+ }
+ eviction_tiles_cache_valid_ = false;
return tile.get();
}
void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
- const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this);
- bool include_borders = true;
+ const PictureLayerTiling* twin_tiling =
+ client_->GetPendingOrActiveTwinTiling(this);
+ bool include_borders = false;
for (TilingData::Iterator iter(
&tiling_data_, live_tiles_rect_, include_borders);
iter;
@@ -135,80 +163,152 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
continue;
CreateTile(key.first, key.second, twin_tiling);
}
+
+ VerifyLiveTilesRect();
}
-void PictureLayerTiling::SetLayerBounds(const gfx::Size& layer_bounds) {
- if (layer_bounds_ == layer_bounds)
- return;
+void PictureLayerTiling::UpdateTilesToCurrentPile(
+ const Region& layer_invalidation,
+ const gfx::Size& new_layer_bounds) {
+ DCHECK(!new_layer_bounds.IsEmpty());
- DCHECK(!layer_bounds.IsEmpty());
+ gfx::Size tile_size = tiling_data_.max_texture_size();
- gfx::Size old_layer_bounds = layer_bounds_;
- layer_bounds_ = layer_bounds;
- gfx::Size content_bounds =
- gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_));
+ if (new_layer_bounds != layer_bounds_) {
+ gfx::Size content_bounds =
+ gfx::ToCeiledSize(gfx::ScaleSize(new_layer_bounds, contents_scale_));
+
+ tile_size = client_->CalculateTileSize(content_bounds);
+ if (tile_size.IsEmpty()) {
+ layer_bounds_ = gfx::Size();
+ content_bounds = gfx::Size();
+ } else {
+ layer_bounds_ = new_layer_bounds;
+ }
+
+ // The SetLiveTilesRect() method would drop tiles outside the new bounds,
+ // but may do so incorrectly if resizing the tiling causes the number of
+ // tiles in the tiling_data_ to change.
+ gfx::Rect content_rect(content_bounds);
+ int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x());
+ int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y());
+ int before_right =
+ tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1);
+ int before_bottom =
+ tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1);
+
+ // The live_tiles_rect_ is clamped to stay within the tiling size as we
+ // change it.
+ live_tiles_rect_.Intersect(content_rect);
+ tiling_data_.SetTilingSize(content_bounds);
+
+ int after_right = -1;
+ int after_bottom = -1;
+ if (!live_tiles_rect_.IsEmpty()) {
+ after_right =
+ tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1);
+ after_bottom =
+ tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1);
+ }
+
+ // There is no recycled twin since this is run on the pending tiling.
+ PictureLayerTiling* recycled_twin = NULL;
+ DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this));
+ DCHECK_EQ(PENDING_TREE, client_->GetTree());
+
+ // Drop tiles outside the new layer bounds if the layer shrank.
+ for (int i = after_right + 1; i <= before_right; ++i) {
+ for (int j = before_top; j <= before_bottom; ++j)
+ RemoveTileAt(i, j, recycled_twin);
+ }
+ for (int i = before_left; i <= after_right; ++i) {
+ for (int j = after_bottom + 1; j <= before_bottom; ++j)
+ RemoveTileAt(i, j, recycled_twin);
+ }
+
+ // If the layer grew, the live_tiles_rect_ is not changed, but a new row
+ // and/or column of tiles may now exist inside the same live_tiles_rect_.
+ const PictureLayerTiling* twin_tiling =
+ client_->GetPendingOrActiveTwinTiling(this);
+ if (after_right > before_right) {
+ DCHECK_EQ(after_right, before_right + 1);
+ for (int j = before_top; j <= after_bottom; ++j)
+ CreateTile(after_right, j, twin_tiling);
+ }
+ if (after_bottom > before_bottom) {
+ DCHECK_EQ(after_bottom, before_bottom + 1);
+ for (int i = before_left; i <= before_right; ++i)
+ CreateTile(i, after_bottom, twin_tiling);
+ }
+ }
- gfx::Size tile_size = client_->CalculateTileSize(content_bounds);
if (tile_size != tiling_data_.max_texture_size()) {
- tiling_data_.SetTilingRect(gfx::Rect(content_bounds));
tiling_data_.SetMaxTextureSize(tile_size);
+ // When the tile size changes, the TilingData positions no longer work
+ // as valid keys to the TileMap, so just drop all tiles.
Reset();
- return;
+ } else {
+ Invalidate(layer_invalidation);
}
- // Any tiles outside our new bounds are invalid and should be dropped.
- gfx::Rect bounded_live_tiles_rect(live_tiles_rect_);
- bounded_live_tiles_rect.Intersect(gfx::Rect(content_bounds));
- SetLiveTilesRect(bounded_live_tiles_rect);
- tiling_data_.SetTilingRect(gfx::Rect(content_bounds));
-
- // Create tiles for newly exposed areas.
- Region layer_region((gfx::Rect(layer_bounds_)));
- layer_region.Subtract(gfx::Rect(old_layer_bounds));
- Invalidate(layer_region);
+ RasterSource* raster_source = client_->GetRasterSource();
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
+ it->second->set_raster_source(raster_source);
+ VerifyLiveTilesRect();
}
void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) {
- DoInvalidate(layer_region, false /* recreate_tiles */);
+ bool recreate_invalidated_tiles = false;
+ DoInvalidate(layer_region, recreate_invalidated_tiles);
}
void PictureLayerTiling::Invalidate(const Region& layer_region) {
- DoInvalidate(layer_region, true /* recreate_tiles */);
+ bool recreate_invalidated_tiles = true;
+ DoInvalidate(layer_region, recreate_invalidated_tiles);
}
void PictureLayerTiling::DoInvalidate(const Region& layer_region,
- bool recreate_tiles) {
+ bool recreate_invalidated_tiles) {
std::vector<TileMapKey> new_tile_keys;
- gfx::Rect expanded_live_tiles_rect(
- tiling_data_.ExpandRectToTileBoundsWithBorders(live_tiles_rect_));
+ gfx::Rect expanded_live_tiles_rect =
+ tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_);
for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) {
gfx::Rect layer_rect = iter.rect();
gfx::Rect content_rect =
gfx::ScaleToEnclosingRect(layer_rect, contents_scale_);
+ // Consider tiles inside the live tiles rect even if only their border
+ // pixels intersect the invalidation. But don't consider tiles outside
+ // the live tiles rect with the same conditions, as they won't exist.
+ int border_pixels = tiling_data_.border_texels();
+ content_rect.Inset(-border_pixels, -border_pixels);
// Avoid needless work by not bothering to invalidate where there aren't
// tiles.
content_rect.Intersect(expanded_live_tiles_rect);
if (content_rect.IsEmpty())
continue;
- bool include_borders = true;
+ // Since the content_rect includes border pixels already, don't include
+ // borders when iterating to avoid double counting them.
+ bool include_borders = false;
for (TilingData::Iterator iter(
&tiling_data_, content_rect, include_borders);
iter;
++iter) {
- TileMapKey key(iter.index());
- TileMap::iterator find = tiles_.find(key);
- if (find == tiles_.end())
- continue;
- tiles_.erase(find);
- if (recreate_tiles)
- new_tile_keys.push_back(key);
+ // There is no recycled twin since this is run on the pending tiling.
+ PictureLayerTiling* recycled_twin = NULL;
+ DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this));
+ DCHECK_EQ(PENDING_TREE, client_->GetTree());
+ if (RemoveTileAt(iter.index_x(), iter.index_y(), recycled_twin))
+ new_tile_keys.push_back(iter.index());
}
}
- if (recreate_tiles) {
- const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this);
- for (size_t i = 0; i < new_tile_keys.size(); ++i)
+ if (recreate_invalidated_tiles && !new_tile_keys.empty()) {
+ for (size_t i = 0; i < new_tile_keys.size(); ++i) {
+ // Don't try to share a tile with the twin layer, it's been invalidated so
+ // we have to make our own tile here.
+ const PictureLayerTiling* twin_tiling = NULL;
CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, twin_tiling);
+ }
}
}
@@ -249,7 +349,7 @@ PictureLayerTiling::CoverageIterator::CoverageIterator(
dest_to_content_scale_);
// IndexFromSrcCoord clamps to valid tile ranges, so it's necessary to
// check for non-intersection first.
- content_rect.Intersect(tiling_->TilingRect());
+ content_rect.Intersect(gfx::Rect(tiling_->tiling_size()));
if (content_rect.IsEmpty())
return;
@@ -350,7 +450,7 @@ gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const {
gfx::RectF texture_rect(current_geometry_rect_);
texture_rect.Scale(dest_to_content_scale_,
dest_to_content_scale_);
- texture_rect.Intersect(tiling_->TilingRect());
+ texture_rect.Intersect(gfx::Rect(tiling_->tiling_size()));
if (texture_rect.IsEmpty())
return texture_rect;
texture_rect.Offset(-tex_origin.OffsetFromOrigin());
@@ -362,9 +462,32 @@ gfx::Size PictureLayerTiling::CoverageIterator::texture_size() const {
return tiling_->tiling_data_.max_texture_size();
}
+bool PictureLayerTiling::RemoveTileAt(int i,
+ int j,
+ PictureLayerTiling* recycled_twin) {
+ TileMap::iterator found = tiles_.find(TileMapKey(i, j));
+ if (found == tiles_.end())
+ return false;
+ found->second->set_shared(false);
+ tiles_.erase(found);
+ eviction_tiles_cache_valid_ = false;
+ if (recycled_twin) {
+ // Recycled twin does not also have a recycled twin, so pass NULL.
+ recycled_twin->RemoveTileAt(i, j, NULL);
+ }
+ return true;
+}
+
void PictureLayerTiling::Reset() {
live_tiles_rect_ = gfx::Rect();
+ PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this);
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
+ it->second->set_shared(false);
+ if (recycled_twin)
+ recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL);
+ }
tiles_.clear();
+ eviction_tiles_cache_valid_ = false;
}
gfx::Rect PictureLayerTiling::ComputeSkewport(
@@ -415,156 +538,104 @@ gfx::Rect PictureLayerTiling::ComputeSkewport(
return skewport;
}
-void PictureLayerTiling::UpdateTilePriorities(
+void PictureLayerTiling::ComputeTilePriorityRects(
WhichTree tree,
- const gfx::Rect& visible_layer_rect,
- float layer_contents_scale,
- double current_frame_time_in_seconds) {
- if (!NeedsUpdateForFrameAtTime(current_frame_time_in_seconds)) {
+ const gfx::Rect& viewport_in_layer_space,
+ float ideal_contents_scale,
+ double current_frame_time_in_seconds,
+ const Occlusion& occlusion_in_layer_space) {
+ if (!NeedsUpdateForFrameAtTimeAndViewport(current_frame_time_in_seconds,
+ viewport_in_layer_space)) {
// This should never be zero for the purposes of has_ever_been_updated().
DCHECK_NE(current_frame_time_in_seconds, 0.0);
return;
}
gfx::Rect visible_rect_in_content_space =
- gfx::ScaleToEnclosingRect(visible_layer_rect, contents_scale_);
+ gfx::ScaleToEnclosingRect(viewport_in_layer_space, contents_scale_);
- if (TilingRect().IsEmpty()) {
+ if (tiling_size().IsEmpty()) {
last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds;
+ last_viewport_in_layer_space_ = viewport_in_layer_space;
last_visible_rect_in_content_space_ = visible_rect_in_content_space;
return;
}
+ // Calculate the skewport.
+ gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds,
+ visible_rect_in_content_space);
+ DCHECK(skewport.Contains(visible_rect_in_content_space));
+
+ // Calculate the eventually/live tiles rect.
size_t max_tiles_for_interest_area = client_->GetMaxTilesForInterestArea();
gfx::Size tile_size = tiling_data_.max_texture_size();
int64 eventually_rect_area =
max_tiles_for_interest_area * tile_size.width() * tile_size.height();
- gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds,
- visible_rect_in_content_space);
- DCHECK(skewport.Contains(visible_rect_in_content_space));
-
gfx::Rect eventually_rect =
ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space,
eventually_rect_area,
- TilingRect(),
+ gfx::Rect(tiling_size()),
&expansion_cache_);
- DCHECK(eventually_rect.IsEmpty() || TilingRect().Contains(eventually_rect));
+ DCHECK(eventually_rect.IsEmpty() ||
+ gfx::Rect(tiling_size()).Contains(eventually_rect))
+ << "tiling_size: " << tiling_size().ToString()
+ << " eventually_rect: " << eventually_rect.ToString();
+
+ // Calculate the soon border rect.
+ content_to_screen_scale_ = ideal_contents_scale / contents_scale_;
+ gfx::Rect soon_border_rect = visible_rect_in_content_space;
+ float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale_;
+ soon_border_rect.Inset(-border, -border, -border, -border);
+ // Update the tiling state.
SetLiveTilesRect(eventually_rect);
last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds;
+ last_viewport_in_layer_space_ = viewport_in_layer_space;
last_visible_rect_in_content_space_ = visible_rect_in_content_space;
- current_visible_rect_in_content_space_ = visible_rect_in_content_space;
- current_skewport_ = skewport;
- current_eventually_rect_ = eventually_rect;
eviction_tiles_cache_valid_ = false;
- TilePriority now_priority(resolution_, TilePriority::NOW, 0);
- float content_to_screen_scale =
- 1.0f / (contents_scale_ * layer_contents_scale);
-
- // Assign now priority to all visible tiles.
- bool include_borders = true;
- for (TilingData::Iterator iter(
- &tiling_data_, visible_rect_in_content_space, include_borders);
- iter;
- ++iter) {
- TileMap::iterator find = tiles_.find(iter.index());
- if (find == tiles_.end())
- continue;
- Tile* tile = find->second.get();
-
- tile->SetPriority(tree, now_priority);
- }
-
- // Assign soon priority to skewport tiles.
- for (TilingData::DifferenceIterator iter(
- &tiling_data_, skewport, visible_rect_in_content_space);
- iter;
- ++iter) {
- TileMap::iterator find = tiles_.find(iter.index());
- if (find == tiles_.end())
- continue;
- Tile* tile = find->second.get();
-
- gfx::Rect tile_bounds =
- tiling_data_.TileBounds(iter.index_x(), iter.index_y());
-
- float distance_to_visible =
- visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) *
- content_to_screen_scale;
-
- TilePriority priority(resolution_, TilePriority::SOON, distance_to_visible);
- tile->SetPriority(tree, priority);
- }
-
- // Assign eventually priority to interest rect tiles.
- for (TilingData::DifferenceIterator iter(
- &tiling_data_, eventually_rect, skewport);
- iter;
- ++iter) {
- TileMap::iterator find = tiles_.find(iter.index());
- if (find == tiles_.end())
- continue;
- Tile* tile = find->second.get();
-
- gfx::Rect tile_bounds =
- tiling_data_.TileBounds(iter.index_x(), iter.index_y());
-
- float distance_to_visible =
- visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) *
- content_to_screen_scale;
- TilePriority priority(
- resolution_, TilePriority::EVENTUALLY, distance_to_visible);
- tile->SetPriority(tree, priority);
- }
+ current_visible_rect_ = visible_rect_in_content_space;
+ current_skewport_rect_ = skewport;
+ current_soon_border_rect_ = soon_border_rect;
+ current_eventually_rect_ = eventually_rect;
+ current_occlusion_in_layer_space_ = occlusion_in_layer_space;
- // Upgrade the priority on border tiles to be SOON.
- current_soon_border_rect_ = visible_rect_in_content_space;
- float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale;
- current_soon_border_rect_.Inset(-border, -border, -border, -border);
- for (TilingData::DifferenceIterator iter(
- &tiling_data_, current_soon_border_rect_, skewport);
- iter;
- ++iter) {
- TileMap::iterator find = tiles_.find(iter.index());
- if (find == tiles_.end())
- continue;
- Tile* tile = find->second.get();
+ // Update has_*_tiles state.
+ gfx::Rect tiling_rect(tiling_size());
- TilePriority priority(resolution_,
- TilePriority::SOON,
- tile->priority(tree).distance_to_visible);
- tile->SetPriority(tree, priority);
- }
+ has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_);
+ has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_);
+ has_soon_border_rect_tiles_ =
+ tiling_rect.Intersects(current_soon_border_rect_);
+ has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_);
}
void PictureLayerTiling::SetLiveTilesRect(
const gfx::Rect& new_live_tiles_rect) {
DCHECK(new_live_tiles_rect.IsEmpty() ||
- TilingRect().Contains(new_live_tiles_rect));
+ gfx::Rect(tiling_size()).Contains(new_live_tiles_rect))
+ << "tiling_size: " << tiling_size().ToString()
+ << " new_live_tiles_rect: " << new_live_tiles_rect.ToString();
if (live_tiles_rect_ == new_live_tiles_rect)
return;
// Iterate to delete all tiles outside of our new live_tiles rect.
+ PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this);
for (TilingData::DifferenceIterator iter(&tiling_data_,
live_tiles_rect_,
new_live_tiles_rect);
iter;
++iter) {
- TileMapKey key(iter.index());
- TileMap::iterator found = tiles_.find(key);
- // If the tile was outside of the recorded region, it won't exist even
- // though it was in the live rect.
- if (found != tiles_.end())
- tiles_.erase(found);
+ RemoveTileAt(iter.index_x(), iter.index_y(), recycled_twin);
}
- const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this);
+ const PictureLayerTiling* twin_tiling =
+ client_->GetPendingOrActiveTwinTiling(this);
// Iterate to allocate new tiles for all regions with newly exposed area.
for (TilingData::DifferenceIterator iter(&tiling_data_,
@@ -577,45 +648,172 @@ void PictureLayerTiling::SetLiveTilesRect(
}
live_tiles_rect_ = new_live_tiles_rect;
+ VerifyLiveTilesRect();
}
-void PictureLayerTiling::DidBecomeRecycled() {
- // DidBecomeActive below will set the active priority for tiles that are
- // still in the tree. Calling this first on an active tiling that is becoming
- // recycled takes care of tiles that are no longer in the active tree (eg.
- // due to a pending invalidation).
- for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
- it->second->SetPriority(ACTIVE_TREE, TilePriority());
+void PictureLayerTiling::VerifyLiveTilesRect() {
+#if DCHECK_IS_ON
+ for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
+ if (!it->second.get())
+ continue;
+ DCHECK(it->first.first < tiling_data_.num_tiles_x())
+ << this << " " << it->first.first << "," << it->first.second
+ << " num_tiles_x " << tiling_data_.num_tiles_x() << " live_tiles_rect "
+ << live_tiles_rect_.ToString();
+ DCHECK(it->first.second < tiling_data_.num_tiles_y())
+ << this << " " << it->first.first << "," << it->first.second
+ << " num_tiles_y " << tiling_data_.num_tiles_y() << " live_tiles_rect "
+ << live_tiles_rect_.ToString();
+ DCHECK(tiling_data_.TileBounds(it->first.first, it->first.second)
+ .Intersects(live_tiles_rect_))
+ << this << " " << it->first.first << "," << it->first.second
+ << " tile bounds "
+ << tiling_data_.TileBounds(it->first.first, it->first.second).ToString()
+ << " live_tiles_rect " << live_tiles_rect_.ToString();
}
+#endif
}
-void PictureLayerTiling::DidBecomeActive() {
- for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
- it->second->SetPriority(ACTIVE_TREE, it->second->priority(PENDING_TREE));
- it->second->SetPriority(PENDING_TREE, TilePriority());
+bool PictureLayerTiling::IsTileOccluded(const Tile* tile) const {
+ DCHECK(tile);
+
+ if (!current_occlusion_in_layer_space_.HasOcclusion())
+ return false;
+
+ gfx::Rect tile_query_rect =
+ gfx::IntersectRects(tile->content_rect(), current_visible_rect_);
- // Tile holds a ref onto a picture pile. If the tile never gets invalidated
- // and recreated, then that picture pile ref could exist indefinitely. To
- // prevent this, ask the client to update the pile to its own ref. This
- // will cause PicturePileImpls and their clones to get deleted once the
- // corresponding PictureLayerImpl and any in flight raster jobs go out of
- // scope.
- client_->UpdatePile(it->second.get());
+ // Explicitly check if the tile is outside the viewport. If so, we need to
+ // return false, since occlusion for this tile is unknown.
+ // TODO(vmpstr): Since the current visible rect is really a viewport in
+ // layer space, we should probably clip tile query rect to tiling bounds
+ // or live tiles rect.
+ if (tile_query_rect.IsEmpty())
+ return false;
+
+ if (contents_scale_ != 1.f) {
+ tile_query_rect =
+ gfx::ScaleToEnclosingRect(tile_query_rect, 1.0f / contents_scale_);
}
+
+ return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect);
}
-void PictureLayerTiling::UpdateTilesToCurrentPile() {
- for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
- client_->UpdatePile(it->second.get());
+bool PictureLayerTiling::IsTileRequiredForActivation(const Tile* tile) const {
+ DCHECK_EQ(PENDING_TREE, client_->GetTree());
+
+ // Note that although this function will determine whether tile is required
+ // for activation assuming that it is in visible (ie in the viewport). That is
+ // to say, even if the tile is outside of the viewport, it will be treated as
+ // if it was inside (there are no explicit checks for this). Hence, this
+ // function is only called for visible tiles to ensure we don't block
+ // activation on tiles outside of the viewport.
+
+ // If we are not allowed to mark tiles as required for activation, then don't
+ // do it.
+ if (!can_require_tiles_for_activation_)
+ return false;
+
+ if (resolution_ != HIGH_RESOLUTION)
+ return false;
+
+ if (IsTileOccluded(tile))
+ return false;
+
+ if (client_->RequiresHighResToDraw())
+ return true;
+
+ const PictureLayerTiling* twin_tiling =
+ client_->GetPendingOrActiveTwinTiling(this);
+ if (!twin_tiling)
+ return true;
+
+ if (twin_tiling->layer_bounds() != layer_bounds())
+ return true;
+
+ if (twin_tiling->current_visible_rect_ != current_visible_rect_)
+ return true;
+
+ Tile* twin_tile =
+ twin_tiling->TileAt(tile->tiling_i_index(), tile->tiling_j_index());
+ // If twin tile is missing, it might not have a recording, so we don't need
+ // this tile to be required for activation.
+ if (!twin_tile)
+ return false;
+
+ return true;
+}
+
+void PictureLayerTiling::UpdateTileAndTwinPriority(Tile* tile) const {
+ UpdateTilePriority(tile);
+
+ const PictureLayerTiling* twin_tiling =
+ client_->GetPendingOrActiveTwinTiling(this);
+ if (!tile->is_shared() || !twin_tiling) {
+ WhichTree tree = client_->GetTree();
+ WhichTree twin_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE;
+ tile->SetPriority(twin_tree, TilePriority());
+ tile->set_is_occluded(twin_tree, false);
+ if (twin_tree == PENDING_TREE)
+ tile->set_required_for_activation(false);
+ return;
+ }
+
+ twin_tiling->UpdateTilePriority(tile);
+}
+
+void PictureLayerTiling::UpdateTilePriority(Tile* tile) const {
+ // TODO(vmpstr): This code should return the priority instead of setting it on
+ // the tile. This should be a part of the change to move tile priority from
+ // tiles into iterators.
+ WhichTree tree = client_->GetTree();
+
+ DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile);
+ gfx::Rect tile_bounds =
+ tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index());
+
+ if (current_visible_rect_.Intersects(tile_bounds)) {
+ tile->SetPriority(tree, TilePriority(resolution_, TilePriority::NOW, 0));
+ if (tree == PENDING_TREE)
+ tile->set_required_for_activation(IsTileRequiredForActivation(tile));
+ tile->set_is_occluded(tree, IsTileOccluded(tile));
+ return;
+ }
+
+ if (tree == PENDING_TREE)
+ tile->set_required_for_activation(false);
+ tile->set_is_occluded(tree, false);
+
+ DCHECK_GT(content_to_screen_scale_, 0.f);
+ float distance_to_visible =
+ current_visible_rect_.ManhattanInternalDistance(tile_bounds) *
+ content_to_screen_scale_;
+
+ if (current_soon_border_rect_.Intersects(tile_bounds) ||
+ current_skewport_rect_.Intersects(tile_bounds)) {
+ tile->SetPriority(
+ tree,
+ TilePriority(resolution_, TilePriority::SOON, distance_to_visible));
+ return;
}
+
+ tile->SetPriority(
+ tree,
+ TilePriority(resolution_, TilePriority::EVENTUALLY, distance_to_visible));
}
-scoped_ptr<base::Value> PictureLayerTiling::AsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
+void PictureLayerTiling::GetAllTilesForTracing(
+ std::set<const Tile*>* tiles) const {
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
+ tiles->insert(it->second.get());
+}
+
+void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const {
state->SetInteger("num_tiles", tiles_.size());
state->SetDouble("content_scale", contents_scale_);
- state->Set("tiling_rect", MathUtil::AsValue(TilingRect()).release());
- return state.PassAs<base::Value>();
+ state->BeginDictionary("tiling_size");
+ MathUtil::AddToTracedValue(tiling_size(), state);
+ state->EndDictionary();
}
size_t PictureLayerTiling::GPUMemoryUsageInBytes() const {
@@ -652,9 +850,11 @@ int ComputeExpansionDelta(int num_x_edges, int num_y_edges,
int64 c = static_cast<int64>(width) * height - target_area;
// Compute the delta for our edges using the quadratic equation.
- return a == 0 ? -c / b :
- (-b + static_cast<int>(
- std::sqrt(static_cast<int64>(b) * b - 4.0 * a * c))) / (2 * a);
+ int delta =
+ (a == 0) ? -c / b : (-b + static_cast<int>(std::sqrt(
+ static_cast<int64>(b) * b - 4.0 * a * c))) /
+ (2 * a);
+ return std::max(0, delta);
}
} // namespace
@@ -782,44 +982,100 @@ void PictureLayerTiling::UpdateEvictionCacheIfNeeded(
eviction_cache_tree_priority_ == tree_priority)
return;
- eviction_tiles_cache_.clear();
- eviction_tiles_cache_.reserve(tiles_.size());
+ eviction_tiles_now_.clear();
+ eviction_tiles_now_and_required_for_activation_.clear();
+ eviction_tiles_soon_.clear();
+ eviction_tiles_soon_and_required_for_activation_.clear();
+ eviction_tiles_eventually_.clear();
+ eviction_tiles_eventually_and_required_for_activation_.clear();
+
for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
- // TODO(vmpstr): This should update the priority if UpdateTilePriorities
- // changes not to do this.
- eviction_tiles_cache_.push_back(it->second);
+ Tile* tile = it->second.get();
+ UpdateTileAndTwinPriority(tile);
+ const TilePriority& priority =
+ tile->priority_for_tree_priority(tree_priority);
+ switch (priority.priority_bin) {
+ case TilePriority::EVENTUALLY:
+ if (tile->required_for_activation())
+ eviction_tiles_eventually_and_required_for_activation_.push_back(
+ tile);
+ else
+ eviction_tiles_eventually_.push_back(tile);
+ break;
+ case TilePriority::SOON:
+ if (tile->required_for_activation())
+ eviction_tiles_soon_and_required_for_activation_.push_back(tile);
+ else
+ eviction_tiles_soon_.push_back(tile);
+ break;
+ case TilePriority::NOW:
+ if (tile->required_for_activation())
+ eviction_tiles_now_and_required_for_activation_.push_back(tile);
+ else
+ eviction_tiles_now_.push_back(tile);
+ break;
+ }
}
- std::sort(eviction_tiles_cache_.begin(),
- eviction_tiles_cache_.end(),
- TileEvictionOrder(tree_priority));
+ // TODO(vmpstr): Do this lazily. One option is to have a "sorted" flag that
+ // can be updated for each of the queues.
+ TileEvictionOrder sort_order(tree_priority);
+ std::sort(eviction_tiles_now_.begin(), eviction_tiles_now_.end(), sort_order);
+ std::sort(eviction_tiles_now_and_required_for_activation_.begin(),
+ eviction_tiles_now_and_required_for_activation_.end(),
+ sort_order);
+ std::sort(
+ eviction_tiles_soon_.begin(), eviction_tiles_soon_.end(), sort_order);
+ std::sort(eviction_tiles_soon_and_required_for_activation_.begin(),
+ eviction_tiles_soon_and_required_for_activation_.end(),
+ sort_order);
+ std::sort(eviction_tiles_eventually_.begin(),
+ eviction_tiles_eventually_.end(),
+ sort_order);
+ std::sort(eviction_tiles_eventually_and_required_for_activation_.begin(),
+ eviction_tiles_eventually_and_required_for_activation_.end(),
+ sort_order);
+
eviction_tiles_cache_valid_ = true;
eviction_cache_tree_priority_ = tree_priority;
}
+const std::vector<Tile*>* PictureLayerTiling::GetEvictionTiles(
+ TreePriority tree_priority,
+ EvictionCategory category) {
+ UpdateEvictionCacheIfNeeded(tree_priority);
+ switch (category) {
+ case EVENTUALLY:
+ return &eviction_tiles_eventually_;
+ case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
+ return &eviction_tiles_eventually_and_required_for_activation_;
+ case SOON:
+ return &eviction_tiles_soon_;
+ case SOON_AND_REQUIRED_FOR_ACTIVATION:
+ return &eviction_tiles_soon_and_required_for_activation_;
+ case NOW:
+ return &eviction_tiles_now_;
+ case NOW_AND_REQUIRED_FOR_ACTIVATION:
+ return &eviction_tiles_now_and_required_for_activation_;
+ }
+ NOTREACHED();
+ return &eviction_tiles_eventually_;
+}
+
PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator()
: tiling_(NULL), current_tile_(NULL) {}
PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator(
- PictureLayerTiling* tiling,
- WhichTree tree)
- : tiling_(tiling),
- type_(TilePriority::NOW),
- visible_rect_in_content_space_(
- tiling_->current_visible_rect_in_content_space_),
- skewport_in_content_space_(tiling_->current_skewport_),
- eventually_rect_in_content_space_(tiling_->current_eventually_rect_),
- soon_border_rect_in_content_space_(tiling_->current_soon_border_rect_),
- tree_(tree),
- current_tile_(NULL),
- visible_iterator_(&tiling->tiling_data_,
- visible_rect_in_content_space_,
- true /* include_borders */),
- spiral_iterator_(&tiling->tiling_data_,
- skewport_in_content_space_,
- visible_rect_in_content_space_,
- visible_rect_in_content_space_),
- skewport_processed_(false) {
+ PictureLayerTiling* tiling)
+ : tiling_(tiling), phase_(VISIBLE_RECT), current_tile_(NULL) {
+ if (!tiling_->has_visible_rect_tiles_) {
+ AdvancePhase();
+ return;
+ }
+
+ visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_,
+ tiling_->current_visible_rect_,
+ false /* include_borders */);
if (!visible_iterator_) {
AdvancePhase();
return;
@@ -827,23 +1083,56 @@ PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator(
current_tile_ =
tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y());
- if (!current_tile_ || !TileNeedsRaster(current_tile_))
+ if (!current_tile_ || !TileNeedsRaster(current_tile_)) {
++(*this);
+ return;
+ }
+ tiling_->UpdateTileAndTwinPriority(current_tile_);
}
PictureLayerTiling::TilingRasterTileIterator::~TilingRasterTileIterator() {}
void PictureLayerTiling::TilingRasterTileIterator::AdvancePhase() {
- DCHECK_LT(type_, TilePriority::EVENTUALLY);
+ DCHECK_LT(phase_, EVENTUALLY_RECT);
do {
- type_ = static_cast<TilePriority::PriorityBin>(type_ + 1);
- if (type_ == TilePriority::EVENTUALLY) {
- spiral_iterator_ = TilingData::SpiralDifferenceIterator(
- &tiling_->tiling_data_,
- eventually_rect_in_content_space_,
- skewport_in_content_space_,
- visible_rect_in_content_space_);
+ phase_ = static_cast<Phase>(phase_ + 1);
+ switch (phase_) {
+ case VISIBLE_RECT:
+ NOTREACHED();
+ return;
+ case SKEWPORT_RECT:
+ if (!tiling_->has_skewport_rect_tiles_)
+ continue;
+
+ spiral_iterator_ = TilingData::SpiralDifferenceIterator(
+ &tiling_->tiling_data_,
+ tiling_->current_skewport_rect_,
+ tiling_->current_visible_rect_,
+ tiling_->current_visible_rect_);
+ break;
+ case SOON_BORDER_RECT:
+ if (!tiling_->has_soon_border_rect_tiles_)
+ continue;
+
+ spiral_iterator_ = TilingData::SpiralDifferenceIterator(
+ &tiling_->tiling_data_,
+ tiling_->current_soon_border_rect_,
+ tiling_->current_skewport_rect_,
+ tiling_->current_visible_rect_);
+ break;
+ case EVENTUALLY_RECT:
+ if (!tiling_->has_eventually_rect_tiles_) {
+ current_tile_ = NULL;
+ return;
+ }
+
+ spiral_iterator_ = TilingData::SpiralDifferenceIterator(
+ &tiling_->tiling_data_,
+ tiling_->current_eventually_rect_,
+ tiling_->current_skewport_rect_,
+ tiling_->current_soon_border_rect_);
+ break;
}
while (spiral_iterator_) {
@@ -854,11 +1143,14 @@ void PictureLayerTiling::TilingRasterTileIterator::AdvancePhase() {
++spiral_iterator_;
}
- if (!spiral_iterator_ && type_ == TilePriority::EVENTUALLY) {
+ if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) {
current_tile_ = NULL;
break;
}
} while (!spiral_iterator_);
+
+ if (current_tile_)
+ tiling_->UpdateTileAndTwinPriority(current_tile_);
}
PictureLayerTiling::TilingRasterTileIterator&
@@ -867,8 +1159,8 @@ operator++() {
current_tile_ = NULL;
while (!current_tile_ || !TileNeedsRaster(current_tile_)) {
std::pair<int, int> next_index;
- switch (type_) {
- case TilePriority::NOW:
+ switch (phase_) {
+ case VISIBLE_RECT:
++visible_iterator_;
if (!visible_iterator_) {
AdvancePhase();
@@ -876,27 +1168,16 @@ operator++() {
}
next_index = visible_iterator_.index();
break;
- case TilePriority::SOON:
+ case SKEWPORT_RECT:
+ case SOON_BORDER_RECT:
++spiral_iterator_;
if (!spiral_iterator_) {
- if (skewport_processed_) {
- AdvancePhase();
- return *this;
- }
- skewport_processed_ = true;
- spiral_iterator_ = TilingData::SpiralDifferenceIterator(
- &tiling_->tiling_data_,
- soon_border_rect_in_content_space_,
- skewport_in_content_space_,
- visible_rect_in_content_space_);
- if (!spiral_iterator_) {
- AdvancePhase();
- return *this;
- }
+ AdvancePhase();
+ return *this;
}
next_index = spiral_iterator_.index();
break;
- case TilePriority::EVENTUALLY:
+ case EVENTUALLY_RECT:
++spiral_iterator_;
if (!spiral_iterator_) {
current_tile_ = NULL;
@@ -907,32 +1188,44 @@ operator++() {
}
current_tile_ = tiling_->TileAt(next_index.first, next_index.second);
}
+
+ if (current_tile_)
+ tiling_->UpdateTileAndTwinPriority(current_tile_);
return *this;
}
PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator()
- : is_valid_(false), tiling_(NULL) {}
+ : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) {
+}
PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator(
PictureLayerTiling* tiling,
- TreePriority tree_priority)
- : is_valid_(false), tiling_(tiling), tree_priority_(tree_priority) {}
-
-PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() {}
+ TreePriority tree_priority,
+ EvictionCategory category)
+ : eviction_tiles_(tiling->GetEvictionTiles(tree_priority, category)),
+ // Note: initializing to "0 - 1" works as overflow is well defined for
+ // unsigned integers.
+ current_eviction_tiles_index_(static_cast<size_t>(0) - 1) {
+ DCHECK(eviction_tiles_);
+ ++(*this);
+}
-PictureLayerTiling::TilingEvictionTileIterator::operator bool() {
- if (!IsValid())
- Initialize();
+PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() {
+}
- return IsValid() && tile_iterator_ != tiling_->eviction_tiles_cache_.end();
+PictureLayerTiling::TilingEvictionTileIterator::operator bool() const {
+ return eviction_tiles_ &&
+ current_eviction_tiles_index_ != eviction_tiles_->size();
}
Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() {
- if (!IsValid())
- Initialize();
+ DCHECK(*this);
+ return (*eviction_tiles_)[current_eviction_tiles_index_];
+}
+const Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() const {
DCHECK(*this);
- return *tile_iterator_;
+ return (*eviction_tiles_)[current_eviction_tiles_index_];
}
PictureLayerTiling::TilingEvictionTileIterator&
@@ -940,24 +1233,11 @@ PictureLayerTiling::TilingEvictionTileIterator::
operator++() {
DCHECK(*this);
do {
- ++tile_iterator_;
- } while (tile_iterator_ != tiling_->eviction_tiles_cache_.end() &&
- (!(*tile_iterator_)->HasResources()));
+ ++current_eviction_tiles_index_;
+ } while (current_eviction_tiles_index_ != eviction_tiles_->size() &&
+ !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources());
return *this;
}
-void PictureLayerTiling::TilingEvictionTileIterator::Initialize() {
- if (!tiling_)
- return;
-
- tiling_->UpdateEvictionCacheIfNeeded(tree_priority_);
- tile_iterator_ = tiling_->eviction_tiles_cache_.begin();
- is_valid_ = true;
- if (tile_iterator_ != tiling_->eviction_tiles_cache_.end() &&
- !(*tile_iterator_)->HasResources()) {
- ++(*this);
- }
-}
-
} // namespace cc
diff --git a/chromium/cc/resources/picture_layer_tiling.h b/chromium/cc/resources/picture_layer_tiling.h
index fc7505c99ad..17da548c916 100644
--- a/chromium/cc/resources/picture_layer_tiling.h
+++ b/chromium/cc/resources/picture_layer_tiling.h
@@ -5,6 +5,7 @@
#ifndef CC_RESOURCES_PICTURE_LAYER_TILING_H_
#define CC_RESOURCES_PICTURE_LAYER_TILING_H_
+#include <set>
#include <utility>
#include <vector>
@@ -16,11 +17,19 @@
#include "cc/base/tiling_data.h"
#include "cc/resources/tile.h"
#include "cc/resources/tile_priority.h"
-#include "ui/gfx/rect.h"
+#include "cc/trees/occlusion.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace base {
+namespace debug {
+class TracedValue;
+}
+}
namespace cc {
class PictureLayerTiling;
+class PicturePileImpl;
class CC_EXPORT PictureLayerTilingClient {
public:
@@ -29,15 +38,21 @@ class CC_EXPORT PictureLayerTilingClient {
virtual scoped_refptr<Tile> CreateTile(
PictureLayerTiling* tiling,
const gfx::Rect& content_rect) = 0;
- virtual void UpdatePile(Tile* tile) = 0;
+ virtual RasterSource* GetRasterSource() = 0;
virtual gfx::Size CalculateTileSize(
const gfx::Size& content_bounds) const = 0;
- virtual const Region* GetInvalidation() = 0;
- virtual const PictureLayerTiling* GetTwinTiling(
+ // This invalidation region defines the area (if any, it can by null) that
+ // tiles can not be shared between pending and active trees.
+ virtual const Region* GetPendingInvalidation() = 0;
+ virtual const PictureLayerTiling* GetPendingOrActiveTwinTiling(
const PictureLayerTiling* tiling) const = 0;
+ virtual PictureLayerTiling* GetRecycledTwinTiling(
+ const PictureLayerTiling* tiling) = 0;
virtual size_t GetMaxTilesForInterestArea() const = 0;
virtual float GetSkewportTargetTimeInSeconds() const = 0;
virtual int GetSkewportExtrapolationLimitInContentPixels() const = 0;
+ virtual WhichTree GetTree() const = 0;
+ virtual bool RequiresHighResToDraw() const = 0;
protected:
virtual ~PictureLayerTilingClient() {}
@@ -45,75 +60,80 @@ class CC_EXPORT PictureLayerTilingClient {
class CC_EXPORT PictureLayerTiling {
public:
+ static const int kBorderTexels = 1;
+
+ enum EvictionCategory {
+ EVENTUALLY,
+ EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION,
+ SOON,
+ SOON_AND_REQUIRED_FOR_ACTIVATION,
+ NOW,
+ NOW_AND_REQUIRED_FOR_ACTIVATION
+ };
+
class CC_EXPORT TilingRasterTileIterator {
public:
TilingRasterTileIterator();
- TilingRasterTileIterator(PictureLayerTiling* tiling, WhichTree tree);
+ explicit TilingRasterTileIterator(PictureLayerTiling* tiling);
~TilingRasterTileIterator();
operator bool() const { return !!current_tile_; }
+ const Tile* operator*() const { return current_tile_; }
Tile* operator*() { return current_tile_; }
- TilePriority::PriorityBin get_type() const { return type_; }
-
- TilingRasterTileIterator& operator++();
-
- gfx::Rect TileBounds() const {
- DCHECK(*this);
- if (type_ == TilePriority::NOW) {
- return tiling_->tiling_data_.TileBounds(visible_iterator_.index_x(),
- visible_iterator_.index_y());
+ TilePriority::PriorityBin get_type() const {
+ switch (phase_) {
+ case VISIBLE_RECT:
+ return TilePriority::NOW;
+ case SKEWPORT_RECT:
+ case SOON_BORDER_RECT:
+ return TilePriority::SOON;
+ case EVENTUALLY_RECT:
+ return TilePriority::EVENTUALLY;
}
- return tiling_->tiling_data_.TileBounds(spiral_iterator_.index_x(),
- spiral_iterator_.index_y());
+ NOTREACHED();
+ return TilePriority::EVENTUALLY;
}
+ TilingRasterTileIterator& operator++();
+
private:
+ enum Phase {
+ VISIBLE_RECT,
+ SKEWPORT_RECT,
+ SOON_BORDER_RECT,
+ EVENTUALLY_RECT
+ };
+
void AdvancePhase();
bool TileNeedsRaster(Tile* tile) const {
- RasterMode mode = tile->DetermineRasterModeForTree(tree_);
- return tile->NeedsRasterForMode(mode);
+ return tile->NeedsRaster() && !tiling_->IsTileOccluded(tile);
}
PictureLayerTiling* tiling_;
- TilePriority::PriorityBin type_;
- gfx::Rect visible_rect_in_content_space_;
- gfx::Rect skewport_in_content_space_;
- gfx::Rect eventually_rect_in_content_space_;
- gfx::Rect soon_border_rect_in_content_space_;
- WhichTree tree_;
+ Phase phase_;
Tile* current_tile_;
TilingData::Iterator visible_iterator_;
TilingData::SpiralDifferenceIterator spiral_iterator_;
- bool skewport_processed_;
};
class CC_EXPORT TilingEvictionTileIterator {
public:
TilingEvictionTileIterator();
TilingEvictionTileIterator(PictureLayerTiling* tiling,
- TreePriority tree_priority);
+ TreePriority tree_priority,
+ EvictionCategory category);
~TilingEvictionTileIterator();
- operator bool();
+ operator bool() const;
+ const Tile* operator*() const;
Tile* operator*();
TilingEvictionTileIterator& operator++();
- TilePriority::PriorityBin get_type() {
- DCHECK(*this);
- const TilePriority& priority =
- (*tile_iterator_)->priority_for_tree_priority(tree_priority_);
- return priority.priority_bin;
- }
private:
- void Initialize();
- bool IsValid() const { return is_valid_; }
-
- bool is_valid_;
- PictureLayerTiling* tiling_;
- TreePriority tree_priority_;
- std::vector<Tile*>::iterator tile_iterator_;
+ const std::vector<Tile*>* eviction_tiles_;
+ size_t current_eviction_tiles_index_;
};
~PictureLayerTiling();
@@ -124,16 +144,19 @@ class CC_EXPORT PictureLayerTiling {
const gfx::Size& layer_bounds,
PictureLayerTilingClient* client);
gfx::Size layer_bounds() const { return layer_bounds_; }
- void SetLayerBounds(const gfx::Size& layer_bounds);
- void Invalidate(const Region& layer_region);
- void RemoveTilesInRegion(const Region& layer_region);
+ void UpdateTilesToCurrentPile(const Region& layer_invalidation,
+ const gfx::Size& new_layer_bounds);
void CreateMissingTilesInLiveTilesRect();
+ void RemoveTilesInRegion(const Region& layer_region);
void SetClient(PictureLayerTilingClient* client);
void set_resolution(TileResolution resolution) { resolution_ = resolution; }
TileResolution resolution() const { return resolution_; }
+ void set_can_require_tiles_for_activation(bool can_require_tiles) {
+ can_require_tiles_for_activation_ = can_require_tiles;
+ }
- gfx::Rect TilingRect() const;
+ gfx::Size tiling_size() const { return tiling_data_.tiling_size(); }
gfx::Rect live_tiles_rect() const { return live_tiles_rect_; }
gfx::Size tile_size() const { return tiling_data_.max_texture_size(); }
float contents_scale() const { return contents_scale_; }
@@ -144,17 +167,46 @@ class CC_EXPORT PictureLayerTiling {
}
void CreateAllTilesForTesting() {
- SetLiveTilesRect(tiling_data_.tiling_rect());
+ SetLiveTilesRect(gfx::Rect(tiling_data_.tiling_size()));
}
+ const TilingData& TilingDataForTesting() const { return tiling_data_; }
+
std::vector<Tile*> AllTilesForTesting() const {
std::vector<Tile*> all_tiles;
- for (TileMap::const_iterator it = tiles_.begin();
- it != tiles_.end(); ++it)
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
all_tiles.push_back(it->second.get());
return all_tiles;
}
+ void UpdateAllTilePrioritiesForTesting() {
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
+ UpdateTileAndTwinPriority(it->second.get());
+ }
+
+ std::vector<scoped_refptr<Tile>> AllRefTilesForTesting() const {
+ std::vector<scoped_refptr<Tile>> all_tiles;
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
+ all_tiles.push_back(it->second);
+ return all_tiles;
+ }
+
+ void SetAllTilesOccludedForTesting() {
+ gfx::Rect viewport_in_layer_space =
+ ScaleToEnclosingRect(current_visible_rect_, 1.0f / contents_scale_);
+ current_occlusion_in_layer_space_ =
+ Occlusion(gfx::Transform(),
+ SimpleEnclosedRegion(viewport_in_layer_space),
+ SimpleEnclosedRegion(viewport_in_layer_space));
+ }
+
+ const gfx::Rect& GetCurrentVisibleRectForTesting() const {
+ return current_visible_rect_;
+ }
+
+ bool IsTileOccluded(const Tile* tile) const;
+ bool IsTileRequiredForActivation(const Tile* tile) const;
+
// Iterate over all tiles to fill content_rect. Even if tiles are invalid
// (i.e. no valid resource) this tiling should still iterate over them.
// The union of all geometry_rect calls for each element iterated over should
@@ -206,30 +258,21 @@ class CC_EXPORT PictureLayerTiling {
void Reset();
- void UpdateTilePriorities(WhichTree tree,
- const gfx::Rect& visible_layer_rect,
- float layer_contents_scale,
- double current_frame_time_in_seconds);
-
- // Copies the src_tree priority into the dst_tree priority for all tiles.
- // The src_tree priority is reset to the lowest priority possible. This
- // also updates the pile on each tile to be the current client's pile.
- void DidBecomeActive();
-
- // Resets the active priority for all tiles in a tiling, when an active
- // tiling is becoming recycled. This may include some tiles which are
- // not in the the pending tiling (due to invalidations). This must
- // be called before DidBecomeActive, as it resets the active priority
- // while DidBecomeActive promotes pending priority on a similar set of tiles.
- void DidBecomeRecycled();
-
- void UpdateTilesToCurrentPile();
-
- bool NeedsUpdateForFrameAtTime(double frame_time_in_seconds) {
- return frame_time_in_seconds != last_impl_frame_time_in_seconds_;
+ void ComputeTilePriorityRects(WhichTree tree,
+ const gfx::Rect& viewport_in_layer_space,
+ float ideal_contents_scale,
+ double current_frame_time_in_seconds,
+ const Occlusion& occlusion_in_layer_space);
+
+ bool NeedsUpdateForFrameAtTimeAndViewport(
+ double frame_time_in_seconds,
+ const gfx::Rect& viewport_in_layer_space) {
+ return frame_time_in_seconds != last_impl_frame_time_in_seconds_ ||
+ viewport_in_layer_space != last_viewport_in_layer_space_;
}
- scoped_ptr<base::Value> AsValue() const;
+ void GetAllTilesForTracing(std::set<const Tile*>* tiles) const;
+ void AsValueInto(base::debug::TracedValue* array) const;
size_t GPUMemoryUsageInBytes() const;
struct RectExpansionCache {
@@ -258,13 +301,16 @@ class CC_EXPORT PictureLayerTiling {
friend class TilingEvictionTileIterator;
typedef std::pair<int, int> TileMapKey;
- typedef base::hash_map<TileMapKey, scoped_refptr<Tile> > TileMap;
+ typedef base::hash_map<TileMapKey, scoped_refptr<Tile>> TileMap;
PictureLayerTiling(float contents_scale,
const gfx::Size& layer_bounds,
PictureLayerTilingClient* client);
void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
+ void VerifyLiveTilesRect();
Tile* CreateTile(int i, int j, const PictureLayerTiling* twin_tiling);
+ // Returns true if the Tile existed and was removed from the tiling.
+ bool RemoveTileAt(int i, int j, PictureLayerTiling* recycled_twin);
// Computes a skewport. The calculation extrapolates the last visible
// rect and the current visible rect to expand the skewport to where it
@@ -275,7 +321,16 @@ class CC_EXPORT PictureLayerTiling {
const;
void UpdateEvictionCacheIfNeeded(TreePriority tree_priority);
- void DoInvalidate(const Region& layer_region, bool recreate_tiles);
+ const std::vector<Tile*>* GetEvictionTiles(TreePriority tree_priority,
+ EvictionCategory category);
+
+ void Invalidate(const Region& layer_region);
+
+ void DoInvalidate(const Region& layer_region,
+ bool recreate_invalidated_tiles);
+
+ void UpdateTileAndTwinPriority(Tile* tile) const;
+ void UpdateTilePriority(Tile* tile) const;
// Given properties.
float contents_scale_;
@@ -290,14 +345,35 @@ class CC_EXPORT PictureLayerTiling {
// State saved for computing velocities based upon finite differences.
double last_impl_frame_time_in_seconds_;
+ gfx::Rect last_viewport_in_layer_space_;
gfx::Rect last_visible_rect_in_content_space_;
+ float content_to_screen_scale_;
- gfx::Rect current_visible_rect_in_content_space_;
- gfx::Rect current_skewport_;
- gfx::Rect current_eventually_rect_;
+ bool can_require_tiles_for_activation_;
+
+ // Iteration rects in content space
+ gfx::Rect current_visible_rect_;
+ gfx::Rect current_skewport_rect_;
gfx::Rect current_soon_border_rect_;
+ gfx::Rect current_eventually_rect_;
+
+ bool has_visible_rect_tiles_;
+ bool has_skewport_rect_tiles_;
+ bool has_soon_border_rect_tiles_;
+ bool has_eventually_rect_tiles_;
+
+ Occlusion current_occlusion_in_layer_space_;
+
+ // TODO(reveman): Remove this in favour of an array of eviction_tiles_ when we
+ // change all enums to have a consistent way of getting the count/last
+ // element.
+ std::vector<Tile*> eviction_tiles_now_;
+ std::vector<Tile*> eviction_tiles_now_and_required_for_activation_;
+ std::vector<Tile*> eviction_tiles_soon_;
+ std::vector<Tile*> eviction_tiles_soon_and_required_for_activation_;
+ std::vector<Tile*> eviction_tiles_eventually_;
+ std::vector<Tile*> eviction_tiles_eventually_and_required_for_activation_;
- std::vector<Tile*> eviction_tiles_cache_;
bool eviction_tiles_cache_valid_;
TreePriority eviction_cache_tree_priority_;
diff --git a/chromium/cc/resources/picture_layer_tiling_perftest.cc b/chromium/cc/resources/picture_layer_tiling_perftest.cc
index 1e698b9e0ec..8f91763c79f 100644
--- a/chromium/cc/resources/picture_layer_tiling_perftest.cc
+++ b/chromium/cc/resources/picture_layer_tiling_perftest.cc
@@ -4,7 +4,13 @@
#include "cc/debug/lap_timer.h"
#include "cc/resources/picture_layer_tiling.h"
+#include "cc/resources/resource_provider.h"
+#include "cc/resources/scoped_resource.h"
+#include "cc/test/fake_output_surface.h"
+#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
+#include "cc/test/test_context_provider.h"
+#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
@@ -22,24 +28,39 @@ class PictureLayerTilingPerfTest : public testing::Test {
PictureLayerTilingPerfTest()
: timer_(kWarmupRuns,
base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
- kTimeCheckInterval) {}
+ kTimeCheckInterval),
+ context_provider_(TestContextProvider::Create()) {
+ output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+
+ shared_bitmap_manager_.reset(new TestSharedBitmapManager());
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1).Pass();
+ }
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
picture_layer_tiling_client_.SetTileSize(gfx::Size(256, 256));
picture_layer_tiling_client_.set_max_tiles_for_interest_area(250);
+ picture_layer_tiling_client_.set_tree(PENDING_TREE);
picture_layer_tiling_ = PictureLayerTiling::Create(
1, gfx::Size(256 * 50, 256 * 50), &picture_layer_tiling_client_);
picture_layer_tiling_->CreateAllTilesForTesting();
}
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
picture_layer_tiling_.reset(NULL);
}
void RunInvalidateTest(const std::string& test_name, const Region& region) {
timer_.Reset();
do {
- picture_layer_tiling_->Invalidate(region);
+ picture_layer_tiling_->UpdateTilesToCurrentPile(
+ region, picture_layer_tiling_->tiling_size());
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
@@ -47,18 +68,19 @@ class PictureLayerTilingPerfTest : public testing::Test {
"invalidation", "", test_name, timer_.LapsPerSecond(), "runs/s", true);
}
- void RunUpdateTilePrioritiesStationaryTest(const std::string& test_name,
- const gfx::Transform& transform) {
+ void RunComputeTilePriorityRectsStationaryTest(
+ const std::string& test_name,
+ const gfx::Transform& transform) {
gfx::Rect viewport_rect(0, 0, 1024, 768);
timer_.Reset();
do {
- picture_layer_tiling_->UpdateTilePriorities(
- ACTIVE_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1);
+ picture_layer_tiling_->ComputeTilePriorityRects(
+ PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion());
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
- perf_test::PrintResult("update_tile_priorities_stationary",
+ perf_test::PrintResult("compute_tile_priority_rects_stationary",
"",
test_name,
timer_.LapsPerSecond(),
@@ -66,8 +88,9 @@ class PictureLayerTilingPerfTest : public testing::Test {
true);
}
- void RunUpdateTilePrioritiesScrollingTest(const std::string& test_name,
- const gfx::Transform& transform) {
+ void RunComputeTilePriorityRectsScrollingTest(
+ const std::string& test_name,
+ const gfx::Transform& transform) {
gfx::Size viewport_size(1024, 768);
gfx::Rect viewport_rect(viewport_size);
int xoffsets[] = {10, 0, -10, 0};
@@ -78,8 +101,8 @@ class PictureLayerTilingPerfTest : public testing::Test {
timer_.Reset();
do {
- picture_layer_tiling_->UpdateTilePriorities(
- ACTIVE_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1);
+ picture_layer_tiling_->ComputeTilePriorityRects(
+ PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion());
viewport_rect = gfx::Rect(viewport_rect.x() + xoffsets[offsetIndex],
viewport_rect.y() + yoffsets[offsetIndex],
@@ -93,7 +116,31 @@ class PictureLayerTilingPerfTest : public testing::Test {
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
- perf_test::PrintResult("update_tile_priorities_scrolling",
+ perf_test::PrintResult("compute_tile_priority_rects_scrolling",
+ "",
+ test_name,
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+ }
+
+ void RunRasterIteratorConstructTest(const std::string& test_name,
+ const gfx::Rect& viewport) {
+ gfx::Size bounds(viewport.size());
+ picture_layer_tiling_ =
+ PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
+ picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
+ picture_layer_tiling_->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+
+ timer_.Reset();
+ do {
+ PictureLayerTiling::TilingRasterTileIterator it(
+ picture_layer_tiling_.get());
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult("tiling_raster_tile_iterator_construct",
"",
test_name,
timer_.LapsPerSecond(),
@@ -101,28 +148,61 @@ class PictureLayerTilingPerfTest : public testing::Test {
true);
}
- void RunTilingRasterTileIteratorTest(const std::string& test_name,
- int num_tiles,
- const gfx::Rect& viewport) {
+ void RunRasterIteratorConstructAndIterateTest(const std::string& test_name,
+ int num_tiles,
+ const gfx::Rect& viewport) {
gfx::Size bounds(10000, 10000);
picture_layer_tiling_ =
PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
- picture_layer_tiling_->UpdateTilePriorities(
- ACTIVE_TREE, viewport, 1.0f, 1.0);
+ picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
+ picture_layer_tiling_->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
timer_.Reset();
do {
int count = num_tiles;
- for (PictureLayerTiling::TilingRasterTileIterator it(
- picture_layer_tiling_.get(), ACTIVE_TREE);
- it && count;
- ++it) {
- --count;
+ PictureLayerTiling::TilingRasterTileIterator it(
+ picture_layer_tiling_.get());
+ while (count--) {
+ ASSERT_TRUE(it) << "count: " << count;
+ ASSERT_TRUE(*it != NULL) << "count: " << count;
+ ++it;
}
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
- perf_test::PrintResult("tiling_raster_tile_iterator",
+ perf_test::PrintResult("tiling_raster_tile_iterator_construct_and_iterate",
+ "",
+ test_name,
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+ }
+
+ void RunEvictionIteratorConstructTest(const std::string& test_name,
+ const gfx::Rect& viewport) {
+ gfx::Size bounds(viewport.size());
+ picture_layer_tiling_ =
+ PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
+ picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
+ picture_layer_tiling_->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+
+ timer_.Reset();
+ TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
+ SMOOTHNESS_TAKES_PRIORITY,
+ NEW_CONTENT_TAKES_PRIORITY};
+ int priority_count = 0;
+ do {
+ PictureLayerTiling::TilingEvictionTileIterator it(
+ picture_layer_tiling_.get(),
+ priorities[priority_count],
+ PictureLayerTiling::NOW);
+ priority_count = (priority_count + 1) % arraysize(priorities);
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult("tiling_eviction_tile_iterator_construct",
"",
test_name,
timer_.LapsPerSecond(),
@@ -130,11 +210,78 @@ class PictureLayerTilingPerfTest : public testing::Test {
true);
}
+ void RunEvictionIteratorConstructAndIterateTest(const std::string& test_name,
+ int num_tiles,
+ const gfx::Rect& viewport) {
+ gfx::Size bounds(10000, 10000);
+ picture_layer_tiling_ =
+ PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
+ picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
+ picture_layer_tiling_->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+
+ TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
+ SMOOTHNESS_TAKES_PRIORITY,
+ NEW_CONTENT_TAKES_PRIORITY};
+
+ // Ensure all tiles have resources.
+ std::vector<Tile*> all_tiles = picture_layer_tiling_->AllTilesForTesting();
+ for (std::vector<Tile*>::iterator tile_it = all_tiles.begin();
+ tile_it != all_tiles.end();
+ ++tile_it) {
+ Tile* tile = *tile_it;
+ ManagedTileState::DrawInfo& draw_info = tile->draw_info();
+ draw_info.SetResourceForTesting(
+ ScopedResource::Create(resource_provider_.get()).Pass());
+ }
+
+ int priority_count = 0;
+ timer_.Reset();
+ do {
+ int count = num_tiles;
+ PictureLayerTiling::TilingEvictionTileIterator it(
+ picture_layer_tiling_.get(),
+ priorities[priority_count],
+ PictureLayerTiling::EVENTUALLY);
+ while (count--) {
+ ASSERT_TRUE(it) << "count: " << count;
+ ASSERT_TRUE(*it != NULL) << "count: " << count;
+ ++it;
+ }
+ priority_count = (priority_count + 1) % arraysize(priorities);
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ // Remove all resources from tiles to make sure the tile version destructor
+ // doesn't complain.
+ for (std::vector<Tile*>::iterator tile_it = all_tiles.begin();
+ tile_it != all_tiles.end();
+ ++tile_it) {
+ Tile* tile = *tile_it;
+ ManagedTileState::DrawInfo& draw_info = tile->draw_info();
+ draw_info.SetResourceForTesting(nullptr);
+ }
+
+ perf_test::PrintResult(
+ "tiling_eviction_tile_iterator_construct_and_iterate",
+ "",
+ test_name,
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+ }
+
private:
FakePictureLayerTilingClient picture_layer_tiling_client_;
scoped_ptr<PictureLayerTiling> picture_layer_tiling_;
LapTimer timer_;
+
+ scoped_refptr<ContextProvider> context_provider_;
+ FakeOutputSurfaceClient output_surface_client_;
+ scoped_ptr<FakeOutputSurface> output_surface_;
+ scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
+ scoped_ptr<ResourceProvider> resource_provider_;
};
TEST_F(PictureLayerTilingPerfTest, Invalidate) {
@@ -150,29 +297,62 @@ TEST_F(PictureLayerTilingPerfTest, Invalidate) {
#if defined(OS_ANDROID)
// TODO(vmpstr): Investigate why this is noisy (crbug.com/310220).
-TEST_F(PictureLayerTilingPerfTest, DISABLED_UpdateTilePriorities) {
+TEST_F(PictureLayerTilingPerfTest, DISABLED_ComputeTilePriorityRects) {
#else
-TEST_F(PictureLayerTilingPerfTest, UpdateTilePriorities) {
+TEST_F(PictureLayerTilingPerfTest, ComputeTilePriorityRects) {
#endif // defined(OS_ANDROID)
gfx::Transform transform;
- RunUpdateTilePrioritiesStationaryTest("no_transform", transform);
- RunUpdateTilePrioritiesScrollingTest("no_transform", transform);
+ RunComputeTilePriorityRectsStationaryTest("no_transform", transform);
+ RunComputeTilePriorityRectsScrollingTest("no_transform", transform);
transform.Rotate(10);
- RunUpdateTilePrioritiesStationaryTest("rotation", transform);
- RunUpdateTilePrioritiesScrollingTest("rotation", transform);
+ RunComputeTilePriorityRectsStationaryTest("rotation", transform);
+ RunComputeTilePriorityRectsScrollingTest("rotation", transform);
transform.ApplyPerspectiveDepth(10);
- RunUpdateTilePrioritiesStationaryTest("perspective", transform);
- RunUpdateTilePrioritiesScrollingTest("perspective", transform);
+ RunComputeTilePriorityRectsStationaryTest("perspective", transform);
+ RunComputeTilePriorityRectsScrollingTest("perspective", transform);
+}
+
+TEST_F(PictureLayerTilingPerfTest, TilingRasterTileIteratorConstruct) {
+ RunRasterIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
+ RunRasterIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100));
+ RunRasterIteratorConstructTest("100_0_100x100", gfx::Rect(100, 0, 100, 100));
+ RunRasterIteratorConstructTest("150_0_100x100", gfx::Rect(150, 0, 100, 100));
+}
+
+TEST_F(PictureLayerTilingPerfTest,
+ TilingRasterTileIteratorConstructAndIterate) {
+ RunRasterIteratorConstructAndIterateTest(
+ "32_100x100", 32, gfx::Rect(0, 0, 100, 100));
+ RunRasterIteratorConstructAndIterateTest(
+ "32_500x500", 32, gfx::Rect(0, 0, 500, 500));
+ RunRasterIteratorConstructAndIterateTest(
+ "64_100x100", 64, gfx::Rect(0, 0, 100, 100));
+ RunRasterIteratorConstructAndIterateTest(
+ "64_500x500", 64, gfx::Rect(0, 0, 500, 500));
+}
+
+TEST_F(PictureLayerTilingPerfTest, TilingEvictionTileIteratorConstruct) {
+ RunEvictionIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
+ RunEvictionIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100));
+ RunEvictionIteratorConstructTest("100_0_100x100",
+ gfx::Rect(100, 0, 100, 100));
+ RunEvictionIteratorConstructTest("150_0_100x100",
+ gfx::Rect(150, 0, 100, 100));
}
-TEST_F(PictureLayerTilingPerfTest, TilingRasterTileIterator) {
- RunTilingRasterTileIteratorTest("32_100x100", 32, gfx::Rect(0, 0, 100, 100));
- RunTilingRasterTileIteratorTest("32_500x500", 32, gfx::Rect(0, 0, 500, 500));
- RunTilingRasterTileIteratorTest("64_100x100", 64, gfx::Rect(0, 0, 100, 100));
- RunTilingRasterTileIteratorTest("64_500x500", 64, gfx::Rect(0, 0, 500, 500));
+TEST_F(PictureLayerTilingPerfTest,
+ TilingEvictionTileIteratorConstructAndIterate) {
+ RunEvictionIteratorConstructAndIterateTest(
+ "32_100x100", 32, gfx::Rect(0, 0, 100, 100));
+ RunEvictionIteratorConstructAndIterateTest(
+ "32_500x500", 32, gfx::Rect(0, 0, 500, 500));
+ RunEvictionIteratorConstructAndIterateTest(
+ "64_100x100", 64, gfx::Rect(0, 0, 100, 100));
+ RunEvictionIteratorConstructAndIterateTest(
+ "64_500x500", 64, gfx::Rect(0, 0, 500, 500));
}
} // namespace
diff --git a/chromium/cc/resources/picture_layer_tiling_set.cc b/chromium/cc/resources/picture_layer_tiling_set.cc
index fe55d76ef13..b2b86b5464c 100644
--- a/chromium/cc/resources/picture_layer_tiling_set.cc
+++ b/chromium/cc/resources/picture_layer_tiling_set.cc
@@ -19,12 +19,8 @@ class LargestToSmallestScaleFunctor {
} // namespace
-
-PictureLayerTilingSet::PictureLayerTilingSet(
- PictureLayerTilingClient* client,
- const gfx::Size& layer_bounds)
- : client_(client),
- layer_bounds_(layer_bounds) {
+PictureLayerTilingSet::PictureLayerTilingSet(PictureLayerTilingClient* client)
+ : client_(client) {
}
PictureLayerTilingSet::~PictureLayerTilingSet() {
@@ -36,13 +32,17 @@ void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
tilings_[i]->SetClient(client_);
}
+void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
+ for (size_t i = 0; i < tilings_.size(); ++i)
+ tilings_[i]->RemoveTilesInRegion(region);
+}
+
bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
const gfx::Size& new_layer_bounds,
const Region& layer_invalidation,
float minimum_contents_scale) {
if (new_layer_bounds.IsEmpty()) {
RemoveAllTilings();
- layer_bounds_ = new_layer_bounds;
return false;
}
@@ -69,18 +69,18 @@ bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
this_tiling->set_resolution(other.tilings_[i]->resolution());
- // These two calls must come before updating the pile, because they may
- // destroy tiles that the new pile cannot raster.
- this_tiling->SetLayerBounds(new_layer_bounds);
- this_tiling->Invalidate(layer_invalidation);
-
- this_tiling->UpdateTilesToCurrentPile();
+ this_tiling->UpdateTilesToCurrentPile(layer_invalidation,
+ new_layer_bounds);
this_tiling->CreateMissingTilesInLiveTilesRect();
if (this_tiling->resolution() == HIGH_RESOLUTION)
have_high_res_tiling = true;
DCHECK(this_tiling->tile_size() ==
- client_->CalculateTileSize(this_tiling->TilingRect().size()));
+ client_->CalculateTileSize(this_tiling->tiling_size()))
+ << "tile_size: " << this_tiling->tile_size().ToString()
+ << " tiling_size: " << this_tiling->tiling_size().ToString()
+ << " CalculateTileSize: "
+ << client_->CalculateTileSize(this_tiling->tiling_size()).ToString();
continue;
}
scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
@@ -94,22 +94,17 @@ bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
}
tilings_.sort(LargestToSmallestScaleFunctor());
- layer_bounds_ = new_layer_bounds;
return have_high_res_tiling;
}
-void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
- for (size_t i = 0; i < tilings_.size(); ++i)
- tilings_[i]->RemoveTilesInRegion(region);
-}
-
-PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
+PictureLayerTiling* PictureLayerTilingSet::AddTiling(
+ float contents_scale,
+ const gfx::Size& layer_bounds) {
for (size_t i = 0; i < tilings_.size(); ++i)
DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
- tilings_.push_back(PictureLayerTiling::Create(contents_scale,
- layer_bounds_,
- client_));
+ tilings_.push_back(
+ PictureLayerTiling::Create(contents_scale, layer_bounds, client_));
PictureLayerTiling* appended = tilings_.back();
tilings_.sort(LargestToSmallestScaleFunctor());
@@ -218,7 +213,14 @@ Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
return *tiling_iter_;
}
-PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
+TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
+ const PictureLayerTiling* tiling = CurrentTiling();
+ DCHECK(tiling);
+ return tiling->resolution();
+}
+
+PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling()
+ const {
if (current_tiling_ < 0)
return NULL;
if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
@@ -307,21 +309,12 @@ PictureLayerTilingSet::CoverageIterator::operator bool() const {
region_iter_.has_rect();
}
-void PictureLayerTilingSet::DidBecomeActive() {
- for (size_t i = 0; i < tilings_.size(); ++i)
- tilings_[i]->DidBecomeActive();
-}
-
-void PictureLayerTilingSet::DidBecomeRecycled() {
- for (size_t i = 0; i < tilings_.size(); ++i)
- tilings_[i]->DidBecomeRecycled();
-}
-
-scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
- scoped_ptr<base::ListValue> state(new base::ListValue());
- for (size_t i = 0; i < tilings_.size(); ++i)
- state->Append(tilings_[i]->AsValue().release());
- return state.PassAs<base::Value>();
+void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
+ for (size_t i = 0; i < tilings_.size(); ++i) {
+ state->BeginDictionary();
+ tilings_[i]->AsValueInto(state);
+ state->EndDictionary();
+ }
}
size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
@@ -331,4 +324,51 @@ size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
return amount;
}
+PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
+ TilingRangeType type) const {
+ // Doesn't seem to be the case right now but if it ever becomes a performance
+ // problem to compute these ranges each time this function is called, we can
+ // compute them only when the tiling set has changed instead.
+ TilingRange high_res_range(0, 0);
+ TilingRange low_res_range(tilings_.size(), tilings_.size());
+ for (size_t i = 0; i < tilings_.size(); ++i) {
+ const PictureLayerTiling* tiling = tilings_[i];
+ if (tiling->resolution() == HIGH_RESOLUTION)
+ high_res_range = TilingRange(i, i + 1);
+ if (tiling->resolution() == LOW_RESOLUTION)
+ low_res_range = TilingRange(i, i + 1);
+ }
+
+ TilingRange range(0, 0);
+ switch (type) {
+ case HIGHER_THAN_HIGH_RES:
+ range = TilingRange(0, high_res_range.start);
+ break;
+ case HIGH_RES:
+ range = high_res_range;
+ break;
+ case BETWEEN_HIGH_AND_LOW_RES:
+ // TODO(vmpstr): This code assumes that high res tiling will come before
+ // low res tiling, however there are cases where this assumption is
+ // violated. As a result, it's better to be safe in these situations,
+ // since otherwise we can end up accessing a tiling that doesn't exist.
+ // See crbug.com/429397 for high res tiling appearing after low res
+ // tiling discussion/fixes.
+ if (high_res_range.start <= low_res_range.start)
+ range = TilingRange(high_res_range.end, low_res_range.start);
+ else
+ range = TilingRange(low_res_range.end, high_res_range.start);
+ break;
+ case LOW_RES:
+ range = low_res_range;
+ break;
+ case LOWER_THAN_LOW_RES:
+ range = TilingRange(low_res_range.end, tilings_.size());
+ break;
+ }
+
+ DCHECK_LE(range.start, range.end);
+ return range;
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/picture_layer_tiling_set.h b/chromium/cc/resources/picture_layer_tiling_set.h
index 67b267c2803..ddde1d7be42 100644
--- a/chromium/cc/resources/picture_layer_tiling_set.h
+++ b/chromium/cc/resources/picture_layer_tiling_set.h
@@ -8,19 +8,40 @@
#include "cc/base/region.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/resources/picture_layer_tiling.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace base {
+namespace debug {
+class TracedValue;
+}
+}
namespace cc {
class CC_EXPORT PictureLayerTilingSet {
public:
- PictureLayerTilingSet(PictureLayerTilingClient* client,
- const gfx::Size& layer_bounds);
+ enum TilingRangeType {
+ HIGHER_THAN_HIGH_RES,
+ HIGH_RES,
+ BETWEEN_HIGH_AND_LOW_RES,
+ LOW_RES,
+ LOWER_THAN_LOW_RES
+ };
+ struct TilingRange {
+ TilingRange(size_t start, size_t end) : start(start), end(end) {}
+
+ size_t start;
+ size_t end;
+ };
+
+ explicit PictureLayerTilingSet(PictureLayerTilingClient* client);
~PictureLayerTilingSet();
void SetClient(PictureLayerTilingClient* client);
const PictureLayerTilingClient* client() const { return client_; }
+ void RemoveTilesInRegion(const Region& region);
+
// Make this set of tilings match the same set of content scales from |other|.
// Delete any tilings that don't meet |minimum_contents_scale|. Recreate
// any tiles that intersect |layer_invalidation|. Update the size of all
@@ -31,11 +52,8 @@ class CC_EXPORT PictureLayerTilingSet {
const Region& layer_invalidation,
float minimum_contents_scale);
- void RemoveTilesInRegion(const Region& region);
-
- gfx::Size layer_bounds() const { return layer_bounds_; }
-
- PictureLayerTiling* AddTiling(float contents_scale);
+ PictureLayerTiling* AddTiling(float contents_scale,
+ const gfx::Size& layer_bounds);
size_t num_tilings() const { return tilings_.size(); }
int NumHighResTilings() const;
PictureLayerTiling* tiling_at(size_t idx) { return tilings_[idx]; }
@@ -54,9 +72,6 @@ class CC_EXPORT PictureLayerTilingSet {
// Remove all tiles; keep all tilings.
void RemoveAllTiles();
- void DidBecomeActive();
- void DidBecomeRecycled();
-
// For a given rect, iterates through tiles that can fill it. If no
// set of tiles with resources can fill the rect, then it will iterate
// through null tiles with valid geometry_rect() until the rect is full.
@@ -84,7 +99,8 @@ class CC_EXPORT PictureLayerTilingSet {
CoverageIterator& operator++();
operator bool() const;
- PictureLayerTiling* CurrentTiling();
+ TileResolution resolution() const;
+ PictureLayerTiling* CurrentTiling() const;
private:
int NextTiling() const;
@@ -101,12 +117,13 @@ class CC_EXPORT PictureLayerTilingSet {
Region::Iterator region_iter_;
};
- scoped_ptr<base::Value> AsValue() const;
+ void AsValueInto(base::debug::TracedValue* array) const;
size_t GPUMemoryUsageInBytes() const;
+ TilingRange GetTilingRange(TilingRangeType type) const;
+
private:
PictureLayerTilingClient* client_;
- gfx::Size layer_bounds_;
ScopedPtrVector<PictureLayerTiling> tilings_;
friend class Iterator;
diff --git a/chromium/cc/resources/picture_layer_tiling_set_unittest.cc b/chromium/cc/resources/picture_layer_tiling_set_unittest.cc
index 259301b8444..0fe8b3c9587 100644
--- a/chromium/cc/resources/picture_layer_tiling_set_unittest.cc
+++ b/chromium/cc/resources/picture_layer_tiling_set_unittest.cc
@@ -7,15 +7,13 @@
#include <map>
#include <vector>
-#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
-#include "cc/test/fake_tile_manager_client.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
namespace cc {
namespace {
@@ -23,12 +21,12 @@ namespace {
TEST(PictureLayerTilingSetTest, NoResources) {
FakePictureLayerTilingClient client;
gfx::Size layer_bounds(1000, 800);
- PictureLayerTilingSet set(&client, layer_bounds);
+ PictureLayerTilingSet set(&client);
client.SetTileSize(gfx::Size(256, 256));
- set.AddTiling(1.0);
- set.AddTiling(1.5);
- set.AddTiling(2.0);
+ set.AddTiling(1.0, layer_bounds);
+ set.AddTiling(1.5, layer_bounds);
+ set.AddTiling(2.0, layer_bounds);
float contents_scale = 2.0;
gfx::Size content_bounds(
@@ -53,6 +51,140 @@ TEST(PictureLayerTilingSetTest, NoResources) {
EXPECT_TRUE(remaining.IsEmpty());
}
+TEST(PictureLayerTilingSetTest, TilingRange) {
+ FakePictureLayerTilingClient client;
+ gfx::Size layer_bounds(10, 10);
+ PictureLayerTilingSet::TilingRange higher_than_high_res_range(0, 0);
+ PictureLayerTilingSet::TilingRange high_res_range(0, 0);
+ PictureLayerTilingSet::TilingRange between_high_and_low_res_range(0, 0);
+ PictureLayerTilingSet::TilingRange low_res_range(0, 0);
+ PictureLayerTilingSet::TilingRange lower_than_low_res_range(0, 0);
+ PictureLayerTiling* high_res_tiling;
+ PictureLayerTiling* low_res_tiling;
+
+ PictureLayerTilingSet set(&client);
+ set.AddTiling(2.0, layer_bounds);
+ high_res_tiling = set.AddTiling(1.0, layer_bounds);
+ high_res_tiling->set_resolution(HIGH_RESOLUTION);
+ set.AddTiling(0.5, layer_bounds);
+ low_res_tiling = set.AddTiling(0.25, layer_bounds);
+ low_res_tiling->set_resolution(LOW_RESOLUTION);
+ set.AddTiling(0.125, layer_bounds);
+
+ higher_than_high_res_range =
+ set.GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
+ EXPECT_EQ(0u, higher_than_high_res_range.start);
+ EXPECT_EQ(1u, higher_than_high_res_range.end);
+
+ high_res_range = set.GetTilingRange(PictureLayerTilingSet::HIGH_RES);
+ EXPECT_EQ(1u, high_res_range.start);
+ EXPECT_EQ(2u, high_res_range.end);
+
+ between_high_and_low_res_range =
+ set.GetTilingRange(PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
+ EXPECT_EQ(2u, between_high_and_low_res_range.start);
+ EXPECT_EQ(3u, between_high_and_low_res_range.end);
+
+ low_res_range = set.GetTilingRange(PictureLayerTilingSet::LOW_RES);
+ EXPECT_EQ(3u, low_res_range.start);
+ EXPECT_EQ(4u, low_res_range.end);
+
+ lower_than_low_res_range =
+ set.GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES);
+ EXPECT_EQ(4u, lower_than_low_res_range.start);
+ EXPECT_EQ(5u, lower_than_low_res_range.end);
+
+ PictureLayerTilingSet set_without_low_res(&client);
+ set_without_low_res.AddTiling(2.0, layer_bounds);
+ high_res_tiling = set_without_low_res.AddTiling(1.0, layer_bounds);
+ high_res_tiling->set_resolution(HIGH_RESOLUTION);
+ set_without_low_res.AddTiling(0.5, layer_bounds);
+ set_without_low_res.AddTiling(0.25, layer_bounds);
+
+ higher_than_high_res_range = set_without_low_res.GetTilingRange(
+ PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
+ EXPECT_EQ(0u, higher_than_high_res_range.start);
+ EXPECT_EQ(1u, higher_than_high_res_range.end);
+
+ high_res_range =
+ set_without_low_res.GetTilingRange(PictureLayerTilingSet::HIGH_RES);
+ EXPECT_EQ(1u, high_res_range.start);
+ EXPECT_EQ(2u, high_res_range.end);
+
+ between_high_and_low_res_range = set_without_low_res.GetTilingRange(
+ PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
+ EXPECT_EQ(2u, between_high_and_low_res_range.start);
+ EXPECT_EQ(4u, between_high_and_low_res_range.end);
+
+ low_res_range =
+ set_without_low_res.GetTilingRange(PictureLayerTilingSet::LOW_RES);
+ EXPECT_EQ(0u, low_res_range.end - low_res_range.start);
+
+ lower_than_low_res_range = set_without_low_res.GetTilingRange(
+ PictureLayerTilingSet::LOWER_THAN_LOW_RES);
+ EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);
+
+ PictureLayerTilingSet set_with_only_high_and_low_res(&client);
+ high_res_tiling = set_with_only_high_and_low_res.AddTiling(1.0, layer_bounds);
+ high_res_tiling->set_resolution(HIGH_RESOLUTION);
+ low_res_tiling = set_with_only_high_and_low_res.AddTiling(0.5, layer_bounds);
+ low_res_tiling->set_resolution(LOW_RESOLUTION);
+
+ higher_than_high_res_range = set_with_only_high_and_low_res.GetTilingRange(
+ PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
+ EXPECT_EQ(0u,
+ higher_than_high_res_range.end - higher_than_high_res_range.start);
+
+ high_res_range = set_with_only_high_and_low_res.GetTilingRange(
+ PictureLayerTilingSet::HIGH_RES);
+ EXPECT_EQ(0u, high_res_range.start);
+ EXPECT_EQ(1u, high_res_range.end);
+
+ between_high_and_low_res_range =
+ set_with_only_high_and_low_res.GetTilingRange(
+ PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
+ EXPECT_EQ(0u,
+ between_high_and_low_res_range.end -
+ between_high_and_low_res_range.start);
+
+ low_res_range = set_with_only_high_and_low_res.GetTilingRange(
+ PictureLayerTilingSet::LOW_RES);
+ EXPECT_EQ(1u, low_res_range.start);
+ EXPECT_EQ(2u, low_res_range.end);
+
+ lower_than_low_res_range = set_with_only_high_and_low_res.GetTilingRange(
+ PictureLayerTilingSet::LOWER_THAN_LOW_RES);
+ EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);
+
+ PictureLayerTilingSet set_with_only_high_res(&client);
+ high_res_tiling = set_with_only_high_res.AddTiling(1.0, layer_bounds);
+ high_res_tiling->set_resolution(HIGH_RESOLUTION);
+
+ higher_than_high_res_range = set_with_only_high_res.GetTilingRange(
+ PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
+ EXPECT_EQ(0u,
+ higher_than_high_res_range.end - higher_than_high_res_range.start);
+
+ high_res_range =
+ set_with_only_high_res.GetTilingRange(PictureLayerTilingSet::HIGH_RES);
+ EXPECT_EQ(0u, high_res_range.start);
+ EXPECT_EQ(1u, high_res_range.end);
+
+ between_high_and_low_res_range = set_with_only_high_res.GetTilingRange(
+ PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
+ EXPECT_EQ(0u,
+ between_high_and_low_res_range.end -
+ between_high_and_low_res_range.start);
+
+ low_res_range =
+ set_with_only_high_res.GetTilingRange(PictureLayerTilingSet::LOW_RES);
+ EXPECT_EQ(0u, low_res_range.end - low_res_range.start);
+
+ lower_than_low_res_range = set_with_only_high_res.GetTilingRange(
+ PictureLayerTilingSet::LOWER_THAN_LOW_RES);
+ EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);
+}
+
class PictureLayerTilingSetTestWithResources : public testing::Test {
public:
void runTest(
@@ -68,17 +200,24 @@ class PictureLayerTilingSetTestWithResources : public testing::Test {
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
- scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false);
+ scoped_ptr<ResourceProvider> resource_provider =
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1);
FakePictureLayerTilingClient client(resource_provider.get());
client.SetTileSize(gfx::Size(256, 256));
+ client.set_tree(PENDING_TREE);
gfx::Size layer_bounds(1000, 800);
- PictureLayerTilingSet set(&client, layer_bounds);
+ PictureLayerTilingSet set(&client);
float scale = min_scale;
for (int i = 0; i < num_tilings; ++i, scale += scale_increment) {
- PictureLayerTiling* tiling = set.AddTiling(scale);
+ PictureLayerTiling* tiling = set.AddTiling(scale, layer_bounds);
tiling->CreateAllTilesForTesting();
std::vector<Tile*> tiles = tiling->AllTilesForTesting();
client.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
@@ -153,9 +292,11 @@ class PictureLayerTilingSetSyncTest : public testing::Test {
source_bounds_(gfx::Size(30, 20)),
target_bounds_(gfx::Size(30, 30)) {
source_client_.SetTileSize(tile_size_);
+ source_client_.set_tree(PENDING_TREE);
target_client_.SetTileSize(tile_size_);
- source_.reset(new PictureLayerTilingSet(&source_client_, source_bounds_));
- target_.reset(new PictureLayerTilingSet(&target_client_, target_bounds_));
+ target_client_.set_tree(PENDING_TREE);
+ source_.reset(new PictureLayerTilingSet(&source_client_));
+ target_.reset(new PictureLayerTilingSet(&target_client_));
}
// Sync from source to target.
@@ -182,10 +323,9 @@ class PictureLayerTilingSetSyncTest : public testing::Test {
SyncTilings(new_bounds, invalidation, minimum_scale);
}
- void VerifyTargetEqualsSource(const gfx::Size& new_bounds) const {
+ void VerifyTargetEqualsSource(const gfx::Size& new_bounds) {
ASSERT_FALSE(new_bounds.IsEmpty());
EXPECT_EQ(target_->num_tilings(), source_->num_tilings());
- EXPECT_EQ(target_->layer_bounds().ToString(), new_bounds.ToString());
for (size_t i = 0; i < target_->num_tilings(); ++i) {
ASSERT_GT(source_->num_tilings(), i);
@@ -202,7 +342,7 @@ class PictureLayerTilingSetSyncTest : public testing::Test {
ValidateTargetTilingSet();
}
- void ValidateTargetTilingSet() const {
+ void ValidateTargetTilingSet() {
// Tilings should be sorted largest to smallest.
if (target_->num_tilings() > 0) {
float last_scale = target_->tiling_at(0)->contents_scale();
@@ -214,23 +354,28 @@ class PictureLayerTilingSetSyncTest : public testing::Test {
}
for (size_t i = 0; i < target_->num_tilings(); ++i)
- ValidateTiling(target_->tiling_at(i), target_client_.pile());
+ ValidateTiling(target_->tiling_at(i), target_client_.GetRasterSource());
}
void ValidateTiling(const PictureLayerTiling* tiling,
- const PicturePileImpl* pile) const {
- if (tiling->TilingRect().IsEmpty())
+ const RasterSource* raster_source) {
+ if (tiling->tiling_size().IsEmpty()) {
EXPECT_TRUE(tiling->live_tiles_rect().IsEmpty());
- else if (!tiling->live_tiles_rect().IsEmpty())
- EXPECT_TRUE(tiling->TilingRect().Contains(tiling->live_tiles_rect()));
+ } else if (!tiling->live_tiles_rect().IsEmpty()) {
+ gfx::Rect tiling_rect(tiling->tiling_size());
+ EXPECT_TRUE(tiling_rect.Contains(tiling->live_tiles_rect()));
+ }
std::vector<Tile*> tiles = tiling->AllTilesForTesting();
for (size_t i = 0; i < tiles.size(); ++i) {
const Tile* tile = tiles[i];
ASSERT_TRUE(!!tile);
- EXPECT_EQ(tile->picture_pile(), pile);
+ EXPECT_EQ(tile->raster_source(), raster_source);
EXPECT_TRUE(tile->content_rect().Intersects(tiling->live_tiles_rect()))
- << "All tiles must be inside the live tiles rect.";
+ << "All tiles must be inside the live tiles rect."
+ << " Tile rect: " << tile->content_rect().ToString()
+ << " Live rect: " << tiling->live_tiles_rect().ToString()
+ << " Scale: " << tiling->contents_scale();
}
for (PictureLayerTiling::CoverageIterator iter(
@@ -255,21 +400,20 @@ class PictureLayerTilingSetSyncTest : public testing::Test {
TEST_F(PictureLayerTilingSetSyncTest, EmptyBounds) {
float source_scales[] = {1.f, 1.2f};
for (size_t i = 0; i < arraysize(source_scales); ++i)
- source_->AddTiling(source_scales[i]);
+ source_->AddTiling(source_scales[i], source_bounds_);
- gfx::Size new_bounds;
- SyncTilings(new_bounds);
+ gfx::Size empty_bounds;
+ SyncTilings(empty_bounds);
EXPECT_EQ(target_->num_tilings(), 0u);
- EXPECT_EQ(target_->layer_bounds().ToString(), new_bounds.ToString());
}
TEST_F(PictureLayerTilingSetSyncTest, AllNew) {
float source_scales[] = {0.5f, 1.f, 1.2f};
for (size_t i = 0; i < arraysize(source_scales); ++i)
- source_->AddTiling(source_scales[i]);
+ source_->AddTiling(source_scales[i], source_bounds_);
float target_scales[] = {0.75f, 1.4f, 3.f};
for (size_t i = 0; i < arraysize(target_scales); ++i)
- target_->AddTiling(target_scales[i]);
+ target_->AddTiling(target_scales[i], target_bounds_);
gfx::Size new_bounds(15, 40);
SyncTilings(new_bounds);
@@ -288,10 +432,10 @@ Tile* FindTileAtOrigin(PictureLayerTiling* tiling) {
TEST_F(PictureLayerTilingSetSyncTest, KeepExisting) {
float source_scales[] = {0.7f, 1.f, 1.1f, 2.f};
for (size_t i = 0; i < arraysize(source_scales); ++i)
- source_->AddTiling(source_scales[i]);
+ source_->AddTiling(source_scales[i], source_bounds_);
float target_scales[] = {0.5f, 1.f, 2.f};
for (size_t i = 0; i < arraysize(target_scales); ++i)
- target_->AddTiling(target_scales[i]);
+ target_->AddTiling(target_scales[i], target_bounds_);
PictureLayerTiling* tiling1 = source_->TilingAtScale(1.f);
ASSERT_TRUE(tiling1);
@@ -323,7 +467,7 @@ TEST_F(PictureLayerTilingSetSyncTest, KeepExisting) {
TEST_F(PictureLayerTilingSetSyncTest, EmptySet) {
float target_scales[] = {0.2f, 1.f};
for (size_t i = 0; i < arraysize(target_scales); ++i)
- target_->AddTiling(target_scales[i]);
+ target_->AddTiling(target_scales[i], target_bounds_);
gfx::Size new_bounds(15, 40);
SyncTilings(new_bounds);
@@ -333,10 +477,10 @@ TEST_F(PictureLayerTilingSetSyncTest, EmptySet) {
TEST_F(PictureLayerTilingSetSyncTest, MinimumScale) {
float source_scales[] = {0.7f, 1.f, 1.1f, 2.f};
for (size_t i = 0; i < arraysize(source_scales); ++i)
- source_->AddTiling(source_scales[i]);
+ source_->AddTiling(source_scales[i], source_bounds_);
float target_scales[] = {0.5f, 0.7f, 1.f, 1.1f, 2.f};
for (size_t i = 0; i < arraysize(target_scales); ++i)
- target_->AddTiling(target_scales[i]);
+ target_->AddTiling(target_scales[i], target_bounds_);
gfx::Size new_bounds(15, 40);
float minimum_scale = 1.5f;
@@ -348,8 +492,8 @@ TEST_F(PictureLayerTilingSetSyncTest, MinimumScale) {
}
TEST_F(PictureLayerTilingSetSyncTest, Invalidation) {
- source_->AddTiling(2.f);
- target_->AddTiling(2.f);
+ source_->AddTiling(2.f, source_bounds_);
+ target_->AddTiling(2.f, target_bounds_);
target_->tiling_at(0)->CreateAllTilesForTesting();
Region layer_invalidation;
@@ -366,7 +510,7 @@ TEST_F(PictureLayerTilingSetSyncTest, Invalidation) {
}
std::vector<Tile*> old_tiles = target_->tiling_at(0)->AllTilesForTesting();
- std::map<gfx::Point, scoped_refptr<Tile> > old_tile_map;
+ std::map<gfx::Point, scoped_refptr<Tile>> old_tile_map;
for (size_t i = 0; i < old_tiles.size(); ++i)
old_tile_map[old_tiles[i]->content_rect().origin()] = old_tiles[i];
@@ -376,7 +520,7 @@ TEST_F(PictureLayerTilingSetSyncTest, Invalidation) {
std::vector<Tile*> new_tiles = target_->tiling_at(0)->AllTilesForTesting();
for (size_t i = 0; i < new_tiles.size(); ++i) {
const Tile* tile = new_tiles[i];
- std::map<gfx::Point, scoped_refptr<Tile> >::iterator find =
+ std::map<gfx::Point, scoped_refptr<Tile>>::iterator find =
old_tile_map.find(tile->content_rect().origin());
if (content_invalidation.Intersects(tile->content_rect()))
EXPECT_NE(tile, find->second.get());
@@ -386,8 +530,8 @@ TEST_F(PictureLayerTilingSetSyncTest, Invalidation) {
}
TEST_F(PictureLayerTilingSetSyncTest, TileSizeChange) {
- source_->AddTiling(1.f);
- target_->AddTiling(1.f);
+ source_->AddTiling(1.f, source_bounds_);
+ target_->AddTiling(1.f, target_bounds_);
target_->tiling_at(0)->CreateAllTilesForTesting();
std::vector<Tile*> original_tiles =
diff --git a/chromium/cc/resources/picture_layer_tiling_unittest.cc b/chromium/cc/resources/picture_layer_tiling_unittest.cc
index bfdd6fce8a5..f793097b7f4 100644
--- a/chromium/cc/resources/picture_layer_tiling_unittest.cc
+++ b/chromium/cc/resources/picture_layer_tiling_unittest.cc
@@ -15,8 +15,9 @@
#include "cc/test/test_context_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
namespace cc {
namespace {
@@ -40,10 +41,11 @@ static void UpdateAllTilePriorities(PictureLayerTilingSet* set,
float layer_contents_scale,
double current_frame_time_in_seconds) {
for (size_t i = 0; i < set->num_tilings(); ++i) {
- set->tiling_at(i)->UpdateTilePriorities(tree,
- visible_layer_rect,
- layer_contents_scale,
- current_frame_time_in_seconds);
+ set->tiling_at(i)->ComputeTilePriorityRects(tree,
+ visible_layer_rect,
+ layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
}
}
@@ -62,7 +64,13 @@ class TestablePictureLayerTiling : public PictureLayerTiling {
client));
}
+ gfx::Rect live_tiles_rect() const { return live_tiles_rect_; }
+ bool eviction_tiles_cache_valid() const {
+ return eviction_tiles_cache_valid_;
+ }
+
using PictureLayerTiling::ComputeSkewport;
+ using PictureLayerTiling::RemoveTileAt;
protected:
TestablePictureLayerTiling(float contents_scale,
@@ -80,6 +88,7 @@ class PictureLayerTilingIteratorTest : public testing::Test {
float contents_scale,
const gfx::Size& layer_bounds) {
client_.SetTileSize(tile_size);
+ client_.set_tree(PENDING_TREE);
tiling_ = TestablePictureLayerTiling::Create(contents_scale,
layer_bounds,
&client_);
@@ -169,7 +178,7 @@ class PictureLayerTilingIteratorTest : public testing::Test {
const gfx::Rect& dest_rect) {
float dest_to_contents_scale = tiling_->contents_scale() / rect_scale;
gfx::Rect clamped_rect = gfx::ScaleToEnclosingRect(
- tiling_->TilingRect(), 1.f / dest_to_contents_scale);
+ gfx::Rect(tiling_->tiling_size()), 1.f / dest_to_contents_scale);
clamped_rect.Intersect(dest_rect);
VerifyTilesExactlyCoverRect(rect_scale, dest_rect, clamped_rect);
}
@@ -187,7 +196,8 @@ class PictureLayerTilingIteratorTest : public testing::Test {
};
TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
- // Verifies that a resize deletes tiles that used to be on the edge.
+ // Verifies that a resize with invalidation for newly exposed pixels will
+ // deletes tiles that intersect that invalidation.
gfx::Size tile_size(100, 100);
gfx::Size original_layer_size(10, 10);
Initialize(tile_size, 1.f, original_layer_size);
@@ -199,8 +209,225 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
// Stop creating tiles so that any invalidations are left as holes.
client_.set_allow_create_tile(false);
- tiling_->SetLayerBounds(gfx::Size(200, 200));
+ Region invalidation =
+ SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
+ tiling_->UpdateTilesToCurrentPile(invalidation, gfx::Size(200, 200));
+ EXPECT_FALSE(tiling_->TileAt(0, 0));
+}
+
+TEST_F(PictureLayerTilingIteratorTest, CreateMissingTilesStaysInsideLiveRect) {
+ // The tiling has three rows and columns.
+ Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 250));
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());
+
+ // The live tiles rect is at the very edge of the right-most and
+ // bottom-most tiles. Their border pixels would still be inside the live
+ // tiles rect, but the tiles should not exist just for that.
+ int right = tiling_->TilingDataForTesting().TileBounds(2, 2).x();
+ int bottom = tiling_->TilingDataForTesting().TileBounds(2, 2).y();
+
+ SetLiveRectAndVerifyTiles(gfx::Rect(right, bottom));
+ EXPECT_FALSE(tiling_->TileAt(2, 0));
+ EXPECT_FALSE(tiling_->TileAt(2, 1));
+ EXPECT_FALSE(tiling_->TileAt(2, 2));
+ EXPECT_FALSE(tiling_->TileAt(1, 2));
+ EXPECT_FALSE(tiling_->TileAt(0, 2));
+
+ // Verify CreateMissingTilesInLiveTilesRect respects this.
+ tiling_->CreateMissingTilesInLiveTilesRect();
+ EXPECT_FALSE(tiling_->TileAt(2, 0));
+ EXPECT_FALSE(tiling_->TileAt(2, 1));
+ EXPECT_FALSE(tiling_->TileAt(2, 2));
+ EXPECT_FALSE(tiling_->TileAt(1, 2));
+ EXPECT_FALSE(tiling_->TileAt(0, 2));
+}
+
+TEST_F(PictureLayerTilingIteratorTest, ResizeTilingOverTileBorders) {
+ // The tiling has four rows and three columns.
+ Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350));
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
+ EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
+
+ // The live tiles rect covers the whole tiling.
+ SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));
+
+ // Tiles in the bottom row and right column exist.
+ EXPECT_TRUE(tiling_->TileAt(2, 0));
+ EXPECT_TRUE(tiling_->TileAt(2, 1));
+ EXPECT_TRUE(tiling_->TileAt(2, 2));
+ EXPECT_TRUE(tiling_->TileAt(2, 3));
+ EXPECT_TRUE(tiling_->TileAt(1, 3));
+ EXPECT_TRUE(tiling_->TileAt(0, 3));
+
+ int right = tiling_->TilingDataForTesting().TileBounds(2, 2).x();
+ int bottom = tiling_->TilingDataForTesting().TileBounds(2, 3).y();
+
+ // Shrink the tiling so that the last tile row/column is entirely in the
+ // border pixels of the interior tiles. That row/column is removed.
+ Region invalidation;
+ tiling_->UpdateTilesToCurrentPile(invalidation,
+ gfx::Size(right + 1, bottom + 1));
+ EXPECT_EQ(2, tiling_->TilingDataForTesting().num_tiles_x());
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());
+
+ // The live tiles rect was clamped to the pile size.
+ EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());
+
+ // Since the row/column is gone, the tiles should be gone too.
+ EXPECT_FALSE(tiling_->TileAt(2, 0));
+ EXPECT_FALSE(tiling_->TileAt(2, 1));
+ EXPECT_FALSE(tiling_->TileAt(2, 2));
+ EXPECT_FALSE(tiling_->TileAt(2, 3));
+ EXPECT_FALSE(tiling_->TileAt(1, 3));
+ EXPECT_FALSE(tiling_->TileAt(0, 3));
+
+ // Growing outside the current right/bottom tiles border pixels should create
+ // the tiles again, even though the live rect has not changed size.
+ tiling_->UpdateTilesToCurrentPile(invalidation,
+ gfx::Size(right + 2, bottom + 2));
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
+ EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
+
+ // Not changed.
+ EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());
+
+ // The last row/column tiles are inside the live tiles rect.
+ EXPECT_TRUE(gfx::Rect(right + 1, bottom + 1).Intersects(
+ tiling_->TilingDataForTesting().TileBounds(2, 0)));
+ EXPECT_TRUE(gfx::Rect(right + 1, bottom + 1).Intersects(
+ tiling_->TilingDataForTesting().TileBounds(0, 3)));
+
+ EXPECT_TRUE(tiling_->TileAt(2, 0));
+ EXPECT_TRUE(tiling_->TileAt(2, 1));
+ EXPECT_TRUE(tiling_->TileAt(2, 2));
+ EXPECT_TRUE(tiling_->TileAt(2, 3));
+ EXPECT_TRUE(tiling_->TileAt(1, 3));
+ EXPECT_TRUE(tiling_->TileAt(0, 3));
+}
+
+TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverTileBorders) {
+ // The tiling has three rows and columns.
+ Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350));
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
+ EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
+
+ // The live tiles rect covers the whole tiling.
+ SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));
+
+ // Tiles in the bottom row and right column exist.
+ EXPECT_TRUE(tiling_->TileAt(2, 0));
+ EXPECT_TRUE(tiling_->TileAt(2, 1));
+ EXPECT_TRUE(tiling_->TileAt(2, 2));
+ EXPECT_TRUE(tiling_->TileAt(2, 3));
+ EXPECT_TRUE(tiling_->TileAt(1, 3));
+ EXPECT_TRUE(tiling_->TileAt(0, 3));
+
+ // Shrink the live tiles rect to the very edge of the right-most and
+ // bottom-most tiles. Their border pixels would still be inside the live
+ // tiles rect, but the tiles should not exist just for that.
+ int right = tiling_->TilingDataForTesting().TileBounds(2, 3).x();
+ int bottom = tiling_->TilingDataForTesting().TileBounds(2, 3).y();
+
+ SetLiveRectAndVerifyTiles(gfx::Rect(right, bottom));
+ EXPECT_FALSE(tiling_->TileAt(2, 0));
+ EXPECT_FALSE(tiling_->TileAt(2, 1));
+ EXPECT_FALSE(tiling_->TileAt(2, 2));
+ EXPECT_FALSE(tiling_->TileAt(2, 3));
+ EXPECT_FALSE(tiling_->TileAt(1, 3));
+ EXPECT_FALSE(tiling_->TileAt(0, 3));
+
+ // Including the bottom row and right column again, should create the tiles.
+ SetLiveRectAndVerifyTiles(gfx::Rect(right + 1, bottom + 1));
+ EXPECT_TRUE(tiling_->TileAt(2, 0));
+ EXPECT_TRUE(tiling_->TileAt(2, 1));
+ EXPECT_TRUE(tiling_->TileAt(2, 2));
+ EXPECT_TRUE(tiling_->TileAt(2, 3));
+ EXPECT_TRUE(tiling_->TileAt(1, 2));
+ EXPECT_TRUE(tiling_->TileAt(0, 2));
+
+ // Shrink the live tiles rect to the very edge of the left-most and
+ // top-most tiles. Their border pixels would still be inside the live
+ // tiles rect, but the tiles should not exist just for that.
+ int left = tiling_->TilingDataForTesting().TileBounds(0, 0).right();
+ int top = tiling_->TilingDataForTesting().TileBounds(0, 0).bottom();
+
+ SetLiveRectAndVerifyTiles(gfx::Rect(left, top, 250 - left, 350 - top));
+ EXPECT_FALSE(tiling_->TileAt(0, 3));
+ EXPECT_FALSE(tiling_->TileAt(0, 2));
+ EXPECT_FALSE(tiling_->TileAt(0, 1));
+ EXPECT_FALSE(tiling_->TileAt(0, 0));
+ EXPECT_FALSE(tiling_->TileAt(1, 0));
+ EXPECT_FALSE(tiling_->TileAt(2, 0));
+
+ // Including the top row and left column again, should create the tiles.
+ SetLiveRectAndVerifyTiles(
+ gfx::Rect(left - 1, top - 1, 250 - left, 350 - top));
+ EXPECT_TRUE(tiling_->TileAt(0, 3));
+ EXPECT_TRUE(tiling_->TileAt(0, 2));
+ EXPECT_TRUE(tiling_->TileAt(0, 1));
+ EXPECT_TRUE(tiling_->TileAt(0, 0));
+ EXPECT_TRUE(tiling_->TileAt(1, 0));
+ EXPECT_TRUE(tiling_->TileAt(2, 0));
+}
+
+TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverSameTiles) {
+ // The tiling has four rows and three columns.
+ Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350));
+ EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
+ EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
+
+ // The live tiles rect covers the whole tiling.
+ SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));
+
+ // All tiles exist.
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 4; ++j)
+ EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
+ }
+
+ // Shrink the live tiles rect, but still cover all the tiles.
+ SetLiveRectAndVerifyTiles(gfx::Rect(1, 1, 249, 349));
+
+ // All tiles still exist.
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 4; ++j)
+ EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
+ }
+
+ // Grow the live tiles rect, but still cover all the same tiles.
+ SetLiveRectAndVerifyTiles(gfx::Rect(0, 0, 250, 350));
+
+ // All tiles still exist.
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 4; ++j)
+ EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
+ }
+}
+
+TEST_F(PictureLayerTilingIteratorTest, ResizeOverBorderPixelsDeletesTiles) {
+ // Verifies that a resize with invalidation for newly exposed pixels will
+ // deletes tiles that intersect that invalidation.
+ gfx::Size tile_size(100, 100);
+ gfx::Size original_layer_size(99, 99);
+ Initialize(tile_size, 1.f, original_layer_size);
+ SetLiveRectAndVerifyTiles(gfx::Rect(original_layer_size));
+
+ // Tiling only has one tile, since its total size is less than one.
+ EXPECT_TRUE(tiling_->TileAt(0, 0));
+
+ // Stop creating tiles so that any invalidations are left as holes.
+ client_.set_allow_create_tile(false);
+
+ Region invalidation =
+ SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size));
+ tiling_->UpdateTilesToCurrentPile(invalidation, gfx::Size(200, 200));
EXPECT_FALSE(tiling_->TileAt(0, 0));
+
+ // The original tile was the same size after resize, but it would include new
+ // border pixels.
+ EXPECT_EQ(gfx::Rect(original_layer_size),
+ tiling_->TilingDataForTesting().TileBounds(0, 0));
}
TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) {
@@ -307,6 +534,7 @@ TEST_F(PictureLayerTilingIteratorTest, NonContainedDestRect) {
TEST(PictureLayerTilingTest, SkewportLimits) {
FakePictureLayerTilingClient client;
client.set_skewport_extrapolation_limit_in_content_pixels(75);
+ client.set_tree(ACTIVE_TREE);
scoped_ptr<TestablePictureLayerTiling> tiling;
gfx::Rect viewport(0, 0, 100, 100);
@@ -315,7 +543,8 @@ TEST(PictureLayerTilingTest, SkewportLimits) {
client.SetTileSize(gfx::Size(100, 100));
tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 1.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.f, 1.0, Occlusion());
// Move viewport down 50 pixels in 0.5 seconds.
gfx::Rect down_skewport =
@@ -378,9 +607,11 @@ TEST(PictureLayerTilingTest, ComputeSkewport) {
gfx::Size layer_bounds(200, 200);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 1.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.f, 1.0, Occlusion());
// Move viewport down 50 pixels in 0.5 seconds.
gfx::Rect down_skewport =
@@ -436,6 +667,7 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
gfx::Size layer_bounds(1500, 1500);
client.SetTileSize(gfx::Size(10, 10));
+ client.set_tree(ACTIVE_TREE);
// Tiling at 0.25 scale: this should create 47x47 tiles of size 10x10.
// The reason is that each tile has a one pixel border, so tile at (1, 2)
@@ -446,7 +678,9 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
gfx::Rect viewport_in_content_space =
gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 1.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.f, 1.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
gfx::Rect soon_rect = viewport;
soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
@@ -475,11 +709,12 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
Tile* tile = tiling->TileAt(i, j);
TilePriority priority = tile->priority(ACTIVE_TREE);
- if (viewport_in_content_space.Intersects(tile->content_rect())) {
+ gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
+ if (viewport_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
have_now = true;
- } else if (soon_rect_in_content_space.Intersects(tile->content_rect())) {
+ } else if (soon_rect_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::SOON, priority.priority_bin);
have_soon = true;
} else {
@@ -529,7 +764,9 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
EXPECT_EQ(25, skewport.width());
EXPECT_EQ(35, skewport.height());
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 2.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.f, 2.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
have_now = false;
have_eventually = false;
@@ -542,14 +779,15 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
Tile* tile = tiling->TileAt(i, j);
TilePriority priority = tile->priority(ACTIVE_TREE);
- if (viewport_in_content_space.Intersects(tile->content_rect())) {
+ gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
+ if (viewport_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::NOW, priority.priority_bin) << "i: " << i
<< " j: " << j;
EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible) << "i: " << i
<< " j: " << j;
have_now = true;
- } else if (skewport.Intersects(tile->content_rect()) ||
- soon_rect_in_content_space.Intersects(tile->content_rect())) {
+ } else if (skewport.Intersects(tile_rect) ||
+ soon_rect_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::SOON, priority.priority_bin) << "i: " << i
<< " j: " << j;
EXPECT_GT(priority.distance_to_visible, 0.f) << "i: " << i
@@ -576,19 +814,49 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
EXPECT_FLOAT_EQ(28.f, priority.distance_to_visible);
priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
- EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
+ EXPECT_FLOAT_EQ(4.f, priority.distance_to_visible);
// Change the underlying layer scale.
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 2.0f, 3.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 2.0f, 3.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
- EXPECT_FLOAT_EQ(34.f, priority.distance_to_visible);
+ EXPECT_FLOAT_EQ(136.f, priority.distance_to_visible);
priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
- EXPECT_FLOAT_EQ(14.f, priority.distance_to_visible);
+ EXPECT_FLOAT_EQ(56.f, priority.distance_to_visible);
priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
- EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
+ EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible);
+
+ // Test additional scales.
+ tiling = TestablePictureLayerTiling::Create(0.2f, layer_bounds, &client);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 4.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
+
+ priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
+ EXPECT_FLOAT_EQ(110.f, priority.distance_to_visible);
+
+ priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
+ EXPECT_FLOAT_EQ(70.f, priority.distance_to_visible);
+
+ priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
+ EXPECT_FLOAT_EQ(60.f, priority.distance_to_visible);
+
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 0.5f, 5.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
+
+ priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
+ EXPECT_FLOAT_EQ(55.f, priority.distance_to_visible);
+
+ priority = tiling->TileAt(2, 5)->priority(ACTIVE_TREE);
+ EXPECT_FLOAT_EQ(35.f, priority.distance_to_visible);
+
+ priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
+ EXPECT_FLOAT_EQ(30.f, priority.distance_to_visible);
}
TEST(PictureLayerTilingTest, ExpandRectEqual) {
@@ -609,7 +877,11 @@ TEST(PictureLayerTilingTest, ExpandRectSmaller) {
EXPECT_EQ(out.bottom() - in.bottom(), in.y() - out.y());
EXPECT_EQ(out.right() - in.right(), in.x() - out.x());
EXPECT_EQ(out.width() - in.width(), out.height() - in.height());
- EXPECT_NEAR(100 * 100, out.width() * out.height(), 50);
+
+ // |in| represents the visible rect, and |out| represents the eventually rect.
+ // If the eventually rect doesn't contain the visible rect, we will start
+ // losing tiles.
+ EXPECT_TRUE(out.Contains(in));
EXPECT_TRUE(bounds.Contains(out));
}
@@ -820,9 +1092,12 @@ TEST(PictureLayerTilingTest, TilingRasterTileIteratorStaticViewport) {
soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
client.SetTileSize(gfx::Size(30, 30));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 1.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
PictureLayerTiling::TilingRasterTileIterator empty_iterator;
EXPECT_FALSE(empty_iterator);
@@ -840,7 +1115,7 @@ TEST(PictureLayerTilingTest, TilingRasterTileIteratorStaticViewport) {
// 3. Third iteration ensures that no tiles are returned, since they were all
// marked as ready to draw.
for (int i = 0; i < 3; ++i) {
- PictureLayerTiling::TilingRasterTileIterator it(tiling.get(), ACTIVE_TREE);
+ PictureLayerTiling::TilingRasterTileIterator it(tiling.get());
// There are 3 bins in TilePriority.
bool have_tiles[3] = {};
@@ -860,10 +1135,8 @@ TEST(PictureLayerTilingTest, TilingRasterTileIteratorStaticViewport) {
// On the second iteration, mark everything as ready to draw (solid color).
if (i == 1) {
- ManagedTileState::TileVersion& tile_version =
- last_tile->GetTileVersionForTesting(
- last_tile->DetermineRasterModeForTree(ACTIVE_TREE));
- tile_version.SetSolidColorForTesting(SK_ColorRED);
+ ManagedTileState::DrawInfo& draw_info = last_tile->draw_info();
+ draw_info.SetSolidColorForTesting(SK_ColorRED);
}
++it;
int eventually_bin_order_correct_count = 0;
@@ -898,10 +1171,8 @@ TEST(PictureLayerTilingTest, TilingRasterTileIteratorStaticViewport) {
// On the second iteration, mark everything as ready to draw (solid
// color).
if (i == 1) {
- ManagedTileState::TileVersion& tile_version =
- last_tile->GetTileVersionForTesting(
- last_tile->DetermineRasterModeForTree(ACTIVE_TREE));
- tile_version.SetSolidColorForTesting(SK_ColorRED);
+ ManagedTileState::DrawInfo& draw_info = last_tile->draw_info();
+ draw_info.SetSolidColorForTesting(SK_ColorRED);
}
}
@@ -927,10 +1198,14 @@ TEST(PictureLayerTilingTest, TilingRasterTileIteratorMovingViewport) {
gfx::Size layer_bounds(1000, 1000);
client.SetTileSize(gfx::Size(30, 30));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.f, layer_bounds, &client);
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 1.0);
- tiling->UpdateTilePriorities(ACTIVE_TREE, moved_viewport, 1.0f, 2.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, moved_viewport, 1.0f, 2.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
gfx::Rect soon_rect = moved_viewport;
soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
@@ -940,9 +1215,7 @@ TEST(PictureLayerTilingTest, TilingRasterTileIteratorMovingViewport) {
Tile* last_tile = NULL;
int eventually_bin_order_correct_count = 0;
int eventually_bin_order_incorrect_count = 0;
- for (PictureLayerTiling::TilingRasterTileIterator it(tiling.get(),
- ACTIVE_TREE);
- it;
+ for (PictureLayerTiling::TilingRasterTileIterator it(tiling.get()); it;
++it) {
if (!last_tile)
last_tile = *it;
@@ -991,59 +1264,95 @@ TEST(PictureLayerTilingTest, TilingEvictionTileIteratorStaticViewport) {
CHECK(output_surface->BindToClient(&output_surface_client));
TestSharedBitmapManager shared_bitmap_manager;
scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
- output_surface.get(), &shared_bitmap_manager, 0, false, 1, false);
+ output_surface.get(), &shared_bitmap_manager, NULL, NULL, 0, false, 1);
FakePictureLayerTilingClient client(resource_provider.get());
scoped_ptr<TestablePictureLayerTiling> tiling;
gfx::Rect viewport(50, 50, 100, 100);
- gfx::Size layer_bounds(200, 200);
+ gfx::Size layer_bounds(2000, 2000);
client.SetTileSize(gfx::Size(30, 30));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
- tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 1.0);
+ tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
PictureLayerTiling::TilingRasterTileIterator empty_iterator;
EXPECT_FALSE(empty_iterator);
std::vector<Tile*> all_tiles = tiling->AllTilesForTesting();
- PictureLayerTiling::TilingEvictionTileIterator it(tiling.get(),
- SMOOTHNESS_TAKES_PRIORITY);
+ PictureLayerTiling::TilingEvictionTileIterator it(
+ tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::NOW);
// Tiles don't have resources to evict.
EXPECT_FALSE(it);
// Sanity check.
- EXPECT_EQ(64u, all_tiles.size());
+ EXPECT_EQ(5184u, all_tiles.size());
client.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
std::set<Tile*> all_tiles_set(all_tiles.begin(), all_tiles.end());
+ std::set<Tile*> eviction_tiles;
+
it = PictureLayerTiling::TilingEvictionTileIterator(
- tiling.get(), SMOOTHNESS_TAKES_PRIORITY);
+ tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::EVENTUALLY);
EXPECT_TRUE(it);
+ for (; it; ++it) {
+ Tile* tile = *it;
+ EXPECT_TRUE(tile);
+ EXPECT_EQ(TilePriority::EVENTUALLY,
+ tile->priority(ACTIVE_TREE).priority_bin);
+ EXPECT_FALSE(tile->required_for_activation());
+ eviction_tiles.insert(tile);
+ }
- std::set<Tile*> eviction_tiles;
- Tile* last_tile = *it;
+ it = PictureLayerTiling::TilingEvictionTileIterator(
+ tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::SOON);
+ EXPECT_TRUE(it);
for (; it; ++it) {
Tile* tile = *it;
EXPECT_TRUE(tile);
- EXPECT_LE(tile->priority(ACTIVE_TREE).priority_bin,
- last_tile->priority(ACTIVE_TREE).priority_bin);
- if (tile->priority(ACTIVE_TREE).priority_bin ==
- last_tile->priority(ACTIVE_TREE).priority_bin) {
- EXPECT_LE(tile->priority(ACTIVE_TREE).distance_to_visible,
- last_tile->priority(ACTIVE_TREE).distance_to_visible);
- }
- last_tile = tile;
+ EXPECT_EQ(TilePriority::SOON, tile->priority(ACTIVE_TREE).priority_bin);
+ EXPECT_FALSE(tile->required_for_activation());
eviction_tiles.insert(tile);
}
+ it = PictureLayerTiling::TilingEvictionTileIterator(
+ tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::NOW);
+ EXPECT_TRUE(it);
+ for (; it; ++it) {
+ Tile* tile = *it;
+ EXPECT_TRUE(tile);
+ EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
+ EXPECT_FALSE(tile->required_for_activation());
+ eviction_tiles.insert(tile);
+ }
+
+ it = PictureLayerTiling::TilingEvictionTileIterator(
+ tiling.get(),
+ SMOOTHNESS_TAKES_PRIORITY,
+ PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION);
+ EXPECT_FALSE(it);
+
EXPECT_GT(all_tiles_set.size(), 0u);
EXPECT_EQ(all_tiles_set, eviction_tiles);
+
+ EXPECT_TRUE(tiling->eviction_tiles_cache_valid());
+ tiling->RemoveTileAt(0, 0, nullptr);
+ EXPECT_FALSE(tiling->eviction_tiles_cache_valid());
+
+ it = PictureLayerTiling::TilingEvictionTileIterator(
+ tiling.get(), SMOOTHNESS_TAKES_PRIORITY,
+ PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION);
+ EXPECT_TRUE(tiling->eviction_tiles_cache_valid());
+ tiling->Reset();
+ EXPECT_FALSE(tiling->eviction_tiles_cache_valid());
}
TEST_F(PictureLayerTilingIteratorTest, TilesExist) {
@@ -1052,18 +1361,21 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExist) {
VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));
- tiling_->UpdateTilePriorities(
+ client_.set_tree(ACTIVE_TREE);
+ tiling_->ComputeTilePriorityRects(
ACTIVE_TREE,
gfx::Rect(layer_bounds), // visible content rect
1.f, // current contents scale
- 1.0); // current frame time
+ 1.0, // current frame time
+ Occlusion());
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
// Make the viewport rect empty. All tiles are killed and become zombies.
- tiling_->UpdateTilePriorities(ACTIVE_TREE,
- gfx::Rect(), // visible content rect
- 1.f, // current contents scale
- 2.0); // current frame time
+ tiling_->ComputeTilePriorityRects(ACTIVE_TREE,
+ gfx::Rect(), // visible content rect
+ 1.f, // current contents scale
+ 2.0, // current frame time
+ Occlusion());
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));
}
@@ -1075,18 +1387,21 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExistGiantViewport) {
gfx::Rect giant_rect(-10000000, -10000000, 1000000000, 1000000000);
- tiling_->UpdateTilePriorities(
+ client_.set_tree(ACTIVE_TREE);
+ tiling_->ComputeTilePriorityRects(
ACTIVE_TREE,
gfx::Rect(layer_bounds), // visible content rect
1.f, // current contents scale
- 1.0); // current frame time
+ 1.0, // current frame time
+ Occlusion());
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
// If the visible content rect is empty, it should still have live tiles.
- tiling_->UpdateTilePriorities(ACTIVE_TREE,
- giant_rect, // visible content rect
- 1.f, // current contents scale
- 2.0); // current frame time
+ tiling_->ComputeTilePriorityRects(ACTIVE_TREE,
+ giant_rect, // visible content rect
+ 1.f, // current contents scale
+ 2.0, // current frame time
+ Occlusion());
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
}
@@ -1101,10 +1416,12 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExistOutsideViewport) {
gfx::Rect viewport_rect(1100, 0, 1000, 1000);
EXPECT_FALSE(viewport_rect.Intersects(gfx::Rect(layer_bounds)));
- tiling_->UpdateTilePriorities(ACTIVE_TREE,
- viewport_rect, // visible content rect
- 1.f, // current contents scale
- 1.0); // current frame time
+ client_.set_tree(ACTIVE_TREE);
+ tiling_->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_rect, // visible content rect
+ 1.f, // current contents scale
+ 1.0, // current frame time
+ Occlusion());
VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
}
@@ -1128,56 +1445,28 @@ TEST_F(PictureLayerTilingIteratorTest,
gfx::Rect visible_rect(8000, 8000, 50, 50);
+ client_.set_tree(ACTIVE_TREE);
set_max_tiles_for_interest_area(1);
- tiling_->UpdateTilePriorities(ACTIVE_TREE,
- visible_rect, // visible content rect
- 1.f, // current contents scale
- 1.0); // current frame time
+ tiling_->ComputeTilePriorityRects(ACTIVE_TREE,
+ visible_rect, // visible content rect
+ 1.f, // current contents scale
+ 1.0, // current frame time
+ Occlusion());
VerifyTiles(1.f,
gfx::Rect(layer_bounds),
base::Bind(&TilesIntersectingRectExist, visible_rect, true));
}
-static void CountExistingTiles(int *count,
- Tile* tile,
- const gfx::Rect& geometry_rect) {
- if (tile != NULL)
- ++(*count);
-}
-
-TEST_F(PictureLayerTilingIteratorTest,
- TilesExistLargeViewportAndLayerWithLargeVisibleArea) {
- gfx::Size layer_bounds(10000, 10000);
- Initialize(gfx::Size(100, 100), 1.f, layer_bounds);
- VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds));
- VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));
-
- set_max_tiles_for_interest_area(1);
- tiling_->UpdateTilePriorities(
- ACTIVE_TREE,
- gfx::Rect(layer_bounds), // visible content rect
- 1.f, // current contents scale
- 1.0); // current frame time
-
- int num_tiles = 0;
- VerifyTiles(1.f,
- gfx::Rect(layer_bounds),
- base::Bind(&CountExistingTiles, &num_tiles));
- // If we're making a rect the size of one tile, it can only overlap up to 4
- // tiles depending on its position.
- EXPECT_LE(num_tiles, 4);
- VerifyTiles(1.f, gfx::Rect(), base::Bind(&TileExists, false));
-}
-
TEST_F(PictureLayerTilingIteratorTest, AddTilingsToMatchScale) {
gfx::Size layer_bounds(1099, 801);
gfx::Size tile_size(100, 100);
client_.SetTileSize(tile_size);
+ client_.set_tree(PENDING_TREE);
- PictureLayerTilingSet active_set(&client_, layer_bounds);
+ PictureLayerTilingSet active_set(&client_);
- active_set.AddTiling(1.f);
+ active_set.AddTiling(1.f, layer_bounds);
VerifyTiles(active_set.tiling_at(0),
1.f,
@@ -1197,7 +1486,7 @@ TEST_F(PictureLayerTilingIteratorTest, AddTilingsToMatchScale) {
base::Bind(&TileExists, true));
// Add the same tilings to the pending set.
- PictureLayerTilingSet pending_set(&client_, layer_bounds);
+ PictureLayerTilingSet pending_set(&client_);
Region invalidation;
pending_set.SyncTilings(active_set, layer_bounds, invalidation, 0.f);
@@ -1207,7 +1496,7 @@ TEST_F(PictureLayerTilingIteratorTest, AddTilingsToMatchScale) {
gfx::Rect(layer_bounds),
base::Bind(&TileExists, false));
- // UpdateTilePriorities on the pending tiling at the same frame time. The
+ // ComputeTilePriorityRects on the pending tiling at the same frame time. The
// pending tiling should get tiles.
UpdateAllTilePriorities(&pending_set,
PENDING_TREE,
@@ -1221,7 +1510,7 @@ TEST_F(PictureLayerTilingIteratorTest, AddTilingsToMatchScale) {
base::Bind(&TileExists, true));
}
-TEST(UpdateTilePrioritiesTest, VisibleTiles) {
+TEST(ComputeTilePriorityRectsTest, VisibleTiles) {
// The TilePriority of visible tiles should have zero distance_to_visible
// and time_to_visible.
@@ -1239,14 +1528,17 @@ TEST(UpdateTilePrioritiesTest, VisibleTiles) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1270,7 +1562,7 @@ TEST(UpdateTilePrioritiesTest, VisibleTiles) {
EXPECT_FLOAT_EQ(TilePriority::NOW, priority.priority_bin);
}
-TEST(UpdateTilePrioritiesTest, OffscreenTiles) {
+TEST(ComputeTilePriorityRectsTest, OffscreenTiles) {
// The TilePriority of offscreen tiles (without movement) should have nonzero
// distance_to_visible and infinite time_to_visible.
@@ -1292,14 +1584,17 @@ TEST(UpdateTilePrioritiesTest, OffscreenTiles) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1333,7 +1628,7 @@ TEST(UpdateTilePrioritiesTest, OffscreenTiles) {
EXPECT_GT(right.distance_to_visible, left.distance_to_visible);
}
-TEST(UpdateTilePrioritiesTest, PartiallyOffscreenLayer) {
+TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenLayer) {
// Sanity check that a layer with some tiles visible and others offscreen has
// correct TilePriorities for each tile.
@@ -1355,14 +1650,17 @@ TEST(UpdateTilePrioritiesTest, PartiallyOffscreenLayer) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1386,9 +1684,9 @@ TEST(UpdateTilePrioritiesTest, PartiallyOffscreenLayer) {
EXPECT_NE(TilePriority::NOW, priority.priority_bin);
}
-TEST(UpdateTilePrioritiesTest, PartiallyOffscreenRotatedLayer) {
+TEST(ComputeTilePriorityRectsTest, PartiallyOffscreenRotatedLayer) {
// Each tile of a layer may be affected differently by a transform; Check
- // that UpdateTilePriorities correctly accounts for the transform between
+ // that ComputeTilePriorityRects correctly accounts for the transform between
// layer space and screen space.
FakePictureLayerTilingClient client;
@@ -1412,14 +1710,17 @@ TEST(UpdateTilePrioritiesTest, PartiallyOffscreenRotatedLayer) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1452,7 +1753,7 @@ TEST(UpdateTilePrioritiesTest, PartiallyOffscreenRotatedLayer) {
EXPECT_EQ(bottom_right.distance_to_visible, top_right.distance_to_visible);
}
-TEST(UpdateTilePrioritiesTest, PerspectiveLayer) {
+TEST(ComputeTilePriorityRectsTest, PerspectiveLayer) {
// Perspective transforms need to take a different code path.
// This test checks tile priorities of a perspective layer.
@@ -1493,14 +1794,17 @@ TEST(UpdateTilePrioritiesTest, PerspectiveLayer) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1538,7 +1842,7 @@ TEST(UpdateTilePrioritiesTest, PerspectiveLayer) {
EXPECT_GT(bottom_left.distance_to_visible, top_left.distance_to_visible);
}
-TEST(UpdateTilePrioritiesTest, PerspectiveLayerClippedByW) {
+TEST(ComputeTilePriorityRectsTest, PerspectiveLayerClippedByW) {
// Perspective transforms need to take a different code path.
// This test checks tile priorities of a perspective layer.
@@ -1584,14 +1888,17 @@ TEST(UpdateTilePrioritiesTest, PerspectiveLayerClippedByW) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1619,7 +1926,7 @@ TEST(UpdateTilePrioritiesTest, PerspectiveLayerClippedByW) {
EXPECT_NE(TilePriority::NOW, priority.priority_bin);
}
-TEST(UpdateTilePrioritiesTest, BasicMotion) {
+TEST(ComputeTilePriorityRectsTest, BasicMotion) {
// Test that time_to_visible is computed correctly when
// there is some motion.
@@ -1645,21 +1952,25 @@ TEST(UpdateTilePrioritiesTest, BasicMotion) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
// previous ("last") frame
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- last_layer_contents_scale,
- last_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ last_layer_contents_scale,
+ last_frame_time_in_seconds,
+ Occlusion());
// current frame
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1685,9 +1996,9 @@ TEST(UpdateTilePrioritiesTest, BasicMotion) {
EXPECT_NE(TilePriority::NOW, priority.priority_bin);
}
-TEST(UpdateTilePrioritiesTest, RotationMotion) {
+TEST(ComputeTilePriorityRectsTest, RotationMotion) {
// Each tile of a layer may be affected differently by a transform; Check
- // that UpdateTilePriorities correctly accounts for the transform between
+ // that ComputeTilePriorityRects correctly accounts for the transform between
// layer space and screen space.
FakePictureLayerTilingClient client;
@@ -1720,21 +2031,25 @@ TEST(UpdateTilePrioritiesTest, RotationMotion) {
current_screen_transform, device_viewport);
client.SetTileSize(gfx::Size(100, 100));
+ client.set_tree(ACTIVE_TREE);
tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
current_layer_bounds,
&client);
// previous ("last") frame
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- last_layer_contents_scale,
- last_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ last_layer_contents_scale,
+ last_frame_time_in_seconds,
+ Occlusion());
// current frame
- tiling->UpdateTilePriorities(ACTIVE_TREE,
- viewport_in_layer_space,
- current_layer_contents_scale,
- current_frame_time_in_seconds);
+ tiling->ComputeTilePriorityRects(ACTIVE_TREE,
+ viewport_in_layer_space,
+ current_layer_contents_scale,
+ current_frame_time_in_seconds,
+ Occlusion());
+ tiling->UpdateAllTilePrioritiesForTesting();
ASSERT_TRUE(tiling->TileAt(0, 0));
ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1754,5 +2069,114 @@ TEST(UpdateTilePrioritiesTest, RotationMotion) {
EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
}
+TEST(PictureLayerTilingTest, RecycledTilesCleared) {
+ // This test performs the following:
+ // Setup:
+ // - Two tilings, one active one recycled with all tiles shared.
+ // Procedure:
+ // - Viewport moves somewhere far away and active tiling clears tiles.
+ // - Viewport moves back and a new active tiling tile is created.
+ // Result:
+ // - Recycle tiling does _not_ have the tile in the same location (thus it
+ // will be shared next time a pending tiling is created).
+
+ FakePictureLayerTilingClient active_client;
+ scoped_ptr<TestablePictureLayerTiling> active_tiling;
+
+ active_client.SetTileSize(gfx::Size(100, 100));
+ active_client.set_tree(ACTIVE_TREE);
+ active_client.set_max_tiles_for_interest_area(10);
+ active_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
+ gfx::Size(10000, 10000),
+ &active_client);
+ // Create all tiles on this tiling.
+ active_tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
+
+ FakePictureLayerTilingClient recycle_client;
+ recycle_client.SetTileSize(gfx::Size(100, 100));
+ recycle_client.set_tree(PENDING_TREE);
+ recycle_client.set_twin_tiling(active_tiling.get());
+ recycle_client.set_max_tiles_for_interest_area(10);
+
+ scoped_ptr<TestablePictureLayerTiling> recycle_tiling;
+ recycle_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
+ gfx::Size(10000, 10000),
+ &recycle_client);
+
+ // Create all tiles on the second tiling. All tiles should be shared.
+ recycle_tiling->ComputeTilePriorityRects(
+ PENDING_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
+
+ // Set the second tiling as recycled.
+ active_client.set_twin_tiling(NULL);
+ active_client.set_recycled_twin_tiling(recycle_tiling.get());
+ recycle_client.set_twin_tiling(NULL);
+
+ // Verify that tiles exist and are shared.
+ EXPECT_TRUE(active_tiling->TileAt(0, 0));
+ EXPECT_TRUE(recycle_tiling->TileAt(0, 0));
+ EXPECT_EQ(active_tiling->TileAt(0, 0), recycle_tiling->TileAt(0, 0));
+
+ // Move the viewport far away from the (0, 0) tile.
+ active_tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, gfx::Rect(9000, 9000, 100, 100), 1.0f, 2.0, Occlusion());
+ // Ensure the tile was deleted on both tilings.
+ EXPECT_FALSE(active_tiling->TileAt(0, 0));
+ EXPECT_FALSE(recycle_tiling->TileAt(0, 0));
+
+ // Move the viewport back to (0, 0) tile.
+ active_tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 3.0, Occlusion());
+
+ // Ensure that we now have a tile here, but the recycle tiling does not.
+ EXPECT_TRUE(active_tiling->TileAt(0, 0));
+ EXPECT_FALSE(recycle_tiling->TileAt(0, 0));
+}
+
+TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) {
+ FakePictureLayerTilingClient active_client;
+ scoped_ptr<TestablePictureLayerTiling> active_tiling;
+
+ active_client.SetTileSize(gfx::Size(100, 100));
+ active_client.set_tree(ACTIVE_TREE);
+ active_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
+ gfx::Size(100, 100),
+ &active_client);
+ // Create all tiles on this tiling.
+ active_tiling->ComputeTilePriorityRects(
+ ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
+
+ FakePictureLayerTilingClient recycle_client;
+ recycle_client.SetTileSize(gfx::Size(100, 100));
+ recycle_client.set_tree(PENDING_TREE);
+ recycle_client.set_twin_tiling(active_tiling.get());
+ recycle_client.set_max_tiles_for_interest_area(10);
+
+ scoped_ptr<TestablePictureLayerTiling> recycle_tiling;
+ recycle_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale
+ gfx::Size(100, 100),
+ &recycle_client);
+
+ // Create all tiles on the recycle tiling. All tiles should be shared.
+ recycle_tiling->ComputeTilePriorityRects(
+ PENDING_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
+
+ // Set the second tiling as recycled.
+ active_client.set_twin_tiling(NULL);
+ active_client.set_recycled_twin_tiling(recycle_tiling.get());
+ recycle_client.set_twin_tiling(NULL);
+
+ // Verify that tiles exist and are shared.
+ EXPECT_TRUE(active_tiling->TileAt(0, 0));
+ EXPECT_TRUE(recycle_tiling->TileAt(0, 0));
+ EXPECT_EQ(active_tiling->TileAt(0, 0), recycle_tiling->TileAt(0, 0));
+
+ // Reset the active tiling. The recycle tiles should be released too.
+ active_tiling->Reset();
+ EXPECT_FALSE(active_tiling->TileAt(0, 0));
+ EXPECT_FALSE(recycle_tiling->TileAt(0, 0));
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/picture_pile.cc b/chromium/cc/resources/picture_pile.cc
index 6341e88b368..ec843a57d1b 100644
--- a/chromium/cc/resources/picture_pile.cc
+++ b/chromium/cc/resources/picture_pile.cc
@@ -10,31 +10,33 @@
#include "cc/base/region.h"
#include "cc/debug/rendering_stats_instrumentation.h"
-#include "cc/resources/picture_pile_impl.h"
#include "cc/resources/raster_worker_pool.h"
-#include "cc/resources/tile_priority.h"
+#include "skia/ext/analysis_canvas.h"
namespace {
// Layout pixel buffer around the visible layer rect to record. Any base
// picture that intersects the visible layer rect expanded by this distance
// will be recorded.
const int kPixelDistanceToRecord = 8000;
+// We don't perform solid color analysis on images that have more than 10 skia
+// operations.
+const int kOpCountThatIsOkToAnalyze = 10;
// TODO(humper): The density threshold here is somewhat arbitrary; need a
// way to set // this from the command line so we can write a benchmark
// script and find a sweet spot.
const float kDensityThreshold = 0.5f;
-bool rect_sort_y(const gfx::Rect &r1, const gfx::Rect &r2) {
+bool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) {
return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x());
}
-bool rect_sort_x(const gfx::Rect &r1, const gfx::Rect &r2) {
+bool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) {
return r1.x() < r2.x() || (r1.x() == r2.x() && r1.y() < r2.y());
}
-float do_clustering(const std::vector<gfx::Rect>& tiles,
- std::vector<gfx::Rect>* clustered_rects) {
+float PerformClustering(const std::vector<gfx::Rect>& tiles,
+ std::vector<gfx::Rect>* clustered_rects) {
// These variables track the record area and invalid area
// for the entire clustering
int total_record_area = 0;
@@ -89,7 +91,7 @@ float do_clustering(const std::vector<gfx::Rect>& tiles,
return static_cast<float>(total_invalid_area) /
static_cast<float>(total_record_area);
- }
+}
float ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
std::vector<gfx::Rect>* record_rects) {
@@ -113,20 +115,25 @@ float ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
float vertical_density;
std::vector<gfx::Rect> vertical_clustering;
- vertical_density = do_clustering(invalid_tiles_vertical,
- &vertical_clustering);
+ vertical_density = PerformClustering(invalid_tiles_vertical,
+ &vertical_clustering);
+
+ // If vertical density is optimal, then we can return early.
+ if (vertical_density == 1.f) {
+ *record_rects = vertical_clustering;
+ return vertical_density;
+ }
// Now try again with a horizontal sort, see which one is best
- // TODO(humper): Heuristics for skipping this step?
std::vector<gfx::Rect> invalid_tiles_horizontal = invalid_tiles;
- std::sort(invalid_tiles_vertical.begin(),
- invalid_tiles_vertical.end(),
+ std::sort(invalid_tiles_horizontal.begin(),
+ invalid_tiles_horizontal.end(),
rect_sort_x);
float horizontal_density;
std::vector<gfx::Rect> horizontal_clustering;
- horizontal_density = do_clustering(invalid_tiles_vertical,
- &horizontal_clustering);
+ horizontal_density = PerformClustering(invalid_tiles_horizontal,
+ &horizontal_clustering);
if (vertical_density < horizontal_density) {
*record_rects = horizontal_clustering;
@@ -141,7 +148,10 @@ float ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
namespace cc {
-PicturePile::PicturePile() : is_suitable_for_gpu_rasterization_(true) {}
+PicturePile::PicturePile()
+ : is_suitable_for_gpu_rasterization_(true),
+ pixel_record_distance_(kPixelDistanceToRecord) {
+}
PicturePile::~PicturePile() {
}
@@ -152,6 +162,7 @@ bool PicturePile::UpdateAndExpandInvalidation(
SkColor background_color,
bool contents_opaque,
bool contents_fill_bounds_completely,
+ const gfx::Size& layer_size,
const gfx::Rect& visible_layer_rect,
int frame_number,
Picture::RecordingMode recording_mode,
@@ -160,53 +171,280 @@ bool PicturePile::UpdateAndExpandInvalidation(
contents_opaque_ = contents_opaque;
contents_fill_bounds_completely_ = contents_fill_bounds_completely;
+ bool updated = false;
+
+ Region resize_invalidation;
+ gfx::Size old_tiling_size = tiling_size();
+ if (old_tiling_size != layer_size) {
+ tiling_.SetTilingSize(layer_size);
+ updated = true;
+ }
+
gfx::Rect interest_rect = visible_layer_rect;
- interest_rect.Inset(
- -kPixelDistanceToRecord,
- -kPixelDistanceToRecord,
- -kPixelDistanceToRecord,
- -kPixelDistanceToRecord);
+ interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_);
recorded_viewport_ = interest_rect;
- recorded_viewport_.Intersect(tiling_rect());
+ recorded_viewport_.Intersect(gfx::Rect(tiling_size()));
gfx::Rect interest_rect_over_tiles =
tiling_.ExpandRectToTileBounds(interest_rect);
- Region invalidation_expanded_to_full_tiles;
-
- bool invalidated = false;
- for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
- gfx::Rect invalid_rect = i.rect();
- // Split this inflated invalidation across tile boundaries and apply it
- // to all tiles that it touches.
- bool include_borders = true;
- for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders);
- iter;
- ++iter) {
- const PictureMapKey& key = iter.index();
-
- PictureMap::iterator picture_it = picture_map_.find(key);
- if (picture_it == picture_map_.end())
+ gfx::Size min_tiling_size(
+ std::min(tiling_size().width(), old_tiling_size.width()),
+ std::min(tiling_size().height(), old_tiling_size.height()));
+ gfx::Size max_tiling_size(
+ std::max(tiling_size().width(), old_tiling_size.width()),
+ std::max(tiling_size().height(), old_tiling_size.height()));
+
+ if (old_tiling_size != layer_size) {
+ has_any_recordings_ = false;
+
+ // Drop recordings that are outside the new or old layer bounds or that
+ // changed size. Newly exposed areas are considered invalidated.
+ // Previously exposed areas that are now outside of bounds also need to
+ // be invalidated, as they may become part of raster when scale < 1.
+ std::vector<PictureMapKey> to_erase;
+ int min_toss_x = tiling_.num_tiles_x();
+ if (max_tiling_size.width() > min_tiling_size.width()) {
+ min_toss_x =
+ tiling_.FirstBorderTileXIndexFromSrcCoord(min_tiling_size.width());
+ }
+ int min_toss_y = tiling_.num_tiles_y();
+ if (max_tiling_size.height() > min_tiling_size.height()) {
+ min_toss_y =
+ tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height());
+ }
+ for (PictureMap::const_iterator it = picture_map_.begin();
+ it != picture_map_.end();
+ ++it) {
+ const PictureMapKey& key = it->first;
+ if (key.first < min_toss_x && key.second < min_toss_y) {
+ has_any_recordings_ |= !!it->second.GetPicture();
continue;
+ }
+ to_erase.push_back(key);
+ }
- // Inform the grid cell that it has been invalidated in this frame.
- invalidated = picture_it->second.Invalidate(frame_number) || invalidated;
+ for (size_t i = 0; i < to_erase.size(); ++i)
+ picture_map_.erase(to_erase[i]);
+
+ // If a recording is dropped and not re-recorded below, invalidate that
+ // full recording to cause any raster tiles that would use it to be
+ // dropped.
+ // If the recording will be replaced below, invalidate newly exposed
+ // areas and previously exposed areas to force raster tiles that include the
+ // old recording to know there is new recording to display.
+ gfx::Rect min_tiling_rect_over_tiles =
+ tiling_.ExpandRectToTileBounds(gfx::Rect(min_tiling_size));
+ if (min_toss_x < tiling_.num_tiles_x()) {
+ // The bounds which we want to invalidate are the tiles along the old
+ // edge of the pile when expanding, or the new edge of the pile when
+ // shrinking. In either case, it's the difference of the two, so we'll
+ // call this bounding box the DELTA EDGE RECT.
+ //
+ // In the picture below, the delta edge rect would be the bounding box of
+ // tiles {h,i,j}. |min_toss_x| would be equal to the horizontal index of
+ // the same tiles.
+ //
+ // min pile edge-v max pile edge-v
+ // ---------------+ - - - - - - - -+
+ // mmppssvvyybbeeh|h .
+ // mmppssvvyybbeeh|h .
+ // nnqqttwwzzccffi|i .
+ // nnqqttwwzzccffi|i .
+ // oorruuxxaaddggj|j .
+ // oorruuxxaaddggj|j .
+ // ---------------+ - - - - - - - -+ <- min pile edge
+ // .
+ // - - - - - - - - - - - - - - - -+ <- max pile edge
+ //
+ // If you were to slide a vertical beam from the left edge of the
+ // delta edge rect toward the right, it would either hit the right edge
+ // of the delta edge rect, or the interest rect (expanded to the bounds
+ // of the tiles it touches). The same is true for a beam parallel to
+ // any of the four edges, sliding across the delta edge rect. We use
+ // the union of these four rectangles generated by these beams to
+ // determine which part of the delta edge rect is outside of the expanded
+ // interest rect.
+ //
+ // Case 1: Intersect rect is outside the delta edge rect. It can be
+ // either on the left or the right. The |left_rect| and |right_rect|,
+ // cover this case, one will be empty and one will cover the full
+ // delta edge rect. In the picture below, |left_rect| would cover the
+ // delta edge rect, and |right_rect| would be empty.
+ // +----------------------+ |^^^^^^^^^^^^^^^|
+ // |===> DELTA EDGE RECT | | |
+ // |===> | | INTEREST RECT |
+ // |===> | | |
+ // |===> | | |
+ // +----------------------+ |vvvvvvvvvvvvvvv|
+ //
+ // Case 2: Interest rect is inside the delta edge rect. It will always
+ // fill the entire delta edge rect horizontally since the old edge rect
+ // is a single tile wide, and the interest rect has been expanded to the
+ // bounds of the tiles it touches. In this case the |left_rect| and
+ // |right_rect| will be empty, but the case is handled by the |top_rect|
+ // and |bottom_rect|. In the picture below, neither the |top_rect| nor
+ // |bottom_rect| would empty, they would each cover the area of the old
+ // edge rect outside the expanded interest rect.
+ // +-----------------+
+ // |:::::::::::::::::|
+ // |:::::::::::::::::|
+ // |vvvvvvvvvvvvvvvvv|
+ // | |
+ // +-----------------+
+ // | INTEREST RECT |
+ // | |
+ // +-----------------+
+ // | |
+ // | DELTA EDGE RECT |
+ // +-----------------+
+ //
+ // Lastly, we need to consider tiles inside the expanded interest rect.
+ // For those tiles, we want to invalidate exactly the newly exposed
+ // pixels. In the picture below the tiles in the delta edge rect have
+ // been resized and the area covered by periods must be invalidated. The
+ // |exposed_rect| will cover exactly that area.
+ // v-min pile edge
+ // +---------+-------+
+ // | ........|
+ // | ........|
+ // | DELTA EDGE.RECT.|
+ // | ........|
+ // | ........|
+ // | ........|
+ // | ........|
+ // | ........|
+ // | ........|
+ // +---------+-------+
+
+ int left = tiling_.TilePositionX(min_toss_x);
+ int right = left + tiling_.TileSizeX(min_toss_x);
+ int top = min_tiling_rect_over_tiles.y();
+ int bottom = min_tiling_rect_over_tiles.bottom();
+
+ int left_until = std::min(interest_rect_over_tiles.x(), right);
+ int right_until = std::max(interest_rect_over_tiles.right(), left);
+ int top_until = std::min(interest_rect_over_tiles.y(), bottom);
+ int bottom_until = std::max(interest_rect_over_tiles.bottom(), top);
+
+ int exposed_left = min_tiling_size.width();
+ int exposed_left_until = max_tiling_size.width();
+ int exposed_top = top;
+ int exposed_bottom = max_tiling_size.height();
+ DCHECK_GE(exposed_left, left);
+
+ gfx::Rect left_rect(left, top, left_until - left, bottom - top);
+ gfx::Rect right_rect(right_until, top, right - right_until, bottom - top);
+ gfx::Rect top_rect(left, top, right - left, top_until - top);
+ gfx::Rect bottom_rect(
+ left, bottom_until, right - left, bottom - bottom_until);
+ gfx::Rect exposed_rect(exposed_left,
+ exposed_top,
+ exposed_left_until - exposed_left,
+ exposed_bottom - exposed_top);
+ resize_invalidation.Union(left_rect);
+ resize_invalidation.Union(right_rect);
+ resize_invalidation.Union(top_rect);
+ resize_invalidation.Union(bottom_rect);
+ resize_invalidation.Union(exposed_rect);
+ }
+ if (min_toss_y < tiling_.num_tiles_y()) {
+ // The same thing occurs here as in the case above, but the invalidation
+ // rect is the bounding box around the bottom row of tiles in the min
+ // pile. This would be tiles {o,r,u,x,a,d,g,j} in the above picture.
+
+ int top = tiling_.TilePositionY(min_toss_y);
+ int bottom = top + tiling_.TileSizeY(min_toss_y);
+ int left = min_tiling_rect_over_tiles.x();
+ int right = min_tiling_rect_over_tiles.right();
+
+ int top_until = std::min(interest_rect_over_tiles.y(), bottom);
+ int bottom_until = std::max(interest_rect_over_tiles.bottom(), top);
+ int left_until = std::min(interest_rect_over_tiles.x(), right);
+ int right_until = std::max(interest_rect_over_tiles.right(), left);
+
+ int exposed_top = min_tiling_size.height();
+ int exposed_top_until = max_tiling_size.height();
+ int exposed_left = left;
+ int exposed_right = max_tiling_size.width();
+ DCHECK_GE(exposed_top, top);
+
+ gfx::Rect left_rect(left, top, left_until - left, bottom - top);
+ gfx::Rect right_rect(right_until, top, right - right_until, bottom - top);
+ gfx::Rect top_rect(left, top, right - left, top_until - top);
+ gfx::Rect bottom_rect(
+ left, bottom_until, right - left, bottom - bottom_until);
+ gfx::Rect exposed_rect(exposed_left,
+ exposed_top,
+ exposed_right - exposed_left,
+ exposed_top_until - exposed_top);
+ resize_invalidation.Union(left_rect);
+ resize_invalidation.Union(right_rect);
+ resize_invalidation.Union(top_rect);
+ resize_invalidation.Union(bottom_rect);
+ resize_invalidation.Union(exposed_rect);
}
+ }
- // Expand invalidation that is outside tiles that intersect the interest
- // rect. These tiles are no longer valid and should be considerered fully
- // invalid, so we can know to not keep around raster tiles that intersect
- // with these recording tiles.
- gfx::Rect invalid_rect_outside_interest_rect_tiles = invalid_rect;
- // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
- // instead of using Rect::Subtract which gives you the bounding box of the
- // subtraction.
- invalid_rect_outside_interest_rect_tiles.Subtract(interest_rect_over_tiles);
- invalidation_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds(
- invalid_rect_outside_interest_rect_tiles));
+ // Detect cases where the full pile is invalidated, in this situation we
+ // can just drop/invalidate everything.
+ if (invalidation->Contains(gfx::Rect(old_tiling_size)) ||
+ invalidation->Contains(gfx::Rect(tiling_size()))) {
+ for (auto& it : picture_map_)
+ updated = it.second.Invalidate(frame_number) || updated;
+ } else {
+ // Expand invalidation that is on tiles that aren't in the interest rect and
+ // will not be re-recorded below. These tiles are no longer valid and should
+ // be considerered fully invalid, so we can know to not keep around raster
+ // tiles that intersect with these recording tiles.
+ Region invalidation_expanded_to_full_tiles;
+
+ for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
+ gfx::Rect invalid_rect = i.rect();
+
+ // This rect covers the bounds (excluding borders) of all tiles whose
+ // bounds (including borders) touch the |interest_rect|. This matches
+ // the iteration of the |invalid_rect| below which includes borders when
+ // calling Invalidate() on pictures.
+ gfx::Rect invalid_rect_outside_interest_rect_tiles =
+ tiling_.ExpandRectToTileBounds(invalid_rect);
+ // We subtract the |interest_rect_over_tiles| which represents the bounds
+ // of tiles that will be re-recorded below. This matches the iteration of
+ // |interest_rect| below which includes borders.
+ // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
+ // instead of using Rect::Subtract which gives you the bounding box of the
+ // subtraction.
+ invalid_rect_outside_interest_rect_tiles.Subtract(
+ interest_rect_over_tiles);
+ invalidation_expanded_to_full_tiles.Union(
+ invalid_rect_outside_interest_rect_tiles);
+
+ // Split this inflated invalidation across tile boundaries and apply it
+ // to all tiles that it touches.
+ bool include_borders = true;
+ for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders);
+ iter;
+ ++iter) {
+ const PictureMapKey& key = iter.index();
+
+ PictureMap::iterator picture_it = picture_map_.find(key);
+ if (picture_it == picture_map_.end())
+ continue;
+
+ // Inform the grid cell that it has been invalidated in this frame.
+ updated = picture_it->second.Invalidate(frame_number) || updated;
+ // Invalidate drops the picture so the whole tile better be invalidated
+ // if it won't be re-recorded below.
+ DCHECK_IMPLIES(!tiling_.TileBounds(key.first, key.second)
+ .Intersects(interest_rect_over_tiles),
+ invalidation_expanded_to_full_tiles.Contains(
+ tiling_.TileBounds(key.first, key.second)));
+ }
+ }
+ invalidation->Union(invalidation_expanded_to_full_tiles);
}
- invalidation->Union(invalidation_expanded_to_full_tiles);
+ invalidation->Union(resize_invalidation);
// Make a list of all invalid tiles; we will attempt to
// cluster these into multiple invalidation regions.
@@ -244,7 +482,7 @@ bool PicturePile::UpdateAndExpandInvalidation(
ClusterTiles(invalid_tiles, &record_rects);
if (record_rects.empty())
- return invalidated;
+ return updated;
for (std::vector<gfx::Rect>::iterator it = record_rects.begin();
it != record_rects.end();
@@ -254,13 +492,12 @@ bool PicturePile::UpdateAndExpandInvalidation(
int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
scoped_refptr<Picture> picture;
- int num_raster_threads = RasterWorkerPool::GetNumRasterThreads();
// Note: Currently, gathering of pixel refs when using a single
// raster thread doesn't provide any benefit. This might change
// in the future but we avoid it for now to reduce the cost of
// Picture::Create.
- bool gather_pixel_refs = num_raster_threads > 1;
+ bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1;
{
base::TimeDelta best_duration = base::TimeDelta::Max();
@@ -270,7 +507,6 @@ bool PicturePile::UpdateAndExpandInvalidation(
painter,
tile_grid_info_,
gather_pixel_refs,
- num_raster_threads,
recording_mode);
// Note the '&&' with previous is-suitable state.
// This means that once a picture-pile becomes unsuitable for gpu
@@ -302,6 +538,7 @@ bool PicturePile::UpdateAndExpandInvalidation(
found_tile_for_recorded_picture = true;
}
}
+ DetermineIfSolidColor();
DCHECK(found_tile_for_recorded_picture);
}
@@ -310,4 +547,54 @@ bool PicturePile::UpdateAndExpandInvalidation(
return true;
}
+void PicturePile::SetEmptyBounds() {
+ tiling_.SetTilingSize(gfx::Size());
+ Clear();
+}
+
+bool PicturePile::CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const {
+ bool include_borders = false;
+ for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
+ tile_iter; ++tile_iter) {
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ return false;
+ if (!map_iter->second.GetPicture())
+ return false;
+ }
+ return true;
+}
+
+void PicturePile::DetermineIfSolidColor() {
+ is_solid_color_ = false;
+ solid_color_ = SK_ColorTRANSPARENT;
+
+ if (picture_map_.empty()) {
+ return;
+ }
+
+ PictureMap::const_iterator it = picture_map_.begin();
+ const Picture* picture = it->second.GetPicture();
+
+ // Missing recordings due to frequent invalidations or being too far away
+ // from the interest rect will cause the a null picture to exist.
+ if (!picture)
+ return;
+
+ // Don't bother doing more work if the first image is too complicated.
+ if (picture->ApproximateOpCount() > kOpCountThatIsOkToAnalyze)
+ return;
+
+ // Make sure all of the mapped images point to the same picture.
+ for (++it; it != picture_map_.end(); ++it) {
+ if (it->second.GetPicture() != picture)
+ return;
+ }
+ skia::AnalysisCanvas canvas(recorded_viewport_.width(),
+ recorded_viewport_.height());
+ canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y());
+ picture->Raster(&canvas, nullptr, Region(), 1.0f);
+ is_solid_color_ = canvas.GetColorIfSolid(&solid_color_);
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/picture_pile.h b/chromium/cc/resources/picture_pile.h
index 86ef32f2182..18e1e5273aa 100644
--- a/chromium/cc/resources/picture_pile.h
+++ b/chromium/cc/resources/picture_pile.h
@@ -5,8 +5,9 @@
#ifndef CC_RESOURCES_PICTURE_PILE_H_
#define CC_RESOURCES_PICTURE_PILE_H_
+#include "base/memory/ref_counted.h"
#include "cc/resources/picture_pile_base.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
namespace cc {
class PicturePileImpl;
@@ -16,6 +17,7 @@ class RenderingStatsInstrumentation;
class CC_EXPORT PicturePile : public PicturePileBase {
public:
PicturePile();
+ ~PicturePile() override;
// Re-record parts of the picture that are invalid.
// Invalidations are in layer space, and will be expanded to cover everything
@@ -28,11 +30,14 @@ class CC_EXPORT PicturePile : public PicturePileBase {
SkColor background_color,
bool contents_opaque,
bool contents_fill_bounds_completely,
+ const gfx::Size& layer_size,
const gfx::Rect& visible_layer_rect,
int frame_number,
Picture::RecordingMode recording_mode,
RenderingStatsInstrumentation* stats_instrumentation);
+ void SetEmptyBounds();
+
void set_slow_down_raster_scale_factor(int factor) {
slow_down_raster_scale_factor_for_debug_ = factor;
}
@@ -48,13 +53,20 @@ class CC_EXPORT PicturePile : public PicturePileBase {
is_suitable_for_gpu_rasterization_ = false;
}
+ void SetPixelRecordDistanceForTesting(int d) { pixel_record_distance_ = d; }
+
protected:
- virtual ~PicturePile();
+ // An internal CanRaster check that goes to the picture_map rather than
+ // using the recorded_viewport hint.
+ bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
private:
friend class PicturePileImpl;
+ void DetermineIfSolidColor();
+
bool is_suitable_for_gpu_rasterization_;
+ int pixel_record_distance_;
DISALLOW_COPY_AND_ASSIGN(PicturePile);
};
diff --git a/chromium/cc/resources/picture_pile_base.cc b/chromium/cc/resources/picture_pile_base.cc
index 8f8bf534874..1184cf1e2a6 100644
--- a/chromium/cc/resources/picture_pile_base.cc
+++ b/chromium/cc/resources/picture_pile_base.cc
@@ -8,12 +8,12 @@
#include <set>
#include <vector>
+#include "base/debug/trace_event_argument.h"
#include "base/logging.h"
#include "base/values.h"
-#include "cc/base/math_util.h"
#include "cc/debug/traced_value.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/geometry/rect_conversions.h"
namespace {
// Dimensions of the tiles in this picture pile as well as the dimensions of
@@ -46,7 +46,10 @@ PicturePileBase::PicturePileBase()
contents_fill_bounds_completely_(false),
show_debug_picture_borders_(false),
clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
- has_any_recordings_(false) {
+ has_any_recordings_(false),
+ is_mask_(false),
+ is_solid_color_(false),
+ solid_color_(SK_ColorTRANSPARENT) {
tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize));
tile_grid_info_.fTileInterval.setEmpty();
tile_grid_info_.fMargin.setEmpty();
@@ -66,70 +69,15 @@ PicturePileBase::PicturePileBase(const PicturePileBase* other)
contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
show_debug_picture_borders_(other->show_debug_picture_borders_),
clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
- has_any_recordings_(other->has_any_recordings_) {}
-
-PicturePileBase::PicturePileBase(const PicturePileBase* other,
- unsigned thread_index)
- : tiling_(other->tiling_),
- recorded_viewport_(other->recorded_viewport_),
- min_contents_scale_(other->min_contents_scale_),
- tile_grid_info_(other->tile_grid_info_),
- background_color_(other->background_color_),
- slow_down_raster_scale_factor_for_debug_(
- other->slow_down_raster_scale_factor_for_debug_),
- contents_opaque_(other->contents_opaque_),
- contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
- show_debug_picture_borders_(other->show_debug_picture_borders_),
- clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
- has_any_recordings_(other->has_any_recordings_) {
- for (PictureMap::const_iterator it = other->picture_map_.begin();
- it != other->picture_map_.end();
- ++it) {
- picture_map_[it->first] = it->second.CloneForThread(thread_index);
- }
+ has_any_recordings_(other->has_any_recordings_),
+ is_mask_(other->is_mask_),
+ is_solid_color_(other->is_solid_color_),
+ solid_color_(other->solid_color_) {
}
PicturePileBase::~PicturePileBase() {
}
-void PicturePileBase::SetTilingRect(const gfx::Rect& new_tiling_rect) {
- if (tiling_rect() == new_tiling_rect)
- return;
-
- gfx::Rect old_tiling_rect = tiling_rect();
- tiling_.SetTilingRect(new_tiling_rect);
-
- has_any_recordings_ = false;
-
- // Don't waste time in Resize figuring out what these hints should be.
- recorded_viewport_ = gfx::Rect();
-
- if (new_tiling_rect.origin() != old_tiling_rect.origin()) {
- picture_map_.clear();
- return;
- }
-
- // Find all tiles that contain any pixels outside the new rect.
- std::vector<PictureMapKey> to_erase;
- int min_toss_x = tiling_.FirstBorderTileXIndexFromSrcCoord(
- std::min(old_tiling_rect.right(), new_tiling_rect.right()));
- int min_toss_y = tiling_.FirstBorderTileYIndexFromSrcCoord(
- std::min(old_tiling_rect.bottom(), new_tiling_rect.bottom()));
- for (PictureMap::const_iterator it = picture_map_.begin();
- it != picture_map_.end();
- ++it) {
- const PictureMapKey& key = it->first;
- if (key.first < min_toss_x && key.second < min_toss_y) {
- has_any_recordings_ |= !!it->second.GetPicture();
- continue;
- }
- to_erase.push_back(key);
- }
-
- for (size_t i = 0; i < to_erase.size(); ++i)
- picture_map_.erase(to_erase[i]);
-}
-
void PicturePileBase::SetMinContentsScale(float min_contents_scale) {
DCHECK(min_contents_scale);
if (min_contents_scale_ == min_contents_scale)
@@ -182,6 +130,8 @@ void PicturePileBase::SetBufferPixels(int new_buffer_pixels) {
void PicturePileBase::Clear() {
picture_map_.clear();
recorded_viewport_ = gfx::Rect();
+ has_any_recordings_ = false;
+ is_solid_color_ = false;
}
bool PicturePileBase::HasRecordingAt(int x, int y) {
@@ -191,72 +141,18 @@ bool PicturePileBase::HasRecordingAt(int x, int y) {
return !!found->second.GetPicture();
}
-bool PicturePileBase::CanRaster(float contents_scale,
- const gfx::Rect& content_rect) {
- if (tiling_.tiling_rect().IsEmpty())
- return false;
- gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
- content_rect, 1.f / contents_scale);
- layer_rect.Intersect(tiling_.tiling_rect());
-
- // Common case inside of viewport to avoid the slower map lookups.
- if (recorded_viewport_.Contains(layer_rect)) {
- // Sanity check that there are no false positives in recorded_viewport_.
- DCHECK(CanRasterSlowTileCheck(layer_rect));
- return true;
- }
-
- return CanRasterSlowTileCheck(layer_rect);
-}
-
-bool PicturePileBase::CanRasterSlowTileCheck(
- const gfx::Rect& layer_rect) const {
- bool include_borders = false;
- for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
- tile_iter;
- ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- return false;
- if (!map_iter->second.GetPicture())
- return false;
- }
- return true;
-}
-
-gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) {
+gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) const {
gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
return PadRect(tile);
}
-gfx::Rect PicturePileBase::PadRect(const gfx::Rect& rect) {
+gfx::Rect PicturePileBase::PadRect(const gfx::Rect& rect) const {
gfx::Rect padded_rect = rect;
padded_rect.Inset(
-buffer_pixels(), -buffer_pixels(), -buffer_pixels(), -buffer_pixels());
return padded_rect;
}
-scoped_ptr<base::Value> PicturePileBase::AsValue() const {
- scoped_ptr<base::ListValue> pictures(new base::ListValue());
- gfx::Rect tiling_rect(tiling_.tiling_rect());
- std::set<void*> appended_pictures;
- bool include_borders = true;
- for (TilingData::Iterator tile_iter(&tiling_, tiling_rect, include_borders);
- tile_iter;
- ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- continue;
-
- Picture* picture = map_iter->second.GetPicture();
- if (picture && (appended_pictures.count(picture) == 0)) {
- appended_pictures.insert(picture);
- pictures->Append(TracedValue::CreateIDRef(picture).release());
- }
- }
- return pictures.PassAs<base::Value>();
-}
-
PicturePileBase::PictureInfo::PictureInfo() : last_frame_number_(0) {}
PicturePileBase::PictureInfo::~PictureInfo() {}
@@ -275,7 +171,7 @@ bool PicturePileBase::PictureInfo::Invalidate(int frame_number) {
AdvanceInvalidationHistory(frame_number);
invalidation_history_.set(0);
- bool did_invalidate = !!picture_;
+ bool did_invalidate = !!picture_.get();
picture_ = NULL;
return did_invalidate;
}
@@ -288,7 +184,7 @@ bool PicturePileBase::PictureInfo::NeedsRecording(int frame_number,
// need a recording if we're within frequent invalidation distance threshold
// or the invalidation is not frequent enough (below invalidation frequency
// threshold).
- return !picture_ &&
+ return !picture_.get() &&
((distance_to_visible <= kFrequentInvalidationDistanceThreshold) ||
(GetInvalidationFrequency() < kInvalidationFrequencyThreshold));
}
@@ -297,18 +193,10 @@ void PicturePileBase::PictureInfo::SetPicture(scoped_refptr<Picture> picture) {
picture_ = picture;
}
-Picture* PicturePileBase::PictureInfo::GetPicture() const {
+const Picture* PicturePileBase::PictureInfo::GetPicture() const {
return picture_.get();
}
-PicturePileBase::PictureInfo PicturePileBase::PictureInfo::CloneForThread(
- int thread_index) const {
- PictureInfo info = *this;
- if (picture_.get())
- info.picture_ = picture_->GetCloneForDrawingOnThread(thread_index);
- return info;
-}
-
float PicturePileBase::PictureInfo::GetInvalidationFrequency() const {
return invalidation_history_.count() /
static_cast<float>(INVALIDATION_FRAMES_TRACKED);
diff --git a/chromium/cc/resources/picture_pile_base.h b/chromium/cc/resources/picture_pile_base.h
index 9f8acffd294..66d37d81b88 100644
--- a/chromium/cc/resources/picture_pile_base.h
+++ b/chromium/cc/resources/picture_pile_base.h
@@ -10,27 +10,27 @@
#include <utility>
#include "base/containers/hash_tables.h"
-#include "base/memory/ref_counted.h"
#include "cc/base/cc_export.h"
#include "cc/base/region.h"
#include "cc/base/tiling_data.h"
#include "cc/resources/picture.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace base {
+namespace debug {
+class TracedValue;
+}
class Value;
}
namespace cc {
-class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
+class CC_EXPORT PicturePileBase {
public:
PicturePileBase();
explicit PicturePileBase(const PicturePileBase* other);
- PicturePileBase(const PicturePileBase* other, unsigned thread_index);
- void SetTilingRect(const gfx::Rect& tiling_rect);
- gfx::Rect tiling_rect() const { return tiling_.tiling_rect(); }
+ gfx::Size tiling_size() const { return tiling_.tiling_size(); }
void SetMinContentsScale(float min_contents_scale);
// If non-empty, all pictures tiles inside this rect are recorded. There may
@@ -42,10 +42,11 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
int num_tiles_y() const { return tiling_.num_tiles_y(); }
gfx::Rect tile_bounds(int x, int y) const { return tiling_.TileBounds(x, y); }
bool HasRecordingAt(int x, int y);
- bool CanRaster(float contents_scale, const gfx::Rect& content_rect);
- // If this pile contains any valid recordings. May have false positives.
- bool HasRecordings() const { return has_any_recordings_; }
+ bool is_solid_color() const { return is_solid_color_; }
+ SkColor solid_color() const { return solid_color_; }
+
+ void set_is_mask(bool is_mask) { is_mask_ = is_mask; }
static void ComputeTileGridInfo(const gfx::Size& tile_grid_size,
SkTileGridFactory::TileGridInfo* info);
@@ -53,7 +54,16 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
void SetTileGridSize(const gfx::Size& tile_grid_size);
TilingData& tiling() { return tiling_; }
- scoped_ptr<base::Value> AsValue() const;
+ SkTileGridFactory::TileGridInfo GetTileGridInfoForTesting() const {
+ return tile_grid_info_;
+ }
+
+ void SetRecordedViewportForTesting(const gfx::Rect& viewport) {
+ recorded_viewport_ = viewport;
+ }
+ void SetHasAnyRecordingsForTesting(bool has_recordings) {
+ has_any_recordings_ = has_recordings;
+ }
protected:
class CC_EXPORT PictureInfo {
@@ -67,9 +77,8 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
bool Invalidate(int frame_number);
bool NeedsRecording(int frame_number, int distance_to_visible);
- PictureInfo CloneForThread(int thread_index) const;
void SetPicture(scoped_refptr<Picture> picture);
- Picture* GetPicture() const;
+ const Picture* GetPicture() const;
float GetInvalidationFrequencyForTesting() const {
return GetInvalidationFrequency();
@@ -80,7 +89,7 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
float GetInvalidationFrequency() const;
int last_frame_number_;
- scoped_refptr<Picture> picture_;
+ scoped_refptr<const Picture> picture_;
std::bitset<INVALIDATION_FRAMES_TRACKED> invalidation_history_;
};
@@ -92,12 +101,8 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
int buffer_pixels() const { return tiling_.border_texels(); }
void Clear();
- gfx::Rect PaddedRect(const PictureMapKey& key);
- gfx::Rect PadRect(const gfx::Rect& rect);
-
- // An internal CanRaster check that goes to the picture_map rather than
- // using the recorded_viewport hint.
- bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
+ gfx::Rect PaddedRect(const PictureMapKey& key) const;
+ gfx::Rect PadRect(const gfx::Rect& rect) const;
// A picture pile is a tiled set of pictures. The picture map is a map of tile
// indices to picture infos.
@@ -115,11 +120,15 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
// A hint about whether there are any recordings. This may be a false
// positive.
bool has_any_recordings_;
+ bool is_mask_;
+ bool is_solid_color_;
+ SkColor solid_color_;
private:
+ friend class PicturePileImpl;
+
void SetBufferPixels(int buffer_pixels);
- friend class base::RefCounted<PicturePileBase>;
DISALLOW_COPY_AND_ASSIGN(PicturePileBase);
};
diff --git a/chromium/cc/resources/picture_pile_impl.cc b/chromium/cc/resources/picture_pile_impl.cc
index 90713b4fc7e..de25c04721b 100644
--- a/chromium/cc/resources/picture_pile_impl.cc
+++ b/chromium/cc/resources/picture_pile_impl.cc
@@ -9,29 +9,13 @@
#include "cc/base/region.h"
#include "cc/debug/debug_colors.h"
#include "cc/resources/picture_pile_impl.h"
-#include "cc/resources/raster_worker_pool.h"
#include "skia/ext/analysis_canvas.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
-#include "third_party/skia/include/core/SkSize.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gfx/skia_util.h"
+#include "ui/gfx/geometry/rect_conversions.h"
namespace cc {
-PicturePileImpl::ClonesForDrawing::ClonesForDrawing(
- const PicturePileImpl* pile, int num_threads) {
- for (int i = 0; i < num_threads; i++) {
- scoped_refptr<PicturePileImpl> clone =
- PicturePileImpl::CreateCloneForDrawing(pile, i);
- clones_.push_back(clone);
- }
-}
-
-PicturePileImpl::ClonesForDrawing::~ClonesForDrawing() {
-}
-
scoped_refptr<PicturePileImpl> PicturePileImpl::Create() {
return make_scoped_refptr(new PicturePileImpl);
}
@@ -41,63 +25,60 @@ scoped_refptr<PicturePileImpl> PicturePileImpl::CreateFromOther(
return make_scoped_refptr(new PicturePileImpl(other));
}
-scoped_refptr<PicturePileImpl> PicturePileImpl::CreateCloneForDrawing(
- const PicturePileImpl* other, unsigned thread_index) {
- return make_scoped_refptr(new PicturePileImpl(other, thread_index));
-}
-
PicturePileImpl::PicturePileImpl()
- : clones_for_drawing_(ClonesForDrawing(this, 0)) {
+ : background_color_(SK_ColorTRANSPARENT),
+ contents_opaque_(false),
+ contents_fill_bounds_completely_(false),
+ is_solid_color_(false),
+ solid_color_(SK_ColorTRANSPARENT),
+ has_any_recordings_(false),
+ is_mask_(false),
+ clear_canvas_with_debug_color_(false),
+ min_contents_scale_(0.f),
+ slow_down_raster_scale_factor_for_debug_(0),
+ likely_to_be_used_for_transform_animation_(false) {
}
PicturePileImpl::PicturePileImpl(const PicturePileBase* other)
- : PicturePileBase(other),
- clones_for_drawing_(ClonesForDrawing(
- this, RasterWorkerPool::GetNumRasterThreads())) {
-}
-
-PicturePileImpl::PicturePileImpl(
- const PicturePileImpl* other, unsigned thread_index)
- : PicturePileBase(other, thread_index),
- clones_for_drawing_(ClonesForDrawing(this, 0)) {
+ : picture_map_(other->picture_map_),
+ tiling_(other->tiling_),
+ background_color_(other->background_color_),
+ contents_opaque_(other->contents_opaque_),
+ contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
+ is_solid_color_(other->is_solid_color_),
+ solid_color_(other->solid_color_),
+ recorded_viewport_(other->recorded_viewport_),
+ has_any_recordings_(other->has_any_recordings_),
+ is_mask_(other->is_mask_),
+ clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
+ min_contents_scale_(other->min_contents_scale_),
+ slow_down_raster_scale_factor_for_debug_(
+ other->slow_down_raster_scale_factor_for_debug_),
+ likely_to_be_used_for_transform_animation_(false) {
}
PicturePileImpl::~PicturePileImpl() {
}
-PicturePileImpl* PicturePileImpl::GetCloneForDrawingOnThread(
- unsigned thread_index) const {
- CHECK_GT(clones_for_drawing_.clones_.size(), thread_index);
- return clones_for_drawing_.clones_[thread_index].get();
-}
-
-void PicturePileImpl::RasterDirect(
- SkCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale,
- RenderingStatsInstrumentation* rendering_stats_instrumentation) {
+void PicturePileImpl::RasterDirect(SkCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const {
RasterCommon(canvas,
NULL,
canvas_rect,
contents_scale,
- rendering_stats_instrumentation,
false);
}
-void PicturePileImpl::RasterForAnalysis(
- skia::AnalysisCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale,
- RenderingStatsInstrumentation* stats_instrumentation) {
- RasterCommon(
- canvas, canvas, canvas_rect, contents_scale, stats_instrumentation, true);
+void PicturePileImpl::RasterForAnalysis(skia::AnalysisCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const {
+ RasterCommon(canvas, canvas, canvas_rect, contents_scale, true);
}
-void PicturePileImpl::RasterToBitmap(
- SkCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale,
- RenderingStatsInstrumentation* rendering_stats_instrumentation) {
+void PicturePileImpl::PlaybackToCanvas(SkCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const {
canvas->discard();
if (clear_canvas_with_debug_color_) {
// Any non-painted areas in the content bounds will be left in this color.
@@ -113,7 +94,7 @@ void PicturePileImpl::RasterToBitmap(
// texel (since the recording won't cover it) and outside the last texel
// (due to linear filtering when using this texture).
gfx::Rect content_tiling_rect = gfx::ToEnclosingRect(
- gfx::ScaleRect(tiling_.tiling_rect(), contents_scale));
+ gfx::ScaleRect(gfx::Rect(tiling_.tiling_size()), contents_scale));
// The final texel of content may only be partially covered by a
// rasterization; this rect represents the content rect that is fully
@@ -159,14 +140,13 @@ void PicturePileImpl::RasterToBitmap(
NULL,
canvas_rect,
contents_scale,
- rendering_stats_instrumentation,
false);
}
void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect,
const gfx::Rect& content_rect,
float contents_scale,
- PictureRegionMap* results) {
+ PictureRegionMap* results) const {
DCHECK(results);
// Rasterize the collection of relevant picture piles.
gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
@@ -197,11 +177,11 @@ void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect,
for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
tile_iter;
++tile_iter) {
- PictureMap::iterator map_iter = picture_map_.find(tile_iter.index());
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
if (map_iter == picture_map_.end())
continue;
- PictureInfo& info = map_iter->second;
- Picture* picture = info.GetPicture();
+ const PictureInfo& info = map_iter->second;
+ const Picture* picture = info.GetPicture();
if (!picture)
continue;
@@ -263,13 +243,12 @@ void PicturePileImpl::RasterCommon(
SkDrawPictureCallback* callback,
const gfx::Rect& canvas_rect,
float contents_scale,
- RenderingStatsInstrumentation* rendering_stats_instrumentation,
- bool is_analysis) {
+ bool is_analysis) const {
DCHECK(contents_scale >= min_contents_scale_);
canvas->translate(-canvas_rect.x(), -canvas_rect.y());
gfx::Rect content_tiling_rect = gfx::ToEnclosingRect(
- gfx::ScaleRect(tiling_.tiling_rect(), contents_scale));
+ gfx::ScaleRect(gfx::Rect(tiling_.tiling_size()), contents_scale));
content_tiling_rect.Intersect(canvas_rect);
canvas->clipRect(gfx::RectToSkRect(content_tiling_rect),
@@ -288,7 +267,7 @@ void PicturePileImpl::RasterCommon(
for (PictureRegionMap::iterator it = picture_region_map.begin();
it != picture_region_map.end();
++it) {
- Picture* picture = it->first;
+ const Picture* picture = it->first;
Region negated_clip_region = it->second;
#ifndef NDEBUG
@@ -299,34 +278,10 @@ void PicturePileImpl::RasterCommon(
total_clip.Union(positive_clip);
#endif // NDEBUG
- base::TimeDelta best_duration = base::TimeDelta::Max();
int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
- int rasterized_pixel_count = 0;
-
- for (int j = 0; j < repeat_count; ++j) {
- base::TimeTicks start_time;
- if (rendering_stats_instrumentation)
- start_time = rendering_stats_instrumentation->StartRecording();
-
- rasterized_pixel_count = picture->Raster(
- canvas, callback, negated_clip_region, contents_scale);
- if (rendering_stats_instrumentation) {
- base::TimeDelta duration =
- rendering_stats_instrumentation->EndRecording(start_time);
- best_duration = std::min(best_duration, duration);
- }
- }
-
- if (rendering_stats_instrumentation) {
- if (is_analysis) {
- rendering_stats_instrumentation->AddAnalysis(best_duration,
- rasterized_pixel_count);
- } else {
- rendering_stats_instrumentation->AddRaster(best_duration,
- rasterized_pixel_count);
- }
- }
+ for (int j = 0; j < repeat_count; ++j)
+ picture->Raster(canvas, callback, negated_clip_region, contents_scale);
}
#ifndef NDEBUG
@@ -345,52 +300,106 @@ void PicturePileImpl::RasterCommon(
skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() {
TRACE_EVENT0("cc", "PicturePileImpl::GetFlattenedPicture");
- gfx::Rect tiling_rect(tiling_.tiling_rect());
+ gfx::Rect tiling_rect(tiling_.tiling_size());
SkPictureRecorder recorder;
SkCanvas* canvas =
recorder.beginRecording(tiling_rect.width(), tiling_rect.height());
if (!tiling_rect.IsEmpty())
- RasterToBitmap(canvas, tiling_rect, 1.0, NULL);
+ PlaybackToCanvas(canvas, tiling_rect, 1.0);
skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
return picture;
}
-void PicturePileImpl::AnalyzeInRect(
+void PicturePileImpl::PerformSolidColorAnalysis(
const gfx::Rect& content_rect,
float contents_scale,
- PicturePileImpl::Analysis* analysis) {
- AnalyzeInRect(content_rect, contents_scale, analysis, NULL);
-}
-
-void PicturePileImpl::AnalyzeInRect(
- const gfx::Rect& content_rect,
- float contents_scale,
- PicturePileImpl::Analysis* analysis,
- RenderingStatsInstrumentation* stats_instrumentation) {
+ RasterSource::SolidColorAnalysis* analysis) const {
DCHECK(analysis);
- TRACE_EVENT0("cc", "PicturePileImpl::AnalyzeInRect");
+ TRACE_EVENT0("cc", "PicturePileImpl::PerformSolidColorAnalysis");
gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
content_rect, 1.0f / contents_scale);
- layer_rect.Intersect(tiling_.tiling_rect());
+ layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height());
- RasterForAnalysis(&canvas, layer_rect, 1.0f, stats_instrumentation);
+ RasterForAnalysis(&canvas, layer_rect, 1.0f);
analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color);
}
-// Since there are situations when we can skip analysis, the variables have to
-// be set to their safest values. That is, we have to assume that the tile is
-// not solid color. As well, we have to assume that the tile has text so we
-// don't early out incorrectly.
-PicturePileImpl::Analysis::Analysis() : is_solid_color(false) {
+void PicturePileImpl::GatherPixelRefs(
+ const gfx::Rect& content_rect,
+ float contents_scale,
+ std::vector<SkPixelRef*>* pixel_refs) const {
+ DCHECK_EQ(0u, pixel_refs->size());
+ for (PixelRefIterator iter(content_rect, contents_scale, this); iter;
+ ++iter) {
+ pixel_refs->push_back(*iter);
+ }
+}
+
+bool PicturePileImpl::CoversRect(const gfx::Rect& content_rect,
+ float contents_scale) const {
+ if (tiling_.tiling_size().IsEmpty())
+ return false;
+ gfx::Rect layer_rect =
+ gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale);
+ layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
+
+ // Common case inside of viewport to avoid the slower map lookups.
+ if (recorded_viewport_.Contains(layer_rect)) {
+ // Sanity check that there are no false positives in recorded_viewport_.
+ DCHECK(CanRasterSlowTileCheck(layer_rect));
+ return true;
+ }
+
+ return CanRasterSlowTileCheck(layer_rect);
+}
+
+gfx::Rect PicturePileImpl::PaddedRect(const PictureMapKey& key) const {
+ gfx::Rect padded_rect = tiling_.TileBounds(key.first, key.second);
+ padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(),
+ -buffer_pixels());
+ return padded_rect;
+}
+
+bool PicturePileImpl::CanRasterSlowTileCheck(
+ const gfx::Rect& layer_rect) const {
+ bool include_borders = false;
+ for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
+ tile_iter; ++tile_iter) {
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ return false;
+ if (!map_iter->second.GetPicture())
+ return false;
+ }
+ return true;
}
-PicturePileImpl::Analysis::~Analysis() {
+bool PicturePileImpl::SuitableForDistanceFieldText() const {
+ return likely_to_be_used_for_transform_animation_;
+}
+
+void PicturePileImpl::AsValueInto(base::debug::TracedValue* pictures) const {
+ gfx::Rect tiling_rect(tiling_.tiling_size());
+ std::set<const void*> appended_pictures;
+ bool include_borders = true;
+ for (TilingData::Iterator tile_iter(&tiling_, tiling_rect, include_borders);
+ tile_iter; ++tile_iter) {
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ continue;
+
+ const Picture* picture = map_iter->second.GetPicture();
+ if (picture && (appended_pictures.count(picture) == 0)) {
+ appended_pictures.insert(picture);
+ TracedValue::AppendIDRef(picture, pictures);
+ }
+ }
}
PicturePileImpl::PixelRefIterator::PixelRefIterator(
@@ -444,11 +453,11 @@ void PicturePileImpl::PixelRefIterator::AdvanceToTilePictureWithPixelRefs() {
}
void PicturePileImpl::DidBeginTracing() {
- std::set<void*> processed_pictures;
+ std::set<const void*> processed_pictures;
for (PictureMap::iterator it = picture_map_.begin();
it != picture_map_.end();
++it) {
- Picture* picture = it->second.GetPicture();
+ const Picture* picture = it->second.GetPicture();
if (picture && (processed_pictures.count(picture) == 0)) {
picture->EmitTraceSnapshot();
processed_pictures.insert(picture);
diff --git a/chromium/cc/resources/picture_pile_impl.h b/chromium/cc/resources/picture_pile_impl.h
index ba193811075..479846bb0ff 100644
--- a/chromium/cc/resources/picture_pile_impl.h
+++ b/chromium/cc/resources/picture_pile_impl.h
@@ -14,72 +14,61 @@
#include "cc/base/cc_export.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/resources/picture_pile_base.h"
+#include "cc/resources/raster_source.h"
#include "skia/ext/analysis_canvas.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkPicture.h"
namespace cc {
-class CC_EXPORT PicturePileImpl : public PicturePileBase {
+// TODO(vmpstr): Clean up PicturePileBase and make it a member.
+class CC_EXPORT PicturePileImpl : public RasterSource {
public:
static scoped_refptr<PicturePileImpl> Create();
static scoped_refptr<PicturePileImpl> CreateFromOther(
const PicturePileBase* other);
- // Get paint-safe version of this picture for a specific thread.
- PicturePileImpl* GetCloneForDrawingOnThread(unsigned thread_index) const;
-
- // Raster a subrect of this PicturePileImpl into the given canvas.
- // It's only safe to call paint on a cloned version. It is assumed
- // that contents_scale has already been applied to this canvas.
- // Writes the total number of pixels rasterized and the time spent
- // rasterizing to the stats if the respective pointer is not
- // NULL. When slow-down-raster-scale-factor is set to a value
- // greater than 1, the reported rasterize time is the minimum
- // measured value over all runs.
- void RasterDirect(
- SkCanvas* canvas,
- const gfx::Rect& canvas_rect,
+ // RasterSource overrides. See RasterSource header for full description.
+ // When slow-down-raster-scale-factor is set to a value greater than 1, the
+ // reported rasterize time (in stats_instrumentation) is the minimum measured
+ // value over all runs.
+ void PlaybackToCanvas(SkCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const override;
+ void PerformSolidColorAnalysis(
+ const gfx::Rect& content_rect,
float contents_scale,
- RenderingStatsInstrumentation* rendering_stats_instrumentation);
+ RasterSource::SolidColorAnalysis* analysis) const override;
+ void GatherPixelRefs(const gfx::Rect& content_rect,
+ float contents_scale,
+ std::vector<SkPixelRef*>* pixel_refs) const override;
+ bool CoversRect(const gfx::Rect& content_rect,
+ float contents_scale) const override;
+ bool SuitableForDistanceFieldText() const override;
- // Similar to the above RasterDirect method, but this is a convenience method
- // for when it is known that the raster is going to an intermediate bitmap
- // that itself will then be blended and thus that a canvas clear is required.
- // Note that this function may write outside the canvas_rect.
- void RasterToBitmap(
- SkCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale,
- RenderingStatsInstrumentation* stats_instrumentation);
-
- // Called when analyzing a tile. We can use AnalysisCanvas as
- // SkDrawPictureCallback, which allows us to early out from analysis.
- void RasterForAnalysis(
- skia::AnalysisCanvas* canvas,
- const gfx::Rect& canvas_rect,
- float contents_scale,
- RenderingStatsInstrumentation* stats_instrumentation);
+ // Raster into the canvas without applying clips.
+ void RasterDirect(SkCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const;
+ // Tracing functionality.
+ void DidBeginTracing();
skia::RefPtr<SkPicture> GetFlattenedPicture();
- struct CC_EXPORT Analysis {
- Analysis();
- ~Analysis();
-
- bool is_solid_color;
- SkColor solid_color;
- };
-
- void AnalyzeInRect(const gfx::Rect& content_rect,
- float contents_scale,
- Analysis* analysis);
+ void set_likely_to_be_used_for_transform_animation() {
+ likely_to_be_used_for_transform_animation_ = true;
+ }
- void AnalyzeInRect(const gfx::Rect& content_rect,
- float contents_scale,
- Analysis* analysis,
- RenderingStatsInstrumentation* stats_instrumentation);
+ gfx::Size tiling_size() const { return tiling_.tiling_size(); }
+ bool is_solid_color() const { return is_solid_color_; }
+ SkColor solid_color() const { return solid_color_; }
+ // If this pile contains any valid recordings. May have false positives.
+ bool HasRecordings() const { return has_any_recordings_; }
+ void AsValueInto(base::debug::TracedValue* array) const;
+ bool is_mask() const { return is_mask_; }
+ // Iterator used to return SkPixelRefs from this picture pile.
+ // Public for testing.
class CC_EXPORT PixelRefIterator {
public:
PixelRefIterator(const gfx::Rect& content_rect,
@@ -102,51 +91,64 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
std::set<const void*> processed_pictures_;
};
- void DidBeginTracing();
-
protected:
friend class PicturePile;
friend class PixelRefIterator;
+ // TODO(vmpstr): Change this when pictures are split from invalidation info,
+ // and when PicturePileBase goes away.
+ using PictureMapKey = PicturePileBase::PictureMapKey;
+ using PictureMap = PicturePileBase::PictureMap;
+ using PictureInfo = PicturePileBase::PictureInfo;
+
PicturePileImpl();
explicit PicturePileImpl(const PicturePileBase* other);
- virtual ~PicturePileImpl();
+ ~PicturePileImpl() override;
+
+ int buffer_pixels() const { return tiling_.border_texels(); }
+
+ PictureMap picture_map_;
+ TilingData tiling_;
+ SkColor background_color_;
+ bool contents_opaque_;
+ bool contents_fill_bounds_completely_;
+ bool is_solid_color_;
+ SkColor solid_color_;
+ gfx::Rect recorded_viewport_;
+ bool has_any_recordings_;
+ bool is_mask_;
+ bool clear_canvas_with_debug_color_;
+ float min_contents_scale_;
+ int slow_down_raster_scale_factor_for_debug_;
private:
- class ClonesForDrawing {
- public:
- ClonesForDrawing(const PicturePileImpl* pile, int num_threads);
- ~ClonesForDrawing();
-
- typedef std::vector<scoped_refptr<PicturePileImpl> > PicturePileVector;
- PicturePileVector clones_;
- };
+ typedef std::map<const Picture*, Region> PictureRegionMap;
- static scoped_refptr<PicturePileImpl> CreateCloneForDrawing(
- const PicturePileImpl* other, unsigned thread_index);
-
- PicturePileImpl(const PicturePileImpl* other, unsigned thread_index);
+ // Called when analyzing a tile. We can use AnalysisCanvas as
+ // SkDrawPictureCallback, which allows us to early out from analysis.
+ void RasterForAnalysis(skia::AnalysisCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const;
- private:
- typedef std::map<Picture*, Region> PictureRegionMap;
void CoalesceRasters(const gfx::Rect& canvas_rect,
const gfx::Rect& content_rect,
float contents_scale,
- PictureRegionMap* result);
+ PictureRegionMap* result) const;
void RasterCommon(
SkCanvas* canvas,
SkDrawPictureCallback* callback,
const gfx::Rect& canvas_rect,
float contents_scale,
- RenderingStatsInstrumentation* rendering_stats_instrumentation,
- bool is_analysis);
-
- // Once instantiated, |clones_for_drawing_| can't be modified. This
- // guarantees thread-safe access during the life time of a PicturePileImpl
- // instance. This member variable must be last so that other member
- // variables have already been initialized and can be clonable.
- const ClonesForDrawing clones_for_drawing_;
+ bool is_analysis) const;
+
+ // An internal CanRaster check that goes to the picture_map rather than
+ // using the recorded_viewport hint.
+ bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
+
+ gfx::Rect PaddedRect(const PictureMapKey& key) const;
+
+ bool likely_to_be_used_for_transform_animation_;
DISALLOW_COPY_AND_ASSIGN(PicturePileImpl);
};
diff --git a/chromium/cc/resources/picture_pile_impl_perftest.cc b/chromium/cc/resources/picture_pile_impl_perftest.cc
index 7ced0eaa1be..7e24724197c 100644
--- a/chromium/cc/resources/picture_pile_impl_perftest.cc
+++ b/chromium/cc/resources/picture_pile_impl_perftest.cc
@@ -6,7 +6,6 @@
#include "cc/debug/lap_timer.h"
#include "cc/test/fake_picture_pile_impl.h"
-#include "cc/test/fake_rendering_stats_instrumentation.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
@@ -33,10 +32,10 @@ class PicturePileImplPerfTest : public testing::Test {
// Content rect that will align with top-left tile at scale 1.0.
gfx::Rect content_rect(0, 0, kTileSize, kTileSize);
- PicturePileImpl::Analysis analysis;
+ RasterSource::SolidColorAnalysis analysis;
timer_.Reset();
do {
- pile->AnalyzeInRect(content_rect, contents_scale, &analysis);
+ pile->PerformSolidColorAnalysis(content_rect, contents_scale, &analysis);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
@@ -51,17 +50,12 @@ class PicturePileImplPerfTest : public testing::Test {
gfx::Rect content_rect(0, 0, kTileSize, kTileSize);
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(1, 1);
SkCanvas canvas(bitmap);
- FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
timer_.Reset();
do {
- pile->RasterToBitmap(&canvas,
- content_rect,
- contents_scale,
- &rendering_stats_instrumentation);
+ pile->PlaybackToCanvas(&canvas, content_rect, contents_scale);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
diff --git a/chromium/cc/resources/picture_pile_impl_unittest.cc b/chromium/cc/resources/picture_pile_impl_unittest.cc
index 40d1615a943..6dcf740e1ab 100644
--- a/chromium/cc/resources/picture_pile_impl_unittest.cc
+++ b/chromium/cc/resources/picture_pile_impl_unittest.cc
@@ -4,14 +4,13 @@
#include "base/memory/scoped_ptr.h"
#include "cc/test/fake_picture_pile_impl.h"
-#include "cc/test/fake_rendering_stats_instrumentation.h"
#include "cc/test/skia_common.h"
#include "skia/ext/refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "third_party/skia/include/core/SkShader.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size_conversions.h"
namespace cc {
namespace {
@@ -37,9 +36,9 @@ TEST(PicturePileImplTest, AnalyzeIsSolidUnscaled) {
// Ensure everything is solid
for (int y = 0; y <= 300; y += 100) {
for (int x = 0; x <= 300; x += 100) {
- PicturePileImpl::Analysis analysis;
+ RasterSource::SolidColorAnalysis analysis;
gfx::Rect rect(x, y, 100, 100);
- pile->AnalyzeInRect(rect, 1.0, &analysis);
+ pile->PerformSolidColorAnalysis(rect, 1.0, &analysis);
EXPECT_TRUE(analysis.is_solid_color) << rect.ToString();
EXPECT_EQ(analysis.solid_color, solid_color) << rect.ToString();
}
@@ -49,27 +48,28 @@ TEST(PicturePileImplTest, AnalyzeIsSolidUnscaled) {
pile->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1), non_solid_paint);
pile->RerecordPile();
- PicturePileImpl::Analysis analysis;
- pile->AnalyzeInRect(gfx::Rect(0, 0, 100, 100), 1.0, &analysis);
+ RasterSource::SolidColorAnalysis analysis;
+ pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 100, 100), 1.0, &analysis);
EXPECT_FALSE(analysis.is_solid_color);
- pile->AnalyzeInRect(gfx::Rect(100, 0, 100, 100), 1.0, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(100, 0, 100, 100), 1.0, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
// Boundaries should be clipped
analysis.is_solid_color = false;
- pile->AnalyzeInRect(gfx::Rect(350, 0, 100, 100), 1.0, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(350, 0, 100, 100), 1.0, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
analysis.is_solid_color = false;
- pile->AnalyzeInRect(gfx::Rect(0, 350, 100, 100), 1.0, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(0, 350, 100, 100), 1.0, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
analysis.is_solid_color = false;
- pile->AnalyzeInRect(gfx::Rect(350, 350, 100, 100), 1.0, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(350, 350, 100, 100), 1.0,
+ &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
}
@@ -95,9 +95,9 @@ TEST(PicturePileImplTest, AnalyzeIsSolidScaled) {
// Ensure everything is solid
for (int y = 0; y <= 30; y += 10) {
for (int x = 0; x <= 30; x += 10) {
- PicturePileImpl::Analysis analysis;
+ RasterSource::SolidColorAnalysis analysis;
gfx::Rect rect(x, y, 10, 10);
- pile->AnalyzeInRect(rect, 0.1f, &analysis);
+ pile->PerformSolidColorAnalysis(rect, 0.1f, &analysis);
EXPECT_TRUE(analysis.is_solid_color) << rect.ToString();
EXPECT_EQ(analysis.solid_color, solid_color) << rect.ToString();
}
@@ -107,27 +107,27 @@ TEST(PicturePileImplTest, AnalyzeIsSolidScaled) {
pile->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1), non_solid_paint);
pile->RerecordPile();
- PicturePileImpl::Analysis analysis;
- pile->AnalyzeInRect(gfx::Rect(0, 0, 10, 10), 0.1f, &analysis);
+ RasterSource::SolidColorAnalysis analysis;
+ pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 10, 10), 0.1f, &analysis);
EXPECT_FALSE(analysis.is_solid_color);
- pile->AnalyzeInRect(gfx::Rect(10, 0, 10, 10), 0.1f, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(10, 0, 10, 10), 0.1f, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
// Boundaries should be clipped
analysis.is_solid_color = false;
- pile->AnalyzeInRect(gfx::Rect(35, 0, 10, 10), 0.1f, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(35, 0, 10, 10), 0.1f, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
analysis.is_solid_color = false;
- pile->AnalyzeInRect(gfx::Rect(0, 35, 10, 10), 0.1f, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(0, 35, 10, 10), 0.1f, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
analysis.is_solid_color = false;
- pile->AnalyzeInRect(gfx::Rect(35, 35, 10, 10), 0.1f, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(35, 35, 10, 10), 0.1f, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
}
@@ -138,10 +138,10 @@ TEST(PicturePileImplTest, AnalyzeIsSolidEmpty) {
scoped_refptr<FakePicturePileImpl> pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- PicturePileImpl::Analysis analysis;
+ RasterSource::SolidColorAnalysis analysis;
EXPECT_FALSE(analysis.is_solid_color);
- pile->AnalyzeInRect(gfx::Rect(0, 0, 400, 400), 1.f, &analysis);
+ pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 400, 400), 1.f, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, SkColorSetARGB(0, 0, 0, 0));
@@ -685,12 +685,7 @@ TEST_P(FullContentsTest, RasterFullContents) {
SkCanvas canvas(bitmap);
canvas.clear(SK_ColorTRANSPARENT);
- FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
-
- pile->RasterToBitmap(&canvas,
- canvas_rect,
- contents_scale,
- &rendering_stats_instrumentation);
+ pile->PlaybackToCanvas(&canvas, canvas_rect, contents_scale);
SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
int num_pixels = bitmap.width() * bitmap.height();
@@ -737,9 +732,7 @@ TEST(PicturePileImpl, RasterContentsTransparent) {
bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height());
SkCanvas canvas(bitmap);
- FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
- pile->RasterToBitmap(
- &canvas, canvas_rect, contents_scale, &rendering_stats_instrumentation);
+ pile->PlaybackToCanvas(&canvas, canvas_rect, contents_scale);
SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
int num_pixels = bitmap.width() * bitmap.height();
@@ -780,17 +773,10 @@ TEST_P(OverlapTest, NoOverlap) {
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- content_bounds.width(),
- content_bounds.height());
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(content_bounds.width(), content_bounds.height());
SkCanvas canvas(bitmap);
- FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
- pile->RasterToBitmap(&canvas,
- gfx::Rect(content_bounds),
- contents_scale,
- &rendering_stats_instrumentation);
+ pile->PlaybackToCanvas(&canvas, gfx::Rect(content_bounds), contents_scale);
for (int y = 0; y < bitmap.height(); y++) {
for (int x = 0; x < bitmap.width(); x++) {
diff --git a/chromium/cc/resources/picture_pile_unittest.cc b/chromium/cc/resources/picture_pile_unittest.cc
index 681166ea877..00b1b0c97fb 100644
--- a/chromium/cc/resources/picture_pile_unittest.cc
+++ b/chromium/cc/resources/picture_pile_unittest.cc
@@ -9,14 +9,16 @@
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_rendering_stats_instrumentation.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
namespace cc {
namespace {
class TestPicturePile : public PicturePile {
public:
+ ~TestPicturePile() override {}
+
using PicturePile::buffer_pixels;
using PicturePile::CanRasterSlowTileCheck;
using PicturePile::Clear;
@@ -24,76 +26,169 @@ class TestPicturePile : public PicturePile {
PictureMap& picture_map() { return picture_map_; }
const gfx::Rect& recorded_viewport() const { return recorded_viewport_; }
- bool CanRasterLayerRect(const gfx::Rect& layer_rect) {
- return CanRaster(1.f, layer_rect);
+ bool CanRasterLayerRect(gfx::Rect layer_rect) {
+ layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
+ if (recorded_viewport_.Contains(layer_rect))
+ return true;
+ return CanRasterSlowTileCheck(layer_rect);
}
+ bool HasRecordings() const { return has_any_recordings_; }
+
typedef PicturePile::PictureInfo PictureInfo;
typedef PicturePile::PictureMapKey PictureMapKey;
typedef PicturePile::PictureMap PictureMap;
-
- protected:
- virtual ~TestPicturePile() {}
};
-class PicturePileTest : public testing::Test {
+class PicturePileTestBase {
public:
- PicturePileTest()
- : pile_(new TestPicturePile()),
- background_color_(SK_ColorBLUE),
+ PicturePileTestBase()
+ : background_color_(SK_ColorBLUE),
min_scale_(0.125),
frame_number_(0),
- contents_opaque_(false) {
- pile_->SetTilingRect(gfx::Rect(pile_->tiling().max_texture_size()));
- pile_->SetTileGridSize(gfx::Size(1000, 1000));
- pile_->SetMinContentsScale(min_scale_);
+ contents_opaque_(false) {}
+
+ void InitializeData() {
+ pile_.SetTileGridSize(gfx::Size(1000, 1000));
+ pile_.SetMinContentsScale(min_scale_);
+ client_ = FakeContentLayerClient();
+ SetTilingSize(pile_.tiling().max_texture_size());
}
- gfx::Rect tiling_rect() const { return pile_->tiling_rect(); }
+ void SetTilingSize(const gfx::Size& tiling_size) {
+ Region invalidation;
+ gfx::Rect viewport_rect(tiling_size);
+ UpdateAndExpandInvalidation(&invalidation, tiling_size, viewport_rect);
+ }
+
+ gfx::Size tiling_size() const { return pile_.tiling_size(); }
+ gfx::Rect tiling_rect() const { return gfx::Rect(pile_.tiling_size()); }
bool UpdateAndExpandInvalidation(Region* invalidation,
+ const gfx::Size& layer_size,
const gfx::Rect& visible_layer_rect) {
frame_number_++;
- return pile_->UpdateAndExpandInvalidation(&client_,
- invalidation,
- background_color_,
- contents_opaque_,
- false,
- visible_layer_rect,
- frame_number_,
- Picture::RECORD_NORMALLY,
- &stats_instrumentation_);
+ return pile_.UpdateAndExpandInvalidation(&client_,
+ invalidation,
+ background_color_,
+ contents_opaque_,
+ false,
+ layer_size,
+ visible_layer_rect,
+ frame_number_,
+ Picture::RECORD_NORMALLY,
+ &stats_instrumentation_);
}
bool UpdateWholePile() {
Region invalidation = tiling_rect();
- bool result = UpdateAndExpandInvalidation(&invalidation, tiling_rect());
+ bool result = UpdateAndExpandInvalidation(
+ &invalidation, tiling_size(), tiling_rect());
EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
return result;
}
FakeContentLayerClient client_;
FakeRenderingStatsInstrumentation stats_instrumentation_;
- scoped_refptr<TestPicturePile> pile_;
+ TestPicturePile pile_;
SkColor background_color_;
float min_scale_;
int frame_number_;
bool contents_opaque_;
};
-TEST_F(PicturePileTest, SmallInvalidateInflated) {
- UpdateWholePile();
+class PicturePileTest : public PicturePileTestBase, public testing::Test {
+ public:
+ virtual void SetUp() override { InitializeData(); }
+};
+
+TEST_F(PicturePileTest, InvalidationOnTileBorderOutsideInterestRect) {
+ // Don't expand the interest rect past what we invalidate.
+ pile_.SetPixelRecordDistanceForTesting(0);
+
+ gfx::Size tile_size(100, 100);
+ pile_.tiling().SetMaxTextureSize(tile_size);
+
+ gfx::Size pile_size(400, 400);
+ SetTilingSize(pile_size);
+
+ // We have multiple tiles.
+ EXPECT_GT(pile_.tiling().num_tiles_x(), 2);
+ EXPECT_GT(pile_.tiling().num_tiles_y(), 2);
+
+ // Record everything.
+ Region invalidation(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
+
+ // +----------+-----------------+-----------+
+ // | | VVVV 1,0| |
+ // | | VVVV | |
+ // | | VVVV | |
+ // | ...|.................|... |
+ // | ...|.................|... |
+ // +----------+-----------------+-----------+
+ // | ...| |... |
+ // | ...| |... |
+ // | ...| |... |
+ // | ...| |... |
+ // | ...| 1,1|... |
+ // +----------+-----------------+-----------+
+ // | ...|.................|... |
+ // | ...|.................|... |
+ // +----------+-----------------+-----------+
+ //
+ // .. = border pixels for tile 1,1
+ // VV = interest rect (what we will record)
+ //
+ // The first invalidation is inside VV, so it does not touch border pixels of
+ // tile 1,1.
+ //
+ // The second invalidation goes below VV into the .. border pixels of 1,1.
+ // This is the VV interest rect which will be entirely inside 1,0 and not
+ // touch the border of 1,1.
+ gfx::Rect interest_rect(
+ pile_.tiling().TilePositionX(1) + pile_.tiling().border_texels(),
+ 0,
+ 10,
+ pile_.tiling().TileSizeY(0) - pile_.tiling().border_texels());
+
+ // Invalidate tile 1,0 only. This is a rect that avoids the borders of any
+ // other tiles.
+ gfx::Rect invalidate_tile = interest_rect;
+ // This should cause the tile 1,0 to be invalidated and re-recorded. The
+ // invalidation did not need to be expanded.
+ invalidation = invalidate_tile;
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
+ EXPECT_EQ(invalidate_tile, invalidation);
+
+ // Invalidate tile 1,0 and 1,1 by invalidating something that only touches the
+ // border of 1,1 (and is inside the tile bounds of 1,0). This is a 10px wide
+ // strip from the top of the tiling onto the border pixels of tile 1,1 that
+ // avoids border pixels of any other tiles.
+ gfx::Rect invalidate_border = interest_rect;
+ invalidate_border.Inset(0, 0, 0, -1);
+ // This should cause the tile 1,0 and 1,1 to be invalidated. The 1,1 tile will
+ // not be re-recorded since it does not touch the interest rect, so the
+ // invalidation should be expanded to cover all of 1,1.
+ invalidation = invalidate_border;
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
+ Region expected_invalidation = invalidate_border;
+ expected_invalidation.Union(pile_.tiling().TileBounds(1, 1));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+}
+
+TEST_F(PicturePileTest, SmallInvalidateInflated) {
// Invalidate something inside a tile.
Region invalidate_rect(gfx::Rect(50, 50, 1, 1));
- UpdateAndExpandInvalidation(&invalidate_rect, tiling_rect());
+ UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
EXPECT_EQ(gfx::Rect(50, 50, 1, 1).ToString(), invalidate_rect.ToString());
- EXPECT_EQ(1, pile_->tiling().num_tiles_x());
- EXPECT_EQ(1, pile_->tiling().num_tiles_y());
+ EXPECT_EQ(1, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(1, pile_.tiling().num_tiles_y());
TestPicturePile::PictureInfo& picture_info =
- pile_->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
+ pile_.picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
// We should have a picture.
EXPECT_TRUE(!!picture_info.GetPicture());
gfx::Rect picture_rect = gfx::ScaleToEnclosedRect(
@@ -106,64 +201,59 @@ TEST_F(PicturePileTest, SmallInvalidateInflated) {
}
TEST_F(PicturePileTest, LargeInvalidateInflated) {
- UpdateWholePile();
-
// Invalidate something inside a tile.
Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
- UpdateAndExpandInvalidation(&invalidate_rect, tiling_rect());
+ UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
- EXPECT_EQ(1, pile_->tiling().num_tiles_x());
- EXPECT_EQ(1, pile_->tiling().num_tiles_y());
+ EXPECT_EQ(1, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(1, pile_.tiling().num_tiles_y());
TestPicturePile::PictureInfo& picture_info =
- pile_->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
+ pile_.picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
EXPECT_TRUE(!!picture_info.GetPicture());
- int expected_inflation = pile_->buffer_pixels();
+ int expected_inflation = pile_.buffer_pixels();
- Picture* base_picture = picture_info.GetPicture();
- gfx::Rect base_picture_rect = pile_->tiling_rect();
+ const Picture* base_picture = picture_info.GetPicture();
+ gfx::Rect base_picture_rect(pile_.tiling_size());
base_picture_rect.Inset(-expected_inflation, -expected_inflation);
EXPECT_EQ(base_picture_rect.ToString(),
base_picture->LayerRect().ToString());
}
TEST_F(PicturePileTest, InvalidateOnTileBoundaryInflated) {
- gfx::Rect new_tiling_rect =
- gfx::ToEnclosedRect(gfx::ScaleRect(pile_->tiling_rect(), 2.f));
- pile_->SetTilingRect(new_tiling_rect);
+ gfx::Size new_tiling_size =
+ gfx::ToCeiledSize(gfx::ScaleSize(pile_.tiling_size(), 2.f));
+ // This creates initial pictures.
+ SetTilingSize(new_tiling_size);
// Due to border pixels, we should have 3 tiles.
- EXPECT_EQ(3, pile_->tiling().num_tiles_x());
- EXPECT_EQ(3, pile_->tiling().num_tiles_y());
+ EXPECT_EQ(3, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(3, pile_.tiling().num_tiles_y());
// We should have 1/.125 - 1 = 7 border pixels.
- EXPECT_EQ(7, pile_->buffer_pixels());
- EXPECT_EQ(7, pile_->tiling().border_texels());
+ EXPECT_EQ(7, pile_.buffer_pixels());
+ EXPECT_EQ(7, pile_.tiling().border_texels());
- // Update the whole layer to create initial pictures.
- UpdateWholePile();
-
- // Invalidate everything again to have a non zero invalidation
- // frequency.
+ // Invalidate everything to have a non zero invalidation frequency.
UpdateWholePile();
// Invalidate something just over a tile boundary by a single pixel.
// This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
Region invalidate_rect(
- gfx::Rect(pile_->tiling().TileBoundsWithBorder(0, 0).right(),
- pile_->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
+ gfx::Rect(pile_.tiling().TileBoundsWithBorder(0, 0).right(),
+ pile_.tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
50,
50));
Region expected_invalidation = invalidate_rect;
- UpdateAndExpandInvalidation(&invalidate_rect, tiling_rect());
+ UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
EXPECT_EQ(expected_invalidation.ToString(), invalidate_rect.ToString());
- for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
TestPicturePile::PictureInfo& picture_info =
- pile_->picture_map()
+ pile_.picture_map()
.find(TestPicturePile::PictureMapKey(i, j))
->second;
@@ -182,13 +272,34 @@ TEST_F(PicturePileTest, InvalidateOnTileBoundaryInflated) {
}
}
+TEST_F(PicturePileTest, InvalidateOnFullLayer) {
+ UpdateWholePile();
+
+ // Everything was invalidated once so far.
+ for (auto& it : pile_.picture_map()) {
+ EXPECT_FLOAT_EQ(
+ 1.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
+ it.second.GetInvalidationFrequencyForTesting());
+ }
+
+ // Invalidate everything,
+ Region invalidation = tiling_rect();
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
+
+ // Everything was invalidated again.
+ for (auto& it : pile_.picture_map()) {
+ EXPECT_FLOAT_EQ(
+ 2.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
+ it.second.GetInvalidationFrequencyForTesting());
+ }
+}
+
TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
- gfx::Rect new_tiling_rect =
- gfx::ToEnclosedRect(gfx::ScaleRect(pile_->tiling_rect(), 4.f));
- pile_->SetTilingRect(new_tiling_rect);
+ gfx::Size new_tiling_size =
+ gfx::ToCeiledSize(gfx::ScaleSize(pile_.tiling_size(), 4.f));
+ SetTilingSize(new_tiling_size);
- gfx::Rect viewport(
- tiling_rect().x(), tiling_rect().y(), tiling_rect().width(), 1);
+ gfx::Rect viewport(tiling_size().width(), 1);
// Update the whole pile until the invalidation frequency is high.
for (int frame = 0; frame < 33; ++frame) {
@@ -196,10 +307,10 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
}
// Make sure we have a high invalidation frequency.
- for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
TestPicturePile::PictureInfo& picture_info =
- pile_->picture_map()
+ pile_.picture_map()
.find(TestPicturePile::PictureMapKey(i, j))
->second;
EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting())
@@ -208,14 +319,14 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
}
// Update once more with a small viewport.
- Region invalidation = tiling_rect();
- UpdateAndExpandInvalidation(&invalidation, viewport);
+ Region invalidation(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
- for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
TestPicturePile::PictureInfo& picture_info =
- pile_->picture_map()
+ pile_.picture_map()
.find(TestPicturePile::PictureMapKey(i, j))
->second;
EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting());
@@ -232,24 +343,25 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
// Update a partial tile that doesn't get recorded. We should expand the
// invalidation to the entire tiles that overlap it.
Region small_invalidation =
- gfx::Rect(pile_->tiling().TileBounds(3, 4).x(),
- pile_->tiling().TileBounds(3, 4).y() + 10,
+ gfx::Rect(pile_.tiling().TileBounds(3, 4).x(),
+ pile_.tiling().TileBounds(3, 4).y() + 10,
1,
1);
- UpdateAndExpandInvalidation(&small_invalidation, viewport);
+ UpdateAndExpandInvalidation(&small_invalidation, tiling_size(), viewport);
EXPECT_TRUE(small_invalidation.Contains(gfx::UnionRects(
- pile_->tiling().TileBounds(2, 4), pile_->tiling().TileBounds(3, 4))))
+ pile_.tiling().TileBounds(2, 4), pile_.tiling().TileBounds(3, 4))))
<< small_invalidation.ToString();
// Now update with no invalidation and full viewport
Region empty_invalidation;
- UpdateAndExpandInvalidation(&empty_invalidation, tiling_rect());
+ UpdateAndExpandInvalidation(
+ &empty_invalidation, tiling_size(), tiling_rect());
EXPECT_EQ(Region().ToString(), empty_invalidation.ToString());
- for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
- for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
TestPicturePile::PictureInfo& picture_info =
- pile_->picture_map()
+ pile_.picture_map()
.find(TestPicturePile::PictureMapKey(i, j))
->second;
// Expect the invalidation frequency to be less than 1, since we just
@@ -263,18 +375,16 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
}
TEST_F(PicturePileTest, ClearingInvalidatesRecordedRect) {
- UpdateWholePile();
-
gfx::Rect rect(0, 0, 5, 5);
- EXPECT_TRUE(pile_->CanRasterLayerRect(rect));
- EXPECT_TRUE(pile_->CanRasterSlowTileCheck(rect));
+ EXPECT_TRUE(pile_.CanRasterLayerRect(rect));
+ EXPECT_TRUE(pile_.CanRasterSlowTileCheck(rect));
- pile_->Clear();
+ pile_.Clear();
// Make sure both the cache-aware check (using recorded region) and the normal
// check are both false after clearing.
- EXPECT_FALSE(pile_->CanRasterLayerRect(rect));
- EXPECT_FALSE(pile_->CanRasterSlowTileCheck(rect));
+ EXPECT_FALSE(pile_.CanRasterLayerRect(rect));
+ EXPECT_FALSE(pile_.CanRasterSlowTileCheck(rect));
}
TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
@@ -282,27 +392,27 @@ TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
// and doesn't get re-recorded, then CanRaster is not true for any
// tiles touching it, but is true for adjacent tiles, even if it
// overlaps on borders (edge case).
- gfx::Rect new_tiling_rect =
- gfx::ToEnclosedRect(gfx::ScaleRect(pile_->tiling_rect(), 4.f));
- pile_->SetTilingRect(new_tiling_rect);
+ gfx::Size new_tiling_size =
+ gfx::ToCeiledSize(gfx::ScaleSize(pile_.tiling_size(), 4.f));
+ SetTilingSize(new_tiling_size);
- gfx::Rect tile01_borders = pile_->tiling().TileBoundsWithBorder(0, 1);
- gfx::Rect tile02_borders = pile_->tiling().TileBoundsWithBorder(0, 2);
- gfx::Rect tile01_noborders = pile_->tiling().TileBounds(0, 1);
- gfx::Rect tile02_noborders = pile_->tiling().TileBounds(0, 2);
+ gfx::Rect tile01_borders = pile_.tiling().TileBoundsWithBorder(0, 1);
+ gfx::Rect tile02_borders = pile_.tiling().TileBoundsWithBorder(0, 2);
+ gfx::Rect tile01_noborders = pile_.tiling().TileBounds(0, 1);
+ gfx::Rect tile02_noborders = pile_.tiling().TileBounds(0, 2);
// Sanity check these two tiles are overlapping with borders, since this is
// what the test is trying to repro.
EXPECT_TRUE(tile01_borders.Intersects(tile02_borders));
EXPECT_FALSE(tile01_noborders.Intersects(tile02_noborders));
UpdateWholePile();
- EXPECT_TRUE(pile_->CanRasterLayerRect(tile01_noborders));
- EXPECT_TRUE(pile_->CanRasterSlowTileCheck(tile01_noborders));
- EXPECT_TRUE(pile_->CanRasterLayerRect(tile02_noborders));
- EXPECT_TRUE(pile_->CanRasterSlowTileCheck(tile02_noborders));
+ EXPECT_TRUE(pile_.CanRasterLayerRect(tile01_noborders));
+ EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile01_noborders));
+ EXPECT_TRUE(pile_.CanRasterLayerRect(tile02_noborders));
+ EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile02_noborders));
// Sanity check that an initial paint goes down the fast path of having
// a valid recorded viewport.
- EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
// Update the whole layer until the invalidation frequency is high.
for (int frame = 0; frame < 33; ++frame) {
@@ -310,75 +420,1163 @@ TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
}
// Update once more with a small viewport.
- gfx::Rect viewport(0, 0, tiling_rect().width(), 1);
+ gfx::Rect viewport(tiling_size().width(), 1);
Region invalidation(tiling_rect());
- UpdateAndExpandInvalidation(&invalidation, viewport);
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
// Sanity check some pictures exist and others don't.
- EXPECT_TRUE(pile_->picture_map()
+ EXPECT_TRUE(pile_.picture_map()
.find(TestPicturePile::PictureMapKey(0, 1))
->second.GetPicture());
- EXPECT_FALSE(pile_->picture_map()
+ EXPECT_FALSE(pile_.picture_map()
.find(TestPicturePile::PictureMapKey(0, 2))
->second.GetPicture());
- EXPECT_TRUE(pile_->CanRasterLayerRect(tile01_noborders));
- EXPECT_TRUE(pile_->CanRasterSlowTileCheck(tile01_noborders));
- EXPECT_FALSE(pile_->CanRasterLayerRect(tile02_noborders));
- EXPECT_FALSE(pile_->CanRasterSlowTileCheck(tile02_noborders));
+ EXPECT_TRUE(pile_.CanRasterLayerRect(tile01_noborders));
+ EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile01_noborders));
+ EXPECT_FALSE(pile_.CanRasterLayerRect(tile02_noborders));
+ EXPECT_FALSE(pile_.CanRasterSlowTileCheck(tile02_noborders));
}
TEST_F(PicturePileTest, NoInvalidationValidViewport) {
// This test validates that the recorded_viewport cache of full tiles
// is still valid for some use cases. If it's not, it's a performance
// issue because CanRaster checks will go down the slow path.
- UpdateWholePile();
- EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
// No invalidation, same viewport.
Region invalidation;
- UpdateAndExpandInvalidation(&invalidation, tiling_rect());
- EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
+ EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
EXPECT_EQ(Region().ToString(), invalidation.ToString());
// Partial invalidation, same viewport.
invalidation = gfx::Rect(0, 0, 1, 1);
- UpdateAndExpandInvalidation(&invalidation, tiling_rect());
- EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
+ EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
// No invalidation, changing viewport.
invalidation = Region();
- UpdateAndExpandInvalidation(&invalidation, gfx::Rect(5, 5, 5, 5));
- EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ UpdateAndExpandInvalidation(
+ &invalidation, tiling_size(), gfx::Rect(5, 5, 5, 5));
+ EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
EXPECT_EQ(Region().ToString(), invalidation.ToString());
}
+TEST_F(PicturePileTest, BigFullLayerInvalidation) {
+ gfx::Size huge_layer_size(100000000, 100000000);
+ gfx::Rect viewport(300000, 400000, 5000, 6000);
+
+ // Resize the pile.
+ Region invalidation;
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
+
+ // Invalidating a huge layer should be fast.
+ base::TimeTicks start = base::TimeTicks::Now();
+ invalidation = gfx::Rect(huge_layer_size);
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
+ base::TimeTicks end = base::TimeTicks::Now();
+ base::TimeDelta length = end - start;
+ // This is verrrry generous to avoid flake.
+ EXPECT_LT(length.InSeconds(), 5);
+}
+
+TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeGrow) {
+ gfx::Size huge_layer_size(100000000, 100000000);
+ gfx::Rect viewport(300000, 400000, 5000, 6000);
+
+ // Resize the pile.
+ Region invalidation;
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
+
+ // Resize the pile even larger, while invalidating everything in the old size.
+ // Invalidating the whole thing should be fast.
+ base::TimeTicks start = base::TimeTicks::Now();
+ gfx::Size bigger_layer_size(huge_layer_size.width() * 2,
+ huge_layer_size.height() * 2);
+ invalidation = gfx::Rect(huge_layer_size);
+ UpdateAndExpandInvalidation(&invalidation, bigger_layer_size, viewport);
+ base::TimeTicks end = base::TimeTicks::Now();
+ base::TimeDelta length = end - start;
+ // This is verrrry generous to avoid flake.
+ EXPECT_LT(length.InSeconds(), 5);
+}
+
+TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeShrink) {
+ gfx::Size huge_layer_size(100000000, 100000000);
+ gfx::Rect viewport(300000, 400000, 5000, 6000);
+
+ // Resize the pile.
+ Region invalidation;
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
+
+ // Resize the pile smaller, while invalidating everything in the new size.
+ // Invalidating the whole thing should be fast.
+ base::TimeTicks start = base::TimeTicks::Now();
+ gfx::Size smaller_layer_size(huge_layer_size.width() - 1000,
+ huge_layer_size.height() - 1000);
+ invalidation = gfx::Rect(smaller_layer_size);
+ UpdateAndExpandInvalidation(&invalidation, smaller_layer_size, viewport);
+ base::TimeTicks end = base::TimeTicks::Now();
+ base::TimeDelta length = end - start;
+ // This is verrrry generous to avoid flake.
+ EXPECT_LT(length.InSeconds(), 5);
+}
+
TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
- gfx::Rect huge_layer_rect(10000000, 20000000);
+ gfx::Size huge_layer_size(10000000, 20000000);
gfx::Rect viewport(300000, 400000, 5000, 6000);
- pile_->SetTilingRect(huge_layer_rect);
+ // Resize the pile and set up the interest rect.
+ Region invalidation;
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
// Invalidation inside the recording rect does not need to be expanded.
- Region invalidation = viewport;
- UpdateAndExpandInvalidation(&invalidation, viewport);
+ invalidation = viewport;
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
EXPECT_EQ(viewport.ToString(), invalidation.ToString());
// Invalidation outside the recording rect should expand to the tiles it
// covers.
gfx::Rect recorded_over_tiles =
- pile_->tiling().ExpandRectToTileBounds(pile_->recorded_viewport());
+ pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
gfx::Rect invalidation_outside(
recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
invalidation = invalidation_outside;
- UpdateAndExpandInvalidation(&invalidation, viewport);
+ UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
gfx::Rect expanded_recorded_viewport =
- pile_->tiling().ExpandRectToTileBounds(pile_->recorded_viewport());
+ pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
Region expected_invalidation =
- pile_->tiling().ExpandRectToTileBounds(invalidation_outside);
+ pile_.tiling().ExpandRectToTileBounds(invalidation_outside);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+}
+
+enum Corner {
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT,
+};
+
+class PicturePileResizeCornerTest : public PicturePileTestBase,
+ public testing::TestWithParam<Corner> {
+ protected:
+ virtual void SetUp() override { InitializeData(); }
+
+ static gfx::Rect CornerSinglePixelRect(Corner corner, const gfx::Size& s) {
+ switch (corner) {
+ case TOP_LEFT:
+ return gfx::Rect(0, 0, 1, 1);
+ case TOP_RIGHT:
+ return gfx::Rect(s.width() - 1, 0, 1, 1);
+ case BOTTOM_LEFT:
+ return gfx::Rect(0, s.height() - 1, 1, 1);
+ case BOTTOM_RIGHT:
+ return gfx::Rect(s.width() - 1, s.height() - 1, 1, 1);
+ }
+ NOTREACHED();
+ return gfx::Rect();
+ }
+};
+
+TEST_P(PicturePileResizeCornerTest, ResizePileOutsideInterestRect) {
+ Corner corner = GetParam();
+
+ // This size chosen to be larger than the interest rect size, which is
+ // at least kPixelDistanceToRecord * 2 in each dimension.
+ int tile_size = 100000;
+ // The small number subtracted keeps the last tile in each axis larger than
+ // the interest rect also.
+ int offset = -100;
+ gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
+ gfx::Size grow_down_tiling_size(6 * tile_size + offset,
+ 8 * tile_size + offset);
+ gfx::Size grow_right_tiling_size(8 * tile_size + offset,
+ 6 * tile_size + offset);
+ gfx::Size grow_both_tiling_size(8 * tile_size + offset,
+ 8 * tile_size + offset);
+
+ Region invalidation;
+ Region expected_invalidation;
+
+ pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
+ SetTilingSize(base_tiling_size);
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ UpdateAndExpandInvalidation(
+ &invalidation,
+ grow_down_tiling_size,
+ CornerSinglePixelRect(corner, grow_down_tiling_size));
+
+ // We should have lost all of the recordings in the bottom row as none of them
+ // are in the current interest rect (which is either the above or below it).
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(8, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < 6; ++i) {
+ for (int j = 0; j < 6; ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_EQ(j < 5, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated all new pixels in the recording.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
+ gfx::Rect(base_tiling_size));
+ // But the new pixels don't cover the whole bottom row.
+ gfx::Rect bottom_row = gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(5, 5));
+ EXPECT_FALSE(expected_invalidation.Contains(bottom_row));
+ // We invalidated the entire old bottom row.
+ expected_invalidation.Union(bottom_row);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation,
+ base_tiling_size,
+ CornerSinglePixelRect(corner, base_tiling_size));
+
+ // When shrinking, we should have lost all the recordings in the bottom row
+ // not touching the interest rect.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ bool expect_tile;
+ switch (corner) {
+ case TOP_LEFT:
+ case TOP_RIGHT:
+ expect_tile = j < 5;
+ break;
+ case BOTTOM_LEFT:
+ // The interest rect in the bottom left tile means we'll record it.
+ expect_tile = j < 5 || (j == 5 && i == 0);
+ break;
+ case BOTTOM_RIGHT:
+ // The interest rect in the bottom right tile means we'll record it.
+ expect_tile = j < 5 || (j == 5 && i == 5);
+ break;
+ }
+ EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // When shrinking, the previously exposed region is invalidated.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
+ gfx::Rect(base_tiling_size));
+ // The whole bottom row of tiles (except any with the interest rect) are
+ // dropped.
+ gfx::Rect bottom_row_minus_existing_corner = gfx::UnionRects(
+ pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
+ switch (corner) {
+ case TOP_LEFT:
+ case TOP_RIGHT:
+ // No tiles are kept in the changed region because it doesn't
+ // intersect with the interest rect.
+ break;
+ case BOTTOM_LEFT:
+ bottom_row_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(0, 5));
+ break;
+ case BOTTOM_RIGHT:
+ bottom_row_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(5, 5));
+ break;
+ }
+
+ expected_invalidation.Union(bottom_row_minus_existing_corner);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(
+ &invalidation,
+ grow_right_tiling_size,
+ CornerSinglePixelRect(corner, grow_right_tiling_size));
+
+ // We should have lost all of the recordings in the right column as none of
+ // them are in the current interest rect (which is either entirely left or
+ // right of it).
+ EXPECT_EQ(8, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < 6; ++i) {
+ for (int j = 0; j < 6; ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_EQ(i < 5, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated all new pixels in the recording.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
+ gfx::Rect(base_tiling_size));
+ // But the new pixels don't cover the whole right_column.
+ gfx::Rect right_column = gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
+ pile_.tiling().TileBounds(5, 5));
+ EXPECT_FALSE(expected_invalidation.Contains(right_column));
+ // We invalidated the entire old right column.
+ expected_invalidation.Union(right_column);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation,
+ base_tiling_size,
+ CornerSinglePixelRect(corner, base_tiling_size));
+
+ // When shrinking, we should have lost all the recordings in the right column
+ // not touching the interest rect.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ bool expect_tile;
+ switch (corner) {
+ case TOP_LEFT:
+ case BOTTOM_LEFT:
+ // No tiles are kept in the changed region because it doesn't
+ // intersect with the interest rect.
+ expect_tile = i < 5;
+ break;
+ case TOP_RIGHT:
+ // The interest rect in the top right tile means we'll record it.
+ expect_tile = i < 5 || (j == 0 && i == 5);
+ break;
+ case BOTTOM_RIGHT:
+ // The interest rect in the bottom right tile means we'll record it.
+ expect_tile = i < 5 || (j == 5 && i == 5);
+ break;
+ }
+ EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // When shrinking, the previously exposed region is invalidated.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
+ gfx::Rect(base_tiling_size));
+ // The whole right column of tiles (except for ones with the interest rect)
+ // are dropped.
+ gfx::Rect right_column_minus_existing_corner = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
+ switch (corner) {
+ case TOP_LEFT:
+ case BOTTOM_LEFT:
+ break;
+ case TOP_RIGHT:
+ right_column_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(5, 0));
+ break;
+ case BOTTOM_RIGHT:
+ right_column_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(5, 5));
+ break;
+ }
+ expected_invalidation.Union(right_column_minus_existing_corner);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(
+ &invalidation,
+ grow_both_tiling_size,
+ CornerSinglePixelRect(corner, grow_both_tiling_size));
+
+ // We should have lost the recordings in the right column and bottom row.
+ EXPECT_EQ(8, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(8, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < 6; ++i) {
+ for (int j = 0; j < 6; ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_EQ(i < 5 && j < 5, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated all new pixels in the recording.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
+ gfx::Rect(base_tiling_size));
+ // But the new pixels don't cover the whole right column or bottom row.
+ Region right_column_and_bottom_row =
+ UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
+ pile_.tiling().TileBounds(5, 5)),
+ gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(5, 5)));
+ EXPECT_FALSE(expected_invalidation.Contains(right_column_and_bottom_row));
+ // We invalidated the entire old right column and the old bottom row.
+ expected_invalidation.Union(right_column_and_bottom_row);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size,
+ CornerSinglePixelRect(corner, base_tiling_size));
+
+ // We should have lost the recordings in the right column and bottom row,
+ // except where it intersects the interest rect.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ bool expect_tile;
+ switch (corner) {
+ case TOP_LEFT:
+ expect_tile = i < 5 && j < 5;
+ break;
+ case TOP_RIGHT:
+ // The interest rect in the top right tile means we'll record it.
+ expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
+ break;
+ case BOTTOM_LEFT:
+ // The interest rect in the bottom left tile means we'll record it.
+ expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
+ break;
+ case BOTTOM_RIGHT:
+ // The interest rect in the bottom right tile means we'll record it.
+ expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
+ break;
+ }
+ EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
+ << i << "," << j;
+ }
+ }
+
+ // We invalidated all previous pixels in the recording.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
+ gfx::Rect(base_tiling_size));
+ // The whole right column and bottom row of tiles (except for ones with the
+ // interest rect) are dropped.
+ Region right_column_and_bottom_row_minus_existing_corner =
+ right_column_and_bottom_row;
+ switch (corner) {
+ case TOP_LEFT:
+ break;
+ case BOTTOM_LEFT:
+ right_column_and_bottom_row_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(0, 5));
+ break;
+ case TOP_RIGHT:
+ right_column_and_bottom_row_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(5, 0));
+ break;
+ case BOTTOM_RIGHT:
+ right_column_and_bottom_row_minus_existing_corner.Subtract(
+ pile_.tiling().TileBounds(5, 5));
+ break;
+ }
+ expected_invalidation.Union(
+ right_column_and_bottom_row_minus_existing_corner);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+}
+
+TEST_P(PicturePileResizeCornerTest, SmallResizePileOutsideInterestRect) {
+ Corner corner = GetParam();
+
+ // This size chosen to be larger than the interest rect size, which is
+ // at least kPixelDistanceToRecord * 2 in each dimension.
+ int tile_size = 100000;
+ // The small number subtracted keeps the last tile in each axis larger than
+ // the interest rect also.
+ int offset = -100;
+ gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
+ gfx::Size grow_down_tiling_size(6 * tile_size + offset,
+ 6 * tile_size + offset + 5);
+ gfx::Size grow_right_tiling_size(6 * tile_size + offset + 5,
+ 6 * tile_size + offset);
+ gfx::Size grow_both_tiling_size(6 * tile_size + offset + 5,
+ 6 * tile_size + offset + 5);
+
+ Region invalidation;
+ Region expected_invalidation;
+
+ pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
+ SetTilingSize(base_tiling_size);
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // In this test (unlike the large resize test), as all growing and shrinking
+ // happens within tiles, the resulting invalidation is symmetrical, so use
+ // this enum to repeat the test both ways.
+ enum ChangeDirection { GROW, SHRINK, LAST_DIRECTION = SHRINK };
+
+ // Grow downward.
+ for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
+ gfx::Size new_tiling_size =
+ dir == GROW ? grow_down_tiling_size : base_tiling_size;
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
+ CornerSinglePixelRect(corner, new_tiling_size));
+
+ // We should have lost the recordings in the bottom row that do not
+ // intersect the interest rect.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ bool expect_tile;
+ switch (corner) {
+ case TOP_LEFT:
+ case TOP_RIGHT:
+ expect_tile = j < 5;
+ break;
+ case BOTTOM_LEFT:
+ // The interest rect in the bottom left tile means we'll record it.
+ expect_tile = j < 5 || (j == 5 && i == 0);
+ break;
+ case BOTTOM_RIGHT:
+ // The interest rect in the bottom right tile means we'll record it.
+ expect_tile = j < 5 || (j == 5 && i == 5);
+ break;
+ }
+ EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the bottom row outside the new interest rect. The tile
+ // that insects the interest rect in invalidated only on its newly
+ // exposed or previously exposed pixels.
+ if (dir == GROW) {
+ // Only calculate the expected invalidation while growing, as the tile
+ // bounds post-growing is the newly exposed / previously exposed sizes.
+ // Post-shrinking, the tile bounds are smaller, so can't be used.
+ switch (corner) {
+ case TOP_LEFT:
+ case TOP_RIGHT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
+ break;
+ case BOTTOM_LEFT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(1, 5), pile_.tiling().TileBounds(5, 5));
+ expected_invalidation.Union(SubtractRects(
+ pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
+ break;
+ case BOTTOM_RIGHT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(4, 5));
+ expected_invalidation.Union(SubtractRects(
+ pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
+ break;
+ }
+ }
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+ }
+
+ // Grow right.
+ for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
+ gfx::Size new_tiling_size =
+ dir == GROW ? grow_right_tiling_size : base_tiling_size;
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
+ CornerSinglePixelRect(corner, new_tiling_size));
+
+ // We should have lost the recordings in the right column.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ bool expect_tile;
+ switch (corner) {
+ case TOP_LEFT:
+ case BOTTOM_LEFT:
+ expect_tile = i < 5;
+ break;
+ case TOP_RIGHT:
+ // The interest rect in the top right tile means we'll record it.
+ expect_tile = i < 5 || (j == 0 && i == 5);
+ break;
+ case BOTTOM_RIGHT:
+ // The interest rect in the bottom right tile means we'll record it.
+ expect_tile = i < 5 || (j == 5 && i == 5);
+ break;
+ }
+ EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the right column outside the new interest rect. The tile
+ // that insects the interest rect in invalidated only on its new or
+ // previously exposed pixels.
+ if (dir == GROW) {
+ // Calculate the expected invalidation the first time through the loop.
+ switch (corner) {
+ case TOP_LEFT:
+ case BOTTOM_LEFT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
+ break;
+ case TOP_RIGHT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
+ expected_invalidation.Union(SubtractRects(
+ pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
+ break;
+ case BOTTOM_RIGHT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
+ expected_invalidation.Union(SubtractRects(
+ pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
+ break;
+ }
+ }
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+ }
+
+ // Grow both.
+ for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
+ gfx::Size new_tiling_size =
+ dir == GROW ? grow_both_tiling_size : base_tiling_size;
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
+ CornerSinglePixelRect(corner, new_tiling_size));
+
+ // We should have lost the recordings in the right column and bottom row.
+ // The tile that insects the interest rect in invalidated only on its new
+ // or previously exposed pixels.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ bool expect_tile;
+ switch (corner) {
+ case TOP_LEFT:
+ expect_tile = i < 5 && j < 5;
+ break;
+ case TOP_RIGHT:
+ // The interest rect in the top right tile means we'll record it.
+ expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
+ break;
+ case BOTTOM_LEFT:
+ // The interest rect in the bottom left tile means we'll record it.
+ expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
+ break;
+ case BOTTOM_RIGHT:
+ // The interest rect in the bottom right tile means we'll record it.
+ expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
+ break;
+ }
+ EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
+ << i << "," << j;
+ }
+ }
+
+ // We invalidated the right column and the bottom row outside the new
+ // interest rect. The tile that insects the interest rect in invalidated
+ // only on its new or previous exposed pixels.
+ if (dir == GROW) {
+ // Calculate the expected invalidation the first time through the loop.
+ switch (corner) {
+ case TOP_LEFT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
+ expected_invalidation.Union(
+ gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(5, 5)));
+ break;
+ case TOP_RIGHT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
+ expected_invalidation.Union(
+ gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(5, 5)));
+ expected_invalidation.Union(SubtractRects(
+ pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
+ break;
+ case BOTTOM_LEFT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
+ expected_invalidation.Union(
+ gfx::UnionRects(pile_.tiling().TileBounds(1, 5),
+ pile_.tiling().TileBounds(5, 5)));
+ expected_invalidation.Union(SubtractRects(
+ pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
+ break;
+ case BOTTOM_RIGHT:
+ expected_invalidation = gfx::UnionRects(
+ pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
+ expected_invalidation.Union(
+ gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(4, 5)));
+ expected_invalidation.Union(SubtractRegions(
+ pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
+ break;
+ }
+ }
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(
+ PicturePileResizeCornerTests,
+ PicturePileResizeCornerTest,
+ ::testing::Values(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT));
+
+TEST_F(PicturePileTest, ResizePileInsideInterestRect) {
+ // This size chosen to be small enough that all the rects below fit inside the
+ // the interest rect, so they are smaller than kPixelDistanceToRecord in each
+ // dimension.
+ int tile_size = 100;
+ gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
+ gfx::Size grow_down_tiling_size(5 * tile_size, 7 * tile_size);
+ gfx::Size grow_right_tiling_size(7 * tile_size, 5 * tile_size);
+ gfx::Size grow_both_tiling_size(7 * tile_size, 7 * tile_size);
+
+ Region invalidation;
+ Region expected_invalidation;
+
+ pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
+ SetTilingSize(base_tiling_size);
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ UpdateAndExpandInvalidation(
+ &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(8, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the newly exposed pixels on the bottom row of tiles.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
+ gfx::Rect(base_tiling_size));
+ Region bottom_row_new_pixels =
+ SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(5, 5)),
+ gfx::Rect(base_tiling_size));
+ EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the previously exposed pixels on the bottom row of tiles.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(
+ &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(8, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the newly exposed pixels on the right column of tiles.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
+ gfx::Rect(base_tiling_size));
+ Region right_column_new_pixels =
+ SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
+ pile_.tiling().TileBounds(5, 5)),
+ gfx::Rect(base_tiling_size));
+ EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
+
+ // We should have lost the recordings that are now outside the tiling only.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the previously exposed pixels on the right column of tiles.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(
+ &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(8, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(8, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the newly exposed pixels on the bottom row and right column
+ // of tiles.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
+ gfx::Rect(base_tiling_size));
+ Region bottom_row_and_right_column_new_pixels = SubtractRegions(
+ UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
+ pile_.tiling().TileBounds(5, 5)),
+ gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
+ pile_.tiling().TileBounds(5, 5))),
+ gfx::Rect(base_tiling_size));
+ EXPECT_TRUE(
+ expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
+
+ // We should have lost the recordings that are now outside the tiling only.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the previously exposed pixels on the bottom row and right
+ // column of tiles.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_TRUE(
+ expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+}
+
+TEST_F(PicturePileTest, SmallResizePileInsideInterestRect) {
+ // This size chosen to be small enough that all the rects below fit inside the
+ // the interest rect, so they are smaller than kPixelDistanceToRecord in each
+ // dimension.
+ int tile_size = 100;
+ gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
+ gfx::Size grow_down_tiling_size(5 * tile_size, 5 * tile_size + 5);
+ gfx::Size grow_right_tiling_size(5 * tile_size + 5, 5 * tile_size);
+ gfx::Size grow_both_tiling_size(5 * tile_size + 5, 5 * tile_size + 5);
+
+ Region invalidation;
+ Region expected_invalidation;
+
+ pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
+ SetTilingSize(base_tiling_size);
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ UpdateAndExpandInvalidation(
+ &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the newly exposed pixels.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the previously exposed pixels.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(
+ &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the newly exposed pixels.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
+
+ // We should have lost the recordings that are now outside the tiling only.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the previously exposed pixels.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(
+ &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
+
+ // We should have a recording for every tile.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the newly exposed pixels.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+
+ UpdateWholePile();
+ UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
+
+ // We should have lost the recordings that are now outside the tiling only.
+ EXPECT_EQ(6, pile_.tiling().num_tiles_x());
+ EXPECT_EQ(6, pile_.tiling().num_tiles_y());
+ for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
+ for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
+ TestPicturePile::PictureMapKey key(i, j);
+ TestPicturePile::PictureMap& map = pile_.picture_map();
+ TestPicturePile::PictureMap::iterator it = map.find(key);
+ EXPECT_TRUE(it != map.end() && it->second.GetPicture());
+ }
+ }
+
+ // We invalidated the previously exposed pixels.
+ expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
+ gfx::Rect(base_tiling_size));
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
+ invalidation.Clear();
+}
+
+TEST_F(PicturePileTest, SolidRectangleIsSolid) {
+ // If the client has no contents, the solid state will be true.
+ Region invalidation1(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation1, tiling_size(), tiling_rect());
+ EXPECT_TRUE(pile_.is_solid_color());
+ EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), pile_.solid_color());
+
+ // If there is a single rect that covers the view, the solid
+ // state will be true.
+ SkPaint paint;
+ paint.setColor(SK_ColorCYAN);
+ client_.add_draw_rect(tiling_rect(), paint);
+ Region invalidation2(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation2, tiling_size(), tiling_rect());
+ EXPECT_TRUE(pile_.is_solid_color());
+ EXPECT_EQ(SK_ColorCYAN, pile_.solid_color());
+
+ // If a second smaller rect is draw that doesn't cover the viewport
+ // completely, the solid state will be false.
+ gfx::Rect smallRect = tiling_rect();
+ smallRect.Inset(10, 10, 10, 10);
+ client_.add_draw_rect(smallRect, paint);
+ Region invalidation3(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation3, tiling_size(), tiling_rect());
+ EXPECT_FALSE(pile_.is_solid_color());
+
+ // If a third rect is drawn over everything, we should be solid again.
+ paint.setColor(SK_ColorRED);
+ client_.add_draw_rect(tiling_rect(), paint);
+ Region invalidation4(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation4, tiling_size(), tiling_rect());
+ EXPECT_TRUE(pile_.is_solid_color());
+ EXPECT_EQ(SK_ColorRED, pile_.solid_color());
+
+ // If we draw too many, we don't bother doing the analysis and we should no
+ // longer be in a solid state. There are 8 rects, two clips and a translate.
+ client_.add_draw_rect(tiling_rect(), paint);
+ client_.add_draw_rect(tiling_rect(), paint);
+ client_.add_draw_rect(tiling_rect(), paint);
+ client_.add_draw_rect(tiling_rect(), paint);
+ client_.add_draw_rect(tiling_rect(), paint);
+ Region invalidation5(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation5, tiling_size(), tiling_rect());
+ EXPECT_FALSE(pile_.is_solid_color());
+}
+
+TEST_F(PicturePileTest, NonSolidRectangleOnOffsettedLayerIsNonSolid) {
+ gfx::Rect visible_rect(tiling_rect());
+ visible_rect.Offset(gfx::Vector2d(1000, 1000));
+ // The picture pile requires that the tiling completely encompass the viewport
+ // to make this test work correctly since the recorded viewport is an
+ // intersection of the tile size and viewport rect. This is possibly a flaw
+ // in |PicturePile|.
+ gfx::Size tiling_size(visible_rect.right(), visible_rect.bottom());
+ // |Setup()| will create pictures here that mess with the test, clear it!
+ pile_.Clear();
+
+ SkPaint paint;
+ paint.setColor(SK_ColorCYAN);
+
+ // Add a rect that doesn't cover the viewport completely, the solid state
+ // will be false.
+ gfx::Rect smallRect = visible_rect;
+ smallRect.Inset(10, 10, 10, 10);
+ client_.add_draw_rect(smallRect, paint);
+ Region invalidation(visible_rect);
+ UpdateAndExpandInvalidation(&invalidation, tiling_size, visible_rect);
+ EXPECT_FALSE(pile_.is_solid_color());
+}
+
+TEST_F(PicturePileTest, SetEmptyBounds) {
+ EXPECT_TRUE(pile_.is_solid_color());
+ EXPECT_FALSE(pile_.tiling_size().IsEmpty());
+ EXPECT_FALSE(pile_.picture_map().empty());
+ EXPECT_TRUE(pile_.HasRecordings());
+ pile_.SetEmptyBounds();
+ EXPECT_FALSE(pile_.is_solid_color());
+ EXPECT_TRUE(pile_.tiling_size().IsEmpty());
+ EXPECT_TRUE(pile_.picture_map().empty());
+ EXPECT_FALSE(pile_.HasRecordings());
}
} // namespace
diff --git a/chromium/cc/resources/picture_unittest.cc b/chromium/cc/resources/picture_unittest.cc
index 1367c5fd89a..07faf0cf4a6 100644
--- a/chromium/cc/resources/picture_unittest.cc
+++ b/chromium/cc/resources/picture_unittest.cc
@@ -11,10 +11,8 @@
#include "cc/test/skia_common.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBBHFactory.h"
-#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkGraphics.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/skia_util.h"
namespace cc {
@@ -45,73 +43,56 @@ TEST(PictureTest, AsBase64String) {
Picture::CreateFromValue(tmp.get());
EXPECT_FALSE(invalid_picture.get());
- Picture::RecordingMode kRecordingModes[] = {Picture::RECORD_NORMALLY,
- Picture::RECORD_WITH_SKRECORD};
-
// Single full-size rect picture.
content_layer_client.add_draw_rect(layer_rect, red_paint);
- for (size_t i = 0; i < arraysize(kRecordingModes); ++i) {
- scoped_refptr<Picture> one_rect_picture =
- Picture::Create(layer_rect,
- &content_layer_client,
- tile_grid_info,
- false,
- 0,
- kRecordingModes[i]);
- scoped_ptr<base::Value> serialized_one_rect(one_rect_picture->AsValue());
-
- // Reconstruct the picture.
- scoped_refptr<Picture> one_rect_picture_check =
- Picture::CreateFromValue(serialized_one_rect.get());
- EXPECT_TRUE(!!one_rect_picture_check.get());
-
- // Check for equivalence.
- unsigned char one_rect_buffer[4 * 100 * 100] = {0};
- DrawPicture(one_rect_buffer, layer_rect, one_rect_picture);
- unsigned char one_rect_buffer_check[4 * 100 * 100] = {0};
- DrawPicture(one_rect_buffer_check, layer_rect, one_rect_picture_check);
-
- EXPECT_EQ(one_rect_picture->LayerRect(),
- one_rect_picture_check->LayerRect());
- EXPECT_EQ(one_rect_picture->OpaqueRect(),
- one_rect_picture_check->OpaqueRect());
- EXPECT_TRUE(memcmp(one_rect_buffer, one_rect_buffer_check, 4 * 100 * 100) ==
- 0);
- }
+ scoped_refptr<Picture> one_rect_picture =
+ Picture::Create(layer_rect,
+ &content_layer_client,
+ tile_grid_info,
+ false,
+ Picture::RECORD_NORMALLY);
+ scoped_ptr<base::Value> serialized_one_rect(one_rect_picture->AsValue());
+
+ // Reconstruct the picture.
+ scoped_refptr<Picture> one_rect_picture_check =
+ Picture::CreateFromValue(serialized_one_rect.get());
+ EXPECT_TRUE(!!one_rect_picture_check.get());
+
+ // Check for equivalence.
+ unsigned char one_rect_buffer[4 * 100 * 100] = {0};
+ DrawPicture(one_rect_buffer, layer_rect, one_rect_picture);
+ unsigned char one_rect_buffer_check[4 * 100 * 100] = {0};
+ DrawPicture(one_rect_buffer_check, layer_rect, one_rect_picture_check);
+
+ EXPECT_EQ(one_rect_picture->LayerRect(), one_rect_picture_check->LayerRect());
+ EXPECT_EQ(0, memcmp(one_rect_buffer, one_rect_buffer_check, 4 * 100 * 100));
// Two rect picture.
content_layer_client.add_draw_rect(gfx::Rect(25, 25, 50, 50), green_paint);
- for (size_t i = 0; i < arraysize(kRecordingModes); ++i) {
- scoped_refptr<Picture> two_rect_picture =
- Picture::Create(layer_rect,
- &content_layer_client,
- tile_grid_info,
- false,
- 0,
- Picture::RECORD_NORMALLY);
-
- scoped_ptr<base::Value> serialized_two_rect(two_rect_picture->AsValue());
-
- // Reconstruct the picture.
- scoped_refptr<Picture> two_rect_picture_check =
- Picture::CreateFromValue(serialized_two_rect.get());
- EXPECT_TRUE(!!two_rect_picture_check.get());
-
- // Check for equivalence.
- unsigned char two_rect_buffer[4 * 100 * 100] = {0};
- DrawPicture(two_rect_buffer, layer_rect, two_rect_picture);
- unsigned char two_rect_buffer_check[4 * 100 * 100] = {0};
- DrawPicture(two_rect_buffer_check, layer_rect, two_rect_picture_check);
-
- EXPECT_EQ(two_rect_picture->LayerRect(),
- two_rect_picture_check->LayerRect());
- EXPECT_EQ(two_rect_picture->OpaqueRect(),
- two_rect_picture_check->OpaqueRect());
- EXPECT_TRUE(memcmp(two_rect_buffer, two_rect_buffer_check, 4 * 100 * 100) ==
- 0);
- }
+ scoped_refptr<Picture> two_rect_picture =
+ Picture::Create(layer_rect,
+ &content_layer_client,
+ tile_grid_info,
+ false,
+ Picture::RECORD_NORMALLY);
+
+ scoped_ptr<base::Value> serialized_two_rect(two_rect_picture->AsValue());
+
+ // Reconstruct the picture.
+ scoped_refptr<Picture> two_rect_picture_check =
+ Picture::CreateFromValue(serialized_two_rect.get());
+ EXPECT_TRUE(!!two_rect_picture_check.get());
+
+ // Check for equivalence.
+ unsigned char two_rect_buffer[4 * 100 * 100] = {0};
+ DrawPicture(two_rect_buffer, layer_rect, two_rect_picture);
+ unsigned char two_rect_buffer_check[4 * 100 * 100] = {0};
+ DrawPicture(two_rect_buffer_check, layer_rect, two_rect_picture_check);
+
+ EXPECT_EQ(two_rect_picture->LayerRect(), two_rect_picture_check->LayerRect());
+ EXPECT_EQ(0, memcmp(two_rect_buffer, two_rect_buffer_check, 4 * 100 * 100));
}
TEST(PictureTest, PixelRefIterator) {
@@ -152,7 +133,6 @@ TEST(PictureTest, PixelRefIterator) {
&content_layer_client,
tile_grid_info,
true,
- 0,
Picture::RECORD_NORMALLY);
// Default iterator does not have any pixel refs
@@ -253,7 +233,6 @@ TEST(PictureTest, PixelRefIteratorNonZeroLayer) {
&content_layer_client,
tile_grid_info,
true,
- 0,
Picture::RECORD_NORMALLY);
// Default iterator does not have any pixel refs
@@ -377,7 +356,6 @@ TEST(PictureTest, PixelRefIteratorOnePixelQuery) {
&content_layer_client,
tile_grid_info,
true,
- 0,
Picture::RECORD_NORMALLY);
for (int y = 0; y < 4; ++y) {
@@ -427,7 +405,6 @@ TEST(PictureTest, CreateFromSkpValue) {
&content_layer_client,
tile_grid_info,
false,
- 0,
Picture::RECORD_NORMALLY);
scoped_ptr<base::Value> serialized_one_rect(
one_rect_picture->AsValue());
@@ -446,8 +423,6 @@ TEST(PictureTest, CreateFromSkpValue) {
EXPECT_EQ(100, one_rect_picture_check->LayerRect().width());
EXPECT_EQ(200, one_rect_picture_check->LayerRect().height());
- EXPECT_EQ(100, one_rect_picture_check->OpaqueRect().width());
- EXPECT_EQ(200, one_rect_picture_check->OpaqueRect().height());
}
TEST(PictureTest, RecordingModes) {
@@ -467,45 +442,33 @@ TEST(PictureTest, RecordingModes) {
&content_layer_client,
tile_grid_info,
false,
- 0,
Picture::RECORD_NORMALLY);
EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_ENABLED,
content_layer_client.last_context_status());
- EXPECT_TRUE(picture);
+ EXPECT_TRUE(picture.get());
picture = Picture::Create(layer_rect,
&content_layer_client,
tile_grid_info,
false,
- 0,
Picture::RECORD_WITH_SK_NULL_CANVAS);
EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_ENABLED,
content_layer_client.last_context_status());
- EXPECT_TRUE(picture);
+ EXPECT_TRUE(picture.get());
picture = Picture::Create(layer_rect,
&content_layer_client,
tile_grid_info,
false,
- 0,
Picture::RECORD_WITH_PAINTING_DISABLED);
EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_DISABLED,
content_layer_client.last_context_status());
- EXPECT_TRUE(picture);
-
- picture = Picture::Create(layer_rect,
- &content_layer_client,
- tile_grid_info,
- false,
- 0,
- Picture::RECORD_WITH_SKRECORD);
- EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_TRUE(picture);
+ EXPECT_TRUE(picture.get());
- EXPECT_EQ(4, Picture::RECORDING_MODE_COUNT);
+ EXPECT_EQ(3, Picture::RECORDING_MODE_COUNT);
}
} // namespace
diff --git a/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc b/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc
index 1df2362a5ae..175e7d40f22 100644
--- a/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc
+++ b/chromium/cc/resources/pixel_buffer_raster_worker_pool.cc
@@ -8,12 +8,53 @@
#include "base/containers/stack_container.h"
#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
+#include "base/strings/stringprintf.h"
#include "cc/debug/traced_value.h"
+#include "cc/resources/raster_buffer.h"
#include "cc/resources/resource.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
namespace cc {
namespace {
+class RasterBufferImpl : public RasterBuffer {
+ public:
+ RasterBufferImpl(ResourceProvider* resource_provider,
+ const Resource* resource)
+ : resource_provider_(resource_provider),
+ resource_(resource),
+ memory_(NULL),
+ stride_(0) {
+ resource_provider_->AcquirePixelBuffer(resource_->id());
+ memory_ = resource_provider_->MapPixelBuffer(resource_->id(), &stride_);
+ }
+
+ ~RasterBufferImpl() override {
+ resource_provider_->ReleasePixelBuffer(resource_->id());
+ }
+
+ // Overridden from RasterBuffer:
+ void Playback(const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) override {
+ if (!memory_)
+ return;
+
+ RasterWorkerPool::PlaybackToMemory(memory_, resource_->format(),
+ resource_->size(), stride_,
+ raster_source, rect, scale);
+ }
+
+ private:
+ ResourceProvider* resource_provider_;
+ const Resource* resource_;
+ uint8_t* memory_;
+ int stride_;
+
+ DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+};
+
const int kCheckForCompletedRasterTasksDelayMs = 6;
const size_t kMaxScheduledRasterTasks = 48;
@@ -21,17 +62,50 @@ const size_t kMaxScheduledRasterTasks = 48;
typedef base::StackVector<RasterTask*, kMaxScheduledRasterTasks>
RasterTaskVector;
+TaskSetCollection NonEmptyTaskSetsFromTaskCounts(const size_t* task_counts) {
+ TaskSetCollection task_sets;
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (task_counts[task_set])
+ task_sets[task_set] = true;
+ }
+ return task_sets;
+}
+
+void AddTaskSetsToTaskCounts(size_t* task_counts,
+ const TaskSetCollection& task_sets) {
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (task_sets[task_set])
+ task_counts[task_set]++;
+ }
+}
+
+void RemoveTaskSetsFromTaskCounts(size_t* task_counts,
+ const TaskSetCollection& task_sets) {
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (task_sets[task_set])
+ task_counts[task_set]--;
+ }
+}
+
} // namespace
+PixelBufferRasterWorkerPool::RasterTaskState::RasterTaskState(
+ RasterTask* task,
+ const TaskSetCollection& task_sets)
+ : type(UNSCHEDULED), task(task), task_sets(task_sets) {
+}
+
// static
scoped_ptr<RasterWorkerPool> PixelBufferRasterWorkerPool::Create(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
ResourceProvider* resource_provider,
size_t max_transfer_buffer_usage_bytes) {
return make_scoped_ptr<RasterWorkerPool>(
new PixelBufferRasterWorkerPool(task_runner,
task_graph_runner,
+ context_provider,
resource_provider,
max_transfer_buffer_usage_bytes));
}
@@ -39,23 +113,19 @@ scoped_ptr<RasterWorkerPool> PixelBufferRasterWorkerPool::Create(
PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
ResourceProvider* resource_provider,
size_t max_transfer_buffer_usage_bytes)
: task_runner_(task_runner),
task_graph_runner_(task_graph_runner),
namespace_token_(task_graph_runner->GetNamespaceToken()),
+ context_provider_(context_provider),
resource_provider_(resource_provider),
shutdown_(false),
scheduled_raster_task_count_(0u),
- raster_tasks_required_for_activation_count_(0u),
bytes_pending_upload_(0u),
max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
has_performed_uploads_since_last_flush_(false),
- should_notify_client_if_no_tasks_are_pending_(false),
- should_notify_client_if_no_tasks_required_for_activation_are_pending_(
- false),
- raster_finished_task_pending_(false),
- raster_required_for_activation_finished_task_pending_(false),
check_for_completed_raster_task_notifier_(
task_runner,
base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks,
@@ -63,6 +133,8 @@ PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
base::TimeDelta::FromMilliseconds(
kCheckForCompletedRasterTasksDelayMs)),
raster_finished_weak_ptr_factory_(this) {
+ DCHECK(context_provider_);
+ std::fill(task_counts_, task_counts_ + kNumberOfTaskSets, 0);
}
PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
@@ -70,7 +142,7 @@ PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size());
DCHECK_EQ(0u, completed_raster_tasks_.size());
DCHECK_EQ(0u, completed_image_decode_tasks_.size());
- DCHECK_EQ(0u, raster_tasks_required_for_activation_count_);
+ DCHECK(NonEmptyTaskSetsFromTaskCounts(task_counts_).none());
}
Rasterizer* PixelBufferRasterWorkerPool::AsRasterizer() { return this; }
@@ -91,7 +163,7 @@ void PixelBufferRasterWorkerPool::Shutdown() {
CheckForCompletedRasterizerTasks();
CheckForCompletedUploads();
- check_for_completed_raster_task_notifier_.Cancel();
+ check_for_completed_raster_task_notifier_.Shutdown();
for (RasterTaskState::Vector::iterator it = raster_task_states_.begin();
it != raster_task_states_.end();
@@ -110,19 +182,11 @@ void PixelBufferRasterWorkerPool::Shutdown() {
void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
- DCHECK_EQ(queue->required_for_activation_count,
- static_cast<size_t>(
- std::count_if(queue->items.begin(),
- queue->items.end(),
- RasterTaskQueue::Item::IsRequiredForActivation)));
-
- if (!should_notify_client_if_no_tasks_are_pending_)
+ if (should_notify_client_if_no_tasks_are_pending_.none())
TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
- should_notify_client_if_no_tasks_are_pending_ = true;
- should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true;
-
- raster_tasks_required_for_activation_count_ = 0u;
+ should_notify_client_if_no_tasks_are_pending_.set();
+ std::fill(task_counts_, task_counts_ + kNumberOfTaskSets, 0);
// Update raster task state and remove items from old queue.
for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
@@ -150,21 +214,19 @@ void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
if (state_it != raster_task_states_.end()) {
RasterTaskState& state = *state_it;
- state.required_for_activation = item.required_for_activation;
+ state.task_sets = item.task_sets;
// |raster_tasks_required_for_activation_count| accounts for all tasks
// that need to complete before we can send a "ready to activate" signal.
// Tasks that have already completed should not be part of this count.
- if (state.type != RasterTaskState::COMPLETED) {
- raster_tasks_required_for_activation_count_ +=
- item.required_for_activation;
- }
+ if (state.type != RasterTaskState::COMPLETED)
+ AddTaskSetsToTaskCounts(task_counts_, item.task_sets);
+
continue;
}
DCHECK(!task->HasBeenScheduled());
- raster_task_states_.push_back(
- RasterTaskState(task, item.required_for_activation));
- raster_tasks_required_for_activation_count_ += item.required_for_activation;
+ raster_task_states_.push_back(RasterTaskState(task, item.task_sets));
+ AddTaskSetsToTaskCounts(task_counts_, item.task_sets);
}
// Determine what tasks in old queue need to be canceled.
@@ -196,8 +258,8 @@ void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
state.type = RasterTaskState::COMPLETED;
}
- // No longer required for activation.
- state.required_for_activation = false;
+ // No longer in any task set.
+ state.task_sets.reset();
}
raster_tasks_.Swap(queue);
@@ -216,12 +278,7 @@ void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
check_for_completed_raster_task_notifier_.Schedule();
TRACE_EVENT_ASYNC_STEP_INTO1(
- "cc",
- "ScheduledTasks",
- this,
- StateName(),
- "state",
- TracedValue::FromValue(StateAsValue().release()));
+ "cc", "ScheduledTasks", this, StateName(), "state", StateAsValue());
}
void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
@@ -259,51 +316,30 @@ void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
completed_raster_tasks_.clear();
}
-SkCanvas* PixelBufferRasterWorkerPool::AcquireCanvasForRaster(
- RasterTask* task) {
- DCHECK(std::find_if(raster_task_states_.begin(),
- raster_task_states_.end(),
- RasterTaskState::TaskComparator(task)) !=
- raster_task_states_.end());
- resource_provider_->AcquirePixelRasterBuffer(task->resource()->id());
- return resource_provider_->MapPixelRasterBuffer(task->resource()->id());
+scoped_ptr<RasterBuffer> PixelBufferRasterWorkerPool::AcquireBufferForRaster(
+ const Resource* resource) {
+ return make_scoped_ptr<RasterBuffer>(
+ new RasterBufferImpl(resource_provider_, resource));
}
-void PixelBufferRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) {
- DCHECK(std::find_if(raster_task_states_.begin(),
- raster_task_states_.end(),
- RasterTaskState::TaskComparator(task)) !=
- raster_task_states_.end());
- resource_provider_->ReleasePixelRasterBuffer(task->resource()->id());
+void PixelBufferRasterWorkerPool::ReleaseBufferForRaster(
+ scoped_ptr<RasterBuffer> buffer) {
+ // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
}
-void PixelBufferRasterWorkerPool::OnRasterFinished() {
- TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::OnRasterFinished");
-
- // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
- // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
- // perform another check in that case as we've already notified the client.
- if (!should_notify_client_if_no_tasks_are_pending_)
+void PixelBufferRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
+ TRACE_EVENT2("cc",
+ "PixelBufferRasterWorkerPool::OnRasterFinished",
+ "task_set",
+ task_set,
+ "should_notify_client_if_no_tasks_are_pending",
+ should_notify_client_if_no_tasks_are_pending_[task_set]);
+
+ // There's no need to call CheckForCompletedRasterTasks() if the client has
+ // already been notified.
+ if (!should_notify_client_if_no_tasks_are_pending_[task_set])
return;
- raster_finished_task_pending_ = false;
-
- // Call CheckForCompletedRasterTasks() when we've finished running all
- // raster tasks needed since last time ScheduleTasks() was called.
- // This reduces latency between the time when all tasks have finished
- // running and the time when the client is notified.
- CheckForCompletedRasterTasks();
-}
-
-void PixelBufferRasterWorkerPool::OnRasterRequiredForActivationFinished() {
- TRACE_EVENT0(
- "cc",
- "PixelBufferRasterWorkerPool::OnRasterRequiredForActivationFinished");
-
- // Analogous to OnRasterTasksFinished(), there's no need to call
- // CheckForCompletedRasterTasks() if the client has already been notified.
- if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_)
- return;
- raster_required_for_activation_finished_task_pending_ = false;
+ raster_finished_tasks_pending_[task_set] = false;
// This reduces latency between the time when all tasks required for
// activation have finished running and the time when the client is
@@ -315,7 +351,7 @@ void PixelBufferRasterWorkerPool::FlushUploads() {
if (!has_performed_uploads_since_last_flush_)
return;
- resource_provider_->ShallowFlushIfSupported();
+ context_provider_->ContextGL()->ShallowFlushCHROMIUM();
has_performed_uploads_since_last_flush_ = false;
}
@@ -343,8 +379,10 @@ void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
}
DCHECK(client_);
+ TaskSetCollection tasks_that_should_be_forced_to_complete =
+ client_->TasksThatShouldBeForcedToComplete();
bool should_force_some_uploads_to_complete =
- shutdown_ || client_->ShouldForceTasksRequiredForActivationToComplete();
+ shutdown_ || tasks_that_should_be_forced_to_complete.any();
if (should_force_some_uploads_to_complete) {
RasterTask::Vector tasks_with_uploads_to_force;
@@ -358,9 +396,10 @@ void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
DCHECK(state_it != raster_task_states_.end());
const RasterTaskState& state = *state_it;
- // Force all uploads required for activation to complete.
+ // Force all uploads to complete for which the client requests to do so.
// During shutdown, force all pending uploads to complete.
- if (shutdown_ || state.required_for_activation) {
+ if (shutdown_ ||
+ (state.task_sets & tasks_that_should_be_forced_to_complete).any()) {
tasks_with_uploads_to_force.push_back(task);
tasks_with_completed_uploads.push_back(task);
it = raster_tasks_with_pending_upload_.erase(it);
@@ -403,20 +442,15 @@ void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
task->CompleteOnOriginThread(this);
task->DidComplete();
- // Async set pixels commands are not necessarily processed in-sequence with
- // drawing commands. Read lock fences are required to ensure that async
- // commands don't access the resource while used for drawing.
- resource_provider_->EnableReadLockFences(task->resource()->id(), true);
-
DCHECK(std::find(completed_raster_tasks_.begin(),
completed_raster_tasks_.end(),
task) == completed_raster_tasks_.end());
completed_raster_tasks_.push_back(task);
state.type = RasterTaskState::COMPLETED;
- DCHECK_LE(static_cast<size_t>(state.required_for_activation),
- raster_tasks_required_for_activation_count_);
- raster_tasks_required_for_activation_count_ -=
- state.required_for_activation;
+ // Triggers if the current task belongs to a set that should be empty.
+ DCHECK((state.task_sets & ~NonEmptyTaskSetsFromTaskCounts(task_counts_))
+ .none());
+ RemoveTaskSetsFromTaskCounts(task_counts_, state.task_sets);
}
}
@@ -427,70 +461,57 @@ void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
// Since this function can be called directly, cancel any pending checks.
check_for_completed_raster_task_notifier_.Cancel();
- DCHECK(should_notify_client_if_no_tasks_are_pending_);
+ DCHECK(should_notify_client_if_no_tasks_are_pending_.any());
CheckForCompletedRasterizerTasks();
CheckForCompletedUploads();
FlushUploads();
// Determine what client notifications to generate.
- bool will_notify_client_that_no_tasks_required_for_activation_are_pending =
- (should_notify_client_if_no_tasks_required_for_activation_are_pending_ &&
- !raster_required_for_activation_finished_task_pending_ &&
- !HasPendingTasksRequiredForActivation());
- bool will_notify_client_that_no_tasks_are_pending =
- (should_notify_client_if_no_tasks_are_pending_ &&
- !raster_required_for_activation_finished_task_pending_ &&
- !raster_finished_task_pending_ && !HasPendingTasks());
+ TaskSetCollection will_notify_client_that_no_tasks_are_pending =
+ should_notify_client_if_no_tasks_are_pending_ &
+ ~raster_finished_tasks_pending_ & ~PendingTasks();
// Adjust the need to generate notifications before scheduling more tasks.
- should_notify_client_if_no_tasks_required_for_activation_are_pending_ &=
- !will_notify_client_that_no_tasks_required_for_activation_are_pending;
should_notify_client_if_no_tasks_are_pending_ &=
- !will_notify_client_that_no_tasks_are_pending;
+ ~will_notify_client_that_no_tasks_are_pending;
scheduled_raster_task_count_ = 0;
if (PendingRasterTaskCount())
ScheduleMoreTasks();
TRACE_EVENT_ASYNC_STEP_INTO1(
- "cc",
- "ScheduledTasks",
- this,
- StateName(),
- "state",
- TracedValue::FromValue(StateAsValue().release()));
+ "cc", "ScheduledTasks", this, StateName(), "state", StateAsValue());
// Schedule another check for completed raster tasks while there are
// pending raster tasks or pending uploads.
- if (HasPendingTasks())
+ if (PendingTasks().any())
check_for_completed_raster_task_notifier_.Schedule();
- // Generate client notifications.
- if (will_notify_client_that_no_tasks_required_for_activation_are_pending) {
- DCHECK(!HasPendingTasksRequiredForActivation());
- client_->DidFinishRunningTasksRequiredForActivation();
- }
- if (will_notify_client_that_no_tasks_are_pending) {
+ if (should_notify_client_if_no_tasks_are_pending_.none())
TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
- DCHECK(!HasPendingTasksRequiredForActivation());
- client_->DidFinishRunningTasks();
+
+ // Generate client notifications.
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (will_notify_client_that_no_tasks_are_pending[task_set]) {
+ DCHECK(!PendingTasks()[task_set]);
+ client_->DidFinishRunningTasks(task_set);
+ }
}
}
void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
- RasterTaskVector tasks;
- RasterTaskVector tasks_required_for_activation;
+ RasterTaskVector tasks[kNumberOfTaskSets];
unsigned priority = kRasterTaskPriorityBase;
graph_.Reset();
size_t bytes_pending_upload = bytes_pending_upload_;
- bool did_throttle_raster_tasks = false;
- bool did_throttle_raster_tasks_required_for_activation = false;
+ TaskSetCollection did_throttle_raster_tasks;
+ size_t scheduled_raster_task_count = 0;
for (RasterTaskQueue::Item::Vector::const_iterator it =
raster_tasks_.items.begin();
@@ -498,6 +519,7 @@ void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
++it) {
const RasterTaskQueue::Item& item = *it;
RasterTask* task = item.task;
+ DCHECK(item.task_sets.any());
// |raster_task_states_| contains the state of all tasks that we have not
// yet run reply callbacks for.
@@ -518,13 +540,14 @@ void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
continue;
}
- // All raster tasks need to be throttled by bytes of pending uploads.
+ // All raster tasks need to be throttled by bytes of pending uploads,
+ // but if it's the only task allow it to complete no matter what its size,
+ // to prevent starvation of the task queue.
size_t new_bytes_pending_upload = bytes_pending_upload;
new_bytes_pending_upload += task->resource()->bytes();
- if (new_bytes_pending_upload > max_bytes_pending_upload_) {
- did_throttle_raster_tasks = true;
- if (item.required_for_activation)
- did_throttle_raster_tasks_required_for_activation = true;
+ if (new_bytes_pending_upload > max_bytes_pending_upload_ &&
+ bytes_pending_upload) {
+ did_throttle_raster_tasks |= item.task_sets;
continue;
}
@@ -536,10 +559,8 @@ void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
}
// Throttle raster tasks based on kMaxScheduledRasterTasks.
- if (tasks.container().size() >= kMaxScheduledRasterTasks) {
- did_throttle_raster_tasks = true;
- if (item.required_for_activation)
- did_throttle_raster_tasks_required_for_activation = true;
+ if (scheduled_raster_task_count >= kMaxScheduledRasterTasks) {
+ did_throttle_raster_tasks |= item.task_sets;
continue;
}
@@ -553,81 +574,57 @@ void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
- tasks.container().push_back(task);
- if (item.required_for_activation)
- tasks_required_for_activation.container().push_back(task);
+ ++scheduled_raster_task_count;
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (item.task_sets[task_set])
+ tasks[task_set].container().push_back(task);
+ }
}
// Cancel existing OnRasterFinished callbacks.
raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
- scoped_refptr<RasterizerTask>
- new_raster_required_for_activation_finished_task;
-
- size_t scheduled_raster_task_required_for_activation_count =
- tasks_required_for_activation.container().size();
- DCHECK_LE(scheduled_raster_task_required_for_activation_count,
- raster_tasks_required_for_activation_count_);
- // Schedule OnRasterTasksRequiredForActivationFinished call only when
- // notification is pending and throttling is not preventing all pending
- // tasks required for activation from being scheduled.
- if (!did_throttle_raster_tasks_required_for_activation &&
- should_notify_client_if_no_tasks_required_for_activation_are_pending_) {
- new_raster_required_for_activation_finished_task =
- CreateRasterRequiredForActivationFinishedTask(
- raster_tasks_.required_for_activation_count,
- task_runner_.get(),
- base::Bind(&PixelBufferRasterWorkerPool::
- OnRasterRequiredForActivationFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr()));
- raster_required_for_activation_finished_task_pending_ = true;
- InsertNodeForTask(&graph_,
- new_raster_required_for_activation_finished_task.get(),
- kRasterRequiredForActivationFinishedTaskPriority,
- scheduled_raster_task_required_for_activation_count);
- for (RasterTaskVector::ContainerType::const_iterator it =
- tasks_required_for_activation.container().begin();
- it != tasks_required_for_activation.container().end();
- ++it) {
- graph_.edges.push_back(TaskGraph::Edge(
- *it, new_raster_required_for_activation_finished_task.get()));
+ scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
+ size_t scheduled_task_counts[kNumberOfTaskSets] = {0};
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ scheduled_task_counts[task_set] = tasks[task_set].container().size();
+ DCHECK_LE(scheduled_task_counts[task_set], task_counts_[task_set]);
+ // Schedule OnRasterFinished call for task set only when notification is
+ // pending and throttling is not preventing all pending tasks in the set
+ // from being scheduled.
+ if (!did_throttle_raster_tasks[task_set] &&
+ should_notify_client_if_no_tasks_are_pending_[task_set]) {
+ new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
+ task_runner_.get(),
+ base::Bind(&PixelBufferRasterWorkerPool::OnRasterFinished,
+ raster_finished_weak_ptr_factory_.GetWeakPtr(),
+ task_set));
+ raster_finished_tasks_pending_[task_set] = true;
+ InsertNodeForTask(&graph_,
+ new_raster_finished_tasks[task_set].get(),
+ kRasterFinishedTaskPriority,
+ scheduled_task_counts[task_set]);
+ for (RasterTaskVector::ContainerType::const_iterator it =
+ tasks[task_set].container().begin();
+ it != tasks[task_set].container().end();
+ ++it) {
+ graph_.edges.push_back(
+ TaskGraph::Edge(*it, new_raster_finished_tasks[task_set].get()));
+ }
}
}
- scoped_refptr<RasterizerTask> new_raster_finished_task;
-
- size_t scheduled_raster_task_count = tasks.container().size();
DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
- // Schedule OnRasterTasksFinished call only when notification is pending
- // and throttling is not preventing all pending tasks from being scheduled.
- if (!did_throttle_raster_tasks &&
- should_notify_client_if_no_tasks_are_pending_) {
- new_raster_finished_task = CreateRasterFinishedTask(
- task_runner_.get(),
- base::Bind(&PixelBufferRasterWorkerPool::OnRasterFinished,
- raster_finished_weak_ptr_factory_.GetWeakPtr()));
- raster_finished_task_pending_ = true;
- InsertNodeForTask(&graph_,
- new_raster_finished_task.get(),
- kRasterFinishedTaskPriority,
- scheduled_raster_task_count);
- for (RasterTaskVector::ContainerType::const_iterator it =
- tasks.container().begin();
- it != tasks.container().end();
- ++it) {
- graph_.edges.push_back(
- TaskGraph::Edge(*it, new_raster_finished_task.get()));
- }
- }
ScheduleTasksOnOriginThread(this, &graph_);
task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
scheduled_raster_task_count_ = scheduled_raster_task_count;
- raster_finished_task_ = new_raster_finished_task;
- raster_required_for_activation_finished_task_ =
- new_raster_required_for_activation_finished_task;
+ std::copy(new_raster_finished_tasks,
+ new_raster_finished_tasks + kNumberOfTaskSets,
+ raster_finished_tasks_);
}
unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
@@ -637,12 +634,8 @@ unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
return raster_task_states_.size() - num_completed_raster_tasks;
}
-bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
- return PendingRasterTaskCount() || !raster_tasks_with_pending_upload_.empty();
-}
-
-bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
- return !!raster_tasks_required_for_activation_count_;
+TaskSetCollection PixelBufferRasterWorkerPool::PendingTasks() const {
+ return NonEmptyTaskSetsFromTaskCounts(task_counts_);
}
const char* PixelBufferRasterWorkerPool::StateName() const {
@@ -686,30 +679,23 @@ void PixelBufferRasterWorkerPool::CheckForCompletedRasterizerTasks() {
RasterTaskState& state = *state_it;
DCHECK_EQ(RasterTaskState::SCHEDULED, state.type);
- // Balanced with MapPixelRasterBuffer() call in AcquireCanvasForRaster().
- bool content_has_changed = resource_provider_->UnmapPixelRasterBuffer(
- raster_task->resource()->id());
+ resource_provider_->UnmapPixelBuffer(raster_task->resource()->id());
- // |content_has_changed| can be false as result of task being canceled or
- // task implementation deciding not to modify bitmap (ie. analysis of raster
- // commands detected content as a solid color).
- if (!content_has_changed) {
+ if (!raster_task->HasFinishedRunning()) {
+ // When priorites change, a raster task can be canceled as a result of
+ // no longer being of high enough priority to fit in our throttled
+ // raster task budget. The task has not yet completed in this case.
raster_task->WillComplete();
raster_task->CompleteOnOriginThread(this);
raster_task->DidComplete();
- if (!raster_task->HasFinishedRunning()) {
- // When priorites change, a raster task can be canceled as a result of
- // no longer being of high enough priority to fit in our throttled
- // raster task budget. The task has not yet completed in this case.
- RasterTaskQueue::Item::Vector::const_iterator item_it =
- std::find_if(raster_tasks_.items.begin(),
- raster_tasks_.items.end(),
- RasterTaskQueue::Item::TaskComparator(raster_task));
- if (item_it != raster_tasks_.items.end()) {
- state.type = RasterTaskState::UNSCHEDULED;
- continue;
- }
+ RasterTaskQueue::Item::Vector::const_iterator item_it =
+ std::find_if(raster_tasks_.items.begin(),
+ raster_tasks_.items.end(),
+ RasterTaskQueue::Item::TaskComparator(raster_task));
+ if (item_it != raster_tasks_.items.end()) {
+ state.type = RasterTaskState::UNSCHEDULED;
+ continue;
}
DCHECK(std::find(completed_raster_tasks_.begin(),
@@ -717,15 +703,13 @@ void PixelBufferRasterWorkerPool::CheckForCompletedRasterizerTasks() {
raster_task) == completed_raster_tasks_.end());
completed_raster_tasks_.push_back(raster_task);
state.type = RasterTaskState::COMPLETED;
- DCHECK_LE(static_cast<size_t>(state.required_for_activation),
- raster_tasks_required_for_activation_count_);
- raster_tasks_required_for_activation_count_ -=
- state.required_for_activation;
+ // Triggers if the current task belongs to a set that should be empty.
+ DCHECK((state.task_sets & ~NonEmptyTaskSetsFromTaskCounts(task_counts_))
+ .none());
+ RemoveTaskSetsFromTaskCounts(task_counts_, state.task_sets);
continue;
}
- DCHECK(raster_task->HasFinishedRunning());
-
resource_provider_->BeginSetPixels(raster_task->resource()->id());
has_performed_uploads_since_last_flush_ = true;
@@ -736,29 +720,30 @@ void PixelBufferRasterWorkerPool::CheckForCompletedRasterizerTasks() {
completed_tasks_.clear();
}
-scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
-
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+PixelBufferRasterWorkerPool::StateAsValue() const {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
state->SetInteger("completed_count", completed_raster_tasks_.size());
- state->SetInteger("pending_count", raster_task_states_.size());
+ state->BeginArray("pending_count");
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
+ state->AppendInteger(task_counts_[task_set]);
+ state->EndArray();
state->SetInteger("pending_upload_count",
raster_tasks_with_pending_upload_.size());
- state->SetInteger("pending_required_for_activation_count",
- raster_tasks_required_for_activation_count_);
- state->Set("throttle_state", ThrottleStateAsValue().release());
- return state.PassAs<base::Value>();
+ state->BeginDictionary("throttle_state");
+ ThrottleStateAsValueInto(state.get());
+ state->EndDictionary();
+ return state;
}
-scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
- const {
- scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue);
-
+void PixelBufferRasterWorkerPool::ThrottleStateAsValueInto(
+ base::debug::TracedValue* throttle_state) const {
throttle_state->SetInteger("bytes_available_for_upload",
max_bytes_pending_upload_ - bytes_pending_upload_);
throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
throttle_state->SetInteger("scheduled_raster_task_count",
scheduled_raster_task_count_);
- return throttle_state.PassAs<base::Value>();
}
} // namespace cc
diff --git a/chromium/cc/resources/pixel_buffer_raster_worker_pool.h b/chromium/cc/resources/pixel_buffer_raster_worker_pool.h
index a2f15fd6f51..7fb45ecd641 100644
--- a/chromium/cc/resources/pixel_buffer_raster_worker_pool.h
+++ b/chromium/cc/resources/pixel_buffer_raster_worker_pool.h
@@ -11,9 +11,17 @@
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "cc/base/delayed_unique_notifier.h"
+#include "cc/output/context_provider.h"
#include "cc/resources/raster_worker_pool.h"
#include "cc/resources/rasterizer.h"
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
namespace cc {
class ResourceProvider;
@@ -21,26 +29,28 @@ class CC_EXPORT PixelBufferRasterWorkerPool : public RasterWorkerPool,
public Rasterizer,
public RasterizerTaskClient {
public:
- virtual ~PixelBufferRasterWorkerPool();
+ ~PixelBufferRasterWorkerPool() override;
static scoped_ptr<RasterWorkerPool> Create(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
ResourceProvider* resource_provider,
size_t max_transfer_buffer_usage_bytes);
// Overridden from RasterWorkerPool:
- virtual Rasterizer* AsRasterizer() OVERRIDE;
+ Rasterizer* AsRasterizer() override;
// Overridden from Rasterizer:
- virtual void SetClient(RasterizerClient* client) OVERRIDE;
- virtual void Shutdown() OVERRIDE;
- virtual void ScheduleTasks(RasterTaskQueue* queue) OVERRIDE;
- virtual void CheckForCompletedTasks() OVERRIDE;
+ void SetClient(RasterizerClient* client) override;
+ void Shutdown() override;
+ void ScheduleTasks(RasterTaskQueue* queue) override;
+ void CheckForCompletedTasks() override;
// Overridden from RasterizerTaskClient:
- virtual SkCanvas* AcquireCanvasForRaster(RasterTask* task) OVERRIDE;
- virtual void ReleaseCanvasForRaster(RasterTask* task) OVERRIDE;
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) override;
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
private:
struct RasterTaskState {
@@ -58,42 +68,39 @@ class CC_EXPORT PixelBufferRasterWorkerPool : public RasterWorkerPool,
typedef std::vector<RasterTaskState> Vector;
- RasterTaskState(RasterTask* task, bool required_for_activation)
- : type(UNSCHEDULED),
- task(task),
- required_for_activation(required_for_activation) {}
+ RasterTaskState(RasterTask* task, const TaskSetCollection& task_sets);
enum { UNSCHEDULED, SCHEDULED, UPLOADING, COMPLETED } type;
RasterTask* task;
- bool required_for_activation;
+ TaskSetCollection task_sets;
};
- typedef std::deque<scoped_refptr<RasterTask> > RasterTaskDeque;
+ typedef std::deque<scoped_refptr<RasterTask>> RasterTaskDeque;
PixelBufferRasterWorkerPool(base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
+ ContextProvider* context_provider,
ResourceProvider* resource_provider,
size_t max_transfer_buffer_usage_bytes);
- void OnRasterFinished();
- void OnRasterRequiredForActivationFinished();
+ void OnRasterFinished(TaskSet task_set);
void FlushUploads();
void CheckForCompletedUploads();
void CheckForCompletedRasterTasks();
void ScheduleMoreTasks();
unsigned PendingRasterTaskCount() const;
- bool HasPendingTasks() const;
- bool HasPendingTasksRequiredForActivation() const;
+ TaskSetCollection PendingTasks() const;
void CheckForCompletedRasterizerTasks();
const char* StateName() const;
- scoped_ptr<base::Value> StateAsValue() const;
- scoped_ptr<base::Value> ThrottleStateAsValue() const;
+ scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+ void ThrottleStateAsValueInto(base::debug::TracedValue* throttle_state) const;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
TaskGraphRunner* task_graph_runner_;
const NamespaceToken namespace_token_;
RasterizerClient* client_;
+ ContextProvider* context_provider_;
ResourceProvider* resource_provider_;
bool shutdown_;
@@ -105,29 +112,26 @@ class CC_EXPORT PixelBufferRasterWorkerPool : public RasterWorkerPool,
RasterizerTask::Vector completed_image_decode_tasks_;
size_t scheduled_raster_task_count_;
- size_t raster_tasks_required_for_activation_count_;
+ size_t task_counts_[kNumberOfTaskSets];
size_t bytes_pending_upload_;
size_t max_bytes_pending_upload_;
bool has_performed_uploads_since_last_flush_;
- bool should_notify_client_if_no_tasks_are_pending_;
- bool should_notify_client_if_no_tasks_required_for_activation_are_pending_;
- bool raster_finished_task_pending_;
- bool raster_required_for_activation_finished_task_pending_;
+ TaskSetCollection should_notify_client_if_no_tasks_are_pending_;
+ TaskSetCollection raster_finished_tasks_pending_;
DelayedUniqueNotifier check_for_completed_raster_task_notifier_;
- base::WeakPtrFactory<PixelBufferRasterWorkerPool>
- raster_finished_weak_ptr_factory_;
-
- scoped_refptr<RasterizerTask> raster_finished_task_;
- scoped_refptr<RasterizerTask> raster_required_for_activation_finished_task_;
+ scoped_refptr<RasterizerTask> raster_finished_tasks_[kNumberOfTaskSets];
// Task graph used when scheduling tasks and vector used to gather
// completed tasks.
TaskGraph graph_;
Task::Vector completed_tasks_;
+ base::WeakPtrFactory<PixelBufferRasterWorkerPool>
+ raster_finished_weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PixelBufferRasterWorkerPool);
};
diff --git a/chromium/cc/resources/platform_color.h b/chromium/cc/resources/platform_color.h
index ecdf7c166f2..4945dccadc5 100644
--- a/chromium/cc/resources/platform_color.h
+++ b/chromium/cc/resources/platform_color.h
@@ -44,7 +44,7 @@ class PlatformColor {
case SOURCE_FORMAT_RGBA8:
return format == RGBA_8888 || format == RGBA_4444;
case SOURCE_FORMAT_BGRA8:
- return format == BGRA_8888;
+ return format == BGRA_8888 || format == RGBA_4444;
}
NOTREACHED();
return false;
diff --git a/chromium/cc/resources/prioritized_resource.h b/chromium/cc/resources/prioritized_resource.h
index 7920f811042..e3bb2bc4d1c 100644
--- a/chromium/cc/resources/prioritized_resource.h
+++ b/chromium/cc/resources/prioritized_resource.h
@@ -9,12 +9,11 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
-#include "cc/resources/priority_calculator.h"
#include "cc/resources/resource.h"
#include "cc/resources/resource_provider.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/vector2d.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d.h"
namespace cc {
diff --git a/chromium/cc/resources/prioritized_resource_manager.cc b/chromium/cc/resources/prioritized_resource_manager.cc
index 81af9fbf6dc..657c14f4ddf 100644
--- a/chromium/cc/resources/prioritized_resource_manager.cc
+++ b/chromium/cc/resources/prioritized_resource_manager.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include "base/debug/trace_event.h"
-#include "base/stl_util.h"
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/priority_calculator.h"
#include "cc/trees/proxy.h"
@@ -455,7 +454,7 @@ PrioritizedResource::Backing* PrioritizedResourceManager::CreateBacking(
size,
GL_TEXTURE_2D,
GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
+ ResourceProvider::TextureHintImmutable,
format);
PrioritizedResource::Backing* backing = new PrioritizedResource::Backing(
resource_id, resource_provider, size, format);
diff --git a/chromium/cc/resources/prioritized_resource_manager.h b/chromium/cc/resources/prioritized_resource_manager.h
index 092b1d720fd..b7583f4315f 100644
--- a/chromium/cc/resources/prioritized_resource_manager.h
+++ b/chromium/cc/resources/prioritized_resource_manager.h
@@ -16,22 +16,10 @@
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/priority_calculator.h"
#include "cc/resources/resource.h"
-#include "cc/trees/proxy.h"
-#include "ui/gfx/size.h"
-
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
-template <> struct hash<cc::PrioritizedResource*> {
- size_t operator()(cc::PrioritizedResource* ptr) const {
- return hash<size_t>()(reinterpret_cast<size_t>(ptr));
- }
-};
-} // namespace BASE_HASH_NAMESPACE
-#endif // COMPILER
+#include "ui/gfx/geometry/size.h"
namespace cc {
-class PriorityCalculator;
class Proxy;
class CC_EXPORT PrioritizedResourceManager {
diff --git a/chromium/cc/resources/prioritized_resource_unittest.cc b/chromium/cc/resources/prioritized_resource_unittest.cc
index 14eb317461c..8869e706036 100644
--- a/chromium/cc/resources/prioritized_resource_unittest.cc
+++ b/chromium/cc/resources/prioritized_resource_unittest.cc
@@ -28,14 +28,18 @@ class PrioritizedResourceTest : public testing::Test {
DebugScopedSetImplThread impl_thread(&proxy_);
CHECK(output_surface_->BindToClient(&output_surface_client_));
shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false);
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1);
}
virtual ~PrioritizedResourceTest() {
DebugScopedSetImplThread impl_thread(&proxy_);
- resource_provider_.reset();
+ resource_provider_ = nullptr;
}
size_t TexturesMemorySize(size_t texture_count) {
@@ -273,7 +277,7 @@ TEST_F(PrioritizedResourceTest, ReduceWastedMemory) {
EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
// Destroy one texture, not enough is wasted to cause cleanup.
- textures[0] = scoped_ptr<PrioritizedResource>();
+ textures[0] = nullptr;
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
@@ -286,7 +290,7 @@ TEST_F(PrioritizedResourceTest, ReduceWastedMemory) {
// Destroy half the textures, leaving behind the backings. Now a cleanup
// should happen.
for (size_t i = 0; i < kMaxTextures / 2; ++i)
- textures[i] = scoped_ptr<PrioritizedResource>();
+ textures[i] = nullptr;
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
@@ -353,7 +357,7 @@ TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) {
// sent to a parent compositor though, so they should not be considered wasted
// and a cleanup should not happen.
for (size_t i = 0; i < kMaxTextures / 2; ++i)
- textures[i] = scoped_ptr<PrioritizedResource>();
+ textures[i] = nullptr;
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
@@ -561,7 +565,7 @@ TEST_F(PrioritizedResourceTest, EvictingTexturesInParent) {
// Drop all the textures. Now we have backings that can be recycled.
for (size_t i = 0; i < 8; ++i)
- textures[0].reset();
+ textures[0] = nullptr;
PrioritizeTexturesAndBackings(resource_manager.get());
// The next commit finishes.
@@ -724,7 +728,7 @@ TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) {
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
- resource_manager.reset();
+ resource_manager = nullptr;
EXPECT_FALSE(texture->can_acquire_backing_texture());
EXPECT_FALSE(texture->have_backing_texture());
@@ -754,7 +758,7 @@ TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) {
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager_one->ClearAllMemory(resource_provider());
}
- resource_manager_one.reset();
+ resource_manager_one = nullptr;
EXPECT_FALSE(texture->can_acquire_backing_texture());
EXPECT_FALSE(texture->have_backing_texture());
diff --git a/chromium/cc/resources/prioritized_tile_set.cc b/chromium/cc/resources/prioritized_tile_set.cc
deleted file mode 100644
index b7b3b5a741e..00000000000
--- a/chromium/cc/resources/prioritized_tile_set.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// 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/prioritized_tile_set.h"
-
-#include <algorithm>
-
-#include "cc/resources/managed_tile_state.h"
-#include "cc/resources/tile.h"
-
-namespace cc {
-
-class BinComparator {
- public:
- bool operator()(const Tile* a,
- const Tile* b) const {
- const ManagedTileState& ams = a->managed_state();
- const ManagedTileState& bms = b->managed_state();
-
- if (ams.priority_bin != bms.priority_bin)
- return ams.priority_bin < bms.priority_bin;
-
- if (ams.required_for_activation != bms.required_for_activation)
- return ams.required_for_activation;
-
- if (ams.resolution != bms.resolution)
- return ams.resolution < bms.resolution;
-
- if (ams.distance_to_visible != bms.distance_to_visible)
- return ams.distance_to_visible < bms.distance_to_visible;
-
- gfx::Rect a_rect = a->content_rect();
- gfx::Rect b_rect = b->content_rect();
- if (a_rect.y() != b_rect.y())
- return a_rect.y() < b_rect.y();
- return a_rect.x() < b_rect.x();
- }
-};
-
-namespace {
-
-typedef std::vector<Tile*> TileVector;
-
-void SortBinTiles(ManagedTileBin bin, TileVector* tiles) {
- switch (bin) {
- case NOW_AND_READY_TO_DRAW_BIN:
- case NEVER_BIN:
- break;
- case NOW_BIN:
- case SOON_BIN:
- case EVENTUALLY_AND_ACTIVE_BIN:
- case EVENTUALLY_BIN:
- case AT_LAST_AND_ACTIVE_BIN:
- case AT_LAST_BIN:
- std::sort(tiles->begin(), tiles->end(), BinComparator());
- break;
- default:
- NOTREACHED();
- }
-}
-
-} // namespace
-
-PrioritizedTileSet::PrioritizedTileSet() {
- for (int bin = 0; bin < NUM_BINS; ++bin)
- bin_sorted_[bin] = true;
-}
-
-PrioritizedTileSet::~PrioritizedTileSet() {}
-
-void PrioritizedTileSet::InsertTile(Tile* tile, ManagedTileBin bin) {
- tiles_[bin].push_back(tile);
- bin_sorted_[bin] = false;
-}
-
-void PrioritizedTileSet::Clear() {
- for (int bin = 0; bin < NUM_BINS; ++bin) {
- tiles_[bin].clear();
- bin_sorted_[bin] = true;
- }
-}
-
-void PrioritizedTileSet::SortBinIfNeeded(ManagedTileBin bin) {
- if (!bin_sorted_[bin]) {
- SortBinTiles(bin, &tiles_[bin]);
- bin_sorted_[bin] = true;
- }
-}
-
-PrioritizedTileSet::Iterator::Iterator(
- PrioritizedTileSet* tile_set, bool use_priority_ordering)
- : tile_set_(tile_set),
- current_bin_(NOW_AND_READY_TO_DRAW_BIN),
- use_priority_ordering_(use_priority_ordering) {
- if (use_priority_ordering_)
- tile_set_->SortBinIfNeeded(current_bin_);
- iterator_ = tile_set->tiles_[current_bin_].begin();
- if (iterator_ == tile_set_->tiles_[current_bin_].end())
- AdvanceList();
-}
-
-PrioritizedTileSet::Iterator::~Iterator() {}
-
-void PrioritizedTileSet::Iterator::DisablePriorityOrdering() {
- use_priority_ordering_ = false;
-}
-
-PrioritizedTileSet::Iterator&
-PrioritizedTileSet::Iterator::operator++() {
- // We can't increment past the end of the tiles.
- DCHECK(iterator_ != tile_set_->tiles_[current_bin_].end());
-
- ++iterator_;
- if (iterator_ == tile_set_->tiles_[current_bin_].end())
- AdvanceList();
- return *this;
-}
-
-Tile* PrioritizedTileSet::Iterator::operator*() {
- DCHECK(iterator_ != tile_set_->tiles_[current_bin_].end());
- return *iterator_;
-}
-
-void PrioritizedTileSet::Iterator::AdvanceList() {
- DCHECK(iterator_ == tile_set_->tiles_[current_bin_].end());
-
- while (current_bin_ != NEVER_BIN) {
- current_bin_ = static_cast<ManagedTileBin>(current_bin_ + 1);
-
- if (use_priority_ordering_)
- tile_set_->SortBinIfNeeded(current_bin_);
-
- iterator_ = tile_set_->tiles_[current_bin_].begin();
- if (iterator_ != tile_set_->tiles_[current_bin_].end())
- break;
- }
-}
-
-} // namespace cc
diff --git a/chromium/cc/resources/prioritized_tile_set.h b/chromium/cc/resources/prioritized_tile_set.h
deleted file mode 100644
index 15d0e4f8b48..00000000000
--- a/chromium/cc/resources/prioritized_tile_set.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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_PRIORITIZED_TILE_SET_H_
-#define CC_RESOURCES_PRIORITIZED_TILE_SET_H_
-
-#include <vector>
-
-#include "cc/base/cc_export.h"
-#include "cc/resources/managed_tile_state.h"
-
-namespace cc {
-class Tile;
-
-class CC_EXPORT PrioritizedTileSet {
- public:
- PrioritizedTileSet();
- ~PrioritizedTileSet();
-
- void InsertTile(Tile* tile, ManagedTileBin bin);
- void Clear();
-
- class CC_EXPORT Iterator {
- public:
- Iterator(PrioritizedTileSet* set, bool use_priority_ordering);
-
- ~Iterator();
-
- void DisablePriorityOrdering();
-
- Iterator& operator++();
- Tile* operator->() { return *(*this); }
- Tile* operator*();
- operator bool() const {
- return iterator_ != tile_set_->tiles_[current_bin_].end();
- }
-
- private:
- void AdvanceList();
-
- PrioritizedTileSet* tile_set_;
- ManagedTileBin current_bin_;
- std::vector<Tile*>::iterator iterator_;
- bool use_priority_ordering_;
- };
-
- private:
- friend class Iterator;
-
- void SortBinIfNeeded(ManagedTileBin bin);
-
- std::vector<Tile*> tiles_[NUM_BINS];
- bool bin_sorted_[NUM_BINS];
-};
-
-} // namespace cc
-
-#endif // CC_RESOURCES_PRIORITIZED_TILE_SET_H_
diff --git a/chromium/cc/resources/prioritized_tile_set_unittest.cc b/chromium/cc/resources/prioritized_tile_set_unittest.cc
deleted file mode 100644
index f0a01d25900..00000000000
--- a/chromium/cc/resources/prioritized_tile_set_unittest.cc
+++ /dev/null
@@ -1,732 +0,0 @@
-// 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 <algorithm>
-#include <vector>
-
-#include "cc/resources/managed_tile_state.h"
-#include "cc/resources/prioritized_tile_set.h"
-#include "cc/resources/tile.h"
-#include "cc/test/fake_output_surface.h"
-#include "cc/test/fake_output_surface_client.h"
-#include "cc/test/fake_picture_pile_impl.h"
-#include "cc/test/fake_tile_manager.h"
-#include "cc/test/fake_tile_manager_client.h"
-#include "cc/test/test_shared_bitmap_manager.h"
-#include "cc/test/test_tile_priorities.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-
-class BinComparator {
- public:
- bool operator()(const scoped_refptr<Tile>& a,
- const scoped_refptr<Tile>& b) const {
- const ManagedTileState& ams = a->managed_state();
- const ManagedTileState& bms = b->managed_state();
-
- if (ams.priority_bin != bms.priority_bin)
- return ams.priority_bin < bms.priority_bin;
-
- if (ams.required_for_activation != bms.required_for_activation)
- return ams.required_for_activation;
-
- if (ams.resolution != bms.resolution)
- return ams.resolution < bms.resolution;
-
- if (ams.distance_to_visible != bms.distance_to_visible)
- return ams.distance_to_visible < bms.distance_to_visible;
-
- gfx::Rect a_rect = a->content_rect();
- gfx::Rect b_rect = b->content_rect();
- if (a_rect.y() != b_rect.y())
- return a_rect.y() < b_rect.y();
- return a_rect.x() < b_rect.x();
- }
-};
-
-namespace {
-
-class PrioritizedTileSetTest : public testing::Test {
- public:
- PrioritizedTileSetTest() {
- output_surface_ = FakeOutputSurface::Create3d().Pass();
- CHECK(output_surface_->BindToClient(&output_surface_client_));
-
- shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ =
- ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false)
- .Pass();
- resource_pool_ = ResourcePool::Create(
- resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
- tile_manager_.reset(
- new FakeTileManager(&tile_manager_client_, resource_pool_.get()));
- picture_pile_ = FakePicturePileImpl::CreateInfiniteFilledPile();
- }
-
- scoped_refptr<Tile> CreateTile() {
- return tile_manager_->CreateTile(picture_pile_.get(),
- settings_.default_tile_size,
- gfx::Rect(),
- gfx::Rect(),
- 1.0,
- 0,
- 0,
- 0);
- }
-
- private:
- LayerTreeSettings settings_;
- FakeOutputSurfaceClient output_surface_client_;
- scoped_ptr<FakeOutputSurface> output_surface_;
- scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
- scoped_ptr<ResourceProvider> resource_provider_;
- scoped_ptr<ResourcePool> resource_pool_;
- FakeTileManagerClient tile_manager_client_;
- scoped_ptr<FakeTileManager> tile_manager_;
- scoped_refptr<FakePicturePileImpl> picture_pile_;
-};
-
-TEST_F(PrioritizedTileSetTest, EmptyIterator) {
- // Creating an iterator to an empty set should work (but create iterator that
- // isn't valid).
-
- PrioritizedTileSet set;
-
- PrioritizedTileSet::Iterator it(&set, true);
- EXPECT_FALSE(it);
-}
-
-TEST_F(PrioritizedTileSetTest, NonEmptyIterator) {
- PrioritizedTileSet set;
- scoped_refptr<Tile> tile = CreateTile();
- set.InsertTile(tile, NOW_BIN);
-
- PrioritizedTileSet::Iterator it(&set, true);
- EXPECT_TRUE(it);
- EXPECT_TRUE(*it == tile.get());
- ++it;
- EXPECT_FALSE(it);
-}
-
-TEST_F(PrioritizedTileSetTest, NowAndReadyToDrawBin) {
- // Ensure that tiles in NOW_AND_READY_TO_DRAW_BIN aren't sorted.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, NOW_AND_READY_TO_DRAW_BIN);
- }
- }
-
- // Tiles should appear in the same order as inserted.
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, NowBin) {
- // Ensure that tiles in NOW_BIN are sorted according to BinComparator.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, NOW_BIN);
- }
- }
-
- // Tiles should appear in BinComparator order.
- std::sort(tiles.begin(), tiles.end(), BinComparator());
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, SoonBin) {
- // Ensure that tiles in SOON_BIN are sorted according to BinComparator.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, SOON_BIN);
- }
- }
-
- // Tiles should appear in BinComparator order.
- std::sort(tiles.begin(), tiles.end(), BinComparator());
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, SoonBinNoPriority) {
- // Ensure that when not using priority iterator, SOON_BIN tiles
- // are not sorted.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, SOON_BIN);
- }
- }
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, false);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, EventuallyAndActiveBin) {
- // Ensure that EVENTUALLY_AND_ACTIVE_BIN tiles are sorted.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, EVENTUALLY_AND_ACTIVE_BIN);
- }
- }
-
- // Tiles should appear in BinComparator order.
- std::sort(tiles.begin(), tiles.end(), BinComparator());
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, EventuallyBin) {
- // Ensure that EVENTUALLY_BIN tiles are sorted.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, EVENTUALLY_BIN);
- }
- }
-
- // Tiles should appear in BinComparator order.
- std::sort(tiles.begin(), tiles.end(), BinComparator());
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, AtLastAndActiveBin) {
- // Ensure that AT_LAST_AND_ACTIVE_BIN tiles are sorted.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, AT_LAST_AND_ACTIVE_BIN);
- }
- }
-
- // Tiles should appear in BinComparator order.
- std::sort(tiles.begin(), tiles.end(), BinComparator());
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, AtLastBin) {
- // Ensure that AT_LAST_BIN tiles are sorted.
-
- PrioritizedTileSet set;
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- std::vector<scoped_refptr<Tile> > tiles;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
- tiles.push_back(tile);
- set.InsertTile(tile, AT_LAST_BIN);
- }
- }
-
- // Tiles should appear in BinComparator order.
- std::sort(tiles.begin(), tiles.end(), BinComparator());
-
- int i = 0;
- for (PrioritizedTileSet::Iterator it(&set, true);
- it;
- ++it) {
- EXPECT_TRUE(*it == tiles[i].get());
- ++i;
- }
- EXPECT_EQ(20, i);
-}
-
-TEST_F(PrioritizedTileSetTest, TilesForEachBin) {
- // Aggregate test with one tile for each of the bins, which
- // should appear in order of the bins.
-
- scoped_refptr<Tile> now_and_ready_to_draw_bin = CreateTile();
- scoped_refptr<Tile> now_bin = CreateTile();
- scoped_refptr<Tile> soon_bin = CreateTile();
- scoped_refptr<Tile> eventually_and_active_bin = CreateTile();
- scoped_refptr<Tile> eventually_bin = CreateTile();
- scoped_refptr<Tile> at_last_bin = CreateTile();
- scoped_refptr<Tile> at_last_and_active_bin = CreateTile();
-
- PrioritizedTileSet set;
- set.InsertTile(soon_bin, SOON_BIN);
- set.InsertTile(at_last_and_active_bin, AT_LAST_AND_ACTIVE_BIN);
- set.InsertTile(eventually_bin, EVENTUALLY_BIN);
- set.InsertTile(now_bin, NOW_BIN);
- set.InsertTile(eventually_and_active_bin, EVENTUALLY_AND_ACTIVE_BIN);
- set.InsertTile(at_last_bin, AT_LAST_BIN);
- set.InsertTile(now_and_ready_to_draw_bin, NOW_AND_READY_TO_DRAW_BIN);
-
- // Tiles should appear in order.
- PrioritizedTileSet::Iterator it(&set, true);
- EXPECT_TRUE(*it == now_and_ready_to_draw_bin.get());
- ++it;
- EXPECT_TRUE(*it == now_bin.get());
- ++it;
- EXPECT_TRUE(*it == soon_bin.get());
- ++it;
- EXPECT_TRUE(*it == eventually_and_active_bin.get());
- ++it;
- EXPECT_TRUE(*it == eventually_bin.get());
- ++it;
- EXPECT_TRUE(*it == at_last_and_active_bin.get());
- ++it;
- EXPECT_TRUE(*it == at_last_bin.get());
- ++it;
- EXPECT_FALSE(it);
-}
-
-TEST_F(PrioritizedTileSetTest, ManyTilesForEachBin) {
- // Aggregate test with many tiles in each of the bins of various
- // priorities. Ensure that they are all returned in a sorted order.
-
- std::vector<scoped_refptr<Tile> > now_and_ready_to_draw_bins;
- std::vector<scoped_refptr<Tile> > now_bins;
- std::vector<scoped_refptr<Tile> > soon_bins;
- std::vector<scoped_refptr<Tile> > eventually_and_active_bins;
- std::vector<scoped_refptr<Tile> > eventually_bins;
- std::vector<scoped_refptr<Tile> > at_last_bins;
- std::vector<scoped_refptr<Tile> > at_last_and_active_bins;
-
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- PrioritizedTileSet set;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
-
- now_and_ready_to_draw_bins.push_back(tile);
- now_bins.push_back(tile);
- soon_bins.push_back(tile);
- eventually_and_active_bins.push_back(tile);
- eventually_bins.push_back(tile);
- at_last_bins.push_back(tile);
- at_last_and_active_bins.push_back(tile);
-
- set.InsertTile(tile, NOW_AND_READY_TO_DRAW_BIN);
- set.InsertTile(tile, NOW_BIN);
- set.InsertTile(tile, SOON_BIN);
- set.InsertTile(tile, EVENTUALLY_AND_ACTIVE_BIN);
- set.InsertTile(tile, EVENTUALLY_BIN);
- set.InsertTile(tile, AT_LAST_BIN);
- set.InsertTile(tile, AT_LAST_AND_ACTIVE_BIN);
- }
- }
-
- PrioritizedTileSet::Iterator it(&set, true);
- std::vector<scoped_refptr<Tile> >::iterator vector_it;
-
- // Now and ready are not sorted.
- for (vector_it = now_and_ready_to_draw_bins.begin();
- vector_it != now_and_ready_to_draw_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Now bins are sorted.
- std::sort(now_bins.begin(), now_bins.end(), BinComparator());
- for (vector_it = now_bins.begin(); vector_it != now_bins.end(); ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Soon bins are sorted.
- std::sort(soon_bins.begin(), soon_bins.end(), BinComparator());
- for (vector_it = soon_bins.begin(); vector_it != soon_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Eventually and active bins are sorted.
- std::sort(eventually_and_active_bins.begin(),
- eventually_and_active_bins.end(),
- BinComparator());
- for (vector_it = eventually_and_active_bins.begin();
- vector_it != eventually_and_active_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Eventually bins are sorted.
- std::sort(eventually_bins.begin(), eventually_bins.end(), BinComparator());
- for (vector_it = eventually_bins.begin(); vector_it != eventually_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // At last and active bins are sorted.
- std::sort(at_last_and_active_bins.begin(),
- at_last_and_active_bins.end(),
- BinComparator());
- for (vector_it = at_last_and_active_bins.begin();
- vector_it != at_last_and_active_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // At last bins are sorted.
- std::sort(at_last_bins.begin(), at_last_bins.end(), BinComparator());
- for (vector_it = at_last_bins.begin(); vector_it != at_last_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- EXPECT_FALSE(it);
-}
-
-TEST_F(PrioritizedTileSetTest, ManyTilesForEachBinDisablePriority) {
- // Aggregate test with many tiles for each of the bins. Tiles should
- // appear in order, until DisablePriorityOrdering is called. After that
- // tiles should appear in the order they were inserted.
-
- std::vector<scoped_refptr<Tile> > now_and_ready_to_draw_bins;
- std::vector<scoped_refptr<Tile> > now_bins;
- std::vector<scoped_refptr<Tile> > soon_bins;
- std::vector<scoped_refptr<Tile> > eventually_and_active_bins;
- std::vector<scoped_refptr<Tile> > eventually_bins;
- std::vector<scoped_refptr<Tile> > at_last_bins;
- std::vector<scoped_refptr<Tile> > at_last_and_active_bins;
-
- TilePriority priorities[4] = {
- TilePriorityForEventualBin(),
- TilePriorityForNowBin(),
- TilePriority(),
- TilePriorityForSoonBin()};
-
- PrioritizedTileSet set;
- for (int priority = 0; priority < 4; ++priority) {
- for (int i = 0; i < 5; ++i) {
- scoped_refptr<Tile> tile = CreateTile();
- tile->SetPriority(ACTIVE_TREE, priorities[priority]);
- tile->SetPriority(PENDING_TREE, priorities[priority]);
-
- now_and_ready_to_draw_bins.push_back(tile);
- now_bins.push_back(tile);
- soon_bins.push_back(tile);
- eventually_and_active_bins.push_back(tile);
- eventually_bins.push_back(tile);
- at_last_bins.push_back(tile);
- at_last_and_active_bins.push_back(tile);
-
- set.InsertTile(tile, NOW_AND_READY_TO_DRAW_BIN);
- set.InsertTile(tile, NOW_BIN);
- set.InsertTile(tile, SOON_BIN);
- set.InsertTile(tile, EVENTUALLY_AND_ACTIVE_BIN);
- set.InsertTile(tile, EVENTUALLY_BIN);
- set.InsertTile(tile, AT_LAST_BIN);
- set.InsertTile(tile, AT_LAST_AND_ACTIVE_BIN);
- }
- }
-
- PrioritizedTileSet::Iterator it(&set, true);
- std::vector<scoped_refptr<Tile> >::iterator vector_it;
-
- // Now and ready are not sorted.
- for (vector_it = now_and_ready_to_draw_bins.begin();
- vector_it != now_and_ready_to_draw_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Now bins are sorted.
- std::sort(now_bins.begin(), now_bins.end(), BinComparator());
- for (vector_it = now_bins.begin(); vector_it != now_bins.end(); ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Soon bins are sorted.
- std::sort(soon_bins.begin(), soon_bins.end(), BinComparator());
- for (vector_it = soon_bins.begin(); vector_it != soon_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // After we disable priority ordering, we already have sorted the next vector.
- it.DisablePriorityOrdering();
-
- // Eventually and active bins are sorted.
- std::sort(eventually_and_active_bins.begin(),
- eventually_and_active_bins.end(),
- BinComparator());
- for (vector_it = eventually_and_active_bins.begin();
- vector_it != eventually_and_active_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // Eventually bins are not sorted.
- for (vector_it = eventually_bins.begin(); vector_it != eventually_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // At last and active bins are not sorted.
- for (vector_it = at_last_and_active_bins.begin();
- vector_it != at_last_and_active_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- // At last bins are not sorted.
- for (vector_it = at_last_bins.begin(); vector_it != at_last_bins.end();
- ++vector_it) {
- EXPECT_TRUE(*vector_it == *it);
- ++it;
- }
-
- EXPECT_FALSE(it);
-}
-
-TEST_F(PrioritizedTileSetTest, TilesForFirstAndLastBins) {
- // Make sure that if we have empty lists between two non-empty lists,
- // we just get two tiles from the iterator.
-
- scoped_refptr<Tile> now_and_ready_to_draw_bin = CreateTile();
- scoped_refptr<Tile> at_last_bin = CreateTile();
-
- PrioritizedTileSet set;
- set.InsertTile(at_last_bin, AT_LAST_BIN);
- set.InsertTile(now_and_ready_to_draw_bin, NOW_AND_READY_TO_DRAW_BIN);
-
- // Only two tiles should appear and they should appear in order.
- PrioritizedTileSet::Iterator it(&set, true);
- EXPECT_TRUE(*it == now_and_ready_to_draw_bin.get());
- ++it;
- EXPECT_TRUE(*it == at_last_bin.get());
- ++it;
- EXPECT_FALSE(it);
-}
-
-TEST_F(PrioritizedTileSetTest, MultipleIterators) {
- // Ensure that multiple iterators don't interfere with each other.
-
- scoped_refptr<Tile> now_and_ready_to_draw_bin = CreateTile();
- scoped_refptr<Tile> now_bin = CreateTile();
- scoped_refptr<Tile> soon_bin = CreateTile();
- scoped_refptr<Tile> eventually_bin = CreateTile();
- scoped_refptr<Tile> at_last_bin = CreateTile();
-
- PrioritizedTileSet set;
- set.InsertTile(soon_bin, SOON_BIN);
- set.InsertTile(eventually_bin, EVENTUALLY_BIN);
- set.InsertTile(now_bin, NOW_BIN);
- set.InsertTile(at_last_bin, AT_LAST_BIN);
- set.InsertTile(now_and_ready_to_draw_bin, NOW_AND_READY_TO_DRAW_BIN);
-
- // Tiles should appear in order.
- PrioritizedTileSet::Iterator it(&set, true);
- EXPECT_TRUE(*it == now_and_ready_to_draw_bin.get());
- ++it;
- EXPECT_TRUE(*it == now_bin.get());
- ++it;
- EXPECT_TRUE(*it == soon_bin.get());
- ++it;
- EXPECT_TRUE(*it == eventually_bin.get());
- ++it;
- EXPECT_TRUE(*it == at_last_bin.get());
- ++it;
- EXPECT_FALSE(it);
-
- // Creating multiple iterators shouldn't affect old iterators.
- PrioritizedTileSet::Iterator second_it(&set, true);
- EXPECT_TRUE(second_it);
- EXPECT_FALSE(it);
-
- ++second_it;
- EXPECT_TRUE(second_it);
- ++second_it;
- EXPECT_TRUE(second_it);
- EXPECT_FALSE(it);
-
- PrioritizedTileSet::Iterator third_it(&set, true);
- EXPECT_TRUE(third_it);
- ++second_it;
- ++second_it;
- EXPECT_TRUE(second_it);
- EXPECT_TRUE(third_it);
- EXPECT_FALSE(it);
-
- ++third_it;
- ++third_it;
- EXPECT_TRUE(third_it);
- EXPECT_TRUE(*third_it == soon_bin.get());
- EXPECT_TRUE(second_it);
- EXPECT_TRUE(*second_it == at_last_bin.get());
- EXPECT_FALSE(it);
-
- ++second_it;
- EXPECT_TRUE(third_it);
- EXPECT_FALSE(second_it);
- EXPECT_FALSE(it);
-
- set.Clear();
-
- PrioritizedTileSet::Iterator empty_it(&set, true);
- EXPECT_FALSE(empty_it);
-}
-
-} // namespace
-} // namespace cc
-
diff --git a/chromium/cc/resources/priority_calculator.cc b/chromium/cc/resources/priority_calculator.cc
index 2a0cd189da1..5f5916fda9c 100644
--- a/chromium/cc/resources/priority_calculator.cc
+++ b/chromium/cc/resources/priority_calculator.cc
@@ -6,7 +6,7 @@
#include <algorithm>
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
namespace cc {
diff --git a/chromium/cc/resources/raster_buffer.cc b/chromium/cc/resources/raster_buffer.cc
new file mode 100644
index 00000000000..8f5671720e3
--- /dev/null
+++ b/chromium/cc/resources/raster_buffer.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 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_buffer.h"
+
+namespace cc {
+
+RasterBuffer::RasterBuffer() {
+}
+
+RasterBuffer::~RasterBuffer() {
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/raster_buffer.h b/chromium/cc/resources/raster_buffer.h
new file mode 100644
index 00000000000..2a72203da4b
--- /dev/null
+++ b/chromium/cc/resources/raster_buffer.h
@@ -0,0 +1,26 @@
+// Copyright 2014 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_RASTER_BUFFER_H_
+#define CC_RESOURCES_RASTER_BUFFER_H_
+
+#include "cc/base/cc_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace cc {
+class RasterSource;
+
+class CC_EXPORT RasterBuffer {
+ public:
+ RasterBuffer();
+ virtual ~RasterBuffer();
+
+ virtual void Playback(const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) = 0;
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_RASTER_BUFFER_H_
diff --git a/chromium/cc/resources/raster_mode.cc b/chromium/cc/resources/raster_mode.cc
deleted file mode 100644
index 5da8ee76e9b..00000000000
--- a/chromium/cc/resources/raster_mode.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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_mode.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-
-namespace cc {
-
-scoped_ptr<base::Value> RasterModeAsValue(RasterMode raster_mode) {
- switch (raster_mode) {
- case HIGH_QUALITY_RASTER_MODE:
- return scoped_ptr<base::Value>(
- new base::StringValue("HIGH_QUALITY_RASTER_MODE"));
- case LOW_QUALITY_RASTER_MODE:
- return scoped_ptr<base::Value>(
- new base::StringValue("LOW_QUALITY_RASTER_MODE"));
- default:
- NOTREACHED() << "Unrecognized RasterMode value " << raster_mode;
- return scoped_ptr<base::Value>(
- new base::StringValue("<unknown RasterMode value>"));
- }
-}
-
-} // namespace cc
diff --git a/chromium/cc/resources/raster_mode.h b/chromium/cc/resources/raster_mode.h
deleted file mode 100644
index 0a2b4c9b076..00000000000
--- a/chromium/cc/resources/raster_mode.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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_RASTER_MODE_H_
-#define CC_RESOURCES_RASTER_MODE_H_
-
-#include "base/memory/scoped_ptr.h"
-
-namespace base {
-class Value;
-}
-
-namespace cc {
-
-// Note that the order of these matters, from "better" to "worse" in terms of
-// quality.
-enum RasterMode {
- HIGH_QUALITY_RASTER_MODE = 0,
- LOW_QUALITY_RASTER_MODE = 1,
- NUM_RASTER_MODES = 2
-};
-
-scoped_ptr<base::Value> RasterModeAsValue(RasterMode mode);
-
-} // namespace cc
-
-#endif // CC_RESOURCES_RASTER_MODE_H_
diff --git a/chromium/cc/resources/raster_source.h b/chromium/cc/resources/raster_source.h
new file mode 100644
index 00000000000..3e2540830bf
--- /dev/null
+++ b/chromium/cc/resources/raster_source.h
@@ -0,0 +1,71 @@
+// Copyright 2014 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_RASTER_SOURCE_H_
+#define CC_RESOURCES_RASTER_SOURCE_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+class SkCanvas;
+
+namespace cc {
+
+class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
+ public:
+ struct CC_EXPORT SolidColorAnalysis {
+ SolidColorAnalysis()
+ : is_solid_color(false), solid_color(SK_ColorTRANSPARENT) {}
+ ~SolidColorAnalysis() {}
+
+ bool is_solid_color;
+ SkColor solid_color;
+ };
+
+ // Raster a subrect of this RasterSource into the given canvas. It is
+ // assumed that contents_scale has already been applied to this canvas.
+ // Writes the total number of pixels rasterized and the time spent
+ // rasterizing to the stats if the respective pointer is not nullptr.
+ virtual void PlaybackToCanvas(SkCanvas* canvas,
+ const gfx::Rect& canvas_rect,
+ float contents_scale) const = 0;
+
+ // Analyze to determine if the given rect at given scale is of solid color in
+ // this raster source.
+ virtual void PerformSolidColorAnalysis(
+ const gfx::Rect& content_rect,
+ float contents_scale,
+ SolidColorAnalysis* analysis) const = 0;
+
+ // Populate the given list with all SkPixelRefs that may overlap the given
+ // rect at given scale.
+ virtual void GatherPixelRefs(const gfx::Rect& content_rect,
+ float contents_scale,
+ std::vector<SkPixelRef*>* pixel_refs) const = 0;
+
+ // Return true iff this raster source can raster the given rect at given
+ // scale.
+ virtual bool CoversRect(const gfx::Rect& content_rect,
+ float contents_scale) const = 0;
+
+ // Return true iff this raster source would benefit from using distance
+ // field text.
+ virtual bool SuitableForDistanceFieldText() const = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<RasterSource>;
+
+ RasterSource() {}
+ virtual ~RasterSource() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RasterSource);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_RASTER_SOURCE_H_
diff --git a/chromium/cc/resources/raster_tile_priority_queue.cc b/chromium/cc/resources/raster_tile_priority_queue.cc
new file mode 100644
index 00000000000..667d54d89c1
--- /dev/null
+++ b/chromium/cc/resources/raster_tile_priority_queue.cc
@@ -0,0 +1,310 @@
+// Copyright 2014 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_tile_priority_queue.h"
+
+namespace cc {
+
+namespace {
+
+class RasterOrderComparator {
+ public:
+ explicit RasterOrderComparator(TreePriority tree_priority)
+ : tree_priority_(tree_priority) {}
+
+ bool operator()(
+ const RasterTilePriorityQueue::PairedPictureLayerQueue* a,
+ const RasterTilePriorityQueue::PairedPictureLayerQueue* b) const {
+ // Note that in this function, we have to return true if and only if
+ // a is strictly lower priority than b. Note that for the sake of
+ // completeness, empty queue is considered to have lowest priority.
+ if (a->IsEmpty() || b->IsEmpty())
+ return b->IsEmpty() < a->IsEmpty();
+
+ WhichTree a_tree = a->NextTileIteratorTree(tree_priority_);
+ const PictureLayerImpl::LayerRasterTileIterator* a_iterator =
+ a_tree == ACTIVE_TREE ? &a->active_iterator : &a->pending_iterator;
+
+ WhichTree b_tree = b->NextTileIteratorTree(tree_priority_);
+ const PictureLayerImpl::LayerRasterTileIterator* b_iterator =
+ b_tree == ACTIVE_TREE ? &b->active_iterator : &b->pending_iterator;
+
+ const Tile* a_tile = **a_iterator;
+ const Tile* b_tile = **b_iterator;
+
+ const TilePriority& a_priority =
+ a_tile->priority_for_tree_priority(tree_priority_);
+ const TilePriority& b_priority =
+ b_tile->priority_for_tree_priority(tree_priority_);
+ bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
+
+ // In smoothness mode, we should return pending NOW tiles before active
+ // EVENTUALLY tiles. So if both priorities here are eventually, we need to
+ // check the pending priority.
+ if (prioritize_low_res &&
+ a_priority.priority_bin == TilePriority::EVENTUALLY &&
+ b_priority.priority_bin == TilePriority::EVENTUALLY) {
+ bool a_is_pending_now =
+ a_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW;
+ bool b_is_pending_now =
+ b_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW;
+ if (a_is_pending_now || b_is_pending_now)
+ return a_is_pending_now < b_is_pending_now;
+
+ // In case neither one is pending now, fall through.
+ }
+
+ // If the bin is the same but the resolution is not, then the order will be
+ // determined by whether we prioritize low res or not.
+ // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile
+ // class but instead produced by the iterators.
+ if (b_priority.priority_bin == a_priority.priority_bin &&
+ b_priority.resolution != a_priority.resolution) {
+ // Non ideal resolution should be sorted lower than other resolutions.
+ if (a_priority.resolution == NON_IDEAL_RESOLUTION)
+ return true;
+
+ if (b_priority.resolution == NON_IDEAL_RESOLUTION)
+ return false;
+
+ if (prioritize_low_res)
+ return b_priority.resolution == LOW_RESOLUTION;
+ return b_priority.resolution == HIGH_RESOLUTION;
+ }
+
+ return b_priority.IsHigherPriorityThan(a_priority);
+ }
+
+ private:
+ TreePriority tree_priority_;
+};
+
+WhichTree HigherPriorityTree(
+ TreePriority tree_priority,
+ const PictureLayerImpl::LayerRasterTileIterator* active_iterator,
+ const PictureLayerImpl::LayerRasterTileIterator* pending_iterator,
+ const Tile* shared_tile) {
+ switch (tree_priority) {
+ case SMOOTHNESS_TAKES_PRIORITY: {
+ const Tile* active_tile = shared_tile ? shared_tile : **active_iterator;
+ const Tile* pending_tile = shared_tile ? shared_tile : **pending_iterator;
+
+ const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE);
+ const TilePriority& pending_priority =
+ pending_tile->priority(PENDING_TREE);
+
+ // If we're down to eventually bin tiles on the active tree, process the
+ // pending tree to allow tiles required for activation to be initialized
+ // when memory policy only allows prepaint.
+ if (active_priority.priority_bin == TilePriority::EVENTUALLY &&
+ pending_priority.priority_bin == TilePriority::NOW) {
+ return PENDING_TREE;
+ }
+ return ACTIVE_TREE;
+ }
+ case NEW_CONTENT_TAKES_PRIORITY:
+ return PENDING_TREE;
+ case SAME_PRIORITY_FOR_BOTH_TREES: {
+ const Tile* active_tile = shared_tile ? shared_tile : **active_iterator;
+ const Tile* pending_tile = shared_tile ? shared_tile : **pending_iterator;
+
+ const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE);
+ const TilePriority& pending_priority =
+ pending_tile->priority(PENDING_TREE);
+
+ if (active_priority.IsHigherPriorityThan(pending_priority))
+ return ACTIVE_TREE;
+ return PENDING_TREE;
+ }
+ default:
+ NOTREACHED();
+ return ACTIVE_TREE;
+ }
+}
+
+} // namespace
+
+RasterTilePriorityQueue::RasterTilePriorityQueue() {
+}
+
+RasterTilePriorityQueue::~RasterTilePriorityQueue() {
+}
+
+void RasterTilePriorityQueue::Build(
+ const std::vector<PictureLayerImpl::Pair>& paired_layers,
+ TreePriority tree_priority) {
+ tree_priority_ = tree_priority;
+ for (std::vector<PictureLayerImpl::Pair>::const_iterator it =
+ paired_layers.begin();
+ it != paired_layers.end();
+ ++it) {
+ paired_queues_.push_back(
+ make_scoped_ptr(new PairedPictureLayerQueue(*it, tree_priority_)));
+ }
+ paired_queues_.make_heap(RasterOrderComparator(tree_priority_));
+}
+
+void RasterTilePriorityQueue::Reset() {
+ paired_queues_.clear();
+}
+
+bool RasterTilePriorityQueue::IsEmpty() const {
+ return paired_queues_.empty() || paired_queues_.front()->IsEmpty();
+}
+
+Tile* RasterTilePriorityQueue::Top() {
+ DCHECK(!IsEmpty());
+ return paired_queues_.front()->Top(tree_priority_);
+}
+
+void RasterTilePriorityQueue::Pop() {
+ DCHECK(!IsEmpty());
+
+ paired_queues_.pop_heap(RasterOrderComparator(tree_priority_));
+ PairedPictureLayerQueue* paired_queue = paired_queues_.back();
+ paired_queue->Pop(tree_priority_);
+ paired_queues_.push_heap(RasterOrderComparator(tree_priority_));
+}
+
+RasterTilePriorityQueue::PairedPictureLayerQueue::PairedPictureLayerQueue() {
+}
+
+RasterTilePriorityQueue::PairedPictureLayerQueue::PairedPictureLayerQueue(
+ const PictureLayerImpl::Pair& layer_pair,
+ TreePriority tree_priority)
+ : active_iterator(layer_pair.active
+ ? PictureLayerImpl::LayerRasterTileIterator(
+ layer_pair.active,
+ tree_priority == SMOOTHNESS_TAKES_PRIORITY)
+ : PictureLayerImpl::LayerRasterTileIterator()),
+ pending_iterator(layer_pair.pending
+ ? PictureLayerImpl::LayerRasterTileIterator(
+ layer_pair.pending,
+ tree_priority == SMOOTHNESS_TAKES_PRIORITY)
+ : PictureLayerImpl::LayerRasterTileIterator()),
+ has_both_layers(layer_pair.active && layer_pair.pending) {
+ if (has_both_layers)
+ SkipTilesReturnedByTwin(tree_priority);
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+ "PairedPictureLayerQueue::PairedPictureLayerQueue",
+ TRACE_EVENT_SCOPE_THREAD,
+ "state",
+ StateAsValue());
+}
+
+RasterTilePriorityQueue::PairedPictureLayerQueue::~PairedPictureLayerQueue() {
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+ "PairedPictureLayerQueue::~PairedPictureLayerQueue",
+ TRACE_EVENT_SCOPE_THREAD,
+ "state",
+ StateAsValue());
+}
+
+bool RasterTilePriorityQueue::PairedPictureLayerQueue::IsEmpty() const {
+ return !active_iterator && !pending_iterator;
+}
+
+Tile* RasterTilePriorityQueue::PairedPictureLayerQueue::Top(
+ TreePriority tree_priority) {
+ DCHECK(!IsEmpty());
+
+ WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ PictureLayerImpl::LayerRasterTileIterator* next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+ DCHECK(*next_iterator);
+ Tile* tile = **next_iterator;
+ DCHECK(returned_tiles_for_debug.find(tile) == returned_tiles_for_debug.end());
+ return tile;
+}
+
+void RasterTilePriorityQueue::PairedPictureLayerQueue::Pop(
+ TreePriority tree_priority) {
+ DCHECK(!IsEmpty());
+
+ WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ PictureLayerImpl::LayerRasterTileIterator* next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+ DCHECK(*next_iterator);
+ DCHECK(returned_tiles_for_debug.insert(**next_iterator).second);
+ ++(*next_iterator);
+
+ if (has_both_layers)
+ SkipTilesReturnedByTwin(tree_priority);
+
+ // If no empty, use Top to do DCHECK the next iterator.
+ DCHECK(IsEmpty() || Top(tree_priority));
+}
+
+void RasterTilePriorityQueue::PairedPictureLayerQueue::SkipTilesReturnedByTwin(
+ TreePriority tree_priority) {
+ // We have both layers (active and pending) thus we can encounter shared
+ // tiles twice (from the active iterator and from the pending iterator).
+ while (!IsEmpty()) {
+ WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ PictureLayerImpl::LayerRasterTileIterator* next_iterator =
+ next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+
+ // Accept all non-shared tiles.
+ const Tile* tile = **next_iterator;
+ if (!tile->is_shared())
+ break;
+
+ // Accept a shared tile if the next tree is the higher priority one
+ // corresponding the iterator (active or pending) which usually (but due
+ // to spiral iterators not always) returns the shared tile first.
+ if (next_tree == HigherPriorityTree(tree_priority, nullptr, nullptr, tile))
+ break;
+
+ ++(*next_iterator);
+ }
+}
+
+WhichTree
+RasterTilePriorityQueue::PairedPictureLayerQueue::NextTileIteratorTree(
+ TreePriority tree_priority) const {
+ DCHECK(!IsEmpty());
+
+ // If we only have one iterator with tiles, return it.
+ if (!active_iterator)
+ return PENDING_TREE;
+ if (!pending_iterator)
+ return ACTIVE_TREE;
+
+ // Now both iterators have tiles, so we have to decide based on tree priority.
+ return HigherPriorityTree(
+ tree_priority, &active_iterator, &pending_iterator, nullptr);
+}
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+RasterTilePriorityQueue::PairedPictureLayerQueue::StateAsValue() const {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
+ state->BeginDictionary("active_iterator");
+ TilePriority::PriorityBin active_priority_bin =
+ active_iterator ? (*active_iterator)->priority(ACTIVE_TREE).priority_bin
+ : TilePriority::EVENTUALLY;
+ TilePriority::PriorityBin pending_priority_bin =
+ active_iterator ? (*active_iterator)->priority(PENDING_TREE).priority_bin
+ : TilePriority::EVENTUALLY;
+ state->SetBoolean("has_tile", !!active_iterator);
+ state->SetInteger("active_priority_bin", active_priority_bin);
+ state->SetInteger("pending_priority_bin", pending_priority_bin);
+ state->EndDictionary();
+
+ state->BeginDictionary("pending_iterator");
+ active_priority_bin =
+ pending_iterator ? (*pending_iterator)->priority(ACTIVE_TREE).priority_bin
+ : TilePriority::EVENTUALLY;
+ pending_priority_bin =
+ pending_iterator
+ ? (*pending_iterator)->priority(PENDING_TREE).priority_bin
+ : TilePriority::EVENTUALLY;
+ state->SetBoolean("has_tile", !!pending_iterator);
+ state->SetInteger("active_priority_bin", active_priority_bin);
+ state->SetInteger("pending_priority_bin", pending_priority_bin);
+ state->EndDictionary();
+ return state;
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/raster_tile_priority_queue.h b/chromium/cc/resources/raster_tile_priority_queue.h
new file mode 100644
index 00000000000..3f04e97ae9d
--- /dev/null
+++ b/chromium/cc/resources/raster_tile_priority_queue.h
@@ -0,0 +1,66 @@
+// Copyright 2014 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_RASTER_TILE_PRIORITY_QUEUE_H_
+#define CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_H_
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "cc/base/cc_export.h"
+#include "cc/layers/picture_layer_impl.h"
+#include "cc/resources/tile_priority.h"
+
+namespace cc {
+
+class CC_EXPORT RasterTilePriorityQueue {
+ public:
+ struct PairedPictureLayerQueue {
+ PairedPictureLayerQueue();
+ PairedPictureLayerQueue(const PictureLayerImpl::Pair& layer_pair,
+ TreePriority tree_priority);
+ ~PairedPictureLayerQueue();
+
+ bool IsEmpty() const;
+ Tile* Top(TreePriority tree_priority);
+ void Pop(TreePriority tree_priority);
+
+ WhichTree NextTileIteratorTree(TreePriority tree_priority) const;
+ void SkipTilesReturnedByTwin(TreePriority tree_priority);
+
+ scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+
+ PictureLayerImpl::LayerRasterTileIterator active_iterator;
+ PictureLayerImpl::LayerRasterTileIterator pending_iterator;
+ bool has_both_layers;
+
+ // Set of returned tiles (excluding the current one) for DCHECKing.
+ std::set<const Tile*> returned_tiles_for_debug;
+ };
+
+ RasterTilePriorityQueue();
+ ~RasterTilePriorityQueue();
+
+ void Build(const std::vector<PictureLayerImpl::Pair>& paired_layers,
+ TreePriority tree_priority);
+ void Reset();
+
+ bool IsEmpty() const;
+ Tile* Top();
+ void Pop();
+
+ private:
+ // TODO(vmpstr): This is potentially unnecessary if it becomes the case that
+ // PairedPictureLayerQueue is fast enough to copy. In that case, we can use
+ // objects directly (ie std::vector<PairedPictureLayerQueue>.
+ ScopedPtrVector<PairedPictureLayerQueue> paired_queues_;
+ TreePriority tree_priority_;
+
+ DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueue);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_H_
diff --git a/chromium/cc/resources/raster_worker_pool.cc b/chromium/cc/resources/raster_worker_pool.cc
index d01bdc80cf4..ca26edd6a41 100644
--- a/chromium/cc/resources/raster_worker_pool.cc
+++ b/chromium/cc/resources/raster_worker_pool.cc
@@ -6,28 +6,19 @@
#include <algorithm>
-#include "base/atomic_sequence_num.h"
-#include "base/debug/trace_event_synthetic_delay.h"
+#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/strings/stringprintf.h"
#include "base/threading/simple_thread.h"
-#include "base/threading/thread_local.h"
#include "cc/base/scoped_ptr_deque.h"
+#include "cc/resources/raster_source.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
namespace cc {
namespace {
-// Synthetic delay for raster tasks that are required for activation. Global to
-// avoid static initializer on critical path.
-struct RasterRequiredForActivationSyntheticDelayInitializer {
- RasterRequiredForActivationSyntheticDelayInitializer()
- : delay(base::debug::TraceEventSyntheticDelay::Lookup(
- "cc.RasterRequiredForActivation")) {}
- base::debug::TraceEventSyntheticDelay* delay;
-};
-static base::LazyInstance<RasterRequiredForActivationSyntheticDelayInitializer>
- g_raster_required_for_activation_delay = LAZY_INSTANCE_INITIALIZER;
-
class RasterTaskGraphRunner : public TaskGraphRunner,
public base::DelegateSimpleThread::Delegate {
public:
@@ -48,36 +39,13 @@ class RasterTaskGraphRunner : public TaskGraphRunner,
}
}
- virtual ~RasterTaskGraphRunner() { NOTREACHED(); }
-
- size_t GetPictureCloneIndexForCurrentThread() {
- // Use index 0 if called on non-raster thread.
- ThreadLocalState* thread_local_state = current_tls_.Get();
- return thread_local_state ? current_tls_.Get()->picture_clone_index : 0;
- }
+ ~RasterTaskGraphRunner() override { NOTREACHED(); }
private:
- struct ThreadLocalState {
- explicit ThreadLocalState(size_t picture_clone_index)
- : picture_clone_index(picture_clone_index) {}
-
- size_t picture_clone_index;
- };
-
// Overridden from base::DelegateSimpleThread::Delegate:
- virtual void Run() OVERRIDE {
- // Use picture clone index 0..num_threads.
- int picture_clone_index = picture_clone_index_sequence_.GetNext();
- DCHECK_LE(0, picture_clone_index);
- DCHECK_GT(RasterWorkerPool::GetNumRasterThreads(), picture_clone_index);
- current_tls_.Set(new ThreadLocalState(picture_clone_index));
-
- TaskGraphRunner::Run();
- }
+ void Run() override { TaskGraphRunner::Run(); }
ScopedPtrDeque<base::DelegateSimpleThread> workers_;
- base::AtomicSequenceNumber picture_clone_index_sequence_;
- base::ThreadLocalPointer<ThreadLocalState> current_tls_;
};
base::LazyInstance<RasterTaskGraphRunner>::Leaky g_task_graph_runner =
@@ -96,18 +64,18 @@ class RasterFinishedTaskImpl : public RasterizerTask {
on_raster_finished_callback_(on_raster_finished_callback) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {
+ void RunOnWorkerThread() override {
TRACE_EVENT0("cc", "RasterFinishedTaskImpl::RunOnWorkerThread");
RasterFinished();
}
// Overridden from RasterizerTask:
- virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
- virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
- virtual void RunReplyOnOriginThread() OVERRIDE {}
+ void ScheduleOnOriginThread(RasterizerTaskClient* client) override {}
+ void CompleteOnOriginThread(RasterizerTaskClient* client) override {}
+ void RunReplyOnOriginThread() override {}
protected:
- virtual ~RasterFinishedTaskImpl() {}
+ ~RasterFinishedTaskImpl() override {}
void RasterFinished() {
task_runner_->PostTask(FROM_HERE, on_raster_finished_callback_);
@@ -120,57 +88,15 @@ class RasterFinishedTaskImpl : public RasterizerTask {
DISALLOW_COPY_AND_ASSIGN(RasterFinishedTaskImpl);
};
-class RasterRequiredForActivationFinishedTaskImpl
- : public RasterFinishedTaskImpl {
- public:
- RasterRequiredForActivationFinishedTaskImpl(
- base::SequencedTaskRunner* task_runner,
- const base::Closure& on_raster_finished_callback,
- size_t tasks_required_for_activation_count)
- : RasterFinishedTaskImpl(task_runner, on_raster_finished_callback),
- tasks_required_for_activation_count_(
- tasks_required_for_activation_count) {
- if (tasks_required_for_activation_count_) {
- g_raster_required_for_activation_delay.Get().delay->BeginParallel(
- &activation_delay_end_time_);
- }
- }
-
- // Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {
- TRACE_EVENT0(
- "cc", "RasterRequiredForActivationFinishedTaskImpl::RunOnWorkerThread");
-
- if (tasks_required_for_activation_count_) {
- g_raster_required_for_activation_delay.Get().delay->EndParallel(
- activation_delay_end_time_);
- }
- RasterFinished();
- }
-
- private:
- virtual ~RasterRequiredForActivationFinishedTaskImpl() {}
-
- base::TimeTicks activation_delay_end_time_;
- const size_t tasks_required_for_activation_count_;
-
- DISALLOW_COPY_AND_ASSIGN(RasterRequiredForActivationFinishedTaskImpl);
-};
-
} // namespace
-// This allows an external rasterize on-demand system to run raster tasks
-// with highest priority using the same task graph runner instance.
-unsigned RasterWorkerPool::kOnDemandRasterTaskPriority = 0u;
// This allows a micro benchmark system to run tasks with highest priority,
// since it should finish as quickly as possible.
unsigned RasterWorkerPool::kBenchmarkRasterTaskPriority = 0u;
// Task priorities that make sure raster finished tasks run before any
// remaining raster tasks.
-unsigned RasterWorkerPool::kRasterFinishedTaskPriority = 2u;
-unsigned RasterWorkerPool::kRasterRequiredForActivationFinishedTaskPriority =
- 1u;
-unsigned RasterWorkerPool::kRasterTaskPriorityBase = 3u;
+unsigned RasterWorkerPool::kRasterFinishedTaskPriority = 1u;
+unsigned RasterWorkerPool::kRasterTaskPriorityBase = 2u;
RasterWorkerPool::RasterWorkerPool() {}
@@ -198,11 +124,6 @@ TaskGraphRunner* RasterWorkerPool::GetTaskGraphRunner() {
}
// static
-size_t RasterWorkerPool::GetPictureCloneIndexForCurrentThread() {
- return g_task_graph_runner.Pointer()->GetPictureCloneIndexForCurrentThread();
-}
-
-// static
scoped_refptr<RasterizerTask> RasterWorkerPool::CreateRasterFinishedTask(
base::SequencedTaskRunner* task_runner,
const base::Closure& on_raster_finished_callback) {
@@ -211,18 +132,6 @@ scoped_refptr<RasterizerTask> RasterWorkerPool::CreateRasterFinishedTask(
}
// static
-scoped_refptr<RasterizerTask>
-RasterWorkerPool::CreateRasterRequiredForActivationFinishedTask(
- size_t tasks_required_for_activation_count,
- base::SequencedTaskRunner* task_runner,
- const base::Closure& on_raster_finished_callback) {
- return make_scoped_refptr(new RasterRequiredForActivationFinishedTaskImpl(
- task_runner,
- on_raster_finished_callback,
- tasks_required_for_activation_count));
-}
-
-// static
void RasterWorkerPool::ScheduleTasksOnOriginThread(RasterizerTaskClient* client,
TaskGraph* graph) {
TRACE_EVENT0("cc", "Rasterizer::ScheduleTasksOnOriginThread");
@@ -287,4 +196,72 @@ void RasterWorkerPool::InsertNodesForRasterTask(
InsertNodeForTask(graph, raster_task, priority, dependencies);
}
+static bool IsSupportedPlaybackToMemoryFormat(ResourceFormat format) {
+ switch (format) {
+ case RGBA_4444:
+ case RGBA_8888:
+ case BGRA_8888:
+ return true;
+ case ALPHA_8:
+ case LUMINANCE_8:
+ case RGB_565:
+ case ETC1:
+ return false;
+ }
+ NOTREACHED();
+ return false;
+}
+
+// static
+void RasterWorkerPool::PlaybackToMemory(void* memory,
+ ResourceFormat format,
+ const gfx::Size& size,
+ int stride,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) {
+ DCHECK(IsSupportedPlaybackToMemoryFormat(format)) << format;
+
+ // Uses kPremul_SkAlphaType since the result is not known to be opaque.
+ SkImageInfo info =
+ SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType);
+ SkColorType buffer_color_type = ResourceFormatToSkColorType(format);
+ bool needs_copy = buffer_color_type != info.colorType();
+
+ // TODO(danakj): Make a SkSurfaceProps with an SkPixelGeometry to enable or
+ // disable LCD text.
+ // TODO(danakj): Disable LCD text on Mac during layout tests:
+ // https://cs.chromium.org#chromium/src/third_party/WebKit/Source/platform/fonts/mac/FontPlatformDataMac.mm&l=55
+ // TODO(danakj): On Windows when LCD text is disabled, ask skia to draw LCD
+ // text offscreen and downsample it to AA text.
+ // https://cs.chromium.org#chromium/src/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp&l=86
+ SkSurfaceProps* surface_props = nullptr;
+
+ if (!stride)
+ stride = info.minRowBytes();
+
+ if (!needs_copy) {
+ skia::RefPtr<SkSurface> surface = skia::AdoptRef(
+ SkSurface::NewRasterDirect(info, memory, stride, surface_props));
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
+ raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
+ return;
+ }
+
+ skia::RefPtr<SkSurface> surface =
+ skia::AdoptRef(SkSurface::NewRaster(info, surface_props));
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
+ raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
+
+ SkImageInfo dst_info = info;
+ dst_info.fColorType = buffer_color_type;
+ // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
+ // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
+ // is fixed.
+ const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
+ DCHECK_EQ(0u, dst_row_bytes % 4);
+ bool success = canvas->readPixels(dst_info, memory, dst_row_bytes, 0, 0);
+ DCHECK_EQ(true, success);
+}
+
} // namespace cc
diff --git a/chromium/cc/resources/raster_worker_pool.h b/chromium/cc/resources/raster_worker_pool.h
index 2c543a0d0c4..5259f835492 100644
--- a/chromium/cc/resources/raster_worker_pool.h
+++ b/chromium/cc/resources/raster_worker_pool.h
@@ -6,19 +6,21 @@
#define CC_RESOURCES_RASTER_WORKER_POOL_H_
#include "cc/resources/rasterizer.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
namespace base {
class SequencedTaskRunner;
}
namespace cc {
+class RasterSource;
+class RenderingStatsInstrumentation;
class CC_EXPORT RasterWorkerPool {
public:
- static unsigned kOnDemandRasterTaskPriority;
static unsigned kBenchmarkRasterTaskPriority;
static unsigned kRasterFinishedTaskPriority;
- static unsigned kRasterRequiredForActivationFinishedTaskPriority;
static unsigned kRasterTaskPriorityBase;
RasterWorkerPool();
@@ -35,24 +37,12 @@ class CC_EXPORT RasterWorkerPool {
// Returns a pointer to the global TaskGraphRunner instance.
static TaskGraphRunner* GetTaskGraphRunner();
- // Returns a unique clone index for the current thread. Guaranteed to be a
- // value between 0 and GetNumRasterThreads() - 1.
- static size_t GetPictureCloneIndexForCurrentThread();
-
// Utility function that can be used to create a "raster finished" task that
// posts |callback| to |task_runner| when run.
static scoped_refptr<RasterizerTask> CreateRasterFinishedTask(
base::SequencedTaskRunner* task_runner,
const base::Closure& callback);
- // Utility function that can be used to create a "raster required for
- // activation finished" task that posts |callback| to |task_runner| when run.
- static scoped_refptr<RasterizerTask>
- CreateRasterRequiredForActivationFinishedTask(
- size_t tasks_required_for_activation_count,
- base::SequencedTaskRunner* task_runner,
- const base::Closure& callback);
-
// Utility function that can be used to call ::ScheduleOnOriginThread() for
// each task in |graph|.
static void ScheduleTasksOnOriginThread(RasterizerTaskClient* client,
@@ -74,6 +64,16 @@ class CC_EXPORT RasterWorkerPool {
const ImageDecodeTask::Vector& decode_tasks,
unsigned priority);
+ // Utility function that will create a temporary bitmap and copy pixels to
+ // |memory| when necessary.
+ static void PlaybackToMemory(void* memory,
+ ResourceFormat format,
+ const gfx::Size& size,
+ int stride,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale);
+
// Type-checking downcast routine.
virtual Rasterizer* AsRasterizer() = 0;
};
diff --git a/chromium/cc/resources/raster_worker_pool_perftest.cc b/chromium/cc/resources/raster_worker_pool_perftest.cc
index a0b63efaf61..0f7a845e8a0 100644
--- a/chromium/cc/resources/raster_worker_pool_perftest.cc
+++ b/chromium/cc/resources/raster_worker_pool_perftest.cc
@@ -4,20 +4,24 @@
#include "cc/resources/raster_worker_pool.h"
+#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "cc/debug/lap_timer.h"
#include "cc/output/context_provider.h"
-#include "cc/resources/direct_raster_worker_pool.h"
-#include "cc/resources/image_copy_raster_worker_pool.h"
-#include "cc/resources/image_raster_worker_pool.h"
+#include "cc/resources/bitmap_raster_worker_pool.h"
+#include "cc/resources/gpu_raster_worker_pool.h"
+#include "cc/resources/one_copy_raster_worker_pool.h"
#include "cc/resources/pixel_buffer_raster_worker_pool.h"
+#include "cc/resources/raster_buffer.h"
#include "cc/resources/rasterizer.h"
#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/scoped_resource.h"
+#include "cc/resources/zero_copy_raster_worker_pool.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/test_context_support.h"
+#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,47 +33,62 @@ namespace {
class PerfGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
// Overridden from gpu::gles2::GLES2Interface:
- virtual GLuint CreateImageCHROMIUM(GLsizei width,
- GLsizei height,
- GLenum internalformat,
- GLenum usage) OVERRIDE {
+ GLuint CreateImageCHROMIUM(ClientBuffer buffer,
+ GLsizei width,
+ GLsizei height,
+ GLenum internalformat) override {
return 1u;
}
- virtual void GenBuffers(GLsizei n, GLuint* buffers) OVERRIDE {
+ void GenBuffers(GLsizei n, GLuint* buffers) override {
for (GLsizei i = 0; i < n; ++i)
buffers[i] = 1u;
}
- virtual void GenTextures(GLsizei n, GLuint* textures) OVERRIDE {
+ void GenTextures(GLsizei n, GLuint* textures) override {
for (GLsizei i = 0; i < n; ++i)
textures[i] = 1u;
}
- virtual void GetIntegerv(GLenum pname, GLint* params) OVERRIDE {
+ void GetIntegerv(GLenum pname, GLint* params) override {
if (pname == GL_MAX_TEXTURE_SIZE)
*params = INT_MAX;
}
+ void GenQueriesEXT(GLsizei n, GLuint* queries) override {
+ for (GLsizei i = 0; i < n; ++i)
+ queries[i] = 1u;
+ }
+ void GetQueryObjectuivEXT(GLuint query,
+ GLenum pname,
+ GLuint* params) override {
+ if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
+ *params = 1;
+ }
};
class PerfContextProvider : public ContextProvider {
public:
PerfContextProvider() : context_gl_(new PerfGLES2Interface) {}
- virtual bool BindToCurrentThread() OVERRIDE { return true; }
- virtual Capabilities ContextCapabilities() OVERRIDE { return Capabilities(); }
- virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
- return context_gl_.get();
+ bool BindToCurrentThread() override { return true; }
+ Capabilities ContextCapabilities() override {
+ Capabilities capabilities;
+ capabilities.gpu.image = true;
+ capabilities.gpu.sync_query = true;
+ return capabilities;
}
- virtual gpu::ContextSupport* ContextSupport() OVERRIDE { return &support_; }
- virtual class GrContext* GrContext() OVERRIDE { return NULL; }
- virtual bool IsContextLost() OVERRIDE { return false; }
- virtual void VerifyContexts() OVERRIDE {}
- virtual void DeleteCachedResources() OVERRIDE {}
- virtual bool DestroyedOnMainThread() OVERRIDE { return false; }
- virtual void SetLostContextCallback(const LostContextCallback& cb) OVERRIDE {}
- virtual void SetMemoryPolicyChangedCallback(
- const MemoryPolicyChangedCallback& cb) OVERRIDE {}
+ gpu::gles2::GLES2Interface* ContextGL() override { return context_gl_.get(); }
+ gpu::ContextSupport* ContextSupport() override { return &support_; }
+ class GrContext* GrContext() override {
+ return NULL;
+ }
+ bool IsContextLost() override { return false; }
+ void VerifyContexts() override {}
+ void DeleteCachedResources() override {}
+ bool DestroyedOnMainThread() override { return false; }
+ void SetLostContextCallback(const LostContextCallback& cb) override {}
+ void SetMemoryPolicyChangedCallback(
+ const MemoryPolicyChangedCallback& cb) override {}
private:
- virtual ~PerfContextProvider() {}
+ ~PerfContextProvider() override {}
scoped_ptr<PerfGLES2Interface> context_gl_;
TestContextSupport support_;
@@ -77,9 +96,10 @@ class PerfContextProvider : public ContextProvider {
enum RasterWorkerPoolType {
RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
- RASTER_WORKER_POOL_TYPE_IMAGE,
- RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
- RASTER_WORKER_POOL_TYPE_DIRECT
+ RASTER_WORKER_POOL_TYPE_ZERO_COPY,
+ RASTER_WORKER_POOL_TYPE_ONE_COPY,
+ RASTER_WORKER_POOL_TYPE_GPU,
+ RASTER_WORKER_POOL_TYPE_BITMAP
};
static const int kTimeLimitMillis = 2000;
@@ -91,12 +111,12 @@ class PerfImageDecodeTaskImpl : public ImageDecodeTask {
PerfImageDecodeTaskImpl() {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {}
+ void RunOnWorkerThread() override {}
// Overridden from RasterizerTask:
- virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
- virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
- virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
+ void ScheduleOnOriginThread(RasterizerTaskClient* client) override {}
+ void CompleteOnOriginThread(RasterizerTaskClient* client) override {}
+ void RunReplyOnOriginThread() override { Reset(); }
void Reset() {
did_run_ = false;
@@ -104,7 +124,7 @@ class PerfImageDecodeTaskImpl : public ImageDecodeTask {
}
protected:
- virtual ~PerfImageDecodeTaskImpl() {}
+ ~PerfImageDecodeTaskImpl() override {}
private:
DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
@@ -117,16 +137,16 @@ class PerfRasterTaskImpl : public RasterTask {
: RasterTask(resource.get(), dependencies), resource_(resource.Pass()) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {}
+ void RunOnWorkerThread() override {}
// Overridden from RasterizerTask:
- virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
- client->AcquireCanvasForRaster(this);
+ void ScheduleOnOriginThread(RasterizerTaskClient* client) override {
+ raster_buffer_ = client->AcquireBufferForRaster(resource());
}
- virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
- client->ReleaseCanvasForRaster(this);
+ void CompleteOnOriginThread(RasterizerTaskClient* client) override {
+ client->ReleaseBufferForRaster(raster_buffer_.Pass());
}
- virtual void RunReplyOnOriginThread() OVERRIDE { Reset(); }
+ void RunReplyOnOriginThread() override { Reset(); }
void Reset() {
did_run_ = false;
@@ -134,35 +154,28 @@ class PerfRasterTaskImpl : public RasterTask {
}
protected:
- virtual ~PerfRasterTaskImpl() {}
+ ~PerfRasterTaskImpl() override {}
private:
scoped_ptr<ScopedResource> resource_;
+ scoped_ptr<RasterBuffer> raster_buffer_;
DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl);
};
class RasterWorkerPoolPerfTestBase {
public:
- typedef std::vector<scoped_refptr<RasterTask> > RasterTaskVector;
+ typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
+
+ enum NamedTaskSet { REQUIRED_FOR_ACTIVATION = 0, ALL = 1 };
RasterWorkerPoolPerfTestBase()
: context_provider_(make_scoped_refptr(new PerfContextProvider)),
+ task_runner_(new base::TestSimpleTaskRunner),
task_graph_runner_(new TaskGraphRunner),
timer_(kWarmupRuns,
base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
- kTimeCheckInterval) {
- output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
- CHECK(output_surface_->BindToClient(&output_surface_client_));
-
- shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ =
- ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false).Pass();
- staging_resource_pool_ = ResourcePool::Create(
- resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
- }
+ kTimeCheckInterval) {}
void CreateImageDecodeTasks(unsigned num_image_decode_tasks,
ImageDecodeTask::Vector* image_decode_tasks) {
@@ -178,7 +191,8 @@ class RasterWorkerPoolPerfTestBase {
for (unsigned i = 0; i < num_raster_tasks; ++i) {
scoped_ptr<ScopedResource> resource(
ScopedResource::Create(resource_provider_.get()));
- resource->Allocate(size, ResourceProvider::TextureUsageAny, RGBA_8888);
+ resource->Allocate(
+ size, ResourceProvider::TextureHintImmutable, RGBA_8888);
ImageDecodeTask::Vector dependencies = image_decode_tasks;
raster_tasks->push_back(
@@ -190,9 +204,11 @@ class RasterWorkerPoolPerfTestBase {
const RasterTaskVector& raster_tasks) {
for (size_t i = 0u; i < raster_tasks.size(); ++i) {
bool required_for_activation = (i % 2) == 0;
- queue->items.push_back(RasterTaskQueue::Item(raster_tasks[i].get(),
- required_for_activation));
- queue->required_for_activation_count += required_for_activation;
+ TaskSetCollection task_set_collection;
+ task_set_collection[ALL] = true;
+ task_set_collection[REQUIRED_FOR_ACTIVATION] = required_for_activation;
+ queue->items.push_back(
+ RasterTaskQueue::Item(raster_tasks[i].get(), task_set_collection));
}
}
@@ -200,9 +216,8 @@ class RasterWorkerPoolPerfTestBase {
scoped_refptr<ContextProvider> context_provider_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<FakeOutputSurface> output_surface_;
- scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
scoped_ptr<ResourceProvider> resource_provider_;
- scoped_ptr<ResourcePool> staging_resource_pool_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_ptr<TaskGraphRunner> task_graph_runner_;
LapTimer timer_;
};
@@ -212,60 +227,72 @@ class RasterWorkerPoolPerfTest
public testing::TestWithParam<RasterWorkerPoolType>,
public RasterizerClient {
public:
- RasterWorkerPoolPerfTest() {
+ // Overridden from testing::Test:
+ virtual void SetUp() override {
switch (GetParam()) {
case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
+ Create3dOutputSurfaceAndResourceProvider();
raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
- base::MessageLoopProxy::current().get(),
+ task_runner_.get(),
task_graph_runner_.get(),
+ context_provider_.get(),
resource_provider_.get(),
std::numeric_limits<size_t>::max());
break;
- case RASTER_WORKER_POOL_TYPE_IMAGE:
- raster_worker_pool_ = ImageRasterWorkerPool::Create(
- base::MessageLoopProxy::current().get(),
- task_graph_runner_.get(),
- resource_provider_.get());
+ case RASTER_WORKER_POOL_TYPE_ZERO_COPY:
+ Create3dOutputSurfaceAndResourceProvider();
+ raster_worker_pool_ =
+ ZeroCopyRasterWorkerPool::Create(task_runner_.get(),
+ task_graph_runner_.get(),
+ resource_provider_.get());
break;
- case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
- raster_worker_pool_ = ImageCopyRasterWorkerPool::Create(
- base::MessageLoopProxy::current().get(),
- task_graph_runner_.get(),
- resource_provider_.get(),
- staging_resource_pool_.get());
+ case RASTER_WORKER_POOL_TYPE_ONE_COPY:
+ Create3dOutputSurfaceAndResourceProvider();
+ staging_resource_pool_ = ResourcePool::Create(
+ resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
+ raster_worker_pool_ =
+ OneCopyRasterWorkerPool::Create(task_runner_.get(),
+ task_graph_runner_.get(),
+ context_provider_.get(),
+ resource_provider_.get(),
+ staging_resource_pool_.get());
break;
- case RASTER_WORKER_POOL_TYPE_DIRECT:
- raster_worker_pool_ = DirectRasterWorkerPool::Create(
- base::MessageLoopProxy::current().get(),
- resource_provider_.get(),
- context_provider_.get());
+ case RASTER_WORKER_POOL_TYPE_GPU:
+ Create3dOutputSurfaceAndResourceProvider();
+ raster_worker_pool_ =
+ GpuRasterWorkerPool::Create(task_runner_.get(),
+ context_provider_.get(),
+ resource_provider_.get(),
+ false);
+ break;
+ case RASTER_WORKER_POOL_TYPE_BITMAP:
+ CreateSoftwareOutputSurfaceAndResourceProvider();
+ raster_worker_pool_ =
+ BitmapRasterWorkerPool::Create(task_runner_.get(),
+ task_graph_runner_.get(),
+ resource_provider_.get());
break;
}
DCHECK(raster_worker_pool_);
raster_worker_pool_->AsRasterizer()->SetClient(this);
}
-
- // Overridden from testing::Test:
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
raster_worker_pool_->AsRasterizer()->Shutdown();
raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
}
// Overriden from RasterizerClient:
- virtual bool ShouldForceTasksRequiredForActivationToComplete() const
- OVERRIDE {
- return false;
- }
- virtual void DidFinishRunningTasks() OVERRIDE {
+ void DidFinishRunningTasks(TaskSet task_set) override {
raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
- base::MessageLoop::current()->Quit();
}
- virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE {}
+ TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
+ return TaskSetCollection();
+ }
void RunMessageLoopUntilAllTasksHaveCompleted() {
task_graph_runner_->RunUntilIdle();
- base::MessageLoop::current()->Run();
+ task_runner_->RunUntilIdle();
}
void RunScheduleTasksTest(const std::string& test_name,
@@ -371,22 +398,52 @@ class RasterWorkerPoolPerfTest
}
private:
+ void Create3dOutputSurfaceAndResourceProvider() {
+ output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ NULL,
+ &gpu_memory_buffer_manager_,
+ NULL,
+ 0,
+ false,
+ 1).Pass();
+ }
+
+ void CreateSoftwareOutputSurfaceAndResourceProvider() {
+ output_surface_ = FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice));
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ &shared_bitmap_manager_,
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1).Pass();
+ }
+
std::string TestModifierString() const {
switch (GetParam()) {
case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
return std::string("_pixel_raster_worker_pool");
- case RASTER_WORKER_POOL_TYPE_IMAGE:
- return std::string("_image_raster_worker_pool");
- case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
- return std::string("_image_copy_raster_worker_pool");
- case RASTER_WORKER_POOL_TYPE_DIRECT:
- return std::string("_direct_raster_worker_pool");
+ case RASTER_WORKER_POOL_TYPE_ZERO_COPY:
+ return std::string("_zero_copy_raster_worker_pool");
+ case RASTER_WORKER_POOL_TYPE_ONE_COPY:
+ return std::string("_one_copy_raster_worker_pool");
+ case RASTER_WORKER_POOL_TYPE_GPU:
+ return std::string("_gpu_raster_worker_pool");
+ case RASTER_WORKER_POOL_TYPE_BITMAP:
+ return std::string("_bitmap_raster_worker_pool");
}
NOTREACHED();
return std::string();
}
+ scoped_ptr<ResourcePool> staging_resource_pool_;
scoped_ptr<RasterWorkerPool> raster_worker_pool_;
+ TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
+ TestSharedBitmapManager shared_bitmap_manager_;
};
TEST_P(RasterWorkerPoolPerfTest, ScheduleTasks) {
@@ -419,13 +476,23 @@ TEST_P(RasterWorkerPoolPerfTest, ScheduleAndExecuteTasks) {
INSTANTIATE_TEST_CASE_P(RasterWorkerPoolPerfTests,
RasterWorkerPoolPerfTest,
::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
- RASTER_WORKER_POOL_TYPE_IMAGE,
- RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
- RASTER_WORKER_POOL_TYPE_DIRECT));
+ RASTER_WORKER_POOL_TYPE_ZERO_COPY,
+ RASTER_WORKER_POOL_TYPE_ONE_COPY,
+ RASTER_WORKER_POOL_TYPE_GPU,
+ RASTER_WORKER_POOL_TYPE_BITMAP));
class RasterWorkerPoolCommonPerfTest : public RasterWorkerPoolPerfTestBase,
public testing::Test {
public:
+ // Overridden from testing::Test:
+ virtual void SetUp() override {
+ output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+ resource_provider_ =
+ ResourceProvider::Create(
+ output_surface_.get(), NULL, NULL, NULL, 0, false, 1).Pass();
+ }
+
void RunBuildRasterTaskQueueTest(const std::string& test_name,
unsigned num_raster_tasks,
unsigned num_image_decode_tasks) {
diff --git a/chromium/cc/resources/raster_worker_pool_unittest.cc b/chromium/cc/resources/raster_worker_pool_unittest.cc
index 7a5f324e39f..9aee8e7bc74 100644
--- a/chromium/cc/resources/raster_worker_pool_unittest.cc
+++ b/chromium/cc/resources/raster_worker_pool_unittest.cc
@@ -8,18 +8,22 @@
#include <vector>
#include "base/cancelable_callback.h"
-#include "cc/resources/direct_raster_worker_pool.h"
-#include "cc/resources/image_copy_raster_worker_pool.h"
-#include "cc/resources/image_raster_worker_pool.h"
+#include "cc/resources/bitmap_raster_worker_pool.h"
+#include "cc/resources/gpu_raster_worker_pool.h"
+#include "cc/resources/one_copy_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/raster_buffer.h"
#include "cc/resources/rasterizer.h"
#include "cc/resources/resource_pool.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/scoped_resource.h"
+#include "cc/resources/zero_copy_raster_worker_pool.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
+#include "cc/test/fake_picture_pile_impl.h"
+#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,42 +31,55 @@
namespace cc {
namespace {
+const size_t kMaxTransferBufferUsageBytes = 10000U;
+// A resource of this dimension^2 * 4 must be greater than the above transfer
+// buffer constant.
+const size_t kLargeResourceDimension = 1000U;
+
enum RasterWorkerPoolType {
RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
- RASTER_WORKER_POOL_TYPE_IMAGE,
- RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
- RASTER_WORKER_POOL_TYPE_DIRECT
+ RASTER_WORKER_POOL_TYPE_ZERO_COPY,
+ RASTER_WORKER_POOL_TYPE_ONE_COPY,
+ RASTER_WORKER_POOL_TYPE_GPU,
+ RASTER_WORKER_POOL_TYPE_BITMAP
};
class TestRasterTaskImpl : public RasterTask {
public:
- typedef base::Callback<
- void(const PicturePileImpl::Analysis& analysis, bool was_canceled)> Reply;
+ typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
+ bool was_canceled)> Reply;
TestRasterTaskImpl(const Resource* resource,
const Reply& reply,
ImageDecodeTask::Vector* dependencies)
- : RasterTask(resource, dependencies), reply_(reply) {}
+ : RasterTask(resource, dependencies),
+ reply_(reply),
+ picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
+ gfx::Size(1, 1))) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {}
+ void RunOnWorkerThread() override {
+ raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0);
+ }
// Overridden from RasterizerTask:
- virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
- client->AcquireCanvasForRaster(this);
+ void ScheduleOnOriginThread(RasterizerTaskClient* client) override {
+ raster_buffer_ = client->AcquireBufferForRaster(resource());
}
- virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
- client->ReleaseCanvasForRaster(this);
+ void CompleteOnOriginThread(RasterizerTaskClient* client) override {
+ client->ReleaseBufferForRaster(raster_buffer_.Pass());
}
- virtual void RunReplyOnOriginThread() OVERRIDE {
- reply_.Run(PicturePileImpl::Analysis(), !HasFinishedRunning());
+ void RunReplyOnOriginThread() override {
+ reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
}
protected:
- virtual ~TestRasterTaskImpl() {}
+ ~TestRasterTaskImpl() override {}
private:
const Reply reply_;
+ scoped_ptr<RasterBuffer> raster_buffer_;
+ scoped_refptr<PicturePileImpl> picture_pile_;
DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
};
@@ -76,16 +93,16 @@ class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
: TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {
+ void RunOnWorkerThread() override {
base::AutoLock lock(*lock_);
TestRasterTaskImpl::RunOnWorkerThread();
}
// Overridden from RasterizerTask:
- virtual void RunReplyOnOriginThread() OVERRIDE {}
+ void RunReplyOnOriginThread() override {}
protected:
- virtual ~BlockingTestRasterTaskImpl() {}
+ ~BlockingTestRasterTaskImpl() override {}
private:
base::Lock* lock_;
@@ -102,76 +119,81 @@ class RasterWorkerPoolTest
bool canceled;
};
- typedef std::vector<scoped_refptr<RasterTask> > RasterTaskVector;
+ typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
+
+ enum NamedTaskSet { REQUIRED_FOR_ACTIVATION = 0, ALL = 1 };
RasterWorkerPoolTest()
: context_provider_(TestContextProvider::Create()),
timeout_seconds_(5),
- timed_out_(false) {
- output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
- CHECK(output_surface_->BindToClient(&output_surface_client_));
-
- shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ =
- ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false).Pass();
- staging_resource_pool_ = ResourcePool::Create(
- resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
+ timed_out_(false) {}
+ // Overridden from testing::Test:
+ virtual void SetUp() override {
switch (GetParam()) {
case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
+ Create3dOutputSurfaceAndResourceProvider();
raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
base::MessageLoopProxy::current().get(),
RasterWorkerPool::GetTaskGraphRunner(),
+ context_provider_.get(),
resource_provider_.get(),
- std::numeric_limits<size_t>::max());
+ kMaxTransferBufferUsageBytes);
break;
- case RASTER_WORKER_POOL_TYPE_IMAGE:
- raster_worker_pool_ = ImageRasterWorkerPool::Create(
+ case RASTER_WORKER_POOL_TYPE_ZERO_COPY:
+ Create3dOutputSurfaceAndResourceProvider();
+ raster_worker_pool_ = ZeroCopyRasterWorkerPool::Create(
base::MessageLoopProxy::current().get(),
RasterWorkerPool::GetTaskGraphRunner(),
resource_provider_.get());
break;
- case RASTER_WORKER_POOL_TYPE_IMAGE_COPY:
- raster_worker_pool_ = ImageCopyRasterWorkerPool::Create(
+ case RASTER_WORKER_POOL_TYPE_ONE_COPY:
+ Create3dOutputSurfaceAndResourceProvider();
+ staging_resource_pool_ = ResourcePool::Create(
+ resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
+ raster_worker_pool_ = OneCopyRasterWorkerPool::Create(
base::MessageLoopProxy::current().get(),
RasterWorkerPool::GetTaskGraphRunner(),
+ context_provider_.get(),
resource_provider_.get(),
staging_resource_pool_.get());
break;
- case RASTER_WORKER_POOL_TYPE_DIRECT:
- raster_worker_pool_ = DirectRasterWorkerPool::Create(
+ case RASTER_WORKER_POOL_TYPE_GPU:
+ Create3dOutputSurfaceAndResourceProvider();
+ raster_worker_pool_ =
+ GpuRasterWorkerPool::Create(base::MessageLoopProxy::current().get(),
+ context_provider_.get(),
+ resource_provider_.get(),
+ false);
+ break;
+ case RASTER_WORKER_POOL_TYPE_BITMAP:
+ CreateSoftwareOutputSurfaceAndResourceProvider();
+ raster_worker_pool_ = BitmapRasterWorkerPool::Create(
base::MessageLoopProxy::current().get(),
- resource_provider_.get(),
- context_provider_.get());
+ RasterWorkerPool::GetTaskGraphRunner(),
+ resource_provider_.get());
break;
}
DCHECK(raster_worker_pool_);
raster_worker_pool_->AsRasterizer()->SetClient(this);
}
- virtual ~RasterWorkerPoolTest() {
- staging_resource_pool_.reset();
- resource_provider_.reset();
- }
- // Overridden from testing::Test:
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
raster_worker_pool_->AsRasterizer()->Shutdown();
raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
}
// Overriden from RasterWorkerPoolClient:
- virtual bool ShouldForceTasksRequiredForActivationToComplete() const
- OVERRIDE {
- return false;
+ void DidFinishRunningTasks(TaskSet task_set) override {
+ if (task_set == ALL) {
+ raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
+ base::MessageLoop::current()->Quit();
+ }
}
- virtual void DidFinishRunningTasks() OVERRIDE {
- raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
- base::MessageLoop::current()->Quit();
+ TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
+ return TaskSetCollection();
}
- virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE {}
void RunMessageLoopUntilAllTasksHaveCompleted() {
if (timeout_seconds_) {
@@ -195,18 +217,19 @@ class RasterWorkerPoolTest
for (RasterTaskVector::const_iterator it = tasks_.begin();
it != tasks_.end();
- ++it)
- queue.items.push_back(RasterTaskQueue::Item(*it, false));
+ ++it) {
+ TaskSetCollection task_sets;
+ task_sets[ALL] = true;
+ queue.items.push_back(RasterTaskQueue::Item(it->get(), task_sets));
+ }
raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
}
- void AppendTask(unsigned id) {
- const gfx::Size size(1, 1);
-
+ void AppendTask(unsigned id, const gfx::Size& size) {
scoped_ptr<ScopedResource> resource(
ScopedResource::Create(resource_provider_.get()));
- resource->Allocate(size, ResourceProvider::TextureUsageAny, RGBA_8888);
+ resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
const Resource* const_resource = resource.get();
ImageDecodeTask::Vector empty;
@@ -219,12 +242,14 @@ class RasterWorkerPoolTest
&empty));
}
+ void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
+
void AppendBlockingTask(unsigned id, base::Lock* lock) {
const gfx::Size size(1, 1);
scoped_ptr<ScopedResource> resource(
ScopedResource::Create(resource_provider_.get()));
- resource->Allocate(size, ResourceProvider::TextureUsageAny, RGBA_8888);
+ resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
const Resource* const_resource = resource.get();
ImageDecodeTask::Vector empty;
@@ -243,9 +268,36 @@ class RasterWorkerPoolTest
}
private:
+ void Create3dOutputSurfaceAndResourceProvider() {
+ output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+ TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
+ context3d->set_support_sync_query(true);
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ NULL,
+ &gpu_memory_buffer_manager_,
+ NULL,
+ 0,
+ false,
+ 1).Pass();
+ }
+
+ void CreateSoftwareOutputSurfaceAndResourceProvider() {
+ output_surface_ = FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice));
+ CHECK(output_surface_->BindToClient(&output_surface_client_));
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ &shared_bitmap_manager_,
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1).Pass();
+ }
+
void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
unsigned id,
- const PicturePileImpl::Analysis& analysis,
+ const RasterSource::SolidColorAnalysis& analysis,
bool was_canceled) {
RasterTaskResult result;
result.id = id;
@@ -262,10 +314,11 @@ class RasterWorkerPoolTest
scoped_refptr<TestContextProvider> context_provider_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<FakeOutputSurface> output_surface_;
- scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
scoped_ptr<ResourceProvider> resource_provider_;
scoped_ptr<ResourcePool> staging_resource_pool_;
scoped_ptr<RasterWorkerPool> raster_worker_pool_;
+ TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
+ TestSharedBitmapManager shared_bitmap_manager_;
base::CancelableClosure timeout_;
int timeout_seconds_;
bool timed_out_;
@@ -286,8 +339,10 @@ TEST_P(RasterWorkerPoolTest, Basic) {
}
TEST_P(RasterWorkerPoolTest, FailedMapResource) {
+ if (GetParam() == RASTER_WORKER_POOL_TYPE_BITMAP)
+ return;
+
TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
- context3d->set_times_map_image_chromium_succeeds(0);
context3d->set_times_map_buffer_chromium_succeeds(0);
AppendTask(0u);
ScheduleTasks();
@@ -322,12 +377,34 @@ TEST_P(RasterWorkerPoolTest, FalseThrottling) {
RunMessageLoopUntilAllTasksHaveCompleted();
}
+TEST_P(RasterWorkerPoolTest, LargeResources) {
+ gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
+
+ {
+ // Verify a resource of this size is larger than the transfer buffer.
+ scoped_ptr<ScopedResource> resource(
+ ScopedResource::Create(resource_provider_.get()));
+ resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
+ EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes);
+ }
+
+ AppendTask(0u, size);
+ AppendTask(1u, size);
+ AppendTask(2u, size);
+ ScheduleTasks();
+
+ // This will time out if a resource that is larger than the throttle limit
+ // never gets scheduled.
+ RunMessageLoopUntilAllTasksHaveCompleted();
+}
+
INSTANTIATE_TEST_CASE_P(RasterWorkerPoolTests,
RasterWorkerPoolTest,
::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
- RASTER_WORKER_POOL_TYPE_IMAGE,
- RASTER_WORKER_POOL_TYPE_IMAGE_COPY,
- RASTER_WORKER_POOL_TYPE_DIRECT));
+ RASTER_WORKER_POOL_TYPE_ZERO_COPY,
+ RASTER_WORKER_POOL_TYPE_ONE_COPY,
+ RASTER_WORKER_POOL_TYPE_GPU,
+ RASTER_WORKER_POOL_TYPE_BITMAP));
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/rasterizer.cc b/chromium/cc/resources/rasterizer.cc
index df7e27ecebc..4ce8987e8ca 100644
--- a/chromium/cc/resources/rasterizer.cc
+++ b/chromium/cc/resources/rasterizer.cc
@@ -56,23 +56,24 @@ RasterTask::~RasterTask() {}
RasterTask* RasterTask::AsRasterTask() { return this; }
-RasterTaskQueue::Item::Item(RasterTask* task, bool required_for_activation)
- : task(task), required_for_activation(required_for_activation) {}
+RasterTaskQueue::Item::Item(RasterTask* task,
+ const TaskSetCollection& task_sets)
+ : task(task), task_sets(task_sets) {
+ DCHECK(task_sets.any());
+}
RasterTaskQueue::Item::~Item() {}
-RasterTaskQueue::RasterTaskQueue() : required_for_activation_count(0u) {}
+RasterTaskQueue::RasterTaskQueue() {
+}
RasterTaskQueue::~RasterTaskQueue() {}
void RasterTaskQueue::Swap(RasterTaskQueue* other) {
items.swap(other->items);
- std::swap(required_for_activation_count,
- other->required_for_activation_count);
}
void RasterTaskQueue::Reset() {
- required_for_activation_count = 0u;
items.clear();
}
diff --git a/chromium/cc/resources/rasterizer.h b/chromium/cc/resources/rasterizer.h
index 17cc94ed6fa..526058c338d 100644
--- a/chromium/cc/resources/rasterizer.h
+++ b/chromium/cc/resources/rasterizer.h
@@ -5,23 +5,24 @@
#ifndef CC_RESOURCES_RASTERIZER_H_
#define CC_RESOURCES_RASTERIZER_H_
+#include <bitset>
#include <vector>
#include "base/callback.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/task_graph_runner.h"
-class SkCanvas;
-
namespace cc {
class ImageDecodeTask;
class RasterTask;
class Resource;
+class RasterBuffer;
class CC_EXPORT RasterizerTaskClient {
public:
- virtual SkCanvas* AcquireCanvasForRaster(RasterTask* task) = 0;
- virtual void ReleaseCanvasForRaster(RasterTask* task) = 0;
+ virtual scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) = 0;
+ virtual void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) = 0;
protected:
virtual ~RasterizerTaskClient() {}
@@ -29,7 +30,7 @@ class CC_EXPORT RasterizerTaskClient {
class CC_EXPORT RasterizerTask : public Task {
public:
- typedef std::vector<scoped_refptr<RasterizerTask> > Vector;
+ typedef std::vector<scoped_refptr<RasterizerTask>> Vector;
virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) = 0;
virtual void CompleteOnOriginThread(RasterizerTaskClient* client) = 0;
@@ -49,7 +50,7 @@ class CC_EXPORT RasterizerTask : public Task {
protected:
RasterizerTask();
- virtual ~RasterizerTask();
+ ~RasterizerTask() override;
bool did_schedule_;
bool did_complete_;
@@ -57,40 +58,43 @@ class CC_EXPORT RasterizerTask : public Task {
class CC_EXPORT ImageDecodeTask : public RasterizerTask {
public:
- typedef std::vector<scoped_refptr<ImageDecodeTask> > Vector;
+ typedef std::vector<scoped_refptr<ImageDecodeTask>> Vector;
// Overridden from RasterizerTask:
- virtual ImageDecodeTask* AsImageDecodeTask() OVERRIDE;
+ ImageDecodeTask* AsImageDecodeTask() override;
protected:
ImageDecodeTask();
- virtual ~ImageDecodeTask();
+ ~ImageDecodeTask() override;
};
class CC_EXPORT RasterTask : public RasterizerTask {
public:
- typedef std::vector<scoped_refptr<RasterTask> > Vector;
+ typedef std::vector<scoped_refptr<RasterTask>> Vector;
// Overridden from RasterizerTask:
- virtual RasterTask* AsRasterTask() OVERRIDE;
+ RasterTask* AsRasterTask() override;
const Resource* resource() const { return resource_; }
const ImageDecodeTask::Vector& dependencies() const { return dependencies_; }
protected:
RasterTask(const Resource* resource, ImageDecodeTask::Vector* dependencies);
- virtual ~RasterTask();
+ ~RasterTask() override;
private:
const Resource* resource_;
ImageDecodeTask::Vector dependencies_;
};
+static const size_t kNumberOfTaskSets = 2;
+typedef size_t TaskSet;
+typedef std::bitset<kNumberOfTaskSets> TaskSetCollection;
+
class CC_EXPORT RasterizerClient {
public:
- virtual bool ShouldForceTasksRequiredForActivationToComplete() const = 0;
- virtual void DidFinishRunningTasks() = 0;
- virtual void DidFinishRunningTasksRequiredForActivation() = 0;
+ virtual void DidFinishRunningTasks(TaskSet task_set) = 0;
+ virtual TaskSetCollection TasksThatShouldBeForcedToComplete() const = 0;
protected:
virtual ~RasterizerClient() {}
@@ -110,15 +114,11 @@ struct CC_EXPORT RasterTaskQueue {
typedef std::vector<Item> Vector;
- Item(RasterTask* task, bool required_for_activation);
+ Item(RasterTask* task, const TaskSetCollection& task_sets);
~Item();
- static bool IsRequiredForActivation(const Item& item) {
- return item.required_for_activation;
- }
-
RasterTask* task;
- bool required_for_activation;
+ TaskSetCollection task_sets;
};
RasterTaskQueue();
@@ -128,7 +128,6 @@ struct CC_EXPORT RasterTaskQueue {
void Reset();
Item::Vector items;
- size_t required_for_activation_count;
};
// This interface can be used to schedule and run raster tasks. The client will
diff --git a/chromium/cc/resources/release_callback_impl.h b/chromium/cc/resources/release_callback_impl.h
new file mode 100644
index 00000000000..89f22b66976
--- /dev/null
+++ b/chromium/cc/resources/release_callback_impl.h
@@ -0,0 +1,20 @@
+// Copyright 2014 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_RELEASE_CALLBACK_IMPL_H_
+#define CC_RESOURCES_RELEASE_CALLBACK_IMPL_H_
+
+#include "base/callback.h"
+
+namespace cc {
+class BlockingTaskRunner;
+
+typedef base::Callback<void(uint32 sync_point,
+ bool is_lost,
+ BlockingTaskRunner* main_thread_task_runner)>
+ ReleaseCallbackImpl;
+
+} // namespace cc
+
+#endif // CC_RESOURCES_RELEASE_CALLBACK_IMPL_H_
diff --git a/chromium/cc/resources/resource.h b/chromium/cc/resources/resource.h
index 24cb88a9f84..707d77e20bf 100644
--- a/chromium/cc/resources/resource.h
+++ b/chromium/cc/resources/resource.h
@@ -8,7 +8,7 @@
#include "cc/base/cc_export.h"
#include "cc/resources/resource_provider.h"
#include "third_party/khronos/GLES2/gl2.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
diff --git a/chromium/cc/resources/resource_format.cc b/chromium/cc/resources/resource_format.cc
index 273085604a4..6cd0a93e921 100644
--- a/chromium/cc/resources/resource_format.cc
+++ b/chromium/cc/resources/resource_format.cc
@@ -12,15 +12,16 @@ SkColorType ResourceFormatToSkColorType(ResourceFormat format) {
return kARGB_4444_SkColorType;
case RGBA_8888:
case BGRA_8888:
- return kPMColor_SkColorType;
+ return kN32_SkColorType;
case ETC1:
+ case ALPHA_8:
case LUMINANCE_8:
case RGB_565:
NOTREACHED();
break;
}
NOTREACHED();
- return kPMColor_SkColorType;
+ return kN32_SkColorType;
}
} // namespace cc
diff --git a/chromium/cc/resources/resource_format.h b/chromium/cc/resources/resource_format.h
index 816c2857913..b51ac7cfe72 100644
--- a/chromium/cc/resources/resource_format.h
+++ b/chromium/cc/resources/resource_format.h
@@ -15,6 +15,7 @@ enum ResourceFormat {
RGBA_8888,
RGBA_4444,
BGRA_8888,
+ ALPHA_8,
LUMINANCE_8,
RGB_565,
ETC1,
diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc
index 31b9b272013..45f36e27816 100644
--- a/chromium/cc/resources/resource_pool.cc
+++ b/chromium/cc/resources/resource_pool.cc
@@ -105,12 +105,15 @@ bool ResourcePool::ResourceUsageTooHigh() {
return false;
}
-void ResourcePool::CheckBusyResources() {
+void ResourcePool::CheckBusyResources(bool wait_if_needed) {
ResourceList::iterator it = busy_resources_.begin();
while (it != busy_resources_.end()) {
ScopedResource* resource = *it;
+ if (wait_if_needed)
+ resource_provider_->WaitReadLockIfNeeded(resource->id());
+
if (resource_provider_->CanLockForWrite(resource->id())) {
DidFinishUsingResource(resource);
it = busy_resources_.erase(it);
diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h
index 5f481e986a1..e1ee35aa72c 100644
--- a/chromium/cc/resources/resource_pool.h
+++ b/chromium/cc/resources/resource_pool.h
@@ -34,7 +34,10 @@ class CC_EXPORT ResourcePool {
size_t max_resource_count);
void ReduceResourceUsage();
- void CheckBusyResources();
+ // This might block if |wait_if_needed| is true and one of the currently
+ // busy resources has a read lock fence that needs to be waited upon before
+ // it can be locked for write again.
+ void CheckBusyResources(bool wait_if_needed);
size_t total_memory_usage_bytes() const { return memory_usage_bytes_; }
size_t acquired_memory_usage_bytes() const {
@@ -44,6 +47,7 @@ class CC_EXPORT ResourcePool {
size_t acquired_resource_count() const {
return resource_count_ - unused_resources_.size();
}
+ size_t busy_resource_count() const { return busy_resources_.size(); }
ResourceFormat resource_format() const { return format_; }
diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc
index e3c21ff7c6b..023a1cdbf06 100644
--- a/chromium/cc/resources/resource_provider.cc
+++ b/chromium/cc/resources/resource_provider.cc
@@ -21,14 +21,15 @@
#include "cc/resources/transferable_resource.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/SkGpuDevice.h"
#include "ui/gfx/frame_time.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/vector2d.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/gpu_memory_buffer.h"
using gpu::gles2::GLES2Interface;
@@ -70,6 +71,7 @@ GLenum TextureToStorageFormat(ResourceFormat format) {
storage_format = GL_BGRA8_EXT;
break;
case RGBA_4444:
+ case ALPHA_8:
case LUMINANCE_8:
case RGB_565:
case ETC1:
@@ -80,12 +82,14 @@ GLenum TextureToStorageFormat(ResourceFormat format) {
return storage_format;
}
-bool IsFormatSupportedForStorage(ResourceFormat format) {
+bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) {
switch (format) {
case RGBA_8888:
- case BGRA_8888:
return true;
+ case BGRA_8888:
+ return use_bgra;
case RGBA_4444:
+ case ALPHA_8:
case LUMINANCE_8:
case RGB_565:
case ETC1:
@@ -109,25 +113,21 @@ GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
return kSkia8888_GrPixelConfig;
}
-class IdentityAllocator : public SkBitmap::Allocator {
- public:
- explicit IdentityAllocator(void* buffer) : buffer_(buffer) {}
- virtual bool allocPixelRef(SkBitmap* dst, SkColorTable*) OVERRIDE {
- dst->setPixels(buffer_);
- return true;
+gfx::GpuMemoryBuffer::Format ToGpuMemoryBufferFormat(ResourceFormat format) {
+ switch (format) {
+ case RGBA_8888:
+ return gfx::GpuMemoryBuffer::Format::RGBA_8888;
+ case BGRA_8888:
+ return gfx::GpuMemoryBuffer::Format::BGRA_8888;
+ case RGBA_4444:
+ case ALPHA_8:
+ case LUMINANCE_8:
+ case RGB_565:
+ case ETC1:
+ break;
}
-
- private:
- void* buffer_;
-};
-
-void CopyBitmap(const SkBitmap& src, uint8_t* dst, SkColorType dst_colorType) {
- SkBitmap dst_bitmap;
- IdentityAllocator allocator(dst);
- src.copyTo(&dst_bitmap, dst_colorType, &allocator);
- // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
- // bitmap data. This check will be removed once crbug.com/293728 is fixed.
- CHECK_EQ(0u, dst_bitmap.rowBytes() % 4);
+ NOTREACHED();
+ return gfx::GpuMemoryBuffer::Format::RGBA_8888;
}
class ScopedSetActiveTexture {
@@ -156,13 +156,13 @@ class TextureIdAllocator : public IdAllocator {
TextureIdAllocator(GLES2Interface* gl,
size_t texture_id_allocation_chunk_size)
: IdAllocator(gl, texture_id_allocation_chunk_size) {}
- virtual ~TextureIdAllocator() {
+ ~TextureIdAllocator() override {
gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
ids_.get() + next_id_index_);
}
// Overridden from IdAllocator:
- virtual GLuint NextId() OVERRIDE {
+ GLuint NextId() override {
if (next_id_index_ == id_allocation_chunk_size_) {
gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
next_id_index_ = 0;
@@ -179,13 +179,13 @@ class BufferIdAllocator : public IdAllocator {
public:
BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
: IdAllocator(gl, buffer_id_allocation_chunk_size) {}
- virtual ~BufferIdAllocator() {
+ ~BufferIdAllocator() override {
gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
ids_.get() + next_id_index_);
}
// Overridden from IdAllocator:
- virtual GLuint NextId() OVERRIDE {
+ GLuint NextId() override {
if (next_id_index_ == id_allocation_chunk_size_) {
gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
next_id_index_ = 0;
@@ -206,15 +206,20 @@ class QueryFence : public ResourceProvider::Fence {
: gl_(gl), query_id_(query_id) {}
// Overridden from ResourceProvider::Fence:
- virtual bool HasPassed() OVERRIDE {
+ void Set() override {}
+ bool HasPassed() override {
unsigned available = 1;
gl_->GetQueryObjectuivEXT(
query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
return !!available;
}
+ void Wait() override {
+ unsigned result = 0;
+ gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
+ }
private:
- virtual ~QueryFence() {}
+ ~QueryFence() override {}
gpu::gles2::GLES2Interface* gl_;
unsigned query_id_;
@@ -241,7 +246,7 @@ ResourceProvider::Resource::Resource()
pending_set_pixels(false),
set_pixels_completion_forced(false),
allocated(false),
- enable_read_lock_fences(false),
+ read_lock_fences_enabled(false),
has_shared_bitmap_id(false),
allow_overlay(false),
read_lock_fence(NULL),
@@ -254,10 +259,12 @@ ResourceProvider::Resource::Resource()
bound_image_id(0),
texture_pool(0),
wrap_mode(0),
- hint(TextureUsageAny),
+ hint(TextureHintImmutable),
type(InvalidType),
format(RGBA_8888),
- shared_bitmap(NULL) {}
+ shared_bitmap(NULL),
+ gpu_memory_buffer(NULL) {
+}
ResourceProvider::Resource::~Resource() {}
@@ -268,7 +275,7 @@ ResourceProvider::Resource::Resource(GLuint texture_id,
GLenum filter,
GLenum texture_pool,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format)
: child_id(0),
gl_id(texture_id),
@@ -286,7 +293,7 @@ ResourceProvider::Resource::Resource(GLuint texture_id,
pending_set_pixels(false),
set_pixels_completion_forced(false),
allocated(false),
- enable_read_lock_fences(false),
+ read_lock_fences_enabled(false),
has_shared_bitmap_id(false),
allow_overlay(false),
read_lock_fence(NULL),
@@ -302,7 +309,8 @@ ResourceProvider::Resource::Resource(GLuint texture_id,
hint(hint),
type(GLTexture),
format(format),
- shared_bitmap(NULL) {
+ shared_bitmap(NULL),
+ gpu_memory_buffer(NULL) {
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
DCHECK_EQ(origin == Internal, !!texture_pool);
}
@@ -329,7 +337,7 @@ ResourceProvider::Resource::Resource(uint8_t* pixels,
pending_set_pixels(false),
set_pixels_completion_forced(false),
allocated(false),
- enable_read_lock_fences(false),
+ read_lock_fences_enabled(false),
has_shared_bitmap_id(!!bitmap),
allow_overlay(false),
read_lock_fence(NULL),
@@ -342,10 +350,11 @@ ResourceProvider::Resource::Resource(uint8_t* pixels,
bound_image_id(0),
texture_pool(0),
wrap_mode(wrap_mode),
- hint(TextureUsageAny),
+ hint(TextureHintImmutable),
type(Bitmap),
format(RGBA_8888),
- shared_bitmap(bitmap) {
+ shared_bitmap(bitmap),
+ gpu_memory_buffer(NULL) {
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
DCHECK(origin == Delegated || pixels);
if (bitmap)
@@ -373,7 +382,7 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
pending_set_pixels(false),
set_pixels_completion_forced(false),
allocated(false),
- enable_read_lock_fences(false),
+ read_lock_fences_enabled(false),
has_shared_bitmap_id(true),
allow_overlay(false),
read_lock_fence(NULL),
@@ -386,209 +395,15 @@ ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id,
bound_image_id(0),
texture_pool(0),
wrap_mode(wrap_mode),
- hint(TextureUsageAny),
+ hint(TextureHintImmutable),
type(Bitmap),
format(RGBA_8888),
shared_bitmap_id(bitmap_id),
- shared_bitmap(NULL) {
+ shared_bitmap(NULL),
+ gpu_memory_buffer(NULL) {
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
}
-ResourceProvider::RasterBuffer::RasterBuffer(
- const Resource* resource,
- ResourceProvider* resource_provider)
- : resource_(resource),
- resource_provider_(resource_provider),
- locked_canvas_(NULL),
- canvas_save_count_(0) {
- DCHECK(resource_);
- DCHECK(resource_provider_);
-}
-
-ResourceProvider::RasterBuffer::~RasterBuffer() {}
-
-SkCanvas* ResourceProvider::RasterBuffer::LockForWrite() {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::RasterBuffer::LockForWrite");
-
- DCHECK(!locked_canvas_);
-
- locked_canvas_ = DoLockForWrite();
- canvas_save_count_ = locked_canvas_ ? locked_canvas_->save() : 0;
- return locked_canvas_;
-}
-
-bool ResourceProvider::RasterBuffer::UnlockForWrite() {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "ResourceProvider::RasterBuffer::UnlockForWrite");
-
- if (locked_canvas_) {
- locked_canvas_->restoreToCount(canvas_save_count_);
- locked_canvas_ = NULL;
- }
- return DoUnlockForWrite();
-}
-
-ResourceProvider::DirectRasterBuffer::DirectRasterBuffer(
- const Resource* resource,
- ResourceProvider* resource_provider,
- bool use_distance_field_text )
- : RasterBuffer(resource, resource_provider),
- surface_generation_id_(0u),
- use_distance_field_text_(use_distance_field_text) {}
-
-ResourceProvider::DirectRasterBuffer::~DirectRasterBuffer() {}
-
-SkCanvas* ResourceProvider::DirectRasterBuffer::DoLockForWrite() {
- if (!surface_)
- surface_ = CreateSurface();
- surface_generation_id_ = surface_ ? surface_->generationID() : 0u;
- return surface_ ? surface_->getCanvas() : NULL;
-}
-
-bool ResourceProvider::DirectRasterBuffer::DoUnlockForWrite() {
- // generationID returns a non-zero, unique value corresponding to the content
- // of surface. Hence, a change since DoLockForWrite was called means the
- // surface has changed.
- return surface_ ? surface_generation_id_ != surface_->generationID() : false;
-}
-
-skia::RefPtr<SkSurface> ResourceProvider::DirectRasterBuffer::CreateSurface() {
- skia::RefPtr<SkSurface> surface;
- switch (resource()->type) {
- case GLTexture: {
- DCHECK(resource()->gl_id);
- class GrContext* gr_context = resource_provider()->GrContext();
- if (gr_context) {
- GrBackendTextureDesc desc;
- desc.fFlags = kRenderTarget_GrBackendTextureFlag;
- desc.fWidth = resource()->size.width();
- desc.fHeight = resource()->size.height();
- desc.fConfig = ToGrPixelConfig(resource()->format);
- desc.fOrigin = kTopLeft_GrSurfaceOrigin;
- desc.fTextureHandle = resource()->gl_id;
- skia::RefPtr<GrTexture> gr_texture =
- skia::AdoptRef(gr_context->wrapBackendTexture(desc));
- SkSurface::TextRenderMode text_render_mode =
- use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode
- : SkSurface::kStandard_TextRenderMode;
- surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
- gr_texture->asRenderTarget(), text_render_mode));
- }
- break;
- }
- case Bitmap: {
- DCHECK(resource()->pixels);
- DCHECK_EQ(RGBA_8888, resource()->format);
- SkImageInfo image_info = SkImageInfo::MakeN32Premul(
- resource()->size.width(), resource()->size.height());
- surface = skia::AdoptRef(SkSurface::NewRasterDirect(
- image_info, resource()->pixels, image_info.minRowBytes()));
- break;
- }
- default:
- NOTREACHED();
- }
- return surface;
-}
-
-ResourceProvider::BitmapRasterBuffer::BitmapRasterBuffer(
- const Resource* resource,
- ResourceProvider* resource_provider)
- : RasterBuffer(resource, resource_provider),
- mapped_buffer_(NULL),
- raster_bitmap_generation_id_(0u) {}
-
-ResourceProvider::BitmapRasterBuffer::~BitmapRasterBuffer() {}
-
-SkCanvas* ResourceProvider::BitmapRasterBuffer::DoLockForWrite() {
- DCHECK(!mapped_buffer_);
- DCHECK(!raster_canvas_);
-
- int stride = 0;
- mapped_buffer_ = MapBuffer(&stride);
- if (!mapped_buffer_)
- return NULL;
-
- switch (resource()->format) {
- case RGBA_4444:
- // Use the default stride if we will eventually convert this
- // bitmap to 4444.
- raster_bitmap_.allocN32Pixels(resource()->size.width(),
- resource()->size.height());
- break;
- case RGBA_8888:
- case BGRA_8888: {
- SkImageInfo info = SkImageInfo::MakeN32Premul(resource()->size.width(),
- resource()->size.height());
- if (0 == stride)
- stride = info.minRowBytes();
- raster_bitmap_.installPixels(info, mapped_buffer_, stride);
- break;
- }
- case LUMINANCE_8:
- case RGB_565:
- case ETC1:
- NOTREACHED();
- break;
- }
- raster_canvas_ = skia::AdoptRef(new SkCanvas(raster_bitmap_));
- raster_bitmap_generation_id_ = raster_bitmap_.getGenerationID();
- return raster_canvas_.get();
-}
-
-bool ResourceProvider::BitmapRasterBuffer::DoUnlockForWrite() {
- raster_canvas_.clear();
-
- // getGenerationID returns a non-zero, unique value corresponding to the
- // pixels in bitmap. Hence, a change since DoLockForWrite was called means the
- // bitmap has changed.
- bool raster_bitmap_changed =
- raster_bitmap_generation_id_ != raster_bitmap_.getGenerationID();
-
- if (raster_bitmap_changed) {
- SkColorType buffer_colorType =
- ResourceFormatToSkColorType(resource()->format);
- if (mapped_buffer_ && (buffer_colorType != raster_bitmap_.colorType()))
- CopyBitmap(raster_bitmap_, mapped_buffer_, buffer_colorType);
- }
- raster_bitmap_.reset();
-
- UnmapBuffer();
- mapped_buffer_ = NULL;
- return raster_bitmap_changed;
-}
-
-ResourceProvider::ImageRasterBuffer::ImageRasterBuffer(
- const Resource* resource,
- ResourceProvider* resource_provider)
- : BitmapRasterBuffer(resource, resource_provider) {}
-
-ResourceProvider::ImageRasterBuffer::~ImageRasterBuffer() {}
-
-uint8_t* ResourceProvider::ImageRasterBuffer::MapBuffer(int* stride) {
- return resource_provider()->MapImage(resource(), stride);
-}
-
-void ResourceProvider::ImageRasterBuffer::UnmapBuffer() {
- resource_provider()->UnmapImage(resource());
-}
-
-ResourceProvider::PixelRasterBuffer::PixelRasterBuffer(
- const Resource* resource,
- ResourceProvider* resource_provider)
- : BitmapRasterBuffer(resource, resource_provider) {}
-
-ResourceProvider::PixelRasterBuffer::~PixelRasterBuffer() {}
-
-uint8_t* ResourceProvider::PixelRasterBuffer::MapBuffer(int* stride) {
- return resource_provider()->MapPixelBuffer(resource(), stride);
-}
-
-void ResourceProvider::PixelRasterBuffer::UnmapBuffer() {
- resource_provider()->UnmapPixelBuffer(resource());
-}
-
ResourceProvider::Child::Child() : marked_for_deletion(false) {}
ResourceProvider::Child::~Child() {}
@@ -596,17 +411,19 @@ ResourceProvider::Child::~Child() {}
scoped_ptr<ResourceProvider> ResourceProvider::Create(
OutputSurface* output_surface,
SharedBitmapManager* shared_bitmap_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
bool use_rgba_4444_texture_format,
- size_t id_allocation_chunk_size,
- bool use_distance_field_text) {
+ size_t id_allocation_chunk_size) {
scoped_ptr<ResourceProvider> resource_provider(
new ResourceProvider(output_surface,
shared_bitmap_manager,
+ gpu_memory_buffer_manager,
+ blocking_main_thread_task_runner,
highp_threshold_min,
use_rgba_4444_texture_format,
- id_allocation_chunk_size,
- use_distance_field_text));
+ id_allocation_chunk_size));
if (resource_provider->ContextGL())
resource_provider->InitializeGL();
@@ -645,7 +462,7 @@ bool ResourceProvider::AllowOverlay(ResourceId id) {
ResourceProvider::ResourceId ResourceProvider::CreateResource(
const gfx::Size& size,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format) {
DCHECK(!size.IsEmpty());
switch (default_resource_type_) {
@@ -671,7 +488,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
const gfx::Size& size,
GLenum target,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format) {
DCHECK(!size.IsEmpty());
switch (default_resource_type_) {
@@ -698,7 +515,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
GLenum target,
GLenum texture_pool,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format) {
DCHECK_LE(size.width(), max_texture_size_);
DCHECK_LE(size.height(), max_texture_size_);
@@ -757,7 +574,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
GL_LINEAR,
GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
GL_CLAMP_TO_EDGE,
- TextureUsageAny,
+ TextureHintImmutable,
RGBA_8888);
LazyCreate(&resource);
GLES2Interface* gl = ContextGL();
@@ -772,7 +589,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface(
ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
const TextureMailbox& mailbox,
- scoped_ptr<SingleReleaseCallback> release_callback) {
+ scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) {
DCHECK(thread_checker_.CalledOnValidThread());
// Just store the information. Mailbox will be consumed in LockForRead().
ResourceId id = next_id_++;
@@ -786,7 +603,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
GL_LINEAR,
0,
GL_CLAMP_TO_EDGE,
- TextureUsageAny,
+ TextureHintImmutable,
RGBA_8888);
} else {
DCHECK(mailbox.IsSharedMemory());
@@ -808,9 +625,9 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
}
resource.allocated = true;
resource.mailbox = mailbox;
- resource.release_callback =
- base::Bind(&SingleReleaseCallback::Run,
- base::Owned(release_callback.release()));
+ resource.release_callback_impl =
+ base::Bind(&SingleReleaseCallbackImpl::Run,
+ base::Owned(release_callback_impl.release()));
resource.allow_overlay = mailbox.allow_overlay();
return id;
}
@@ -842,10 +659,6 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
if (style == ForShutdown && resource->exported_count > 0)
lost_resource = true;
- resource->direct_raster_buffer.reset();
- resource->image_raster_buffer.reset();
- resource->pixel_raster_buffer.reset();
-
if (resource->image_id) {
DCHECK(resource->origin == Resource::Internal);
GLES2Interface* gl = ContextGL();
@@ -894,7 +707,8 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
resource->shared_bitmap = NULL;
}
}
- resource->release_callback.Run(sync_point, lost_resource);
+ resource->release_callback_impl.Run(
+ sync_point, lost_resource, blocking_main_thread_task_runner_);
}
if (resource->gl_id) {
GLES2Interface* gl = ContextGL();
@@ -911,6 +725,12 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
if (resource->pixels) {
DCHECK(resource->origin == Resource::Internal);
delete[] resource->pixels;
+ resource->pixels = NULL;
+ }
+ if (resource->gpu_memory_buffer) {
+ DCHECK(resource->origin == Resource::Internal);
+ delete resource->gpu_memory_buffer;
+ resource->gpu_memory_buffer = NULL;
}
resources_.erase(it);
}
@@ -1027,30 +847,6 @@ base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
}
-void ResourceProvider::Flush() {
- DCHECK(thread_checker_.CalledOnValidThread());
- GLES2Interface* gl = ContextGL();
- if (gl)
- gl->Flush();
-}
-
-void ResourceProvider::Finish() {
- DCHECK(thread_checker_.CalledOnValidThread());
- GLES2Interface* gl = ContextGL();
- if (gl)
- gl->Finish();
-}
-
-bool ResourceProvider::ShallowFlushIfSupported() {
- DCHECK(thread_checker_.CalledOnValidThread());
- GLES2Interface* gl = ContextGL();
- if (!gl)
- return false;
-
- gl->ShallowFlushCHROMIUM();
- return true;
-}
-
ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
DCHECK(thread_checker_.CalledOnValidThread());
ResourceMap::iterator it = resources_.find(id);
@@ -1073,12 +869,13 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
if (resource->type == GLTexture && !resource->gl_id) {
DCHECK(resource->origin != Resource::Internal);
DCHECK(resource->mailbox.IsTexture());
+
+ // Mailbox sync_points must be processed by a call to
+ // WaitSyncPointIfNeeded() prior to calling LockForRead().
+ DCHECK(!resource->mailbox.sync_point());
+
GLES2Interface* gl = ContextGL();
DCHECK(gl);
- if (resource->mailbox.sync_point()) {
- GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
- resource->mailbox.set_sync_point(0);
- }
resource->gl_id = texture_id_allocator_->NextId();
GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
GLC(gl,
@@ -1098,8 +895,11 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
}
resource->lock_for_read_count++;
- if (resource->enable_read_lock_fences)
+ if (resource->read_lock_fences_enabled) {
+ if (current_read_lock_fence_.get())
+ current_read_lock_fence_->Set();
resource->read_lock_fence = current_read_lock_fence_;
+ }
return resource;
}
@@ -1126,16 +926,9 @@ void ResourceProvider::UnlockForRead(ResourceId id) {
}
}
-const ResourceProvider::Resource* ResourceProvider::LockForWrite(
- ResourceId id) {
+ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
Resource* resource = GetResource(id);
- DCHECK(!resource->locked_for_write);
- DCHECK(!resource->lock_for_read_count);
- DCHECK_EQ(resource->exported_count, 0);
- DCHECK(resource->origin == Resource::Internal);
- DCHECK(!resource->lost);
- DCHECK(ReadLockFenceHasPassed(resource));
- LazyAllocate(resource);
+ DCHECK(CanLockForWrite(id));
resource->locked_for_write = true;
return resource;
@@ -1148,8 +941,7 @@ bool ResourceProvider::CanLockForWrite(ResourceId id) {
!resource->lost && ReadLockFenceHasPassed(resource);
}
-void ResourceProvider::UnlockForWrite(ResourceId id) {
- Resource* resource = GetResource(id);
+void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
DCHECK(resource->locked_for_write);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(resource->origin == Resource::Internal);
@@ -1195,13 +987,14 @@ ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
- resource_id_(resource_id),
- texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
+ resource_(resource_provider->LockForWrite(resource_id)) {
+ resource_provider_->LazyAllocate(resource_);
+ texture_id_ = resource_->gl_id;
DCHECK(texture_id_);
}
ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
- resource_provider_->UnlockForWrite(resource_id_);
+ resource_provider_->UnlockForWrite(resource_);
}
void ResourceProvider::PopulateSkBitmapWithResource(
@@ -1230,39 +1023,174 @@ ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
- resource_id_(resource_id) {
- ResourceProvider::PopulateSkBitmapWithResource(
- &sk_bitmap_, resource_provider->LockForWrite(resource_id));
+ resource_(resource_provider->LockForWrite(resource_id)) {
+ ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
DCHECK(valid());
sk_canvas_.reset(new SkCanvas(sk_bitmap_));
}
ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
- resource_provider_->UnlockForWrite(resource_id_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ resource_provider_->UnlockForWrite(resource_);
+}
+
+ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
+ ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
+ ResourceProvider::ResourceId resource_id)
+ : resource_provider_(resource_provider),
+ resource_(resource_provider->LockForWrite(resource_id)),
+ gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
+ gpu_memory_buffer_(nullptr),
+ size_(resource_->size),
+ format_(resource_->format) {
+ DCHECK_EQ(GLTexture, resource_->type);
+ std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
+}
+
+ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
+ ~ScopedWriteLockGpuMemoryBuffer() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ resource_provider_->UnlockForWrite(resource_);
+ if (!gpu_memory_buffer_)
+ return;
+
+ if (!resource_->image_id) {
+ GLES2Interface* gl = resource_provider_->ContextGL();
+ DCHECK(gl);
+
+ resource_->image_id =
+ gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
+ size_.width(),
+ size_.height(),
+ GL_RGBA);
+ }
+
+ std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
+ resource_->allocated = true;
+ resource_->dirty_image = true;
+
+ // GpuMemoryBuffer provides direct access to the memory used by the GPU.
+ // Read lock fences are required to ensure that we're not trying to map a
+ // buffer that is currently in-use by the GPU.
+ resource_->read_lock_fences_enabled = true;
+}
+
+gfx::GpuMemoryBuffer*
+ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
+ if (!gpu_memory_buffer_) {
+ scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
+ gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
+ size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP);
+ gpu_memory_buffer_ = gpu_memory_buffer.release();
+ }
+
+ return gpu_memory_buffer_;
+}
+
+ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
+ ResourceProvider* resource_provider,
+ ResourceProvider::ResourceId resource_id)
+ : resource_provider_(resource_provider),
+ resource_(resource_provider->LockForWrite(resource_id)) {
+}
+
+ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ resource_provider_->UnlockForWrite(resource_);
}
-ResourceProvider::ResourceProvider(OutputSurface* output_surface,
- SharedBitmapManager* shared_bitmap_manager,
- int highp_threshold_min,
- bool use_rgba_4444_texture_format,
- size_t id_allocation_chunk_size,
- bool use_distance_field_text)
+SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface(
+ bool use_distance_field_text) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(resource_->locked_for_write);
+
+ // If the surface doesn't exist, or doesn't have the correct dff setting,
+ // recreate the surface within the resource.
+ if (!resource_->sk_surface ||
+ use_distance_field_text !=
+ resource_->sk_surface->props().isUseDistanceFieldFonts()) {
+ class GrContext* gr_context = resource_provider_->GrContext();
+ // TODO(alokp): Implement TestContextProvider::GrContext().
+ if (!gr_context)
+ return nullptr;
+
+ resource_provider_->LazyAllocate(resource_);
+
+ GrBackendTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrBackendTextureFlag;
+ desc.fWidth = resource_->size.width();
+ desc.fHeight = resource_->size.height();
+ desc.fConfig = ToGrPixelConfig(resource_->format);
+ desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+ desc.fTextureHandle = resource_->gl_id;
+ skia::RefPtr<GrTexture> gr_texture =
+ skia::AdoptRef(gr_context->wrapBackendTexture(desc));
+ if (!gr_texture)
+ return nullptr;
+ SkSurface::TextRenderMode text_render_mode =
+ use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode
+ : SkSurface::kStandard_TextRenderMode;
+ resource_->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
+ gr_texture->asRenderTarget(), text_render_mode));
+ }
+ return resource_->sk_surface.get();
+}
+
+ResourceProvider::SynchronousFence::SynchronousFence(
+ gpu::gles2::GLES2Interface* gl)
+ : gl_(gl), has_synchronized_(true) {
+}
+
+ResourceProvider::SynchronousFence::~SynchronousFence() {
+}
+
+void ResourceProvider::SynchronousFence::Set() {
+ has_synchronized_ = false;
+}
+
+bool ResourceProvider::SynchronousFence::HasPassed() {
+ if (!has_synchronized_) {
+ has_synchronized_ = true;
+ Synchronize();
+ }
+ return true;
+}
+
+void ResourceProvider::SynchronousFence::Wait() {
+ HasPassed();
+}
+
+void ResourceProvider::SynchronousFence::Synchronize() {
+ TRACE_EVENT0("cc", "ResourceProvider::SynchronousFence::Synchronize");
+ gl_->Finish();
+}
+
+ResourceProvider::ResourceProvider(
+ OutputSurface* output_surface,
+ SharedBitmapManager* shared_bitmap_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ BlockingTaskRunner* blocking_main_thread_task_runner,
+ int highp_threshold_min,
+ bool use_rgba_4444_texture_format,
+ size_t id_allocation_chunk_size)
: output_surface_(output_surface),
shared_bitmap_manager_(shared_bitmap_manager),
+ gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
+ blocking_main_thread_task_runner_(blocking_main_thread_task_runner),
lost_output_surface_(false),
highp_threshold_min_(highp_threshold_min),
next_id_(1),
next_child_(1),
default_resource_type_(InvalidType),
use_texture_storage_ext_(false),
+ use_texture_format_bgra_(false),
use_texture_usage_hint_(false),
use_compressed_texture_etc1_(false),
max_texture_size_(0),
best_texture_format_(RGBA_8888),
use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
id_allocation_chunk_size_(id_allocation_chunk_size),
- use_sync_query_(false),
- use_distance_field_text_(use_distance_field_text) {
+ use_sync_query_(false) {
DCHECK(output_surface_->HasClient());
DCHECK(id_allocation_chunk_size_);
}
@@ -1293,6 +1221,7 @@ void ResourceProvider::InitializeGL() {
bool use_bgra = caps.gpu.texture_format_bgra8888;
use_texture_storage_ext_ = caps.gpu.texture_storage;
+ use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888;
use_texture_usage_hint_ = caps.gpu.texture_usage;
use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1;
use_sync_query_ = caps.gpu.sync_query;
@@ -1330,10 +1259,10 @@ void ResourceProvider::CleanUpGLIfNeeded() {
}
#endif // DCHECK_IS_ON
- texture_uploader_.reset();
- texture_id_allocator_.reset();
- buffer_id_allocator_.reset();
- Finish();
+ texture_uploader_ = nullptr;
+ texture_id_allocator_ = nullptr;
+ buffer_id_allocator_ = nullptr;
+ gl->Finish();
}
int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
@@ -1434,7 +1363,8 @@ void ResourceProvider::ReceiveFromChild(
TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
ReturnedResourceArray to_return;
to_return.push_back(it->ToReturnedResource());
- child_info.return_callback.Run(to_return);
+ child_info.return_callback.Run(to_return,
+ blocking_main_thread_task_runner_);
continue;
}
@@ -1454,7 +1384,7 @@ void ResourceProvider::ReceiveFromChild(
it->filter,
0,
it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE,
- TextureUsageAny,
+ TextureHintImmutable,
it->format);
resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox,
it->mailbox_holder.texture_target,
@@ -1464,6 +1394,7 @@ void ResourceProvider::ReceiveFromChild(
// Don't allocate a texture for a child.
resource.allocated = true;
resource.imported_count = 1;
+ resource.allow_overlay = it->allow_overlay;
child_info.parent_to_child_map[local_id] = it->id;
child_info.child_to_parent_map[it->id] = local_id;
}
@@ -1521,7 +1452,7 @@ void ResourceProvider::ReceiveReturnsFromParent(
int child_id = 0;
ResourceIdArray resources_for_child;
- std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
+ std::vector<std::pair<ReturnedResource, ResourceMap::iterator>>
sorted_resources;
for (ReturnedResourceArray::const_iterator it = resources.begin();
@@ -1558,8 +1489,11 @@ void ResourceProvider::ReceiveReturnsFromParent(
// Need to wait for the current read lock fence to pass before we can
// recycle this resource.
- if (resource->enable_read_lock_fences)
+ if (resource->read_lock_fences_enabled) {
+ if (current_read_lock_fence_.get())
+ current_read_lock_fence_->Set();
resource->read_lock_fence = current_read_lock_fence_;
+ }
if (returned.sync_point) {
DCHECK(!resource->has_shared_bitmap_id);
@@ -1621,6 +1555,7 @@ void ResourceProvider::TransferResource(GLES2Interface* gl,
resource->filter = source->filter;
resource->size = source->size;
resource->is_repeated = (source->wrap_mode == GL_REPEAT);
+ resource->allow_overlay = source->allow_overlay;
if (source->type == Bitmap) {
resource->mailbox_holder.mailbox = source->shared_bitmap_id;
@@ -1744,7 +1679,8 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
}
if (!to_return.empty())
- child_info->return_callback.Run(to_return);
+ child_info->return_callback.Run(to_return,
+ blocking_main_thread_task_runner_);
if (child_info->marked_for_deletion &&
child_info->parent_to_child_map.empty()) {
@@ -1753,67 +1689,11 @@ void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
}
}
-SkCanvas* ResourceProvider::MapDirectRasterBuffer(ResourceId id) {
- // Resource needs to be locked for write since DirectRasterBuffer writes
- // directly to it.
- LockForWrite(id);
- Resource* resource = GetResource(id);
- if (!resource->direct_raster_buffer.get()) {
- resource->direct_raster_buffer.reset(
- new DirectRasterBuffer(resource, this, use_distance_field_text_));
- }
- return resource->direct_raster_buffer->LockForWrite();
-}
-
-void ResourceProvider::UnmapDirectRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- DCHECK(resource->direct_raster_buffer.get());
- resource->direct_raster_buffer->UnlockForWrite();
- UnlockForWrite(id);
-}
-
-SkCanvas* ResourceProvider::MapImageRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- AcquireImage(resource);
- if (!resource->image_raster_buffer.get())
- resource->image_raster_buffer.reset(new ImageRasterBuffer(resource, this));
- return resource->image_raster_buffer->LockForWrite();
-}
-
-bool ResourceProvider::UnmapImageRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- resource->dirty_image = true;
- return resource->image_raster_buffer->UnlockForWrite();
-}
-
-void ResourceProvider::AcquirePixelRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- AcquirePixelBuffer(resource);
- resource->pixel_raster_buffer.reset(new PixelRasterBuffer(resource, this));
-}
-
-void ResourceProvider::ReleasePixelRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- resource->pixel_raster_buffer.reset();
- ReleasePixelBuffer(resource);
-}
-
-SkCanvas* ResourceProvider::MapPixelRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- DCHECK(resource->pixel_raster_buffer.get());
- return resource->pixel_raster_buffer->LockForWrite();
-}
-
-bool ResourceProvider::UnmapPixelRasterBuffer(ResourceId id) {
- Resource* resource = GetResource(id);
- DCHECK(resource->pixel_raster_buffer.get());
- return resource->pixel_raster_buffer->UnlockForWrite();
-}
-
-void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
+void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"ResourceProvider::AcquirePixelBuffer");
+ Resource* resource = GetResource(id);
DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
@@ -1835,10 +1715,11 @@ void ResourceProvider::AcquirePixelBuffer(Resource* resource) {
gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
-void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
+void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"ResourceProvider::ReleasePixelBuffer");
+ Resource* resource = GetResource(id);
DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
@@ -1867,11 +1748,11 @@ void ResourceProvider::ReleasePixelBuffer(Resource* resource) {
gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
-uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
- int* stride) {
+uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"ResourceProvider::MapPixelBuffer");
+ Resource* resource = GetResource(id);
DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
@@ -1891,10 +1772,11 @@ uint8_t* ResourceProvider::MapPixelBuffer(const Resource* resource,
return image;
}
-void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
+void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"ResourceProvider::UnmapPixelBuffer");
+ Resource* resource = GetResource(id);
DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
@@ -1909,10 +1791,9 @@ void ResourceProvider::UnmapPixelBuffer(const Resource* resource) {
gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
-GLenum ResourceProvider::BindForSampling(
- ResourceProvider::ResourceId resource_id,
- GLenum unit,
- GLenum filter) {
+GLenum ResourceProvider::BindForSampling(ResourceId resource_id,
+ GLenum unit,
+ GLenum filter) {
DCHECK(thread_checker_.CalledOnValidThread());
GLES2Interface* gl = ContextGL();
ResourceMap::iterator it = resources_.find(resource_id);
@@ -1999,6 +1880,7 @@ void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
"ResourceProvider::ForceSetPixelsToComplete");
Resource* resource = GetResource(id);
+
DCHECK(resource->locked_for_write);
DCHECK(resource->pending_set_pixels);
DCHECK(!resource->set_pixels_completion_forced);
@@ -2018,6 +1900,7 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
"ResourceProvider::DidSetPixelsComplete");
Resource* resource = GetResource(id);
+
DCHECK(resource->locked_for_write);
DCHECK(resource->pending_set_pixels);
@@ -2033,7 +1916,12 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
}
resource->pending_set_pixels = false;
- UnlockForWrite(id);
+ UnlockForWrite(resource);
+
+ // Async set pixels commands are not necessarily processed in-sequence with
+ // drawing commands. Read lock fences are required to ensure that async
+ // commands don't access the resource while used for drawing.
+ resource->read_lock_fences_enabled = true;
return true;
}
@@ -2065,9 +1953,11 @@ void ResourceProvider::LazyCreate(Resource* resource) {
// Create and set texture properties. Allocation is delayed until needed.
GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
GLC(gl,
- gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ gl->TexParameteri(
+ resource->target, GL_TEXTURE_MIN_FILTER, resource->original_filter));
GLC(gl,
- gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ gl->TexParameteri(
+ resource->target, GL_TEXTURE_MAG_FILTER, resource->original_filter));
GLC(gl,
gl->TexParameteri(
resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
@@ -2077,7 +1967,7 @@ void ResourceProvider::LazyCreate(Resource* resource) {
GLC(gl,
gl->TexParameteri(
resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
- if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
+ if (use_texture_usage_hint_ && (resource->hint & TextureHintFramebuffer)) {
GLC(gl,
gl->TexParameteri(resource->target,
GL_TEXTURE_USAGE_ANGLE,
@@ -2091,10 +1981,10 @@ void ResourceProvider::AllocateForTesting(ResourceId id) {
void ResourceProvider::LazyAllocate(Resource* resource) {
DCHECK(resource);
+ if (resource->allocated)
+ return;
LazyCreate(resource);
-
- DCHECK(resource->gl_id || resource->allocated);
- if (resource->allocated || !resource->gl_id)
+ if (!resource->gl_id)
return;
resource->allocated = true;
GLES2Interface* gl = ContextGL();
@@ -2102,8 +1992,9 @@ void ResourceProvider::LazyAllocate(Resource* resource) {
DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
ResourceFormat format = resource->format;
GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
- if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
- resource->hint != TextureUsageFramebuffer) {
+ if (use_texture_storage_ext_ &&
+ IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
+ (resource->hint & TextureHintImmutable)) {
GLenum storage_format = TextureToStorageFormat(format);
GLC(gl,
gl->TexStorage2DEXT(
@@ -2138,81 +2029,6 @@ void ResourceProvider::BindImageForSampling(Resource* resource) {
resource->dirty_image = false;
}
-void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
- bool enable) {
- Resource* resource = GetResource(id);
- resource->enable_read_lock_fences = enable;
-}
-
-void ResourceProvider::AcquireImage(Resource* resource) {
- DCHECK(resource->origin == Resource::Internal);
- DCHECK_EQ(resource->exported_count, 0);
-
- if (resource->type != GLTexture)
- return;
-
- if (resource->image_id)
- return;
-
- resource->allocated = true;
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- resource->image_id =
- gl->CreateImageCHROMIUM(resource->size.width(),
- resource->size.height(),
- TextureToStorageFormat(resource->format),
- GL_IMAGE_MAP_CHROMIUM);
- DCHECK(resource->image_id);
-}
-
-void ResourceProvider::ReleaseImage(Resource* resource) {
- DCHECK(resource->origin == Resource::Internal);
- DCHECK_EQ(resource->exported_count, 0);
-
- if (!resource->image_id)
- return;
-
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- gl->DestroyImageCHROMIUM(resource->image_id);
- resource->image_id = 0;
- resource->bound_image_id = 0;
- resource->dirty_image = false;
- resource->allocated = false;
-}
-
-uint8_t* ResourceProvider::MapImage(const Resource* resource, int* stride) {
- DCHECK(ReadLockFenceHasPassed(resource));
- DCHECK(resource->origin == Resource::Internal);
- DCHECK_EQ(resource->exported_count, 0);
-
- if (resource->type == GLTexture) {
- DCHECK(resource->image_id);
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM.
- uint8_t* pixels =
- static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id));
- gl->GetImageParameterivCHROMIUM(
- resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride);
- return pixels;
- }
- DCHECK_EQ(Bitmap, resource->type);
- *stride = 0;
- return resource->pixels;
-}
-
-void ResourceProvider::UnmapImage(const Resource* resource) {
- DCHECK(resource->origin == Resource::Internal);
- DCHECK_EQ(resource->exported_count, 0);
-
- if (resource->image_id) {
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- gl->UnmapImageCHROMIUM(resource->image_id);
- }
-}
-
void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
TRACE_EVENT0("cc", "ResourceProvider::CopyResource");
@@ -2220,6 +2036,7 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
DCHECK(!source_resource->lock_for_read_count);
DCHECK(source_resource->origin == Resource::Internal);
DCHECK_EQ(source_resource->exported_count, 0);
+ DCHECK_EQ(GLTexture, source_resource->type);
DCHECK(source_resource->allocated);
LazyCreate(source_resource);
@@ -2228,47 +2045,75 @@ void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) {
DCHECK(!dest_resource->lock_for_read_count);
DCHECK(dest_resource->origin == Resource::Internal);
DCHECK_EQ(dest_resource->exported_count, 0);
+ DCHECK_EQ(GLTexture, dest_resource->type);
LazyCreate(dest_resource);
DCHECK_EQ(source_resource->type, dest_resource->type);
DCHECK_EQ(source_resource->format, dest_resource->format);
DCHECK(source_resource->size == dest_resource->size);
- if (source_resource->type == GLTexture) {
- GLES2Interface* gl = ContextGL();
- DCHECK(gl);
- if (source_resource->image_id && source_resource->dirty_image) {
- gl->BindTexture(source_resource->target, source_resource->gl_id);
- BindImageForSampling(source_resource);
- }
- DCHECK(use_sync_query_) << "CHROMIUM_sync_query extension missing";
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ if (source_resource->image_id && source_resource->dirty_image) {
+ gl->BindTexture(source_resource->target, source_resource->gl_id);
+ BindImageForSampling(source_resource);
+ }
+ if (use_sync_query_) {
if (!source_resource->gl_read_lock_query_id)
gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id);
gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
source_resource->gl_read_lock_query_id);
- DCHECK(!dest_resource->image_id);
- dest_resource->allocated = true;
- gl->CopyTextureCHROMIUM(dest_resource->target,
- source_resource->gl_id,
- dest_resource->gl_id,
- 0,
- GLInternalFormat(dest_resource->format),
- GLDataType(dest_resource->format));
+ }
+ DCHECK(!dest_resource->image_id);
+ dest_resource->allocated = true;
+ gl->CopyTextureCHROMIUM(dest_resource->target,
+ source_resource->gl_id,
+ dest_resource->gl_id,
+ 0,
+ GLInternalFormat(dest_resource->format),
+ GLDataType(dest_resource->format));
+ if (source_resource->gl_read_lock_query_id) {
// End query and create a read lock fence that will prevent access to
// source resource until CopyTextureCHROMIUM command has completed.
gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
source_resource->read_lock_fence = make_scoped_refptr(
new QueryFence(gl, source_resource->gl_read_lock_query_id));
} else {
- DCHECK_EQ(Bitmap, source_resource->type);
- DCHECK_EQ(RGBA_8888, source_resource->format);
- LazyAllocate(dest_resource);
-
- size_t bytes = SharedBitmap::CheckedSizeInBytes(source_resource->size);
- memcpy(dest_resource->pixels, source_resource->pixels, bytes);
+ // Create a SynchronousFence when CHROMIUM_sync_query extension is missing.
+ // Try to use one synchronous fence for as many CopyResource operations as
+ // possible as that reduce the number of times we have to synchronize with
+ // the GL.
+ if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized())
+ synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl));
+ source_resource->read_lock_fence = synchronous_fence_;
+ source_resource->read_lock_fence->Set();
}
}
+void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) {
+ Resource* resource = GetResource(id);
+ DCHECK_EQ(resource->exported_count, 0);
+ DCHECK(resource->allocated);
+ if (resource->type != GLTexture || resource->gl_id)
+ return;
+ if (!resource->mailbox.sync_point())
+ return;
+ DCHECK(resource->mailbox.IsValid());
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
+ resource->mailbox.set_sync_point(0);
+}
+
+void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) {
+ Resource* resource = GetResource(id);
+ DCHECK_EQ(resource->exported_count, 0);
+ if (!resource->read_lock_fence.get())
+ return;
+
+ resource->read_lock_fence->Wait();
+}
+
GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
GLint active_unit = 0;
gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
diff --git a/chromium/cc/resources/resource_provider.h b/chromium/cc/resources/resource_provider.h
index 1d991e2b144..40103f6b3e3 100644
--- a/chromium/cc/resources/resource_provider.h
+++ b/chromium/cc/resources/resource_provider.h
@@ -20,33 +20,36 @@
#include "cc/base/cc_export.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
-#include "cc/resources/release_callback.h"
+#include "cc/resources/release_callback_impl.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/return_callback.h"
#include "cc/resources/shared_bitmap.h"
-#include "cc/resources/single_release_callback.h"
+#include "cc/resources/single_release_callback_impl.h"
#include "cc/resources/texture_mailbox.h"
#include "cc/resources/transferable_resource.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
class GrContext;
namespace gpu {
+class GpuMemoryBufferManager;
namespace gles {
class GLES2Interface;
}
}
namespace gfx {
+class GpuMemoryBuffer;
class Rect;
class Vector2d;
}
namespace cc {
+class BlockingTaskRunner;
class IdAllocator;
class SharedBitmap;
class SharedBitmapManager;
@@ -55,14 +58,20 @@ class TextureUploader;
// This class is not thread-safe and can only be called from the thread it was
// created on (in practice, the impl thread).
class CC_EXPORT ResourceProvider {
+ private:
+ struct Resource;
+
public:
typedef unsigned ResourceId;
typedef std::vector<ResourceId> ResourceIdArray;
typedef std::set<ResourceId> ResourceIdSet;
typedef base::hash_map<ResourceId, ResourceId> ResourceIdMap;
- enum TextureUsageHint {
- TextureUsageAny,
- TextureUsageFramebuffer,
+ enum TextureHint {
+ TextureHintDefault = 0x0,
+ TextureHintImmutable = 0x1,
+ TextureHintFramebuffer = 0x2,
+ TextureHintImmutableFramebuffer =
+ TextureHintImmutable | TextureHintFramebuffer
};
enum ResourceType {
InvalidType = 0,
@@ -73,10 +82,11 @@ class CC_EXPORT ResourceProvider {
static scoped_ptr<ResourceProvider> Create(
OutputSurface* output_surface,
SharedBitmapManager* shared_bitmap_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
bool use_rgba_4444_texture_format,
- size_t id_allocation_chunk_size,
- bool use_distance_field_text);
+ size_t id_allocation_chunk_size);
virtual ~ResourceProvider();
void InitializeSoftware();
@@ -106,7 +116,7 @@ class CC_EXPORT ResourceProvider {
// Creates a resource of the default resource type.
ResourceId CreateResource(const gfx::Size& size,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format);
// Creates a resource which is tagged as being managed for GPU memory
@@ -114,7 +124,7 @@ class CC_EXPORT ResourceProvider {
ResourceId CreateManagedResource(const gfx::Size& size,
GLenum target,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format);
// You can also explicitly create a specific resource type.
@@ -122,7 +132,7 @@ class CC_EXPORT ResourceProvider {
GLenum target,
GLenum texture_pool,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format);
ResourceId CreateBitmap(const gfx::Size& size, GLint wrap_mode);
@@ -133,7 +143,7 @@ class CC_EXPORT ResourceProvider {
// Wraps an external texture mailbox into a GL resource.
ResourceId CreateResourceFromTextureMailbox(
const TextureMailbox& mailbox,
- scoped_ptr<SingleReleaseCallback> release_callback);
+ scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl);
void DeleteResource(ResourceId id);
@@ -153,14 +163,6 @@ class CC_EXPORT ResourceProvider {
void ReleaseCachedData();
base::TimeTicks EstimatedUploadCompletionTime(size_t uploads_per_tick);
- // Flush all context operations, kicking uploads and ensuring ordering with
- // respect to other contexts.
- void Flush();
-
- // Finish all context operations, causing any pending callbacks to be
- // scheduled.
- void Finish();
-
// Only flush the command buffer if supported.
// Returns true if the shallow flush occurred, false otherwise.
bool ShallowFlushIfSupported();
@@ -238,7 +240,7 @@ class CC_EXPORT ResourceProvider {
ResourceProvider::ResourceId resource_id,
GLenum unit,
GLenum filter);
- virtual ~ScopedSamplerGL();
+ ~ScopedSamplerGL() override;
GLenum target() const { return target_; }
@@ -259,7 +261,7 @@ class CC_EXPORT ResourceProvider {
private:
ResourceProvider* resource_provider_;
- ResourceProvider::ResourceId resource_id_;
+ ResourceProvider::Resource* resource_;
unsigned texture_id_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
@@ -299,17 +301,57 @@ class CC_EXPORT ResourceProvider {
private:
ResourceProvider* resource_provider_;
- ResourceProvider::ResourceId resource_id_;
+ ResourceProvider::Resource* resource_;
SkBitmap sk_bitmap_;
scoped_ptr<SkCanvas> sk_canvas_;
+ base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware);
};
+ class CC_EXPORT ScopedWriteLockGpuMemoryBuffer {
+ public:
+ ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
+ ResourceProvider::ResourceId resource_id);
+ ~ScopedWriteLockGpuMemoryBuffer();
+
+ gfx::GpuMemoryBuffer* GetGpuMemoryBuffer();
+
+ private:
+ ResourceProvider* resource_provider_;
+ ResourceProvider::Resource* resource_;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
+ gfx::GpuMemoryBuffer* gpu_memory_buffer_;
+ gfx::Size size_;
+ ResourceFormat format_;
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer);
+ };
+
+ class CC_EXPORT ScopedWriteLockGr {
+ public:
+ ScopedWriteLockGr(ResourceProvider* resource_provider,
+ ResourceProvider::ResourceId resource_id);
+ ~ScopedWriteLockGr();
+
+ SkSurface* GetSkSurface(bool use_distance_field_text);
+
+ private:
+ ResourceProvider* resource_provider_;
+ ResourceProvider::Resource* resource_;
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGr);
+ };
+
class Fence : public base::RefCounted<Fence> {
public:
Fence() {}
+
+ virtual void Set() = 0;
virtual bool HasPassed() = 0;
+ virtual void Wait() = 0;
protected:
friend class base::RefCounted<Fence>;
@@ -319,31 +361,36 @@ class CC_EXPORT ResourceProvider {
DISALLOW_COPY_AND_ASSIGN(Fence);
};
- // Returns a canvas for direct rasterization.
- // Call Unmap before the resource can be read or used for compositing.
- // It is used for direct gpu rasterization.
- SkCanvas* MapDirectRasterBuffer(ResourceId id);
- void UnmapDirectRasterBuffer(ResourceId id);
-
- // Returns a canvas backed by an image buffer. UnmapImageRasterBuffer
- // returns true if canvas was written to while mapped.
- // Rasterizing to the canvas writes the content into the image buffer,
- // which is internally bound to the underlying resource when read.
- // Call Unmap before the resource can be read or used for compositing.
- // It is used by ImageRasterWorkerPool.
- SkCanvas* MapImageRasterBuffer(ResourceId id);
- bool UnmapImageRasterBuffer(ResourceId id);
-
- // Returns a canvas backed by pixel buffer. UnmapPixelRasterBuffer
- // returns true if canvas was written to while mapped.
- // The pixel buffer needs to be uploaded to the underlying resource
- // using BeginSetPixels before the resouce can be used for compositing.
- // It is used by PixelRasterWorkerPool.
- void AcquirePixelRasterBuffer(ResourceId id);
- void ReleasePixelRasterBuffer(ResourceId id);
- SkCanvas* MapPixelRasterBuffer(ResourceId id);
- bool UnmapPixelRasterBuffer(ResourceId id);
+ class SynchronousFence : public ResourceProvider::Fence {
+ public:
+ explicit SynchronousFence(gpu::gles2::GLES2Interface* gl);
+
+ // Overridden from Fence:
+ void Set() override;
+ bool HasPassed() override;
+ void Wait() override;
+
+ // Returns true if fence has been set but not yet synchornized.
+ bool has_synchronized() const { return has_synchronized_; }
+
+ private:
+ ~SynchronousFence() override;
+ void Synchronize();
+
+ gpu::gles2::GLES2Interface* gl_;
+ bool has_synchronized_;
+
+ DISALLOW_COPY_AND_ASSIGN(SynchronousFence);
+ };
+
+ // Acquire pixel buffer for resource. The pixel buffer can be used to
+ // set resource pixels without performing unnecessary copying.
+ void AcquirePixelBuffer(ResourceId resource);
+ void ReleasePixelBuffer(ResourceId resource);
+ // Map/unmap the acquired pixel buffer.
+ uint8_t* MapPixelBuffer(ResourceId id, int* stride);
+ void UnmapPixelBuffer(ResourceId id);
// Asynchronously update pixels from acquired pixel buffer.
void BeginSetPixels(ResourceId id);
void ForceSetPixelsToComplete(ResourceId id);
@@ -363,22 +410,19 @@ class CC_EXPORT ResourceProvider {
// until this fence has passed.
void SetReadLockFence(Fence* fence) { current_read_lock_fence_ = fence; }
- // Enable read lock fences for a specific resource.
- void EnableReadLockFences(ResourceProvider::ResourceId id, bool enable);
-
// Indicates if we can currently lock this resource for write.
bool CanLockForWrite(ResourceId id);
// Copy pixels from source to destination.
void CopyResource(ResourceId source_id, ResourceId dest_id);
+ void WaitSyncPointIfNeeded(ResourceId id);
+
+ void WaitReadLockIfNeeded(ResourceId id);
+
static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
private:
- class DirectRasterBuffer;
- class ImageRasterBuffer;
- class PixelRasterBuffer;
-
struct Resource {
enum Origin { Internal, External, Delegated };
@@ -391,7 +435,7 @@ class CC_EXPORT ResourceProvider {
GLenum filter,
GLenum texture_pool,
GLint wrap_mode,
- TextureUsageHint hint,
+ TextureHint hint,
ResourceFormat format);
Resource(uint8_t* pixels,
SharedBitmap* bitmap,
@@ -414,7 +458,7 @@ class CC_EXPORT ResourceProvider {
// Query used to determine when read lock fence has passed.
unsigned gl_read_lock_query_id;
TextureMailbox mailbox;
- ReleaseCallback release_callback;
+ ReleaseCallbackImpl release_callback_impl;
uint8_t* pixels;
int lock_for_read_count;
int imported_count;
@@ -426,7 +470,7 @@ class CC_EXPORT ResourceProvider {
bool pending_set_pixels : 1;
bool set_pixels_completion_forced : 1;
bool allocated : 1;
- bool enable_read_lock_fences : 1;
+ bool read_lock_fences_enabled : 1;
bool has_shared_bitmap_id : 1;
bool allow_overlay : 1;
scoped_refptr<Fence> read_lock_fence;
@@ -440,109 +484,16 @@ class CC_EXPORT ResourceProvider {
unsigned bound_image_id;
GLenum texture_pool;
GLint wrap_mode;
- TextureUsageHint hint;
+ TextureHint hint;
ResourceType type;
ResourceFormat format;
SharedBitmapId shared_bitmap_id;
SharedBitmap* shared_bitmap;
- linked_ptr<DirectRasterBuffer> direct_raster_buffer;
- linked_ptr<ImageRasterBuffer> image_raster_buffer;
- linked_ptr<PixelRasterBuffer> pixel_raster_buffer;
+ gfx::GpuMemoryBuffer* gpu_memory_buffer;
+ skia::RefPtr<SkSurface> sk_surface;
};
typedef base::hash_map<ResourceId, Resource> ResourceMap;
- class RasterBuffer {
- public:
- virtual ~RasterBuffer();
-
- SkCanvas* LockForWrite();
- // Returns true if canvas was written to while locked.
- bool UnlockForWrite();
-
- protected:
- RasterBuffer(const Resource* resource, ResourceProvider* resource_provider);
- const Resource* resource() const { return resource_; }
- ResourceProvider* resource_provider() const { return resource_provider_; }
-
- virtual SkCanvas* DoLockForWrite() = 0;
- virtual bool DoUnlockForWrite() = 0;
-
- private:
- const Resource* resource_;
- ResourceProvider* resource_provider_;
- SkCanvas* locked_canvas_;
- int canvas_save_count_;
- };
-
- class DirectRasterBuffer : public RasterBuffer {
- public:
- DirectRasterBuffer(const Resource* resource,
- ResourceProvider* resource_provider,
- bool use_distance_field_text);
- virtual ~DirectRasterBuffer();
-
- protected:
- virtual SkCanvas* DoLockForWrite() OVERRIDE;
- virtual bool DoUnlockForWrite() OVERRIDE;
- skia::RefPtr<SkSurface> CreateSurface();
-
- private:
- skia::RefPtr<SkSurface> surface_;
- uint32_t surface_generation_id_;
- const bool use_distance_field_text_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectRasterBuffer);
- };
-
- class BitmapRasterBuffer : public RasterBuffer {
- public:
- virtual ~BitmapRasterBuffer();
-
- protected:
- BitmapRasterBuffer(const Resource* resource,
- ResourceProvider* resource_provider);
-
- virtual SkCanvas* DoLockForWrite() OVERRIDE;
- virtual bool DoUnlockForWrite() OVERRIDE;
-
- virtual uint8_t* MapBuffer(int* stride) = 0;
- virtual void UnmapBuffer() = 0;
-
- private:
- uint8_t* mapped_buffer_;
- SkBitmap raster_bitmap_;
- uint32_t raster_bitmap_generation_id_;
- skia::RefPtr<SkCanvas> raster_canvas_;
- };
-
- class ImageRasterBuffer : public BitmapRasterBuffer {
- public:
- ImageRasterBuffer(const Resource* resource,
- ResourceProvider* resource_provider);
- virtual ~ImageRasterBuffer();
-
- protected:
- virtual uint8_t* MapBuffer(int* stride) OVERRIDE;
- virtual void UnmapBuffer() OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ImageRasterBuffer);
- };
-
- class PixelRasterBuffer : public BitmapRasterBuffer {
- public:
- PixelRasterBuffer(const Resource* resource,
- ResourceProvider* resource_provider);
- virtual ~PixelRasterBuffer();
-
- protected:
- virtual uint8_t* MapBuffer(int* stride) OVERRIDE;
- virtual void UnmapBuffer() OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PixelRasterBuffer);
- };
-
static bool CompareResourceMapIteratorsByChildId(
const std::pair<ReturnedResource, ResourceMap::iterator>& a,
const std::pair<ReturnedResource, ResourceMap::iterator>& b);
@@ -566,18 +517,20 @@ class CC_EXPORT ResourceProvider {
ResourceProvider(OutputSurface* output_surface,
SharedBitmapManager* shared_bitmap_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ BlockingTaskRunner* blocking_main_thread_task_runner,
int highp_threshold_min,
bool use_rgba_4444_texture_format,
- size_t id_allocation_chunk_size,
- bool use_distance_field_text);
+ size_t id_allocation_chunk_size);
void CleanUpGLIfNeeded();
Resource* GetResource(ResourceId id);
const Resource* LockForRead(ResourceId id);
void UnlockForRead(ResourceId id);
- const Resource* LockForWrite(ResourceId id);
- void UnlockForWrite(ResourceId id);
+ Resource* LockForWrite(ResourceId id);
+ void UnlockForWrite(Resource* resource);
+
static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
const Resource* resource);
@@ -596,32 +549,11 @@ class CC_EXPORT ResourceProvider {
void LazyCreate(Resource* resource);
void LazyAllocate(Resource* resource);
- // TODO(alokp): Move the implementation to PixelRasterBuffer.
- // Acquire pixel buffer for resource. The pixel buffer can be used to
- // set resource pixels without performing unnecessary copying.
- void AcquirePixelBuffer(Resource* resource);
- void ReleasePixelBuffer(Resource* resource);
- // Map/unmap the acquired pixel buffer.
- uint8_t* MapPixelBuffer(const Resource* resource, int* stride);
- void UnmapPixelBuffer(const Resource* resource);
-
- // TODO(alokp): Move the implementation to ImageRasterBuffer.
- // Acquire and release an image. The image allows direct
- // manipulation of texture memory.
- void AcquireImage(Resource* resource);
- void ReleaseImage(Resource* resource);
- // Maps the acquired image so that its pixels could be modified.
- // Unmap is called when all pixels are set.
- uint8_t* MapImage(const Resource* resource, int* stride);
- void UnmapImage(const Resource* resource);
-
void BindImageForSampling(Resource* resource);
// Binds the given GL resource to a texture target for sampling using the
// specified filter for both minification and magnification. Returns the
// texture target used. The resource must be locked for reading.
- GLenum BindForSampling(ResourceProvider::ResourceId resource_id,
- GLenum unit,
- GLenum filter);
+ GLenum BindForSampling(ResourceId resource_id, GLenum unit, GLenum filter);
// Returns NULL if the output_surface_ does not have a ContextProvider.
gpu::gles2::GLES2Interface* ContextGL() const;
@@ -629,6 +561,8 @@ class CC_EXPORT ResourceProvider {
OutputSurface* output_surface_;
SharedBitmapManager* shared_bitmap_manager_;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
+ BlockingTaskRunner* blocking_main_thread_task_runner_;
bool lost_output_surface_;
int highp_threshold_min_;
ResourceId next_id_;
@@ -638,6 +572,7 @@ class CC_EXPORT ResourceProvider {
ResourceType default_resource_type_;
bool use_texture_storage_ext_;
+ bool use_texture_format_bgra_;
bool use_texture_usage_hint_;
bool use_compressed_texture_etc1_;
scoped_ptr<TextureUploader> texture_uploader_;
@@ -654,8 +589,8 @@ class CC_EXPORT ResourceProvider {
scoped_ptr<IdAllocator> buffer_id_allocator_;
bool use_sync_query_;
-
- bool use_distance_field_text_;
+ // Fence used for CopyResource if CHROMIUM_sync_query is not supported.
+ scoped_refptr<SynchronousFence> synchronous_fence_;
DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
};
@@ -669,6 +604,7 @@ inline unsigned BitsPerPixel(ResourceFormat format) {
32, // RGBA_8888
16, // RGBA_4444
32, // BGRA_8888
+ 8, // ALPHA_8
8, // LUMINANCE_8
16, // RGB_565,
4 // ETC1
@@ -682,6 +618,7 @@ inline GLenum GLDataType(ResourceFormat format) {
GL_UNSIGNED_BYTE, // RGBA_8888
GL_UNSIGNED_SHORT_4_4_4_4, // RGBA_4444
GL_UNSIGNED_BYTE, // BGRA_8888
+ GL_UNSIGNED_BYTE, // ALPHA_8
GL_UNSIGNED_BYTE, // LUMINANCE_8
GL_UNSIGNED_SHORT_5_6_5, // RGB_565,
GL_UNSIGNED_BYTE // ETC1
@@ -695,6 +632,7 @@ inline GLenum GLDataFormat(ResourceFormat format) {
GL_RGBA, // RGBA_8888
GL_RGBA, // RGBA_4444
GL_BGRA_EXT, // BGRA_8888
+ GL_ALPHA, // ALPHA_8
GL_LUMINANCE, // LUMINANCE_8
GL_RGB, // RGB_565
GL_ETC1_RGB8_OES // ETC1
diff --git a/chromium/cc/resources/resource_provider_unittest.cc b/chromium/cc/resources/resource_provider_unittest.cc
index 4bf9ec0565e..e507ad67a93 100644
--- a/chromium/cc/resources/resource_provider_unittest.cc
+++ b/chromium/cc/resources/resource_provider_unittest.cc
@@ -19,15 +19,18 @@
#include "cc/resources/single_release_callback.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
+#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_texture.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "cc/trees/blocking_task_runner.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/gpu_memory_buffer.h"
using testing::Mock;
using testing::NiceMock;
@@ -39,18 +42,28 @@ using testing::_;
namespace cc {
namespace {
-static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {}
-
-static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
- uint32 sync_point,
- bool lost_resource) {}
+static void EmptyReleaseCallback(uint32 sync_point,
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner) {
+}
-static void ReleaseTextureMailbox(uint32* release_sync_point,
- bool* release_lost_resource,
- uint32 sync_point,
- bool lost_resource) {
+static void ReleaseCallback(
+ uint32* release_sync_point,
+ bool* release_lost_resource,
+ BlockingTaskRunner** release_main_thread_task_runner,
+ uint32 sync_point,
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner) {
*release_sync_point = sync_point;
*release_lost_resource = lost_resource;
+ *release_main_thread_task_runner = main_thread_task_runner;
+}
+
+static void SharedMemoryReleaseCallback(
+ scoped_ptr<base::SharedMemory> memory,
+ uint32 sync_point,
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner) {
}
static void ReleaseSharedMemoryCallback(
@@ -59,7 +72,8 @@ static void ReleaseSharedMemoryCallback(
uint32* release_sync_point,
bool* lost_resource_result,
uint32 sync_point,
- bool lost_resource) {
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner) {
*release_called = true;
*release_sync_point = sync_point;
*lost_resource_result = lost_resource;
@@ -89,11 +103,11 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D {
// Force all textures to be consecutive numbers starting at "1",
// so we easily can test for them.
- virtual GLuint NextTextureId() OVERRIDE {
+ virtual GLuint NextTextureId() override {
base::AutoLock lock(namespace_->lock);
return namespace_->next_texture_id++;
}
- virtual void RetireTextureId(GLuint) OVERRIDE {}
+ virtual void RetireTextureId(GLuint) override {}
};
// Shared data between multiple ResourceProviderContext. This contains mailbox
@@ -144,7 +158,7 @@ class ContextSharedData {
uint32 next_sync_point_;
unsigned next_mailbox_;
- typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
+ typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
TextureMap textures_;
base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
};
@@ -156,7 +170,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
return make_scoped_ptr(new ResourceProviderContext(shared_data));
}
- virtual GLuint insertSyncPoint() OVERRIDE {
+ GLuint insertSyncPoint() override {
uint32 sync_point = shared_data_->InsertSyncPoint();
// Commit the produceTextureCHROMIUM calls at this point, so that
// they're associated with the sync point.
@@ -171,17 +185,17 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
return sync_point;
}
- virtual void waitSyncPoint(GLuint sync_point) OVERRIDE {
+ void waitSyncPoint(GLuint sync_point) override {
last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
}
unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
- virtual void texStorage2DEXT(GLenum target,
- GLint levels,
- GLuint internalformat,
- GLint width,
- GLint height) OVERRIDE {
+ void texStorage2DEXT(GLenum target,
+ GLint levels,
+ GLuint internalformat,
+ GLint width,
+ GLint height) override {
CheckTextureIsBound(target);
ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
ASSERT_EQ(1, levels);
@@ -198,15 +212,15 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
AllocateTexture(gfx::Size(width, height), format);
}
- virtual void texImage2D(GLenum target,
- GLint level,
- GLenum internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void* pixels) OVERRIDE {
+ void texImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void* pixels) override {
CheckTextureIsBound(target);
ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
ASSERT_FALSE(level);
@@ -218,15 +232,15 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
SetPixels(0, 0, width, height, pixels);
}
- virtual void texSubImage2D(GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const void* pixels) OVERRIDE {
+ void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) override {
CheckTextureIsBound(target);
ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
ASSERT_FALSE(level);
@@ -239,12 +253,11 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
SetPixels(xoffset, yoffset, width, height, pixels);
}
- virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
+ void genMailboxCHROMIUM(GLbyte* mailbox) override {
return shared_data_->GenMailbox(mailbox);
}
- virtual void produceTextureCHROMIUM(GLenum target,
- const GLbyte* mailbox) OVERRIDE {
+ void produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
CheckTextureIsBound(target);
// Delay moving the texture into the mailbox until the next
@@ -257,8 +270,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
pending_produce_textures_.push_back(pending.Pass());
}
- virtual void consumeTextureCHROMIUM(GLenum target,
- const GLbyte* mailbox) OVERRIDE {
+ void consumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
CheckTextureIsBound(target);
base::AutoLock lock_for_texture_access(namespace_->lock);
scoped_refptr<TestTexture> texture =
@@ -339,6 +351,7 @@ void GetResourcePixels(ResourceProvider* resource_provider,
const gfx::Size& size,
ResourceFormat format,
uint8_t* pixels) {
+ resource_provider->WaitSyncPointIfNeeded(id);
switch (resource_provider->default_resource_type()) {
case ResourceProvider::GLTexture: {
ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
@@ -367,7 +380,8 @@ class ResourceProviderTest
ResourceProviderTest()
: shared_data_(ContextSharedData::Create()),
context3d_(NULL),
- child_context_(NULL) {
+ child_context_(NULL),
+ main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
switch (GetParam()) {
case ResourceProvider::GLTexture: {
scoped_ptr<ResourceProviderContext> context3d(
@@ -375,16 +389,15 @@ class ResourceProviderTest
context3d_ = context3d.get();
scoped_refptr<TestContextProvider> context_provider =
- TestContextProvider::Create(
- context3d.PassAs<TestWebGraphicsContext3D>());
+ TestContextProvider::Create(context3d.Pass());
output_surface_ = FakeOutputSurface::Create3d(context_provider);
scoped_ptr<ResourceProviderContext> child_context_owned =
ResourceProviderContext::Create(shared_data_.get());
child_context_ = child_context_owned.get();
- child_output_surface_ = FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>());
+ child_output_surface_ =
+ FakeOutputSurface::Create3d(child_context_owned.Pass());
break;
}
case ResourceProvider::Bitmap:
@@ -400,22 +413,30 @@ class ResourceProviderTest
CHECK(output_surface_->BindToClient(&output_surface_client_));
CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
- shared_bitmap_manager_.reset(new TestSharedBitmapManager());
+ shared_bitmap_manager_.reset(new TestSharedBitmapManager);
+ gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
- resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false);
- child_resource_provider_ = ResourceProvider::Create(
- child_output_surface_.get(),
- shared_bitmap_manager_.get(),
- 0,
- false,
- 1,
- false);
+ resource_provider_ =
+ ResourceProvider::Create(output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ main_thread_task_runner_.get(),
+ 0,
+ false,
+ 1);
+ child_resource_provider_ =
+ ResourceProvider::Create(child_output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ main_thread_task_runner_.get(),
+ 0,
+ false,
+ 1);
}
static void CollectResources(ReturnedResourceArray* array,
- const ReturnedResourceArray& returned) {
+ const ReturnedResourceArray& returned,
+ BlockingTaskRunner* main_thread_task_runner) {
array->insert(array->end(), returned.begin(), returned.end());
}
@@ -446,12 +467,13 @@ class ResourceProviderTest
EXPECT_LT(0u, *sync_point);
scoped_ptr<base::SharedMemory> shared_memory;
- scoped_ptr<SingleReleaseCallback> callback =
- SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
- base::Passed(&shared_memory),
- release_called,
- release_sync_point,
- lost_resource));
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(
+ base::Bind(ReleaseSharedMemoryCallback,
+ base::Passed(&shared_memory),
+ release_called,
+ release_sync_point,
+ lost_resource));
return child_resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
callback.Pass());
@@ -461,12 +483,13 @@ class ResourceProviderTest
CreateAndFillSharedMemory(size, 0));
base::SharedMemory* shared_memory_ptr = shared_memory.get();
- scoped_ptr<SingleReleaseCallback> callback =
- SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
- base::Passed(&shared_memory),
- release_called,
- release_sync_point,
- lost_resource));
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(
+ base::Bind(ReleaseSharedMemoryCallback,
+ base::Passed(&shared_memory),
+ release_called,
+ release_sync_point,
+ lost_resource));
return child_resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(shared_memory_ptr, size), callback.Pass());
}
@@ -480,9 +503,11 @@ class ResourceProviderTest
FakeOutputSurfaceClient child_output_surface_client_;
scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<OutputSurface> child_output_surface_;
+ scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
scoped_ptr<ResourceProvider> resource_provider_;
scoped_ptr<ResourceProvider> child_resource_provider_;
scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
+ scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
};
void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
@@ -496,7 +521,7 @@ void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
if (expected_default_type == ResourceProvider::GLTexture)
EXPECT_EQ(0u, context->NumTextures());
@@ -528,7 +553,7 @@ TEST_P(ResourceProviderTest, Upload) {
ASSERT_EQ(16U, pixel_size);
ResourceProvider::ResourceId id = resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t image[16] = { 0 };
gfx::Rect image_rect(size);
@@ -597,20 +622,23 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data2[4] = { 5, 5, 5, 5 };
child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- child_resource_provider_->MapImageRasterBuffer(id3);
- child_resource_provider_->UnmapImageRasterBuffer(id3);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
+ {
+ ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
+ child_resource_provider_.get(), id3);
+ EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
+ }
GLuint external_texture_id = child_context_->createExternalTexture();
child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
@@ -624,7 +652,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
child_resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(
external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
- SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
+ SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
ReturnedResourceArray returned_to_child;
int child_id =
@@ -664,6 +692,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
EXPECT_NE(list[0].mailbox_holder.sync_point,
context3d_->last_waited_sync_point());
{
+ resource_provider_->WaitSyncPointIfNeeded(list[0].id);
ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
list[0].id);
}
@@ -753,6 +782,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
{
+ child_resource_provider_->WaitSyncPointIfNeeded(id1);
ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
id1);
ASSERT_NE(0U, lock.texture_id());
@@ -761,6 +791,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
EXPECT_EQ(0, memcmp(data1, result, pixel_size));
}
{
+ child_resource_provider_->WaitSyncPointIfNeeded(id2);
ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
id2);
ASSERT_NE(0U, lock.texture_id());
@@ -769,6 +800,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
EXPECT_EQ(0, memcmp(data2, result, pixel_size));
}
{
+ child_resource_provider_->WaitSyncPointIfNeeded(id3);
ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
id3);
ASSERT_NE(0U, lock.texture_id());
@@ -834,7 +866,7 @@ TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
ResourceFormat format = RGBA_8888;
ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = {1, 2, 3, 4};
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
@@ -854,6 +886,7 @@ TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
resource_provider_->ReceiveFromChild(child_id, list);
+ resource_provider_->WaitSyncPointIfNeeded(list[0].id);
ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
list[0].id);
@@ -866,6 +899,7 @@ TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
{
+ child_resource_provider_->WaitSyncPointIfNeeded(id1);
ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
id1);
child_resource_provider_->DeleteResource(id1);
@@ -877,6 +911,57 @@ TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
resource_provider_->DestroyChild(child_id);
}
+TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
+ // Overlays only supported on the GL path.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+
+ uint32 sync_point = 0;
+ TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
+ mailbox.set_allow_overlay(true);
+ scoped_ptr<SingleReleaseCallbackImpl> release_callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
+ ResourceProvider::ResourceId id1 =
+ child_resource_provider_->CreateResourceFromTextureMailbox(
+ mailbox, release_callback.Pass());
+
+ TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
+ mailbox2.set_allow_overlay(false);
+ scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
+ SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
+ ResourceProvider::ResourceId id2 =
+ child_resource_provider_->CreateResourceFromTextureMailbox(
+ mailbox2, release_callback2.Pass());
+
+ ReturnedResourceArray returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer some resources to the parent.
+ ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ resource_ids_to_transfer.push_back(id1);
+ resource_ids_to_transfer.push_back(id2);
+ TransferableResourceArray list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+ &list);
+ ASSERT_EQ(2u, list.size());
+ resource_provider_->ReceiveFromChild(child_id, list);
+ EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
+ EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
+
+ resource_provider_->DeclareUsedResourcesFromChild(
+ child_id, ResourceProvider::ResourceIdArray());
+
+ EXPECT_EQ(2u, returned_to_child.size());
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+ child_resource_provider_->DeleteResource(id1);
+ child_resource_provider_->DeleteResource(id2);
+ EXPECT_EQ(0u, child_resource_provider_->num_resources());
+
+ resource_provider_->DestroyChild(child_id);
+}
+
TEST_P(ResourceProviderTest, TransferSoftwareResources) {
if (GetParam() != ResourceProvider::Bitmap)
return;
@@ -887,31 +972,23 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data2[4] = { 5, 5, 5, 5 };
child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
- ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- uint8_t data3[4] = { 6, 7, 8, 9 };
- SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
- SkCanvas* raster_canvas = child_resource_provider_->MapImageRasterBuffer(id3);
- raster_canvas->writePixels(info, data3, info.minRowBytes(), 0, 0);
- child_resource_provider_->UnmapImageRasterBuffer(id3);
-
scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
shared_memory->CreateAndMapAnonymous(1);
base::SharedMemory* shared_memory_ptr = shared_memory.get();
- ResourceProvider::ResourceId id4 =
+ ResourceProvider::ResourceId id3 =
child_resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
- SingleReleaseCallback::Create(base::Bind(
+ SingleReleaseCallbackImpl::Create(base::Bind(
&SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
ReturnedResourceArray returned_to_child;
@@ -923,39 +1000,33 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
resource_ids_to_transfer.push_back(id3);
- resource_ids_to_transfer.push_back(id4);
TransferableResourceArray list;
child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
&list);
- ASSERT_EQ(4u, list.size());
+ ASSERT_EQ(3u, list.size());
EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
- EXPECT_EQ(0u, list[3].mailbox_holder.sync_point);
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
- EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
}
- EXPECT_EQ(4u, resource_provider_->num_resources());
+ EXPECT_EQ(3u, resource_provider_->num_resources());
ResourceProvider::ResourceIdMap resource_map =
resource_provider_->GetChildToParentMap(child_id);
ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
- ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
EXPECT_NE(0u, mapped_id1);
EXPECT_NE(0u, mapped_id2);
EXPECT_NE(0u, mapped_id3);
- EXPECT_NE(0u, mapped_id4);
EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
- EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
uint8_t result[4] = { 0 };
GetResourcePixels(
@@ -966,24 +1037,18 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
resource_provider_.get(), context(), mapped_id2, size, format, result);
EXPECT_EQ(0, memcmp(data2, result, pixel_size));
- GetResourcePixels(
- resource_provider_.get(), context(), mapped_id3, size, format, result);
- EXPECT_EQ(0, memcmp(data3, result, pixel_size));
-
{
// Check that transfering again the same resource from the child to the
// parent works.
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
- resource_ids_to_transfer.push_back(id3);
TransferableResourceArray list;
child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
&list);
- EXPECT_EQ(3u, list.size());
+ EXPECT_EQ(2u, list.size());
EXPECT_EQ(id1, list[0].id);
EXPECT_EQ(id2, list[1].id);
- EXPECT_EQ(id3, list[2].id);
ReturnedResourceArray returned;
TransferableResource::ReturnResources(list, &returned);
child_resource_provider_->ReceiveReturnsFromParent(returned);
@@ -991,7 +1056,6 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
// be in-use.
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
- EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
}
{
EXPECT_EQ(0u, returned_to_child.size());
@@ -1001,31 +1065,27 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
ResourceProvider::ResourceIdArray no_resources;
resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
- ASSERT_EQ(4u, returned_to_child.size());
+ ASSERT_EQ(3u, returned_to_child.size());
EXPECT_EQ(0u, returned_to_child[0].sync_point);
EXPECT_EQ(0u, returned_to_child[1].sync_point);
EXPECT_EQ(0u, returned_to_child[2].sync_point);
- EXPECT_EQ(0u, returned_to_child[3].sync_point);
std::set<ResourceProvider::ResourceId> expected_ids;
expected_ids.insert(id1);
expected_ids.insert(id2);
expected_ids.insert(id3);
- expected_ids.insert(id4);
std::set<ResourceProvider::ResourceId> returned_ids;
- for (unsigned i = 0; i < 4; i++)
+ for (unsigned i = 0; i < 3; i++)
returned_ids.insert(returned_to_child[i].id);
EXPECT_EQ(expected_ids, returned_ids);
EXPECT_FALSE(returned_to_child[0].lost);
EXPECT_FALSE(returned_to_child[1].lost);
EXPECT_FALSE(returned_to_child[2].lost);
- EXPECT_FALSE(returned_to_child[3].lost);
child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
returned_to_child.clear();
}
EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
- EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
{
ResourceProvider::ScopedReadLockSoftware lock(
@@ -1044,32 +1104,21 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
}
{
- ResourceProvider::ScopedReadLockSoftware lock(
- child_resource_provider_.get(), id3);
- const SkBitmap* sk_bitmap = lock.sk_bitmap();
- EXPECT_EQ(sk_bitmap->width(), size.width());
- EXPECT_EQ(sk_bitmap->height(), size.height());
- EXPECT_EQ(0, memcmp(data3, sk_bitmap->getPixels(), pixel_size));
- }
- {
// Transfer resources to the parent again.
ResourceProvider::ResourceIdArray resource_ids_to_transfer;
resource_ids_to_transfer.push_back(id1);
resource_ids_to_transfer.push_back(id2);
resource_ids_to_transfer.push_back(id3);
- resource_ids_to_transfer.push_back(id4);
TransferableResourceArray list;
child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
&list);
- ASSERT_EQ(4u, list.size());
+ ASSERT_EQ(3u, list.size());
EXPECT_EQ(id1, list[0].id);
EXPECT_EQ(id2, list[1].id);
EXPECT_EQ(id3, list[2].id);
- EXPECT_EQ(id4, list[3].id);
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
- EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
resource_provider_->ReceiveFromChild(child_id, list);
resource_provider_->DeclareUsedResourcesFromChild(child_id,
resource_ids_to_transfer);
@@ -1077,28 +1126,25 @@ TEST_P(ResourceProviderTest, TransferSoftwareResources) {
EXPECT_EQ(0u, returned_to_child.size());
- EXPECT_EQ(4u, resource_provider_->num_resources());
+ EXPECT_EQ(3u, resource_provider_->num_resources());
resource_provider_->DestroyChild(child_id);
EXPECT_EQ(0u, resource_provider_->num_resources());
- ASSERT_EQ(4u, returned_to_child.size());
+ ASSERT_EQ(3u, returned_to_child.size());
EXPECT_EQ(0u, returned_to_child[0].sync_point);
EXPECT_EQ(0u, returned_to_child[1].sync_point);
EXPECT_EQ(0u, returned_to_child[2].sync_point);
- EXPECT_EQ(0u, returned_to_child[3].sync_point);
std::set<ResourceProvider::ResourceId> expected_ids;
expected_ids.insert(id1);
expected_ids.insert(id2);
expected_ids.insert(id3);
- expected_ids.insert(id4);
std::set<ResourceProvider::ResourceId> returned_ids;
- for (unsigned i = 0; i < 4; i++)
+ for (unsigned i = 0; i < 3; i++)
returned_ids.insert(returned_to_child[i].id);
EXPECT_EQ(expected_ids, returned_ids);
EXPECT_FALSE(returned_to_child[0].lost);
EXPECT_FALSE(returned_to_child[1].lost);
EXPECT_FALSE(returned_to_child[2].lost);
- EXPECT_FALSE(returned_to_child[3].lost);
}
TEST_P(ResourceProviderTest, TransferGLToSoftware) {
@@ -1109,13 +1155,18 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) {
ResourceProviderContext::Create(shared_data_.get()));
FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> child_output_surface(
+ FakeOutputSurface::Create3d(child_context_owned.Pass()));
CHECK(child_output_surface->BindToClient(&child_output_surface_client));
- scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
- child_output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false));
+ scoped_ptr<ResourceProvider> child_resource_provider(
+ ResourceProvider::Create(child_output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -1123,7 +1174,7 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
@@ -1170,7 +1221,7 @@ TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
@@ -1218,13 +1269,13 @@ TEST_P(ResourceProviderTest, DeleteExportedResources) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data2[4] = {5, 5, 5, 5};
child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
@@ -1312,13 +1363,13 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data1[4] = {1, 2, 3, 4};
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data2[4] = {5, 5, 5, 5};
child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
@@ -1407,7 +1458,7 @@ TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
// Destroy the parent resource provider. The resource that's left should be
// lost at this point, and returned.
- resource_provider_.reset();
+ resource_provider_ = nullptr;
ASSERT_EQ(1u, returned_to_child.size());
if (GetParam() == ResourceProvider::GLTexture) {
EXPECT_NE(0u, returned_to_child[0].sync_point);
@@ -1423,7 +1474,7 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data[4] = { 1, 2, 3, 4 };
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
@@ -1473,7 +1524,7 @@ TEST_P(ResourceProviderTest, UnuseTransferredResources) {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
uint8_t data[4] = {1, 2, 3, 4};
gfx::Rect rect(size);
child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
@@ -1584,8 +1635,8 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
TextureStateTrackingContext* child_context = child_context_owned.get();
FakeOutputSurfaceClient child_output_surface_client;
- scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
- child_context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> child_output_surface(
+ FakeOutputSurface::Create3d(child_context_owned.Pass()));
CHECK(child_output_surface->BindToClient(&child_output_surface_client));
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
@@ -1593,27 +1644,29 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
scoped_ptr<ResourceProvider> child_resource_provider(
ResourceProvider::Create(child_output_surface.get(),
shared_bitmap_manager.get(),
+ NULL,
+ NULL,
0,
false,
- 1,
- false));
+ 1));
scoped_ptr<TextureStateTrackingContext> parent_context_owned(
new TextureStateTrackingContext);
TextureStateTrackingContext* parent_context = parent_context_owned.get();
FakeOutputSurfaceClient parent_output_surface_client;
- scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
- parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> parent_output_surface(
+ FakeOutputSurface::Create3d(parent_context_owned.Pass()));
CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
scoped_ptr<ResourceProvider> parent_resource_provider(
ResourceProvider::Create(parent_output_surface.get(),
shared_bitmap_manager.get(),
+ NULL,
+ NULL,
0,
false,
- 1,
- false));
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -1624,7 +1677,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
ASSERT_EQ(4U, pixel_size);
ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
// The new texture is created with GL_LINEAR.
EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
@@ -1691,6 +1744,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
parent_resource_provider->ReceiveFromChild(child_id, list);
{
+ parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
list[0].id);
}
@@ -1779,12 +1833,15 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
uint32 release_sync_point = 0;
bool lost_resource = false;
- ReleaseCallback callback =
- base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
+ BlockingTaskRunner* main_thread_task_runner = NULL;
+ ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
+ &release_sync_point,
+ &lost_resource,
+ &main_thread_task_runner);
ResourceProvider::ResourceId resource =
resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
- SingleReleaseCallback::Create(callback));
+ SingleReleaseCallbackImpl::Create(callback));
EXPECT_EQ(1u, context()->NumTextures());
EXPECT_EQ(0u, release_sync_point);
{
@@ -1825,6 +1882,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
resource_provider_->DeleteResource(resource);
EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
EXPECT_FALSE(lost_resource);
+ EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
}
// We're going to do the same thing as above, but testing the case where we
@@ -1834,7 +1892,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
release_sync_point = 0;
resource = resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
- SingleReleaseCallback::Create(callback));
+ SingleReleaseCallbackImpl::Create(callback));
EXPECT_EQ(1u, context()->NumTextures());
EXPECT_EQ(0u, release_sync_point);
{
@@ -1876,6 +1934,7 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
resource_provider_->ReceiveReturnsFromParent(returned);
EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
EXPECT_FALSE(lost_resource);
+ EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
}
context()->waitSyncPoint(release_sync_point);
@@ -1889,7 +1948,10 @@ TEST_P(ResourceProviderTest, LostResourceInParent) {
ResourceFormat format = RGBA_8888;
ResourceProvider::ResourceId resource =
child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureHintImmutable,
+ format);
child_resource_provider_->AllocateForTesting(resource);
// Expect a GL resource to be lost.
bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
@@ -1942,7 +2004,10 @@ TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
ResourceFormat format = RGBA_8888;
ResourceProvider::ResourceId resource =
child_resource_provider_->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureHintImmutable,
+ format);
child_resource_provider_->AllocateForTesting(resource);
ReturnedResourceArray returned_to_child;
@@ -2142,7 +2207,7 @@ TEST_P(ResourceProviderTest, Shutdown) {
EXPECT_EQ(0u, release_sync_point);
EXPECT_FALSE(lost_resource);
- child_resource_provider_.reset();
+ child_resource_provider_ = nullptr;
if (GetParam() == ResourceProvider::GLTexture) {
EXPECT_LE(sync_point, release_sync_point);
@@ -2169,7 +2234,7 @@ TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
EXPECT_EQ(0u, release_sync_point);
EXPECT_FALSE(lost_resource);
- child_resource_provider_.reset();
+ child_resource_provider_ = nullptr;
// Since the resource is in the parent, the child considers it lost.
EXPECT_EQ(0u, release_sync_point);
@@ -2191,19 +2256,25 @@ TEST_P(ResourceProviderTest, LostContext) {
uint32 release_sync_point = 0;
bool lost_resource = false;
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
+ BlockingTaskRunner* main_thread_task_runner = NULL;
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
+ &release_sync_point,
+ &lost_resource,
+ &main_thread_task_runner));
resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
EXPECT_EQ(0u, release_sync_point);
EXPECT_FALSE(lost_resource);
+ EXPECT_EQ(NULL, main_thread_task_runner);
resource_provider_->DidLoseOutputSurface();
- resource_provider_.reset();
+ resource_provider_ = nullptr;
EXPECT_LE(sync_point, release_sync_point);
EXPECT_TRUE(lost_resource);
+ EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
}
TEST_P(ResourceProviderTest, ScopedSampler) {
@@ -2216,19 +2287,25 @@ TEST_P(ResourceProviderTest, ScopedSampler) {
TextureStateTrackingContext* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
int texture_id = 1;
ResourceProvider::ResourceId id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
// Check that the texture gets created with the right sampler settings.
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
@@ -2297,12 +2374,18 @@ TEST_P(ResourceProviderTest, ManagedResource) {
TextureStateTrackingContext* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2313,7 +2396,7 @@ TEST_P(ResourceProviderTest, ManagedResource) {
size,
GL_TEXTURE_2D,
GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
+ ResourceProvider::TextureHintImmutable,
format);
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
EXPECT_CALL(*context,
@@ -2346,12 +2429,18 @@ TEST_P(ResourceProviderTest, TextureWrapMode) {
TextureStateTrackingContext* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(1, 1);
ResourceFormat format = RGBA_8888;
@@ -2360,12 +2449,76 @@ TEST_P(ResourceProviderTest, TextureWrapMode) {
for (int texture_id = 1; texture_id <= 2; ++texture_id) {
GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
// Check that the texture gets created with the right sampler settings.
+ ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
+ size,
+ GL_TEXTURE_2D,
+ texture_pool,
+ wrap_mode,
+ ResourceProvider::TextureHintImmutable,
+ format);
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_POOL_CHROMIUM,
+ GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
+ resource_provider->CreateForTesting(id);
+ EXPECT_NE(0u, id);
+
+ Mock::VerifyAndClearExpectations(context);
+ }
+}
+
+TEST_P(ResourceProviderTest, TextureHint) {
+ // Sampling is only supported for GL textures.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+
+ scoped_ptr<TextureStateTrackingContext> context_owned(
+ new TextureStateTrackingContext);
+ TextureStateTrackingContext* context = context_owned.get();
+ context->set_support_texture_storage(true);
+ context->set_support_texture_usage(true);
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
+
+ gfx::Size size(1, 1);
+ ResourceFormat format = RGBA_8888;
+ GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
+
+ const ResourceProvider::TextureHint hints[4] = {
+ ResourceProvider::TextureHintDefault,
+ ResourceProvider::TextureHintImmutable,
+ ResourceProvider::TextureHintFramebuffer,
+ ResourceProvider::TextureHintImmutableFramebuffer,
+ };
+ for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
+ // Check that the texture gets created with the right sampler settings.
ResourceProvider::ResourceId id =
resource_provider->CreateGLTexture(size,
GL_TEXTURE_2D,
texture_pool,
- wrap_mode,
- ResourceProvider::TextureUsageAny,
+ GL_CLAMP_TO_EDGE,
+ hints[texture_id - 1],
format);
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
EXPECT_CALL(*context,
@@ -2374,14 +2527,22 @@ TEST_P(ResourceProviderTest, TextureWrapMode) {
texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
EXPECT_CALL(
*context,
- texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
EXPECT_CALL(
*context,
- texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
EXPECT_CALL(*context,
texParameteri(GL_TEXTURE_2D,
GL_TEXTURE_POOL_CHROMIUM,
GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
+ // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
+ bool is_framebuffer_hint =
+ hints[texture_id - 1] & ResourceProvider::TextureHintFramebuffer;
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_USAGE_ANGLE,
+ GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
+ .Times(is_framebuffer_hint ? 1 : 0);
resource_provider->CreateForTesting(id);
EXPECT_NE(0u, id);
@@ -2404,11 +2565,23 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
new SoftwareOutputDevice)));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ main_thread_task_runner_.get(),
+ 0,
+ false,
+ 1));
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(&EmptyReleaseCallback));
+ uint32 release_sync_point = 0;
+ bool lost_resource = false;
+ BlockingTaskRunner* main_thread_task_runner = NULL;
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
+ &release_sync_point,
+ &lost_resource,
+ &main_thread_task_runner));
TextureMailbox mailbox(shared_memory.get(), size);
ResourceProvider::ResourceId id =
@@ -2423,6 +2596,11 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
EXPECT_EQ(sk_bitmap->height(), size.height());
EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
}
+
+ resource_provider->DeleteResource(id);
+ EXPECT_EQ(0u, release_sync_point);
+ EXPECT_FALSE(lost_resource);
+ EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
}
TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
@@ -2435,12 +2613,18 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
TextureStateTrackingContext* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ main_thread_task_runner_.get(),
+ 0,
+ false,
+ 1));
unsigned texture_id = 1;
uint32 sync_point = 30;
@@ -2454,8 +2638,14 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
gpu::Mailbox gpu_mailbox;
memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(&EmptyReleaseCallback));
+ uint32 release_sync_point = 0;
+ bool lost_resource = false;
+ BlockingTaskRunner* main_thread_task_runner = NULL;
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
+ &release_sync_point,
+ &lost_resource,
+ &main_thread_task_runner));
TextureMailbox mailbox(gpu_mailbox, target, sync_point);
@@ -2467,9 +2657,13 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
Mock::VerifyAndClearExpectations(context);
{
+ // Mailbox sync point WaitSyncPoint before using the texture.
+ EXPECT_CALL(*context, waitSyncPoint(sync_point));
+ resource_provider->WaitSyncPointIfNeeded(id);
+ Mock::VerifyAndClearExpectations(context);
+
// Using the texture does a consume of the mailbox.
EXPECT_CALL(*context, bindTexture(target, texture_id));
- EXPECT_CALL(*context, waitSyncPoint(sync_point));
EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
EXPECT_CALL(*context, insertSyncPoint()).Times(0);
@@ -2487,6 +2681,11 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
}
+
+ resource_provider->DeleteResource(id);
+ EXPECT_EQ(0u, release_sync_point);
+ EXPECT_FALSE(lost_resource);
+ EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
}
TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
@@ -2499,12 +2698,18 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
TextureStateTrackingContext* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
unsigned texture_id = 1;
uint32 sync_point = 30;
@@ -2518,8 +2723,8 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
gpu::Mailbox gpu_mailbox;
memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
- scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
- base::Bind(&EmptyReleaseCallback));
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
TextureMailbox mailbox(gpu_mailbox, target, sync_point);
@@ -2531,9 +2736,13 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
Mock::VerifyAndClearExpectations(context);
{
+ // Mailbox sync point WaitSyncPoint before using the texture.
+ EXPECT_CALL(*context, waitSyncPoint(sync_point));
+ resource_provider->WaitSyncPointIfNeeded(id);
+ Mock::VerifyAndClearExpectations(context);
+
// Using the texture does a consume of the mailbox.
EXPECT_CALL(*context, bindTexture(target, texture_id));
- EXPECT_CALL(*context, waitSyncPoint(sync_point));
EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
EXPECT_CALL(*context, insertSyncPoint()).Times(0);
@@ -2553,6 +2762,120 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
}
}
+TEST_P(ResourceProviderTest,
+ TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
+ // Mailboxing is only supported for GL textures.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+
+ scoped_ptr<TextureStateTrackingContext> context_owned(
+ new TextureStateTrackingContext);
+ TextureStateTrackingContext* context = context_owned.get();
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
+
+ uint32 sync_point = 30;
+ unsigned target = GL_TEXTURE_2D;
+
+ EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
+ EXPECT_CALL(*context, insertSyncPoint()).Times(0);
+ EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
+ EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+
+ gpu::Mailbox gpu_mailbox;
+ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
+
+ TextureMailbox mailbox(gpu_mailbox, target, sync_point);
+
+ ResourceProvider::ResourceId id =
+ resource_provider->CreateResourceFromTextureMailbox(mailbox,
+ callback.Pass());
+ EXPECT_NE(0u, id);
+
+ Mock::VerifyAndClearExpectations(context);
+
+ {
+ // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
+ EXPECT_CALL(*context, waitSyncPoint(sync_point));
+ resource_provider->WaitSyncPointIfNeeded(id);
+ Mock::VerifyAndClearExpectations(context);
+
+ // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
+ EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
+ resource_provider->WaitSyncPointIfNeeded(id);
+ Mock::VerifyAndClearExpectations(context);
+ }
+}
+
+TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
+ // Mailboxing is only supported for GL textures.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+
+ scoped_ptr<TextureStateTrackingContext> context_owned(
+ new TextureStateTrackingContext);
+ TextureStateTrackingContext* context = context_owned.get();
+
+ FakeOutputSurfaceClient output_surface_client;
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
+ CHECK(output_surface->BindToClient(&output_surface_client));
+
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
+
+ uint32 sync_point = 0;
+ unsigned target = GL_TEXTURE_2D;
+
+ EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
+ EXPECT_CALL(*context, insertSyncPoint()).Times(0);
+ EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
+ EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
+
+ gpu::Mailbox gpu_mailbox;
+ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
+ scoped_ptr<SingleReleaseCallbackImpl> callback =
+ SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
+
+ TextureMailbox mailbox(gpu_mailbox, target, sync_point);
+
+ ResourceProvider::ResourceId id =
+ resource_provider->CreateResourceFromTextureMailbox(mailbox,
+ callback.Pass());
+ EXPECT_NE(0u, id);
+
+ Mock::VerifyAndClearExpectations(context);
+
+ {
+ // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
+ EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
+ resource_provider->WaitSyncPointIfNeeded(id);
+ Mock::VerifyAndClearExpectations(context);
+ }
+}
+
class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
public:
MOCK_METHOD0(NextTextureId, GLuint());
@@ -2614,11 +2937,9 @@ class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
GLsizei image_size,
const void* data));
MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
- MOCK_METHOD4(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum, GLenum));
+ MOCK_METHOD4(createImageCHROMIUM,
+ GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
- MOCK_METHOD1(mapImageCHROMIUM, void*(GLuint));
- MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
- MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
@@ -2637,12 +2958,18 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
AllocationTrackingContext3D* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(2, 2);
gfx::Vector2d offset(0, 0);
@@ -2654,7 +2981,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
// Lazy allocation. Don't allocate when creating the resource.
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
@@ -2667,7 +2994,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
// Do allocate when we set the pixels.
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
@@ -2682,8 +3009,8 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
// Same for async version.
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- resource_provider->AcquirePixelRasterBuffer(id);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
+ resource_provider->AcquirePixelBuffer(id);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
@@ -2692,7 +3019,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
resource_provider->BeginSetPixels(id);
ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
- resource_provider->ReleasePixelRasterBuffer(id);
+ resource_provider->ReleasePixelBuffer(id);
EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
@@ -2700,7 +3027,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) {
Mock::VerifyAndClearExpectations(context);
}
-TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
+TEST_P(ResourceProviderTest, TextureAllocationHint) {
// Only for GL textures.
if (GetParam() != ResourceProvider::GLTexture)
return;
@@ -2708,73 +3035,113 @@ TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
new StrictMock<AllocationTrackingContext3D>);
AllocationTrackingContext3D* context = context_owned.get();
context->set_support_texture_storage(true);
+ context->set_support_texture_usage(true);
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(2, 2);
- ResourceFormat format = RGBA_8888;
- ResourceProvider::ResourceId id = 0;
- int texture_id = 123;
-
- // Lazy allocation. Don't allocate when creating the resource.
- id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-
- EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
- EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1);
- resource_provider->AllocateForTesting(id);
- EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
- resource_provider->DeleteResource(id);
-
- Mock::VerifyAndClearExpectations(context);
+ const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
+ const ResourceProvider::TextureHint hints[4] = {
+ ResourceProvider::TextureHintDefault,
+ ResourceProvider::TextureHintImmutable,
+ ResourceProvider::TextureHintFramebuffer,
+ ResourceProvider::TextureHintImmutableFramebuffer,
+ };
+ for (size_t i = 0; i < arraysize(formats); ++i) {
+ for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
+ // Lazy allocation. Don't allocate when creating the resource.
+ ResourceProvider::ResourceId id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
+
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
+ bool is_immutable_hint =
+ hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
+ bool support_immutable_texture =
+ is_immutable_hint && formats[i] == RGBA_8888;
+ EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
+ .Times(support_immutable_texture ? 1 : 0);
+ EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
+ .Times(support_immutable_texture ? 0 : 1);
+ resource_provider->AllocateForTesting(id);
+
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
+ resource_provider->DeleteResource(id);
+
+ Mock::VerifyAndClearExpectations(context);
+ }
+ }
}
-TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) {
+TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
// Only for GL textures.
if (GetParam() != ResourceProvider::GLTexture)
return;
scoped_ptr<AllocationTrackingContext3D> context_owned(
new StrictMock<AllocationTrackingContext3D>);
AllocationTrackingContext3D* context = context_owned.get();
+ context->set_support_texture_format_bgra8888(true);
context->set_support_texture_storage(true);
+ context->set_support_texture_usage(true);
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
gfx::Size size(2, 2);
- ResourceFormat format = RGBA_8888;
- ResourceProvider::ResourceId id = 0;
- int texture_id = 123;
-
- // Lazy allocation. Don't allocate when creating the resource.
- id = resource_provider->CreateResource(
- size,
- GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageFramebuffer,
- format);
-
- EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
- EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
- EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
- resource_provider->AllocateForTesting(id);
+ const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
- EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
- resource_provider->DeleteResource(id);
-
- Mock::VerifyAndClearExpectations(context);
+ const ResourceProvider::TextureHint hints[4] = {
+ ResourceProvider::TextureHintDefault,
+ ResourceProvider::TextureHintImmutable,
+ ResourceProvider::TextureHintFramebuffer,
+ ResourceProvider::TextureHintImmutableFramebuffer,
+ };
+ for (size_t i = 0; i < arraysize(formats); ++i) {
+ for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
+ // Lazy allocation. Don't allocate when creating the resource.
+ ResourceProvider::ResourceId id = resource_provider->CreateResource(
+ size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
+
+ EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
+ bool is_immutable_hint =
+ hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
+ EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
+ .Times(is_immutable_hint ? 1 : 0);
+ EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
+ .Times(is_immutable_hint ? 0 : 1);
+ resource_provider->AllocateForTesting(id);
+
+ EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
+ resource_provider->DeleteResource(id);
+
+ Mock::VerifyAndClearExpectations(context);
+ }
+ }
}
TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
@@ -2785,8 +3152,8 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
AllocationTrackingContext3D* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
gfx::Size size(2, 2);
@@ -2794,12 +3161,18 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
ResourceProvider::ResourceId id = 0;
int texture_id = 123;
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- resource_provider->AcquirePixelRasterBuffer(id);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
+ resource_provider->AcquirePixelBuffer(id);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
@@ -2809,7 +3182,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
- resource_provider->ReleasePixelRasterBuffer(id);
+ resource_provider->ReleasePixelBuffer(id);
EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
@@ -2826,8 +3199,8 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
AllocationTrackingContext3D* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
gfx::Size size(2, 2);
@@ -2835,12 +3208,18 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
ResourceProvider::ResourceId id = 0;
int texture_id = 123;
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
- resource_provider->AcquirePixelRasterBuffer(id);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
+ resource_provider->AcquirePixelBuffer(id);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
@@ -2853,7 +3232,7 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
resource_provider->ForceSetPixelsToComplete(id);
- resource_provider->ReleasePixelRasterBuffer(id);
+ resource_provider->ReleasePixelBuffer(id);
EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
resource_provider->DeleteResource(id);
@@ -2867,8 +3246,8 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) {
AllocationTrackingContext3D* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
gfx::Size size(2, 2);
@@ -2876,21 +3255,27 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) {
ResourceProvider::ResourceId id = 0;
int texture_id = 123;
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
GL_INNOCENT_CONTEXT_RESET_ARB);
- resource_provider->AcquirePixelRasterBuffer(id);
- SkCanvas* raster_canvas = resource_provider->MapPixelRasterBuffer(id);
- EXPECT_TRUE(raster_canvas == NULL);
- resource_provider->UnmapPixelRasterBuffer(id);
- resource_provider->ReleasePixelRasterBuffer(id);
+ resource_provider->AcquirePixelBuffer(id);
+ int stride;
+ void* buffer = resource_provider->MapPixelBuffer(id, &stride);
+ EXPECT_FALSE(buffer);
+ resource_provider->UnmapPixelBuffer(id);
Mock::VerifyAndClearExpectations(context);
}
@@ -2903,8 +3288,8 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
AllocationTrackingContext3D* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
const int kWidth = 2;
@@ -2915,33 +3300,26 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
const unsigned kTextureId = 123u;
const unsigned kImageId = 234u;
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
- const int kStride = 4;
- void* dummy_mapped_buffer_address = NULL;
- EXPECT_CALL(
- *context,
- createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
+ EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
.WillOnce(Return(kImageId))
.RetiresOnSaturation();
- EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
- GL_IMAGE_ROWBYTES_CHROMIUM,
- _))
- .WillOnce(SetArgPointee<2>(kStride))
- .RetiresOnSaturation();
- EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
- .WillOnce(Return(dummy_mapped_buffer_address))
- .RetiresOnSaturation();
- resource_provider->MapImageRasterBuffer(id);
-
- EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
- .Times(1)
- .RetiresOnSaturation();
- resource_provider->UnmapImageRasterBuffer(id);
+ {
+ ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
+ resource_provider.get(), id);
+ EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
+ }
EXPECT_CALL(*context, NextTextureId())
.WillOnce(Return(kTextureId))
@@ -2958,20 +3336,11 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
EXPECT_EQ(kTextureId, lock_gl.texture_id());
}
- EXPECT_CALL(
- *context,
- getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
- .WillOnce(SetArgPointee<2>(kStride))
- .RetiresOnSaturation();
- EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
- .WillOnce(Return(dummy_mapped_buffer_address))
- .RetiresOnSaturation();
- resource_provider->MapImageRasterBuffer(id);
-
- EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
- .Times(1)
- .RetiresOnSaturation();
- resource_provider->UnmapImageRasterBuffer(id);
+ {
+ ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
+ resource_provider.get(), id);
+ EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
+ }
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
.RetiresOnSaturation();
@@ -2995,45 +3364,6 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
.RetiresOnSaturation();
}
-TEST_P(ResourceProviderTest, Image_Bitmap) {
- if (GetParam() != ResourceProvider::Bitmap)
- return;
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(
- FakeOutputSurface::CreateSoftware(make_scoped_ptr(
- new SoftwareOutputDevice)));
- CHECK(output_surface->BindToClient(&output_surface_client));
-
- gfx::Size size(1, 1);
- ResourceFormat format = RGBA_8888;
- ResourceProvider::ResourceId id = 0;
- const uint32_t kBadBeef = 0xbadbeef;
-
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
-
- id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-
- SkBitmap bitmap;
- bitmap.allocN32Pixels(size.width(), size.height());
- *(bitmap.getAddr32(0, 0)) = kBadBeef;
- SkCanvas* canvas = resource_provider->MapImageRasterBuffer(id);
- ASSERT_TRUE(!!canvas);
- canvas->writePixels(bitmap, 0, 0);
- resource_provider->UnmapImageRasterBuffer(id);
-
- {
- ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
- const SkBitmap* sk_bitmap = lock.sk_bitmap();
- EXPECT_EQ(sk_bitmap->width(), size.width());
- EXPECT_EQ(sk_bitmap->height(), size.height());
- EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
- }
-
- resource_provider->DeleteResource(id);
-}
-
TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
if (GetParam() != ResourceProvider::GLTexture)
return;
@@ -3043,8 +3373,8 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
context_owned->set_support_sync_query(true);
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
const int kWidth = 2;
@@ -3057,38 +3387,30 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
const unsigned kDestTextureId = 321u;
const unsigned kImageId = 234u;
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
+ 0,
+ false,
+ 1));
source_id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
- const int kStride = 4;
- void* dummy_mapped_buffer_address = NULL;
- EXPECT_CALL(
- *context,
- createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
+ EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
.WillOnce(Return(kImageId))
.RetiresOnSaturation();
- EXPECT_CALL(
- *context,
- getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
- .WillOnce(SetArgPointee<2>(kStride))
- .RetiresOnSaturation();
- EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
- .WillOnce(Return(dummy_mapped_buffer_address))
- .RetiresOnSaturation();
- resource_provider->MapImageRasterBuffer(source_id);
- Mock::VerifyAndClearExpectations(context);
-
- EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
- .Times(1)
- .RetiresOnSaturation();
- resource_provider->UnmapImageRasterBuffer(source_id);
+ {
+ ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
+ resource_provider.get(), source_id);
+ EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
+ }
Mock::VerifyAndClearExpectations(context);
dest_id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
EXPECT_CALL(*context, NextTextureId())
.WillOnce(Return(kDestTextureId))
@@ -3121,52 +3443,6 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
resource_provider->DeleteResource(dest_id);
}
-TEST_P(ResourceProviderTest, CopyResource_Bitmap) {
- if (GetParam() != ResourceProvider::Bitmap)
- return;
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::CreateSoftware(
- make_scoped_ptr(new SoftwareOutputDevice)));
- CHECK(output_surface->BindToClient(&output_surface_client));
-
- gfx::Size size(1, 1);
- ResourceFormat format = RGBA_8888;
- ResourceProvider::ResourceId source_id = 0;
- ResourceProvider::ResourceId dest_id = 0;
- const uint32_t kBadBeef = 0xbadbeef;
-
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
-
- source_id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-
- SkBitmap bitmap;
- bitmap.allocN32Pixels(size.width(), size.height());
- *(bitmap.getAddr32(0, 0)) = kBadBeef;
- SkCanvas* canvas = resource_provider->MapImageRasterBuffer(source_id);
- ASSERT_TRUE(!!canvas);
- canvas->writePixels(bitmap, 0, 0);
- resource_provider->UnmapImageRasterBuffer(source_id);
-
- dest_id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-
- resource_provider->CopyResource(source_id, dest_id);
-
- {
- ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(),
- dest_id);
- const SkBitmap* sk_bitmap = lock.sk_bitmap();
- EXPECT_EQ(sk_bitmap->width(), size.width());
- EXPECT_EQ(sk_bitmap->height(), size.height());
- EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
- }
-
- resource_provider->DeleteResource(source_id);
- resource_provider->DeleteResource(dest_id);
-}
-
void InitializeGLAndCheck(ContextSharedData* shared_data,
ResourceProvider* resource_provider,
FakeOutputSurface* output_surface) {
@@ -3175,8 +3451,7 @@ void InitializeGLAndCheck(ContextSharedData* shared_data,
ResourceProviderContext* context = context_owned.get();
scoped_refptr<TestContextProvider> context_provider =
- TestContextProvider::Create(
- context_owned.PassAs<TestWebGraphicsContext3D>());
+ TestContextProvider::Create(context_owned.Pass());
output_surface->InitializeAndSetContext3d(context_provider);
resource_provider->InitializeGL();
@@ -3194,8 +3469,14 @@ TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
EXPECT_TRUE(output_surface->BindToClient(&client));
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1));
CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
@@ -3222,22 +3503,23 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
context_owned->set_support_compressed_texture_etc1(true);
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
gfx::Size size(4, 4);
scoped_ptr<ResourceProvider> resource_provider(
ResourceProvider::Create(output_surface.get(),
shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
0,
false,
- 1,
- false));
+ 1));
int texture_id = 123;
ResourceProvider::ResourceId id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
EXPECT_NE(0u, id);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
@@ -3257,23 +3539,24 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
context_owned->set_support_compressed_texture_etc1(true);
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
gfx::Size size(4, 4);
scoped_ptr<ResourceProvider> resource_provider(
ResourceProvider::Create(output_surface.get(),
shared_bitmap_manager_.get(),
+ gpu_memory_buffer_manager_.get(),
+ NULL,
0,
false,
- 1,
- false));
+ 1));
int texture_id = 123;
uint8_t pixels[8];
ResourceProvider::ResourceId id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
EXPECT_NE(0u, id);
EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
@@ -3294,11 +3577,11 @@ INSTANTIATE_TEST_CASE_P(
class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
public:
- virtual GLuint NextTextureId() OVERRIDE {
+ GLuint NextTextureId() override {
base::AutoLock lock(namespace_->lock);
return namespace_->next_texture_id++;
}
- virtual void RetireTextureId(GLuint) OVERRIDE {}
+ void RetireTextureId(GLuint) override {}
GLuint PeekTextureId() {
base::AutoLock lock(namespace_->lock);
return namespace_->next_texture_id;
@@ -3311,8 +3594,8 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) {
TextureIdAllocationTrackingContext* context = context_owned.get();
FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
- context_owned.PassAs<TestWebGraphicsContext3D>()));
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::Create3d(context_owned.Pass()));
CHECK(output_surface->BindToClient(&output_surface_client));
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
@@ -3325,13 +3608,14 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) {
scoped_ptr<ResourceProvider> resource_provider(
ResourceProvider::Create(output_surface.get(),
shared_bitmap_manager.get(),
+ NULL,
+ NULL,
0,
false,
- kTextureAllocationChunkSize,
- false));
+ kTextureAllocationChunkSize));
ResourceProvider::ResourceId id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
resource_provider->AllocateForTesting(id);
Mock::VerifyAndClearExpectations(context);
@@ -3344,13 +3628,14 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) {
scoped_ptr<ResourceProvider> resource_provider(
ResourceProvider::Create(output_surface.get(),
shared_bitmap_manager.get(),
+ NULL,
+ NULL,
0,
false,
- kTextureAllocationChunkSize,
- false));
+ kTextureAllocationChunkSize));
ResourceProvider::ResourceId id = resource_provider->CreateResource(
- size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+ size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
resource_provider->AllocateForTesting(id);
Mock::VerifyAndClearExpectations(context);
diff --git a/chromium/cc/resources/resource_update.h b/chromium/cc/resources/resource_update.h
index 1eddf83c094..d49114171d4 100644
--- a/chromium/cc/resources/resource_update.h
+++ b/chromium/cc/resources/resource_update.h
@@ -6,8 +6,8 @@
#define CC_RESOURCES_RESOURCE_UPDATE_H_
#include "cc/base/cc_export.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/vector2d.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
class SkBitmap;
diff --git a/chromium/cc/resources/resource_update_controller_unittest.cc b/chromium/cc/resources/resource_update_controller_unittest.cc
index 0fb899d1461..d6b4f39b40b 100644
--- a/chromium/cc/resources/resource_update_controller_unittest.cc
+++ b/chromium/cc/resources/resource_update_controller_unittest.cc
@@ -32,20 +32,19 @@ class WebGraphicsContext3DForUploadTest : public TestWebGraphicsContext3D {
explicit WebGraphicsContext3DForUploadTest(ResourceUpdateControllerTest* test)
: test_(test) {}
- virtual void flush() OVERRIDE;
- virtual void shallowFlushCHROMIUM() OVERRIDE;
- virtual void texSubImage2D(GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const void* pixels) OVERRIDE;
-
- virtual void getQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* value)
- OVERRIDE;
+ void flush() override;
+ void shallowFlushCHROMIUM() override;
+ void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) override;
+
+ void getQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* value) override;
private:
ResourceUpdateControllerTest* test_;
@@ -125,9 +124,13 @@ class ResourceUpdateControllerTest : public Test {
CHECK(output_surface_->BindToClient(&output_surface_client_));
shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false);
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1);
}
void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count,
@@ -324,7 +327,7 @@ class FakeResourceUpdateControllerClient
void Reset() { ready_to_finalize_called_ = false; }
bool ReadyToFinalizeCalled() const { return ready_to_finalize_called_; }
- virtual void ReadyToFinalizeTextureUpdates() OVERRIDE {
+ void ReadyToFinalizeTextureUpdates() override {
ready_to_finalize_called_ = true;
}
@@ -348,7 +351,7 @@ class FakeResourceUpdateController : public ResourceUpdateController {
void SetUpdateTextureTime(base::TimeDelta time) {
update_textures_time_ = time;
}
- virtual base::TimeTicks UpdateMoreTexturesCompletionTime() OVERRIDE {
+ base::TimeTicks UpdateMoreTexturesCompletionTime() override {
size_t total_updates =
resource_provider_->NumBlockingUploads() + update_more_textures_size_;
return now_ + total_updates * update_textures_time_;
@@ -356,7 +359,7 @@ class FakeResourceUpdateController : public ResourceUpdateController {
void SetUpdateMoreTexturesSize(size_t size) {
update_more_textures_size_ = size;
}
- virtual size_t UpdateMoreTexturesSize() const OVERRIDE {
+ size_t UpdateMoreTexturesSize() const override {
return update_more_textures_size_;
}
diff --git a/chromium/cc/resources/return_callback.h b/chromium/cc/resources/return_callback.h
index d12254bd662..abf5aec1d14 100644
--- a/chromium/cc/resources/return_callback.h
+++ b/chromium/cc/resources/return_callback.h
@@ -9,8 +9,11 @@
#include "cc/resources/returned_resource.h"
namespace cc {
+class BlockingTaskRunner;
-typedef base::Callback<void(const ReturnedResourceArray&)> ReturnCallback;
+typedef base::Callback<void(const ReturnedResourceArray&,
+ BlockingTaskRunner* main_thread_task_runner)>
+ ReturnCallback;
} // namespace cc
diff --git a/chromium/cc/resources/scoped_gpu_raster.cc b/chromium/cc/resources/scoped_gpu_raster.cc
new file mode 100644
index 00000000000..517c7a7d814
--- /dev/null
+++ b/chromium/cc/resources/scoped_gpu_raster.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 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/scoped_gpu_raster.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+
+using gpu::gles2::GLES2Interface;
+
+namespace cc {
+
+ScopedGpuRaster::ScopedGpuRaster(ContextProvider* context_provider)
+ : context_provider_(context_provider) {
+ BeginGpuRaster();
+}
+
+ScopedGpuRaster::~ScopedGpuRaster() {
+ EndGpuRaster();
+}
+
+void ScopedGpuRaster::BeginGpuRaster() {
+ GLES2Interface* gl = context_provider_->ContextGL();
+
+ // TODO(alokp): Use a trace macro to push/pop markers.
+ // Using push/pop functions directly incurs cost to evaluate function
+ // arguments even when tracing is disabled.
+ gl->PushGroupMarkerEXT(0, "GpuRasterization");
+
+ class GrContext* gr_context = context_provider_->GrContext();
+ // TODO(sohanjg): Remove when TestContextProvider gives a GrContext.
+ if (gr_context)
+ gr_context->resetContext();
+}
+
+void ScopedGpuRaster::EndGpuRaster() {
+ GLES2Interface* gl = context_provider_->ContextGL();
+
+ class GrContext* gr_context = context_provider_->GrContext();
+ // TODO(sohanjg): Remove when TestContextProvider gives a GrContext.
+ if (gr_context)
+ gr_context->flush();
+
+ // TODO(alokp): Use a trace macro to push/pop markers.
+ // Using push/pop functions directly incurs cost to evaluate function
+ // arguments even when tracing is disabled.
+ gl->PopGroupMarkerEXT();
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/scoped_gpu_raster.h b/chromium/cc/resources/scoped_gpu_raster.h
new file mode 100644
index 00000000000..a322ccbbe9a
--- /dev/null
+++ b/chromium/cc/resources/scoped_gpu_raster.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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_SCOPED_GPU_RASTER_H_
+#define CC_RESOURCES_SCOPED_GPU_RASTER_H_
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/output/context_provider.h"
+
+namespace cc {
+
+// The following class is needed to modify GL resources using GPU
+// raster. The user must ensure that they only use GPU raster on
+// GL resources while an instance of this class is alive.
+class CC_EXPORT ScopedGpuRaster {
+ public:
+ ScopedGpuRaster(ContextProvider* context_provider);
+ ~ScopedGpuRaster();
+
+ private:
+ void BeginGpuRaster();
+ void EndGpuRaster();
+
+ ContextProvider* context_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedGpuRaster);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_SCOPED_GPU_RASTER_H_
diff --git a/chromium/cc/resources/scoped_resource.cc b/chromium/cc/resources/scoped_resource.cc
index 68ae59fc0ba..c83efb59fd9 100644
--- a/chromium/cc/resources/scoped_resource.cc
+++ b/chromium/cc/resources/scoped_resource.cc
@@ -16,7 +16,7 @@ ScopedResource::~ScopedResource() {
}
void ScopedResource::Allocate(const gfx::Size& size,
- ResourceProvider::TextureUsageHint hint,
+ ResourceProvider::TextureHint hint,
ResourceFormat format) {
DCHECK(!id());
DCHECK(!size.IsEmpty());
@@ -41,7 +41,7 @@ void ScopedResource::AllocateManaged(const gfx::Size& size,
size,
target,
GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
+ ResourceProvider::TextureHintImmutable,
format));
#if DCHECK_IS_ON
@@ -59,8 +59,4 @@ void ScopedResource::Free() {
set_id(0);
}
-void ScopedResource::Leak() {
- set_id(0);
-}
-
} // namespace cc
diff --git a/chromium/cc/resources/scoped_resource.h b/chromium/cc/resources/scoped_resource.h
index 9f58395a94c..4241b38eae6 100644
--- a/chromium/cc/resources/scoped_resource.h
+++ b/chromium/cc/resources/scoped_resource.h
@@ -26,13 +26,12 @@ class CC_EXPORT ScopedResource : public Resource {
virtual ~ScopedResource();
void Allocate(const gfx::Size& size,
- ResourceProvider::TextureUsageHint hint,
+ ResourceProvider::TextureHint hint,
ResourceFormat format);
void AllocateManaged(const gfx::Size& size,
GLenum target,
ResourceFormat format);
void Free();
- void Leak();
protected:
explicit ScopedResource(ResourceProvider* provider);
diff --git a/chromium/cc/resources/scoped_resource_unittest.cc b/chromium/cc/resources/scoped_resource_unittest.cc
index 50422213736..a141218a053 100644
--- a/chromium/cc/resources/scoped_resource_unittest.cc
+++ b/chromium/cc/resources/scoped_resource_unittest.cc
@@ -21,8 +21,14 @@ TEST(ScopedResourceTest, NewScopedResource) {
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1));
scoped_ptr<ScopedResource> texture =
ScopedResource::Create(resource_provider.get());
@@ -41,13 +47,18 @@ TEST(ScopedResourceTest, CreateScopedResource) {
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1));
scoped_ptr<ScopedResource> texture =
ScopedResource::Create(resource_provider.get());
- texture->Allocate(gfx::Size(30, 30),
- ResourceProvider::TextureUsageAny,
- RGBA_8888);
+ texture->Allocate(
+ gfx::Size(30, 30), ResourceProvider::TextureHintImmutable, RGBA_8888);
// The texture has an allocated byte-size now.
size_t expected_bytes = 30 * 30 * 4;
@@ -65,16 +76,21 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) {
scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
new TestSharedBitmapManager());
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(),
+ shared_bitmap_manager.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1));
{
scoped_ptr<ScopedResource> texture =
ScopedResource::Create(resource_provider.get());
EXPECT_EQ(0u, resource_provider->num_resources());
- texture->Allocate(gfx::Size(30, 30),
- ResourceProvider::TextureUsageAny,
- RGBA_8888);
+ texture->Allocate(
+ gfx::Size(30, 30), ResourceProvider::TextureHintImmutable, RGBA_8888);
EXPECT_LT(0u, texture->id());
EXPECT_EQ(1u, resource_provider->num_resources());
}
@@ -84,9 +100,8 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) {
scoped_ptr<ScopedResource> texture =
ScopedResource::Create(resource_provider.get());
EXPECT_EQ(0u, resource_provider->num_resources());
- texture->Allocate(gfx::Size(30, 30),
- ResourceProvider::TextureUsageAny,
- RGBA_8888);
+ texture->Allocate(
+ gfx::Size(30, 30), ResourceProvider::TextureHintImmutable, RGBA_8888);
EXPECT_LT(0u, texture->id());
EXPECT_EQ(1u, resource_provider->num_resources());
texture->Free();
@@ -94,37 +109,5 @@ TEST(ScopedResourceTest, ScopedResourceIsDeleted) {
}
}
-TEST(ScopedResourceTest, LeakScopedResource) {
- FakeOutputSurfaceClient output_surface_client;
- scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
- CHECK(output_surface->BindToClient(&output_surface_client));
-
- scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
- new TestSharedBitmapManager());
- scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
- output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
- {
- scoped_ptr<ScopedResource> texture =
- ScopedResource::Create(resource_provider.get());
-
- EXPECT_EQ(0u, resource_provider->num_resources());
- texture->Allocate(gfx::Size(30, 30),
- ResourceProvider::TextureUsageAny,
- RGBA_8888);
- EXPECT_LT(0u, texture->id());
- EXPECT_EQ(1u, resource_provider->num_resources());
-
- texture->Leak();
- EXPECT_EQ(0u, texture->id());
- EXPECT_EQ(1u, resource_provider->num_resources());
-
- texture->Free();
- EXPECT_EQ(0u, texture->id());
- EXPECT_EQ(1u, resource_provider->num_resources());
- }
-
- EXPECT_EQ(1u, resource_provider->num_resources());
-}
-
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/scoped_ui_resource.h b/chromium/cc/resources/scoped_ui_resource.h
index c257e1e25dc..0e5a02c7dbb 100644
--- a/chromium/cc/resources/scoped_ui_resource.h
+++ b/chromium/cc/resources/scoped_ui_resource.h
@@ -9,7 +9,6 @@
#include "cc/base/cc_export.h"
#include "cc/resources/ui_resource_bitmap.h"
#include "cc/resources/ui_resource_client.h"
-#include "ui/gfx/size.h"
namespace cc {
@@ -25,11 +24,10 @@ class CC_EXPORT ScopedUIResource : public UIResourceClient {
public:
static scoped_ptr<ScopedUIResource> Create(LayerTreeHost* host,
const UIResourceBitmap& bitmap);
- virtual ~ScopedUIResource();
+ ~ScopedUIResource() override;
// UIResourceClient implementation.
- virtual UIResourceBitmap GetBitmap(UIResourceId uid,
- bool resource_lost) OVERRIDE;
+ UIResourceBitmap GetBitmap(UIResourceId uid, bool resource_lost) override;
UIResourceId id() { return id_; }
protected:
diff --git a/chromium/cc/resources/shared_bitmap.h b/chromium/cc/resources/shared_bitmap.h
index a90e47a084c..ca1271061f0 100644
--- a/chromium/cc/resources/shared_bitmap.h
+++ b/chromium/cc/resources/shared_bitmap.h
@@ -10,7 +10,7 @@
#include "base/memory/shared_memory.h"
#include "cc/base/cc_export.h"
#include "gpu/command_buffer/common/mailbox.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace base { class SharedMemory; }
diff --git a/chromium/cc/resources/shared_bitmap_manager.h b/chromium/cc/resources/shared_bitmap_manager.h
index e6e49aff523..fe61b0998b8 100644
--- a/chromium/cc/resources/shared_bitmap_manager.h
+++ b/chromium/cc/resources/shared_bitmap_manager.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
#include "cc/resources/shared_bitmap.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
diff --git a/chromium/cc/resources/single_release_callback_impl.cc b/chromium/cc/resources/single_release_callback_impl.cc
new file mode 100644
index 00000000000..6f3c5353819
--- /dev/null
+++ b/chromium/cc/resources/single_release_callback_impl.cc
@@ -0,0 +1,34 @@
+// Copyright 2014 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/single_release_callback_impl.h"
+
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "cc/trees/blocking_task_runner.h"
+
+namespace cc {
+
+SingleReleaseCallbackImpl::SingleReleaseCallbackImpl(
+ const ReleaseCallbackImpl& callback)
+ : has_been_run_(false), callback_(callback) {
+ DCHECK(!callback_.is_null())
+ << "Use a NULL SingleReleaseCallbackImpl for an empty callback.";
+}
+
+SingleReleaseCallbackImpl::~SingleReleaseCallbackImpl() {
+ DCHECK(callback_.is_null() || has_been_run_)
+ << "SingleReleaseCallbackImpl was never run.";
+}
+
+void SingleReleaseCallbackImpl::Run(
+ uint32 sync_point,
+ bool is_lost,
+ BlockingTaskRunner* main_thread_task_runner) {
+ DCHECK(!has_been_run_) << "SingleReleaseCallbackImpl was run more than once.";
+ has_been_run_ = true;
+ callback_.Run(sync_point, is_lost, main_thread_task_runner);
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/single_release_callback_impl.h b/chromium/cc/resources/single_release_callback_impl.h
new file mode 100644
index 00000000000..41220dc29e8
--- /dev/null
+++ b/chromium/cc/resources/single_release_callback_impl.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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_SINGLE_RELEASE_CALLBACK_IMPL_H_
+#define CC_RESOURCES_SINGLE_RELEASE_CALLBACK_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/release_callback_impl.h"
+
+namespace cc {
+
+class CC_EXPORT SingleReleaseCallbackImpl {
+ public:
+ static scoped_ptr<SingleReleaseCallbackImpl> Create(
+ const ReleaseCallbackImpl& cb) {
+ return make_scoped_ptr(new SingleReleaseCallbackImpl(cb));
+ }
+
+ ~SingleReleaseCallbackImpl();
+
+ void Run(uint32 sync_point,
+ bool is_lost,
+ BlockingTaskRunner* main_thread_task_runner);
+
+ private:
+ explicit SingleReleaseCallbackImpl(const ReleaseCallbackImpl& callback);
+
+ bool has_been_run_;
+ ReleaseCallbackImpl callback_;
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_SINGLE_RELEASE_CALLBACK_IMPL_H_
diff --git a/chromium/cc/resources/skpicture_content_layer_updater.cc b/chromium/cc/resources/skpicture_content_layer_updater.cc
index eb12385f460..bd524f235f1 100644
--- a/chromium/cc/resources/skpicture_content_layer_updater.cc
+++ b/chromium/cc/resources/skpicture_content_layer_updater.cc
@@ -23,27 +23,27 @@ SkPictureContentLayerUpdater::SkPictureContentLayerUpdater(
SkPictureContentLayerUpdater::~SkPictureContentLayerUpdater() {}
void SkPictureContentLayerUpdater::PrepareToUpdate(
- const gfx::Rect& content_rect,
- const gfx::Size&,
+ const gfx::Size& content_size,
+ const gfx::Rect& paint_rect,
+ const gfx::Size& tile_size,
float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect) {
+ float contents_height_scale) {
SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(
- content_rect.width(), content_rect.height(), NULL, 0);
- DCHECK_EQ(content_rect.width(), canvas->getBaseLayerSize().width());
- DCHECK_EQ(content_rect.height(), canvas->getBaseLayerSize().height());
+ SkCanvas* canvas =
+ recorder.beginRecording(paint_rect.width(), paint_rect.height(), NULL, 0);
+ DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width());
+ DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height());
base::TimeTicks start_time =
rendering_stats_instrumentation_->StartRecording();
PaintContents(canvas,
- content_rect,
+ content_size,
+ paint_rect,
contents_width_scale,
- contents_height_scale,
- resulting_opaque_rect);
+ contents_height_scale);
base::TimeDelta duration =
rendering_stats_instrumentation_->EndRecording(start_time);
rendering_stats_instrumentation_->AddRecord(
- duration, content_rect.width() * content_rect.height());
+ duration, paint_rect.width() * paint_rect.height());
picture_ = skia::AdoptRef(recorder.endRecording());
}
diff --git a/chromium/cc/resources/skpicture_content_layer_updater.h b/chromium/cc/resources/skpicture_content_layer_updater.h
index a567976a2d8..ec49aaecdbb 100644
--- a/chromium/cc/resources/skpicture_content_layer_updater.h
+++ b/chromium/cc/resources/skpicture_content_layer_updater.h
@@ -23,13 +23,13 @@ class SkPictureContentLayerUpdater : public ContentLayerUpdater {
scoped_ptr<LayerPainter> painter,
RenderingStatsInstrumentation* stats_instrumentation,
int layer_id);
- virtual ~SkPictureContentLayerUpdater();
+ ~SkPictureContentLayerUpdater() override;
- virtual void PrepareToUpdate(const gfx::Rect& content_rect,
- const gfx::Size& tile_size,
- float contents_width_scale,
- float contents_height_scale,
- gfx::Rect* resulting_opaque_rect) OVERRIDE;
+ void PrepareToUpdate(const gfx::Size& content_size,
+ const gfx::Rect& paint_rect,
+ const gfx::Size& tile_size,
+ float contents_width_scale,
+ float contents_height_scale) override;
void DrawPicture(SkCanvas* canvas);
private:
diff --git a/chromium/cc/resources/task_graph_runner.cc b/chromium/cc/resources/task_graph_runner.cc
index 913c06d9b28..bcbc0dd351c 100644
--- a/chromium/cc/resources/task_graph_runner.cc
+++ b/chromium/cc/resources/task_graph_runner.cc
@@ -17,7 +17,10 @@ namespace {
class DependentIterator {
public:
DependentIterator(TaskGraph* graph, const Task* task)
- : graph_(graph), task_(task), current_index_(-1), current_node_(NULL) {
+ : graph_(graph),
+ task_(task),
+ current_index_(static_cast<size_t>(-1)),
+ current_node_(NULL) {
++(*this);
}
diff --git a/chromium/cc/resources/task_graph_runner.h b/chromium/cc/resources/task_graph_runner.h
index 0ed714097ad..2ff085d76cb 100644
--- a/chromium/cc/resources/task_graph_runner.h
+++ b/chromium/cc/resources/task_graph_runner.h
@@ -17,7 +17,7 @@ namespace cc {
class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> {
public:
- typedef std::vector<scoped_refptr<Task> > Vector;
+ typedef std::vector<scoped_refptr<Task>> Vector;
virtual void RunOnWorkerThread() = 0;
diff --git a/chromium/cc/resources/task_graph_runner_perftest.cc b/chromium/cc/resources/task_graph_runner_perftest.cc
index bfa4ebe8ac3..7809e587975 100644
--- a/chromium/cc/resources/task_graph_runner_perftest.cc
+++ b/chromium/cc/resources/task_graph_runner_perftest.cc
@@ -22,17 +22,17 @@ static const int kTimeCheckInterval = 10;
class PerfTaskImpl : public Task {
public:
- typedef std::vector<scoped_refptr<PerfTaskImpl> > Vector;
+ typedef std::vector<scoped_refptr<PerfTaskImpl>> Vector;
PerfTaskImpl() {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {}
+ void RunOnWorkerThread() override {}
void Reset() { did_run_ = false; }
private:
- virtual ~PerfTaskImpl() {}
+ ~PerfTaskImpl() override {}
DISALLOW_COPY_AND_ASSIGN(PerfTaskImpl);
};
@@ -45,11 +45,11 @@ class TaskGraphRunnerPerfTest : public testing::Test {
kTimeCheckInterval) {}
// Overridden from testing::Test:
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
task_graph_runner_ = make_scoped_ptr(new TaskGraphRunner);
namespace_token_ = task_graph_runner_->GetNamespaceToken();
}
- virtual void TearDown() OVERRIDE { task_graph_runner_.reset(); }
+ virtual void TearDown() override { task_graph_runner_ = nullptr; }
void AfterTest(const std::string& test_name) {
// Format matches chrome/test/perf/perf_test.h:PrintResult
diff --git a/chromium/cc/resources/task_graph_runner_unittest.cc b/chromium/cc/resources/task_graph_runner_unittest.cc
index 1a6256c5835..ad23b66087a 100644
--- a/chromium/cc/resources/task_graph_runner_unittest.cc
+++ b/chromium/cc/resources/task_graph_runner_unittest.cc
@@ -118,7 +118,7 @@ class TaskGraphRunnerTestBase {
: test_(test), namespace_index_(namespace_index), id_(id) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {
+ void RunOnWorkerThread() override {
test_->RunTaskOnWorkerThread(namespace_index_, id_);
}
@@ -127,7 +127,7 @@ class TaskGraphRunnerTestBase {
}
protected:
- virtual ~FakeTaskImpl() {}
+ ~FakeTaskImpl() override {}
private:
TaskGraphRunnerTestBase* test_;
@@ -145,10 +145,10 @@ class TaskGraphRunnerTestBase {
: FakeTaskImpl(test, namespace_index, id) {}
// Overridden from FakeTaskImpl:
- virtual void CompleteOnOriginThread() OVERRIDE {}
+ void CompleteOnOriginThread() override {}
private:
- virtual ~FakeDependentTaskImpl() {}
+ ~FakeDependentTaskImpl() override {}
DISALLOW_COPY_AND_ASSIGN(FakeDependentTaskImpl);
};
@@ -167,7 +167,7 @@ class TaskGraphRunnerTest : public TaskGraphRunnerTestBase,
public base::DelegateSimpleThread::Delegate {
public:
// Overridden from testing::Test:
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
const size_t num_threads = GetParam();
while (workers_.size() < num_threads) {
scoped_ptr<base::DelegateSimpleThread> worker =
@@ -179,7 +179,7 @@ class TaskGraphRunnerTest : public TaskGraphRunnerTestBase,
for (int i = 0; i < kNamespaceCount; ++i)
namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
}
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
task_graph_runner_->Shutdown();
while (workers_.size()) {
scoped_ptr<base::DelegateSimpleThread> worker = workers_.take_front();
@@ -189,7 +189,7 @@ class TaskGraphRunnerTest : public TaskGraphRunnerTestBase,
private:
// Overridden from base::DelegateSimpleThread::Delegate:
- virtual void Run() OVERRIDE { task_graph_runner_->Run(); }
+ void Run() override { task_graph_runner_->Run(); }
ScopedPtrDeque<base::DelegateSimpleThread> workers_;
};
@@ -285,21 +285,21 @@ class TaskGraphRunnerSingleThreadTest
public base::DelegateSimpleThread::Delegate {
public:
// Overridden from testing::Test:
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
worker_.reset(new base::DelegateSimpleThread(this, "TestWorker"));
worker_->Start();
for (int i = 0; i < kNamespaceCount; ++i)
namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
}
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
task_graph_runner_->Shutdown();
worker_->Join();
}
private:
// Overridden from base::DelegateSimpleThread::Delegate:
- virtual void Run() OVERRIDE { task_graph_runner_->Run(); }
+ void Run() override { task_graph_runner_->Run(); }
scoped_ptr<base::DelegateSimpleThread> worker_;
};
diff --git a/chromium/cc/resources/texture_mailbox.cc b/chromium/cc/resources/texture_mailbox.cc
index 90ce6be79c7..92736f41fe7 100644
--- a/chromium/cc/resources/texture_mailbox.cc
+++ b/chromium/cc/resources/texture_mailbox.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "cc/resources/shared_bitmap.h"
-#include "third_party/khronos/GLES2/gl2.h"
namespace cc {
diff --git a/chromium/cc/resources/texture_mailbox.h b/chromium/cc/resources/texture_mailbox.h
index 4626dd36698..4a0b76afea0 100644
--- a/chromium/cc/resources/texture_mailbox.h
+++ b/chromium/cc/resources/texture_mailbox.h
@@ -7,11 +7,10 @@
#include <string>
-#include "base/callback.h"
#include "base/memory/shared_memory.h"
#include "cc/base/cc_export.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
diff --git a/chromium/cc/resources/texture_mailbox_deleter_unittest.cc b/chromium/cc/resources/texture_mailbox_deleter_unittest.cc
index 0d04c9917f0..05e33a313aa 100644
--- a/chromium/cc/resources/texture_mailbox_deleter_unittest.cc
+++ b/chromium/cc/resources/texture_mailbox_deleter_unittest.cc
@@ -34,7 +34,7 @@ TEST(TextureMailboxDeleterTest, Destroy) {
// When the deleter is destroyed, it immediately drops its ref on the
// ContextProvider, and deletes the texture.
- deleter.reset();
+ deleter = nullptr;
EXPECT_TRUE(context_provider->HasOneRef());
EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
diff --git a/chromium/cc/resources/texture_uploader.cc b/chromium/cc/resources/texture_uploader.cc
index eb4e6c097a4..9526fcb9238 100644
--- a/chromium/cc/resources/texture_uploader.cc
+++ b/chromium/cc/resources/texture_uploader.cc
@@ -10,14 +10,13 @@
#include "base/debug/trace_event.h"
#include "base/metrics/histogram.h"
#include "cc/base/util.h"
-#include "cc/resources/prioritized_resource.h"
#include "cc/resources/resource.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/vector2d.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
using gpu::gles2::GLES2Interface;
@@ -116,6 +115,12 @@ double TextureUploader::EstimatedTexturesPerSecond() {
}
void TextureUploader::BeginQuery() {
+ // Check to see if any of the pending queries are free before allocating a
+ // new one. If this is not done, queries may be allocated without bound.
+ // http://crbug.com/398072
+ if (available_queries_.empty())
+ ProcessQueries();
+
if (available_queries_.empty())
available_queries_.push_back(Query::Create(gl_));
diff --git a/chromium/cc/resources/texture_uploader_unittest.cc b/chromium/cc/resources/texture_uploader_unittest.cc
index 8390b28ceef..72491727291 100644
--- a/chromium/cc/resources/texture_uploader_unittest.cc
+++ b/chromium/cc/resources/texture_uploader_unittest.cc
@@ -19,7 +19,7 @@ class TextureUploadTestContext : public gpu::gles2::GLES2InterfaceStub {
public:
TextureUploadTestContext() : result_available_(0), unpack_alignment_(4) {}
- virtual void PixelStorei(GLenum pname, GLint param) OVERRIDE {
+ void PixelStorei(GLenum pname, GLint param) override {
switch (pname) {
case GL_UNPACK_ALIGNMENT:
// Param should be a power of two <= 8.
@@ -41,9 +41,7 @@ class TextureUploadTestContext : public gpu::gles2::GLES2InterfaceStub {
}
}
- virtual void GetQueryObjectuivEXT(GLuint,
- GLenum type,
- GLuint* value) OVERRIDE {
+ void GetQueryObjectuivEXT(GLuint, GLenum type, GLuint* value) override {
switch (type) {
case GL_QUERY_RESULT_AVAILABLE_EXT:
*value = result_available_;
@@ -54,15 +52,15 @@ class TextureUploadTestContext : public gpu::gles2::GLES2InterfaceStub {
}
}
- virtual void TexSubImage2D(GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const void* pixels) OVERRIDE {
+ void TexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) override {
EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
EXPECT_EQ(0, level);
EXPECT_LE(0, width);
@@ -217,6 +215,15 @@ TEST(TextureUploaderTest, UploadContentsTest) {
}
UploadTexture(uploader.get(), RGBA_8888, gfx::Size(41, 43), buffer);
+ // Upload a tightly packed 41x86 ALPHA texture.
+ memset(buffer, 0, sizeof(buffer));
+ for (int i = 0; i < 86; ++i) {
+ // Mark the beginning and end of each row, for the test.
+ buffer[i * 1 * 41] = 0x1;
+ buffer[(i + 1) * 41 - 1] = 0x2;
+ }
+ UploadTexture(uploader.get(), ALPHA_8, gfx::Size(41, 86), buffer);
+
// Upload a tightly packed 82x86 LUMINANCE texture.
memset(buffer, 0, sizeof(buffer));
for (int i = 0; i < 86; ++i) {
diff --git a/chromium/cc/resources/tile.cc b/chromium/cc/resources/tile.cc
index d59dc029ccc..d6bd3c4b583 100644
--- a/chromium/cc/resources/tile.cc
+++ b/chromium/cc/resources/tile.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/debug/trace_event_argument.h"
#include "cc/base/math_util.h"
#include "cc/debug/traced_value.h"
#include "cc/resources/tile_manager.h"
@@ -16,25 +17,29 @@ namespace cc {
Tile::Id Tile::s_next_id_ = 0;
Tile::Tile(TileManager* tile_manager,
- PicturePileImpl* picture_pile,
+ RasterSource* raster_source,
const gfx::Size& tile_size,
const gfx::Rect& content_rect,
- const gfx::Rect& opaque_rect,
float contents_scale,
int layer_id,
int source_frame_number,
int flags)
: RefCountedManaged<Tile>(tile_manager),
tile_manager_(tile_manager),
- tile_size_(tile_size),
+ size_(tile_size),
content_rect_(content_rect),
contents_scale_(contents_scale),
- opaque_rect_(opaque_rect),
layer_id_(layer_id),
source_frame_number_(source_frame_number),
flags_(flags),
+ is_shared_(false),
+ tiling_i_index_(-1),
+ tiling_j_index_(-1),
+ required_for_activation_(false),
id_(s_next_id_++) {
- set_picture_pile(picture_pile);
+ set_raster_source(raster_source);
+ for (int i = 0; i < NUM_TREES; i++)
+ is_occluded_[i] = false;
}
Tile::~Tile() {
@@ -43,60 +48,43 @@ Tile::~Tile() {
"cc::Tile", this);
}
-void Tile::SetPriority(WhichTree tree, const TilePriority& priority) {
- if (priority == priority_[tree])
- return;
+void Tile::AsValueInto(base::debug::TracedValue* res) const {
+ TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug"), res, "cc::Tile", this);
+ TracedValue::SetIDRef(raster_source_.get(), res, "picture_pile");
+ res->SetDouble("contents_scale", contents_scale_);
- priority_[tree] = priority;
- tile_manager_->DidChangeTilePriority(this);
-}
+ res->BeginArray("content_rect");
+ MathUtil::AddToTracedValue(content_rect_, res);
+ res->EndArray();
-void Tile::MarkRequiredForActivation() {
- if (priority_[PENDING_TREE].required_for_activation)
- return;
+ res->SetInteger("layer_id", layer_id_);
- priority_[PENDING_TREE].required_for_activation = true;
- tile_manager_->DidChangeTilePriority(this);
-}
+ res->BeginDictionary("active_priority");
+ priority_[ACTIVE_TREE].AsValueInto(res);
+ res->EndDictionary();
-scoped_ptr<base::Value> Tile::AsValue() const {
- scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
- TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
- TRACE_DISABLED_BY_DEFAULT("cc.debug"), res.get(), "cc::Tile", this);
- res->Set("picture_pile",
- TracedValue::CreateIDRef(picture_pile_.get()).release());
- res->SetDouble("contents_scale", contents_scale_);
- res->Set("content_rect", MathUtil::AsValue(content_rect_).release());
- res->SetInteger("layer_id", layer_id_);
- res->Set("active_priority", priority_[ACTIVE_TREE].AsValue().release());
- res->Set("pending_priority", priority_[PENDING_TREE].AsValue().release());
- res->Set("managed_state", managed_state_.AsValue().release());
- res->SetBoolean("use_picture_analysis", use_picture_analysis());
- return res.PassAs<base::Value>();
-}
+ res->BeginDictionary("pending_priority");
+ priority_[PENDING_TREE].AsValueInto(res);
+ res->EndDictionary();
-size_t Tile::GPUMemoryUsageInBytes() const {
- size_t total_size = 0;
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode)
- total_size += managed_state_.tile_versions[mode].GPUMemoryUsageInBytes();
- return total_size;
-}
+ res->BeginDictionary("managed_state");
+ managed_state_.AsValueInto(res);
+ res->EndDictionary();
-RasterMode Tile::DetermineRasterModeForTree(WhichTree tree) const {
- return DetermineRasterModeForResolution(priority(tree).resolution);
+ res->SetBoolean("use_picture_analysis", use_picture_analysis());
+
+ res->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
}
-RasterMode Tile::DetermineOverallRasterMode() const {
- return DetermineRasterModeForResolution(managed_state_.resolution);
+size_t Tile::GPUMemoryUsageInBytes() const {
+ if (managed_state_.draw_info.resource_)
+ return managed_state_.draw_info.resource_->bytes();
+ return 0;
}
-RasterMode Tile::DetermineRasterModeForResolution(
- TileResolution resolution) const {
- RasterMode current_mode = managed_state_.raster_mode;
- RasterMode raster_mode = resolution == LOW_RESOLUTION
- ? LOW_QUALITY_RASTER_MODE
- : HIGH_QUALITY_RASTER_MODE;
- return std::min(raster_mode, current_mode);
+bool Tile::HasRasterTask() const {
+ return !!managed_state_.raster_task.get();
}
} // namespace cc
diff --git a/chromium/cc/resources/tile.h b/chromium/cc/resources/tile.h
index 69ef56fde8c..c6413677eb9 100644
--- a/chromium/cc/resources/tile.h
+++ b/chromium/cc/resources/tile.h
@@ -6,15 +6,12 @@
#define CC_RESOURCES_TILE_H_
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
#include "cc/base/ref_counted_managed.h"
#include "cc/resources/managed_tile_state.h"
-#include "cc/resources/picture_pile_impl.h"
-#include "cc/resources/raster_mode.h"
+#include "cc/resources/raster_source.h"
#include "cc/resources/tile_priority.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -28,13 +25,9 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
return id_;
}
- PicturePileImpl* picture_pile() {
- return picture_pile_.get();
- }
+ RasterSource* raster_source() { return raster_source_.get(); }
- const PicturePileImpl* picture_pile() const {
- return picture_pile_.get();
- }
+ const RasterSource* raster_source() const { return raster_source_.get(); }
const TilePriority& priority(WhichTree tree) const {
return priority_[tree];
@@ -48,9 +41,10 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
return priority_[PENDING_TREE];
case SAME_PRIORITY_FOR_BOTH_TREES:
return combined_priority();
+ default:
+ NOTREACHED();
+ return TilePriority();
}
- NOTREACHED();
- return TilePriority();
}
TilePriority combined_priority() const {
@@ -58,49 +52,63 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
priority_[PENDING_TREE]);
}
- void SetPriority(WhichTree tree, const TilePriority& priority);
+ void SetPriority(WhichTree tree, const TilePriority& priority) {
+ priority_[tree] = priority;
+ }
+
+ // TODO(vmpstr): Move this to the iterators.
+ void set_is_occluded(WhichTree tree, bool is_occluded) {
+ is_occluded_[tree] = is_occluded;
+ }
+
+ bool is_occluded(WhichTree tree) const { return is_occluded_[tree]; }
- void MarkRequiredForActivation();
+ void set_shared(bool is_shared) { is_shared_ = is_shared; }
+ bool is_shared() const { return is_shared_; }
+
+ bool is_occluded_for_tree_priority(TreePriority tree_priority) const {
+ switch (tree_priority) {
+ case SMOOTHNESS_TAKES_PRIORITY:
+ return is_occluded_[ACTIVE_TREE];
+ case NEW_CONTENT_TAKES_PRIORITY:
+ return is_occluded_[PENDING_TREE];
+ case SAME_PRIORITY_FOR_BOTH_TREES:
+ return is_occluded_[ACTIVE_TREE] && is_occluded_[PENDING_TREE];
+ default:
+ NOTREACHED();
+ return false;
+ }
+ }
- bool required_for_activation() const {
- return priority_[PENDING_TREE].required_for_activation;
+ // TODO(vmpstr): Move this to the iterators.
+ bool required_for_activation() const { return required_for_activation_; }
+ void set_required_for_activation(bool is_required) {
+ required_for_activation_ = is_required;
}
bool use_picture_analysis() const {
return !!(flags_ & USE_PICTURE_ANALYSIS);
}
- bool NeedsRasterForMode(RasterMode mode) const {
- return !managed_state_.tile_versions[mode].IsReadyToDraw();
- }
-
- bool HasResources() const {
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- if (managed_state_.tile_versions[mode].has_resource())
- return true;
- }
- return false;
+ bool HasResources() const { return managed_state_.draw_info.has_resource(); }
+ bool NeedsRaster() const {
+ return managed_state_.draw_info.mode() ==
+ ManagedTileState::DrawInfo::PICTURE_PILE_MODE ||
+ !managed_state_.draw_info.IsReadyToDraw();
}
- scoped_ptr<base::Value> AsValue() const;
+ void AsValueInto(base::debug::TracedValue* dict) const;
inline bool IsReadyToDraw() const {
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- if (managed_state_.tile_versions[mode].IsReadyToDraw())
- return true;
- }
- return false;
+ return managed_state_.draw_info.IsReadyToDraw();
}
- const ManagedTileState::TileVersion& GetTileVersionForDrawing() const {
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- if (managed_state_.tile_versions[mode].IsReadyToDraw())
- return managed_state_.tile_versions[mode];
- }
- return managed_state_.tile_versions[HIGH_QUALITY_RASTER_MODE];
+ const ManagedTileState::DrawInfo& draw_info() const {
+ return managed_state_.draw_info;
}
- gfx::Rect opaque_rect() const { return opaque_rect_; }
+ ManagedTileState::DrawInfo& draw_info() { return managed_state_.draw_info; }
+
float contents_scale() const { return contents_scale_; }
gfx::Rect content_rect() const { return content_rect_; }
@@ -108,25 +116,24 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
int source_frame_number() const { return source_frame_number_; }
- void set_picture_pile(scoped_refptr<PicturePileImpl> pile) {
- DCHECK(pile->CanRaster(contents_scale_, content_rect_));
- picture_pile_ = pile;
+ void set_raster_source(scoped_refptr<RasterSource> raster_source) {
+ DCHECK(raster_source->CoversRect(content_rect_, contents_scale_))
+ << "Recording rect: "
+ << gfx::ScaleToEnclosingRect(content_rect_, 1.f / contents_scale_)
+ .ToString();
+ raster_source_ = raster_source;
}
size_t GPUMemoryUsageInBytes() const;
- gfx::Size size() const { return tile_size_.size(); }
-
- RasterMode DetermineRasterModeForTree(WhichTree tree) const;
- RasterMode DetermineOverallRasterMode() const;
+ gfx::Size size() const { return size_; }
- // Functionality used in tests.
- RasterMode GetRasterModeForTesting() const {
- return managed_state().raster_mode;
- }
- ManagedTileState::TileVersion& GetTileVersionForTesting(RasterMode mode) {
- return managed_state_.tile_versions[mode];
+ void set_tiling_index(int i, int j) {
+ tiling_i_index_ = i;
+ tiling_j_index_ = j;
}
+ int tiling_i_index() const { return tiling_i_index_; }
+ int tiling_j_index() const { return tiling_j_index_; }
private:
friend class TileManager;
@@ -137,10 +144,9 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
// Methods called by by tile manager.
Tile(TileManager* tile_manager,
- PicturePileImpl* picture_pile,
+ RasterSource* raster_source,
const gfx::Size& tile_size,
const gfx::Rect& content_rect,
- const gfx::Rect& opaque_rect,
float contents_scale,
int layer_id,
int source_frame_number,
@@ -149,20 +155,25 @@ class CC_EXPORT Tile : public RefCountedManaged<Tile> {
ManagedTileState& managed_state() { return managed_state_; }
const ManagedTileState& managed_state() const { return managed_state_; }
- RasterMode DetermineRasterModeForResolution(TileResolution resolution) const;
+
+ bool HasRasterTask() const;
TileManager* tile_manager_;
- scoped_refptr<PicturePileImpl> picture_pile_;
- gfx::Rect tile_size_;
+ scoped_refptr<RasterSource> raster_source_;
+ gfx::Size size_;
gfx::Rect content_rect_;
float contents_scale_;
- gfx::Rect opaque_rect_;
+ bool is_occluded_[NUM_TREES];
TilePriority priority_[NUM_TREES];
ManagedTileState managed_state_;
int layer_id_;
int source_frame_number_;
int flags_;
+ bool is_shared_;
+ int tiling_i_index_;
+ int tiling_j_index_;
+ bool required_for_activation_;
Id id_;
static Id s_next_id_;
diff --git a/chromium/cc/resources/tile_manager.cc b/chromium/cc/resources/tile_manager.cc
index d508f6a0a17..8b6a72afc6f 100644
--- a/chromium/cc/resources/tile_manager.cc
+++ b/chromium/cc/resources/tile_manager.cc
@@ -9,6 +9,7 @@
#include <string>
#include "base/bind.h"
+#include "base/debug/trace_event_argument.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
@@ -16,12 +17,10 @@
#include "cc/debug/frame_viewer_instrumentation.h"
#include "cc/debug/traced_value.h"
#include "cc/layers/picture_layer_impl.h"
-#include "cc/resources/raster_worker_pool.h"
+#include "cc/resources/raster_buffer.h"
+#include "cc/resources/rasterizer.h"
#include "cc/resources/tile.h"
-#include "skia/ext/paint_simplifier.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/geometry/rect_conversions.h"
namespace cc {
namespace {
@@ -34,82 +33,71 @@ class RasterTaskImpl : public RasterTask {
public:
RasterTaskImpl(
const Resource* resource,
- PicturePileImpl* picture_pile,
+ RasterSource* raster_source,
const gfx::Rect& content_rect,
float contents_scale,
- RasterMode raster_mode,
TileResolution tile_resolution,
int layer_id,
const void* tile_id,
int source_frame_number,
bool analyze_picture,
RenderingStatsInstrumentation* rendering_stats,
- const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply,
+ const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>&
+ reply,
ImageDecodeTask::Vector* dependencies)
: RasterTask(resource, dependencies),
- picture_pile_(picture_pile),
+ raster_source_(raster_source),
content_rect_(content_rect),
contents_scale_(contents_scale),
- raster_mode_(raster_mode),
tile_resolution_(tile_resolution),
layer_id_(layer_id),
tile_id_(tile_id),
source_frame_number_(source_frame_number),
analyze_picture_(analyze_picture),
rendering_stats_(rendering_stats),
- reply_(reply),
- canvas_(NULL) {}
+ reply_(reply) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {
+ void RunOnWorkerThread() override {
TRACE_EVENT0("cc", "RasterizerTaskImpl::RunOnWorkerThread");
- DCHECK(picture_pile_);
- if (canvas_) {
- AnalyzeAndRaster(picture_pile_->GetCloneForDrawingOnThread(
- RasterWorkerPool::GetPictureCloneIndexForCurrentThread()));
+ DCHECK(raster_source_.get());
+ DCHECK(raster_buffer_);
+
+ if (analyze_picture_) {
+ Analyze(raster_source_.get());
+ if (analysis_.is_solid_color)
+ return;
}
+
+ Raster(raster_source_.get());
}
// Overridden from RasterizerTask:
- virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
- DCHECK(!canvas_);
- canvas_ = client->AcquireCanvasForRaster(this);
+ void ScheduleOnOriginThread(RasterizerTaskClient* client) override {
+ DCHECK(!raster_buffer_);
+ raster_buffer_ = client->AcquireBufferForRaster(resource());
}
- virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
- canvas_ = NULL;
- client->ReleaseCanvasForRaster(this);
+ void CompleteOnOriginThread(RasterizerTaskClient* client) override {
+ client->ReleaseBufferForRaster(raster_buffer_.Pass());
}
- virtual void RunReplyOnOriginThread() OVERRIDE {
- DCHECK(!canvas_);
+ void RunReplyOnOriginThread() override {
+ DCHECK(!raster_buffer_);
reply_.Run(analysis_, !HasFinishedRunning());
}
protected:
- virtual ~RasterTaskImpl() { DCHECK(!canvas_); }
+ ~RasterTaskImpl() override { DCHECK(!raster_buffer_); }
private:
- void AnalyzeAndRaster(PicturePileImpl* picture_pile) {
- DCHECK(picture_pile);
- DCHECK(canvas_);
-
- if (analyze_picture_) {
- Analyze(picture_pile);
- if (analysis_.is_solid_color)
- return;
- }
-
- Raster(picture_pile);
- }
-
- void Analyze(PicturePileImpl* picture_pile) {
+ void Analyze(const RasterSource* raster_source) {
frame_viewer_instrumentation::ScopedAnalyzeTask analyze_task(
tile_id_, tile_resolution_, source_frame_number_, layer_id_);
- DCHECK(picture_pile);
+ DCHECK(raster_source);
- picture_pile->AnalyzeInRect(
- content_rect_, contents_scale_, &analysis_, rendering_stats_);
+ raster_source->PerformSolidColorAnalysis(content_rect_, contents_scale_,
+ &analysis_);
// Record the solid color prediction.
UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
@@ -119,67 +107,31 @@ class RasterTaskImpl : public RasterTask {
analysis_.is_solid_color &= kUseColorEstimator;
}
- void Raster(PicturePileImpl* picture_pile) {
+ void Raster(const RasterSource* raster_source) {
frame_viewer_instrumentation::ScopedRasterTask raster_task(
- tile_id_,
- tile_resolution_,
- source_frame_number_,
- layer_id_,
- raster_mode_);
+ tile_id_, tile_resolution_, source_frame_number_, layer_id_);
devtools_instrumentation::ScopedLayerTask layer_task(
devtools_instrumentation::kRasterTask, layer_id_);
- skia::RefPtr<SkDrawFilter> draw_filter;
- switch (raster_mode_) {
- case LOW_QUALITY_RASTER_MODE:
- draw_filter = skia::AdoptRef(new skia::PaintSimplifier);
- break;
- case HIGH_QUALITY_RASTER_MODE:
- break;
- case NUM_RASTER_MODES:
- default:
- NOTREACHED();
- }
- canvas_->setDrawFilter(draw_filter.get());
-
- base::TimeDelta prev_rasterize_time =
- rendering_stats_->impl_thread_rendering_stats().rasterize_time;
-
- // Only record rasterization time for highres tiles, because
- // lowres tiles are not required for activation and therefore
- // introduce noise in the measurement (sometimes they get rasterized
- // before we draw and sometimes they aren't)
- RenderingStatsInstrumentation* stats =
- tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL;
- DCHECK(picture_pile);
- picture_pile->RasterToBitmap(
- canvas_, content_rect_, contents_scale_, stats);
-
- if (rendering_stats_->record_rendering_stats()) {
- base::TimeDelta current_rasterize_time =
- rendering_stats_->impl_thread_rendering_stats().rasterize_time;
- HISTOGRAM_CUSTOM_COUNTS(
- "Renderer4.PictureRasterTimeUS",
- (current_rasterize_time - prev_rasterize_time).InMicroseconds(),
- 0,
- 100000,
- 100);
- }
+ DCHECK(raster_source);
+
+ raster_buffer_->Playback(raster_source_.get(), content_rect_,
+ contents_scale_);
}
- PicturePileImpl::Analysis analysis_;
- scoped_refptr<PicturePileImpl> picture_pile_;
+ RasterSource::SolidColorAnalysis analysis_;
+ scoped_refptr<RasterSource> raster_source_;
gfx::Rect content_rect_;
float contents_scale_;
- RasterMode raster_mode_;
TileResolution tile_resolution_;
int layer_id_;
const void* tile_id_;
int source_frame_number_;
bool analyze_picture_;
RenderingStatsInstrumentation* rendering_stats_;
- const base::Callback<void(const PicturePileImpl::Analysis&, bool)> reply_;
- SkCanvas* canvas_;
+ const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>
+ reply_;
+ scoped_ptr<RasterBuffer> raster_buffer_;
DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl);
};
@@ -196,7 +148,7 @@ class ImageDecodeTaskImpl : public ImageDecodeTask {
reply_(reply) {}
// Overridden from Task:
- virtual void RunOnWorkerThread() OVERRIDE {
+ void RunOnWorkerThread() override {
TRACE_EVENT0("cc", "ImageDecodeTaskImpl::RunOnWorkerThread");
devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
@@ -207,14 +159,12 @@ class ImageDecodeTaskImpl : public ImageDecodeTask {
}
// Overridden from RasterizerTask:
- virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
- virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
- virtual void RunReplyOnOriginThread() OVERRIDE {
- reply_.Run(!HasFinishedRunning());
- }
+ void ScheduleOnOriginThread(RasterizerTaskClient* client) override {}
+ void CompleteOnOriginThread(RasterizerTaskClient* client) override {}
+ void RunReplyOnOriginThread() override { reply_.Run(!HasFinishedRunning()); }
protected:
- virtual ~ImageDecodeTaskImpl() {}
+ ~ImageDecodeTaskImpl() override {}
private:
skia::RefPtr<SkPixelRef> pixel_ref_;
@@ -225,123 +175,18 @@ class ImageDecodeTaskImpl : public ImageDecodeTask {
DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
};
-const size_t kScheduledRasterTasksLimit = 32u;
-
-// Memory limit policy works by mapping some bin states to the NEVER bin.
-const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
- // [ALLOW_NOTHING]
- {NEVER_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NEVER_BIN, // [NOW_BIN]
- NEVER_BIN, // [SOON_BIN]
- NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- NEVER_BIN, // [EVENTUALLY_BIN]
- NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- NEVER_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- },
- // [ALLOW_ABSOLUTE_MINIMUM]
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- NEVER_BIN, // [SOON_BIN]
- NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- NEVER_BIN, // [EVENTUALLY_BIN]
- NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- NEVER_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- },
- // [ALLOW_PREPAINT_ONLY]
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- NEVER_BIN, // [EVENTUALLY_BIN]
- NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- NEVER_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- },
- // [ALLOW_ANYTHING]
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- EVENTUALLY_BIN, // [EVENTUALLY_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- AT_LAST_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- }};
-
-// Ready to draw works by mapping NOW_BIN to NOW_AND_READY_TO_DRAW_BIN.
-const ManagedTileBin kBinReadyToDrawMap[2][NUM_BINS] = {
- // Not ready
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- EVENTUALLY_BIN, // [EVENTUALLY_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- AT_LAST_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- },
- // Ready
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_AND_READY_TO_DRAW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- EVENTUALLY_BIN, // [EVENTUALLY_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- AT_LAST_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- }};
-
-// Active works by mapping some bin stats to equivalent _ACTIVE_BIN state.
-const ManagedTileBin kBinIsActiveMap[2][NUM_BINS] = {
- // Inactive
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- EVENTUALLY_BIN, // [EVENTUALLY_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- AT_LAST_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- },
- // Active
- {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
- NOW_BIN, // [NOW_BIN]
- SOON_BIN, // [SOON_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
- EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
- AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_BIN]
- NEVER_BIN // [NEVER_BIN]
- }};
-
-// Determine bin based on three categories of tiles: things we need now,
-// things we need soon, and eventually.
-inline ManagedTileBin BinFromTilePriority(const TilePriority& prio) {
- if (prio.priority_bin == TilePriority::NOW)
- return NOW_BIN;
-
- if (prio.priority_bin == TilePriority::SOON)
- return SOON_BIN;
-
- if (prio.distance_to_visible == std::numeric_limits<float>::infinity())
- return NEVER_BIN;
-
- return EVENTUALLY_BIN;
-}
-
} // namespace
RasterTaskCompletionStats::RasterTaskCompletionStats()
: completed_count(0u), canceled_count(0u) {}
-scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
- const RasterTaskCompletionStats& stats) {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
state->SetInteger("completed_count", stats.completed_count);
state->SetInteger("canceled_count", stats.canceled_count);
- return state.PassAs<base::Value>();
+ return state;
}
// static
@@ -350,35 +195,35 @@ scoped_ptr<TileManager> TileManager::Create(
base::SequencedTaskRunner* task_runner,
ResourcePool* resource_pool,
Rasterizer* rasterizer,
- RenderingStatsInstrumentation* rendering_stats_instrumentation) {
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ size_t scheduled_raster_task_limit) {
return make_scoped_ptr(new TileManager(client,
task_runner,
resource_pool,
rasterizer,
- rendering_stats_instrumentation));
+ rendering_stats_instrumentation,
+ scheduled_raster_task_limit));
}
TileManager::TileManager(
TileManagerClient* client,
- base::SequencedTaskRunner* task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
ResourcePool* resource_pool,
Rasterizer* rasterizer,
- RenderingStatsInstrumentation* rendering_stats_instrumentation)
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ size_t scheduled_raster_task_limit)
: client_(client),
task_runner_(task_runner),
resource_pool_(resource_pool),
rasterizer_(rasterizer),
- prioritized_tiles_dirty_(false),
- all_tiles_that_need_to_be_rasterized_have_memory_(true),
- all_tiles_required_for_activation_have_memory_(true),
- bytes_releasable_(0),
- resources_releasable_(0),
- ever_exceeded_memory_budget_(false),
+ scheduled_raster_task_limit_(scheduled_raster_task_limit),
+ all_tiles_that_need_to_be_rasterized_are_scheduled_(true),
rendering_stats_instrumentation_(rendering_stats_instrumentation),
did_initialize_visible_tile_(false),
did_check_for_completed_tasks_since_last_schedule_tasks_(true),
+ did_oom_on_last_assign_(false),
ready_to_activate_check_notifier_(
- task_runner_,
+ task_runner_.get(),
base::Bind(&TileManager::CheckIfReadyToActivate,
base::Unretained(this))) {
rasterizer_->SetClient(this);
@@ -389,9 +234,6 @@ TileManager::~TileManager() {
// our memory usage to drop to zero.
global_state_ = GlobalStateThatImpactsTilePriority();
- CleanUpReleasedTiles();
- DCHECK_EQ(0u, tiles_.size());
-
RasterTaskQueue empty;
rasterizer_->ScheduleTasks(&empty);
orphan_raster_tasks_.clear();
@@ -401,35 +243,41 @@ TileManager::~TileManager() {
rasterizer_->Shutdown();
rasterizer_->CheckForCompletedTasks();
- DCHECK_EQ(0u, bytes_releasable_);
- DCHECK_EQ(0u, resources_releasable_);
+ FreeResourcesForReleasedTiles();
+ CleanUpReleasedTiles();
}
void TileManager::Release(Tile* tile) {
- prioritized_tiles_dirty_ = true;
released_tiles_.push_back(tile);
}
-void TileManager::DidChangeTilePriority(Tile* tile) {
- prioritized_tiles_dirty_ = true;
+TaskSetCollection TileManager::TasksThatShouldBeForcedToComplete() const {
+ TaskSetCollection tasks_that_should_be_forced_to_complete;
+ if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY)
+ tasks_that_should_be_forced_to_complete[REQUIRED_FOR_ACTIVATION] = true;
+ return tasks_that_should_be_forced_to_complete;
}
-bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
- return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY;
-}
-
-void TileManager::CleanUpReleasedTiles() {
+void TileManager::FreeResourcesForReleasedTiles() {
for (std::vector<Tile*>::iterator it = released_tiles_.begin();
it != released_tiles_.end();
++it) {
Tile* tile = *it;
- ManagedTileState& mts = tile->managed_state();
+ FreeResourcesForTile(tile);
+ }
+}
+
+void TileManager::CleanUpReleasedTiles() {
+ std::vector<Tile*>::iterator it = released_tiles_.begin();
+ while (it != released_tiles_.end()) {
+ Tile* tile = *it;
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- FreeResourceForTile(tile, static_cast<RasterMode>(mode));
- orphan_raster_tasks_.push_back(mts.tile_versions[mode].raster_task_);
+ if (tile->HasRasterTask()) {
+ ++it;
+ continue;
}
+ DCHECK(!tile->HasResources());
DCHECK(tiles_.find(tile->id()) != tiles_.end());
tiles_.erase(tile->id());
@@ -442,208 +290,96 @@ void TileManager::CleanUpReleasedTiles() {
}
delete tile;
+ it = released_tiles_.erase(it);
}
-
- released_tiles_.clear();
}
-void TileManager::UpdatePrioritizedTileSetIfNeeded() {
- if (!prioritized_tiles_dirty_)
- return;
+void TileManager::DidFinishRunningTasks(TaskSet task_set) {
+ if (task_set == ALL) {
+ TRACE_EVENT1("cc", "TileManager::DidFinishRunningTasks", "task_set", "ALL");
- CleanUpReleasedTiles();
+ bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() >
+ global_state_.soft_memory_limit_in_bytes;
- prioritized_tiles_.Clear();
- GetTilesWithAssignedBins(&prioritized_tiles_);
- prioritized_tiles_dirty_ = false;
-}
-
-void TileManager::DidFinishRunningTasks() {
- TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks");
+ // When OOM, keep re-assigning memory until we reach a steady state
+ // where top-priority tiles are initialized.
+ if (all_tiles_that_need_to_be_rasterized_are_scheduled_ &&
+ !memory_usage_above_limit)
+ return;
- bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() >
- global_state_.soft_memory_limit_in_bytes;
-
- // When OOM, keep re-assigning memory until we reach a steady state
- // where top-priority tiles are initialized.
- if (all_tiles_that_need_to_be_rasterized_have_memory_ &&
- !memory_usage_above_limit)
- return;
-
- rasterizer_->CheckForCompletedTasks();
- did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
-
- TileVector tiles_that_need_to_be_rasterized;
- AssignGpuMemoryToTiles(&prioritized_tiles_,
- &tiles_that_need_to_be_rasterized);
-
- // |tiles_that_need_to_be_rasterized| will be empty when we reach a
- // steady memory state. Keep scheduling tasks until we reach this state.
- if (!tiles_that_need_to_be_rasterized.empty()) {
- ScheduleTasks(tiles_that_need_to_be_rasterized);
- return;
- }
-
- resource_pool_->ReduceResourceUsage();
-
- // We don't reserve memory for required-for-activation tiles during
- // accelerated gestures, so we just postpone activation when we don't
- // have these tiles, and activate after the accelerated gesture.
- bool allow_rasterize_on_demand =
- global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY;
-
- // Use on-demand raster for any required-for-activation tiles that have not
- // been been assigned memory after reaching a steady memory state. This
- // ensures that we activate even when OOM.
- for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
- Tile* tile = it->second;
- ManagedTileState& mts = tile->managed_state();
- ManagedTileState::TileVersion& tile_version =
- mts.tile_versions[mts.raster_mode];
+ rasterizer_->CheckForCompletedTasks();
+ did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
- if (tile->required_for_activation() && !tile_version.IsReadyToDraw()) {
- // If we can't raster on demand, give up early (and don't activate).
- if (!allow_rasterize_on_demand)
- return;
+ TileVector tiles_that_need_to_be_rasterized;
+ AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized);
- tile_version.set_rasterize_on_demand();
- client_->NotifyTileStateChanged(tile);
+ // |tiles_that_need_to_be_rasterized| will be empty when we reach a
+ // steady memory state. Keep scheduling tasks until we reach this state.
+ if (!tiles_that_need_to_be_rasterized.empty()) {
+ ScheduleTasks(tiles_that_need_to_be_rasterized);
+ return;
}
- }
-
- DCHECK(IsReadyToActivate());
- ready_to_activate_check_notifier_.Schedule();
-}
-
-void TileManager::DidFinishRunningTasksRequiredForActivation() {
- // This is only a true indication that all tiles required for
- // activation are initialized when no tiles are OOM. We need to
- // wait for DidFinishRunningTasks() to be called, try to re-assign
- // memory and in worst case use on-demand raster when tiles
- // required for activation are OOM.
- if (!all_tiles_required_for_activation_have_memory_)
- return;
-
- ready_to_activate_check_notifier_.Schedule();
-}
-
-void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
- TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins");
-
- const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy;
- const TreePriority tree_priority = global_state_.tree_priority;
- // For each tree, bin into different categories of tiles.
- for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
- Tile* tile = it->second;
- ManagedTileState& mts = tile->managed_state();
-
- const ManagedTileState::TileVersion& tile_version =
- tile->GetTileVersionForDrawing();
- bool tile_is_ready_to_draw = tile_version.IsReadyToDraw();
- bool tile_is_active = tile_is_ready_to_draw ||
- mts.tile_versions[mts.raster_mode].raster_task_;
-
- // Get the active priority and bin.
- TilePriority active_priority = tile->priority(ACTIVE_TREE);
- ManagedTileBin active_bin = BinFromTilePriority(active_priority);
-
- // Get the pending priority and bin.
- TilePriority pending_priority = tile->priority(PENDING_TREE);
- ManagedTileBin pending_bin = BinFromTilePriority(pending_priority);
-
- bool pending_is_low_res = pending_priority.resolution == LOW_RESOLUTION;
- bool pending_is_non_ideal =
- pending_priority.resolution == NON_IDEAL_RESOLUTION;
- bool active_is_non_ideal =
- active_priority.resolution == NON_IDEAL_RESOLUTION;
-
- // Adjust bin state based on if ready to draw.
- active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin];
- pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin];
-
- // Adjust bin state based on if active.
- active_bin = kBinIsActiveMap[tile_is_active][active_bin];
- pending_bin = kBinIsActiveMap[tile_is_active][pending_bin];
-
- // We never want to paint new non-ideal tiles, as we always have
- // a high-res tile covering that content (paint that instead).
- if (!tile_is_ready_to_draw && active_is_non_ideal)
- active_bin = NEVER_BIN;
- if (!tile_is_ready_to_draw && pending_is_non_ideal)
- pending_bin = NEVER_BIN;
-
- ManagedTileBin tree_bin[NUM_TREES];
- tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
- tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
-
- // Adjust pending bin state for low res tiles. This prevents pending tree
- // low-res tiles from being initialized before high-res tiles.
- if (pending_is_low_res)
- tree_bin[PENDING_TREE] = std::max(tree_bin[PENDING_TREE], EVENTUALLY_BIN);
-
- TilePriority tile_priority;
- switch (tree_priority) {
- case SAME_PRIORITY_FOR_BOTH_TREES:
- mts.bin = std::min(tree_bin[ACTIVE_TREE], tree_bin[PENDING_TREE]);
- tile_priority = tile->combined_priority();
- break;
- case SMOOTHNESS_TAKES_PRIORITY:
- mts.bin = tree_bin[ACTIVE_TREE];
- tile_priority = active_priority;
- break;
- case NEW_CONTENT_TAKES_PRIORITY:
- mts.bin = tree_bin[PENDING_TREE];
- tile_priority = pending_priority;
- break;
+ FreeResourcesForReleasedTiles();
+
+ resource_pool_->ReduceResourceUsage();
+
+ // We don't reserve memory for required-for-activation tiles during
+ // accelerated gestures, so we just postpone activation when we don't
+ // have these tiles, and activate after the accelerated gesture.
+ // Likewise if we don't allow any tiles (as is the case when we're
+ // invisible), if we have tiles that aren't ready, then we shouldn't
+ // activate as activation can cause checkerboards.
+ bool allow_rasterize_on_demand =
+ global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY &&
+ global_state_.memory_limit_policy != ALLOW_NOTHING;
+
+ // Use on-demand raster for any required-for-activation tiles that have not
+ // been been assigned memory after reaching a steady memory state. This
+ // ensures that we activate even when OOM. Note that we have to rebuilt the
+ // queue in case the last AssignGpuMemoryToTiles evicted some tiles that
+ // would otherwise not be picked up by the old raster queue.
+ client_->BuildRasterQueue(&raster_priority_queue_,
+ global_state_.tree_priority);
+ bool ready_to_activate = true;
+ while (!raster_priority_queue_.IsEmpty()) {
+ Tile* tile = raster_priority_queue_.Top();
+ ManagedTileState& mts = tile->managed_state();
+
+ if (tile->required_for_activation() && !mts.draw_info.IsReadyToDraw()) {
+ // If we can't raster on demand, give up early (and don't activate).
+ if (!allow_rasterize_on_demand) {
+ ready_to_activate = false;
+ break;
+ }
+
+ mts.draw_info.set_rasterize_on_demand();
+ client_->NotifyTileStateChanged(tile);
+ }
+ raster_priority_queue_.Pop();
}
- // Bump up the priority if we determined it's NEVER_BIN on one tree,
- // but is still required on the other tree.
- bool is_in_never_bin_on_both_trees = tree_bin[ACTIVE_TREE] == NEVER_BIN &&
- tree_bin[PENDING_TREE] == NEVER_BIN;
-
- if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees)
- mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN;
-
- mts.resolution = tile_priority.resolution;
- mts.priority_bin = tile_priority.priority_bin;
- mts.distance_to_visible = tile_priority.distance_to_visible;
- mts.required_for_activation = tile_priority.required_for_activation;
-
- mts.visible_and_ready_to_draw =
- tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
-
- // Tiles that are required for activation shouldn't be in NEVER_BIN unless
- // smoothness takes priority or memory policy allows nothing to be
- // initialized.
- DCHECK(!mts.required_for_activation || mts.bin != NEVER_BIN ||
- tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
- memory_policy == ALLOW_NOTHING);
-
- // If the tile is in NEVER_BIN and it does not have an active task, then we
- // can release the resources early. If it does have the task however, we
- // should keep it in the prioritized tile set to ensure that AssignGpuMemory
- // can visit it.
- if (mts.bin == NEVER_BIN &&
- !mts.tile_versions[mts.raster_mode].raster_task_) {
- FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
- continue;
+ if (ready_to_activate) {
+ DCHECK(IsReadyToActivate());
+ ready_to_activate_check_notifier_.Schedule();
}
+ raster_priority_queue_.Reset();
+ return;
+ }
- // Insert the tile into a priority set.
- tiles->InsertTile(tile, mts.bin);
+ if (task_set == REQUIRED_FOR_ACTIVATION) {
+ TRACE_EVENT1("cc",
+ "TileManager::DidFinishRunningTasks",
+ "task_set",
+ "REQUIRED_FOR_ACTIVATION");
+ ready_to_activate_check_notifier_.Schedule();
}
}
void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
TRACE_EVENT0("cc", "TileManager::ManageTiles");
- // Update internal state.
- if (state != global_state_) {
- global_state_ = state;
- prioritized_tiles_dirty_ = true;
- }
+ global_state_ = state;
// We need to call CheckForCompletedTasks() once in-between each call
// to ScheduleTasks() to prevent canceled tasks from being scheduled.
@@ -652,11 +388,11 @@ void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
}
- UpdatePrioritizedTileSetIfNeeded();
+ FreeResourcesForReleasedTiles();
+ CleanUpReleasedTiles();
TileVector tiles_that_need_to_be_rasterized;
- AssignGpuMemoryToTiles(&prioritized_tiles_,
- &tiles_that_need_to_be_rasterized);
+ AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized);
// Finally, schedule rasterizer tasks.
ScheduleTasks(tiles_that_need_to_be_rasterized);
@@ -665,7 +401,7 @@ void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
"DidManage",
TRACE_EVENT_SCOPE_THREAD,
"state",
- TracedValue::FromValue(BasicStateAsValue().release()));
+ BasicStateAsValue());
TRACE_COUNTER_ID1("cc",
"unused_memory_bytes",
@@ -685,8 +421,7 @@ bool TileManager::UpdateVisibleTiles() {
"DidUpdateVisibleTiles",
TRACE_EVENT_SCOPE_THREAD,
"stats",
- TracedValue::FromValue(RasterTaskCompletionStatsAsValue(
- update_visible_tiles_stats_).release()));
+ RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_));
update_visible_tiles_stats_ = RasterTaskCompletionStats();
bool did_initialize_visible_tile = did_initialize_visible_tile_;
@@ -694,230 +429,210 @@ bool TileManager::UpdateVisibleTiles() {
return did_initialize_visible_tile;
}
-scoped_ptr<base::Value> TileManager::BasicStateAsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+TileManager::BasicStateAsValue() const {
+ scoped_refptr<base::debug::TracedValue> value =
+ new base::debug::TracedValue();
+ BasicStateAsValueInto(value.get());
+ return value;
+}
+
+void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const {
state->SetInteger("tile_count", tiles_.size());
- state->Set("global_state", global_state_.AsValue().release());
- return state.PassAs<base::Value>();
+ state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_);
+ state->BeginDictionary("global_state");
+ global_state_.AsValueInto(state);
+ state->EndDictionary();
+}
+
+void TileManager::RebuildEvictionQueueIfNeeded() {
+ TRACE_EVENT1("cc",
+ "TileManager::RebuildEvictionQueueIfNeeded",
+ "eviction_priority_queue_is_up_to_date",
+ eviction_priority_queue_is_up_to_date_);
+ if (eviction_priority_queue_is_up_to_date_)
+ return;
+
+ eviction_priority_queue_.Reset();
+ client_->BuildEvictionQueue(&eviction_priority_queue_,
+ global_state_.tree_priority);
+ eviction_priority_queue_is_up_to_date_ = true;
}
-scoped_ptr<base::Value> TileManager::AllTilesAsValue() const {
- scoped_ptr<base::ListValue> state(new base::ListValue());
- for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
- state->Append(it->second->AsValue().release());
+bool TileManager::FreeTileResourcesUntilUsageIsWithinLimit(
+ const MemoryUsage& limit,
+ MemoryUsage* usage) {
+ while (usage->Exceeds(limit)) {
+ RebuildEvictionQueueIfNeeded();
+ if (eviction_priority_queue_.IsEmpty())
+ return false;
- return state.PassAs<base::Value>();
+ Tile* tile = eviction_priority_queue_.Top();
+ *usage -= MemoryUsage::FromTile(tile);
+ FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
+ eviction_priority_queue_.Pop();
+ }
+ return true;
+}
+
+bool TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
+ const MemoryUsage& limit,
+ const TilePriority& other_priority,
+ MemoryUsage* usage) {
+ while (usage->Exceeds(limit)) {
+ RebuildEvictionQueueIfNeeded();
+ if (eviction_priority_queue_.IsEmpty())
+ return false;
+
+ Tile* tile = eviction_priority_queue_.Top();
+ if (!other_priority.IsHigherPriorityThan(tile->combined_priority()))
+ return false;
+
+ *usage -= MemoryUsage::FromTile(tile);
+ FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
+ eviction_priority_queue_.Pop();
+ }
+ return true;
+}
+
+bool TileManager::TilePriorityViolatesMemoryPolicy(
+ const TilePriority& priority) {
+ switch (global_state_.memory_limit_policy) {
+ case ALLOW_NOTHING:
+ return true;
+ case ALLOW_ABSOLUTE_MINIMUM:
+ return priority.priority_bin > TilePriority::NOW;
+ case ALLOW_PREPAINT_ONLY:
+ return priority.priority_bin > TilePriority::SOON;
+ case ALLOW_ANYTHING:
+ return priority.distance_to_visible ==
+ std::numeric_limits<float>::infinity();
+ }
+ NOTREACHED();
+ return true;
}
void TileManager::AssignGpuMemoryToTiles(
- PrioritizedTileSet* tiles,
TileVector* tiles_that_need_to_be_rasterized) {
- TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
+ TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles");
// Maintain the list of released resources that can potentially be re-used
// or deleted.
// If this operation becomes expensive too, only do this after some
// resource(s) was returned. Note that in that case, one also need to
// invalidate when releasing some resource from the pool.
- resource_pool_->CheckBusyResources();
+ resource_pool_->CheckBusyResources(false);
// Now give memory out to the tiles until we're out, and build
// the needs-to-be-rasterized queue.
- all_tiles_that_need_to_be_rasterized_have_memory_ = true;
- all_tiles_required_for_activation_have_memory_ = true;
-
- // Cast to prevent overflow.
- int64 soft_bytes_available =
- static_cast<int64>(bytes_releasable_) +
- static_cast<int64>(global_state_.soft_memory_limit_in_bytes) -
- static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
- int64 hard_bytes_available =
- static_cast<int64>(bytes_releasable_) +
- static_cast<int64>(global_state_.hard_memory_limit_in_bytes) -
- static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
- int resources_available = resources_releasable_ +
- global_state_.num_resources_limit -
- resource_pool_->acquired_resource_count();
- size_t soft_bytes_allocatable =
- std::max(static_cast<int64>(0), soft_bytes_available);
- size_t hard_bytes_allocatable =
- std::max(static_cast<int64>(0), hard_bytes_available);
- size_t resources_allocatable = std::max(0, resources_available);
-
- size_t bytes_that_exceeded_memory_budget = 0;
- size_t soft_bytes_left = soft_bytes_allocatable;
- size_t hard_bytes_left = hard_bytes_allocatable;
-
- size_t resources_left = resources_allocatable;
- bool oomed_soft = false;
- bool oomed_hard = false;
- bool have_hit_soft_memory = false; // Soft memory comes after hard.
-
unsigned schedule_priority = 1u;
- for (PrioritizedTileSet::Iterator it(tiles, true); it; ++it) {
- Tile* tile = *it;
- ManagedTileState& mts = tile->managed_state();
-
- mts.scheduled_priority = schedule_priority++;
-
- mts.raster_mode = tile->DetermineOverallRasterMode();
-
- ManagedTileState::TileVersion& tile_version =
- mts.tile_versions[mts.raster_mode];
-
- // If this tile doesn't need a resource, then nothing to do.
- if (!tile_version.requires_resource())
- continue;
-
- // If the tile is not needed, free it up.
- if (mts.bin == NEVER_BIN) {
- FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
- continue;
- }
-
- const bool tile_uses_hard_limit = mts.bin <= NOW_BIN;
- const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile);
- const size_t tile_bytes_left =
- (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left;
-
- // Hard-limit is reserved for tiles that would cause a calamity
- // if they were to go away, so by definition they are the highest
- // priority memory, and must be at the front of the list.
- DCHECK(!(have_hit_soft_memory && tile_uses_hard_limit));
- have_hit_soft_memory |= !tile_uses_hard_limit;
-
- size_t tile_bytes = 0;
- size_t tile_resources = 0;
-
- // It costs to maintain a resource.
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- if (mts.tile_versions[mode].resource_) {
- tile_bytes += bytes_if_allocated;
- tile_resources++;
- }
+ all_tiles_that_need_to_be_rasterized_are_scheduled_ = true;
+ bool had_enough_memory_to_schedule_tiles_needed_now = true;
+
+ MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes,
+ global_state_.num_resources_limit);
+ MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes,
+ global_state_.num_resources_limit);
+ MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(),
+ resource_pool_->acquired_resource_count());
+
+ eviction_priority_queue_is_up_to_date_ = false;
+ client_->BuildRasterQueue(&raster_priority_queue_,
+ global_state_.tree_priority);
+
+ while (!raster_priority_queue_.IsEmpty()) {
+ Tile* tile = raster_priority_queue_.Top();
+ TilePriority priority = tile->combined_priority();
+
+ if (TilePriorityViolatesMemoryPolicy(priority)) {
+ TRACE_EVENT_INSTANT0(
+ "cc",
+ "TileManager::AssignGpuMemory tile violates memory policy",
+ TRACE_EVENT_SCOPE_THREAD);
+ break;
}
- // Allow lower priority tiles with initialized resources to keep
- // their memory by only assigning memory to new raster tasks if
- // they can be scheduled.
- bool reached_scheduled_raster_tasks_limit =
- tiles_that_need_to_be_rasterized->size() >= kScheduledRasterTasksLimit;
- if (!reached_scheduled_raster_tasks_limit) {
- // If we don't have the required version, and it's not in flight
- // then we'll have to pay to create a new task.
- if (!tile_version.resource_ && !tile_version.raster_task_) {
- tile_bytes += bytes_if_allocated;
- tile_resources++;
- }
+ // 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_) {
+ all_tiles_that_need_to_be_rasterized_are_scheduled_ = false;
+ break;
}
- // Tile is OOM.
- if (tile_bytes > tile_bytes_left || tile_resources > resources_left) {
- bool was_ready_to_draw = tile->IsReadyToDraw();
-
- FreeResourcesForTile(tile);
-
- // This tile was already on screen and now its resources have been
- // released. In order to prevent checkerboarding, set this tile as
- // rasterize on demand immediately.
- if (mts.visible_and_ready_to_draw)
- tile_version.set_rasterize_on_demand();
-
- if (was_ready_to_draw)
- client_->NotifyTileStateChanged(tile);
-
- oomed_soft = true;
- if (tile_uses_hard_limit) {
- oomed_hard = true;
- bytes_that_exceeded_memory_budget += tile_bytes;
- }
- } else {
- resources_left -= tile_resources;
- hard_bytes_left -= tile_bytes;
- soft_bytes_left =
- (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0;
- if (tile_version.resource_)
- continue;
+ ManagedTileState& mts = tile->managed_state();
+ mts.scheduled_priority = schedule_priority++;
+ mts.resolution = priority.resolution;
+
+ DCHECK(mts.draw_info.mode() ==
+ ManagedTileState::DrawInfo::PICTURE_PILE_MODE ||
+ !mts.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
+ // more memory to create a raster task.
+ MemoryUsage memory_required_by_tile_to_be_scheduled;
+ if (!mts.raster_task.get()) {
+ memory_required_by_tile_to_be_scheduled = MemoryUsage::FromConfig(
+ tile->size(), resource_pool_->resource_format());
}
- DCHECK(!tile_version.resource_);
-
- // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized|
- // has reached it's limit or we've failed to assign gpu memory to this
- // or any higher priority tile. Preventing tiles that fit into memory
- // budget to be rasterized when higher priority tile is oom is
- // important for two reasons:
- // 1. Tile size should not impact raster priority.
- // 2. Tiles with existing raster task could otherwise incorrectly
- // be added as they are not affected by |bytes_allocatable|.
- bool can_schedule_tile =
- !oomed_soft && !reached_scheduled_raster_tasks_limit;
-
- if (!can_schedule_tile) {
- all_tiles_that_need_to_be_rasterized_have_memory_ = false;
- if (tile->required_for_activation())
- all_tiles_required_for_activation_have_memory_ = false;
- it.DisablePriorityOrdering();
- continue;
+ bool tile_is_needed_now = priority.priority_bin == TilePriority::NOW;
+
+ // This is the memory limit that will be used by this tile. Depending on
+ // the tile priority, it will be one of hard_memory_limit or
+ // soft_memory_limit.
+ MemoryUsage& tile_memory_limit =
+ tile_is_needed_now ? hard_memory_limit : soft_memory_limit;
+
+ bool memory_usage_is_within_limit =
+ FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
+ tile_memory_limit - memory_required_by_tile_to_be_scheduled,
+ priority,
+ &memory_usage);
+
+ // If we couldn't fit the tile into our current memory limit, then we're
+ // done.
+ if (!memory_usage_is_within_limit) {
+ if (tile_is_needed_now)
+ had_enough_memory_to_schedule_tiles_needed_now = false;
+ all_tiles_that_need_to_be_rasterized_are_scheduled_ = false;
+ break;
}
+ memory_usage += memory_required_by_tile_to_be_scheduled;
tiles_that_need_to_be_rasterized->push_back(tile);
+ raster_priority_queue_.Pop();
}
- // OOM reporting uses hard-limit, soft-OOM is normal depending on limit.
- ever_exceeded_memory_budget_ |= oomed_hard;
- if (ever_exceeded_memory_budget_) {
- TRACE_COUNTER_ID2("cc",
- "over_memory_budget",
- this,
- "budget",
- global_state_.hard_memory_limit_in_bytes,
- "over",
- bytes_that_exceeded_memory_budget);
- }
+ // Note that we should try and further reduce memory in case the above loop
+ // didn't reduce memory. This ensures that we always release as many resources
+ // as possible to stay within the memory limit.
+ FreeTileResourcesUntilUsageIsWithinLimit(hard_memory_limit, &memory_usage);
+
+ UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget",
+ !had_enough_memory_to_schedule_tiles_needed_now);
+ did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now;
+
memory_stats_from_last_assign_.total_budget_in_bytes =
global_state_.hard_memory_limit_in_bytes;
- memory_stats_from_last_assign_.bytes_allocated =
- hard_bytes_allocatable - hard_bytes_left;
- memory_stats_from_last_assign_.bytes_unreleasable =
- resource_pool_->acquired_memory_usage_bytes() - bytes_releasable_;
- memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget;
-}
-
-void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) {
- ManagedTileState& mts = tile->managed_state();
- if (mts.tile_versions[mode].resource_) {
- resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass());
+ memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes();
+ memory_stats_from_last_assign_.had_enough_memory =
+ had_enough_memory_to_schedule_tiles_needed_now;
- DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile));
- DCHECK_GE(resources_releasable_, 1u);
+ raster_priority_queue_.Reset();
- bytes_releasable_ -= BytesConsumedIfAllocated(tile);
- --resources_releasable_;
- }
+ TRACE_EVENT_END2("cc",
+ "TileManager::AssignGpuMemoryToTiles",
+ "all_tiles_that_need_to_be_rasterized_are_scheduled",
+ all_tiles_that_need_to_be_rasterized_are_scheduled_,
+ "had_enough_memory_to_schedule_tiles_needed_now",
+ had_enough_memory_to_schedule_tiles_needed_now);
}
void TileManager::FreeResourcesForTile(Tile* tile) {
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- FreeResourceForTile(tile, static_cast<RasterMode>(mode));
- }
-}
-
-void TileManager::FreeUnusedResourcesForTile(Tile* tile) {
- DCHECK(tile->IsReadyToDraw());
ManagedTileState& mts = tile->managed_state();
- RasterMode used_mode = LOW_QUALITY_RASTER_MODE;
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- if (mts.tile_versions[mode].IsReadyToDraw()) {
- used_mode = static_cast<RasterMode>(mode);
- break;
- }
- }
-
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- if (mode != used_mode)
- FreeResourceForTile(tile, static_cast<RasterMode>(mode));
- }
+ if (mts.draw_info.resource_)
+ resource_pool_->ReleaseResource(mts.draw_info.resource_.Pass());
}
void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(
@@ -946,28 +661,28 @@ void TileManager::ScheduleTasks(
++it) {
Tile* tile = *it;
ManagedTileState& mts = tile->managed_state();
- ManagedTileState::TileVersion& tile_version =
- mts.tile_versions[mts.raster_mode];
- DCHECK(tile_version.requires_resource());
- DCHECK(!tile_version.resource_);
+ DCHECK(mts.draw_info.requires_resource());
+ DCHECK(!mts.draw_info.resource_);
- if (!tile_version.raster_task_)
- tile_version.raster_task_ = CreateRasterTask(tile);
+ if (!mts.raster_task.get())
+ mts.raster_task = CreateRasterTask(tile);
- raster_queue_.items.push_back(RasterTaskQueue::Item(
- tile_version.raster_task_.get(), tile->required_for_activation()));
- raster_queue_.required_for_activation_count +=
- tile->required_for_activation();
+ TaskSetCollection task_sets;
+ if (tile->required_for_activation())
+ task_sets.set(REQUIRED_FOR_ACTIVATION);
+ task_sets.set(ALL);
+ raster_queue_.items.push_back(
+ RasterTaskQueue::Item(mts.raster_task.get(), task_sets));
}
// We must reduce the amount of unused resoruces before calling
// ScheduleTasks to prevent usage from rising above limits.
resource_pool_->ReduceResourceUsage();
- // Schedule running of |raster_tasks_|. This replaces any previously
+ // Schedule running of |raster_queue_|. This replaces any previously
// scheduled tasks and effectively cancels all tasks not present
- // in |raster_tasks_|.
+ // in |raster_queue_|.
rasterizer_->ScheduleTasks(&raster_queue_);
// It's now safe to clean up orphan tasks as raster worker pool is not
@@ -995,17 +710,16 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(Tile* tile) {
ManagedTileState& mts = tile->managed_state();
scoped_ptr<ScopedResource> resource =
- resource_pool_->AcquireResource(tile->tile_size_.size());
+ resource_pool_->AcquireResource(tile->size());
const ScopedResource* const_resource = resource.get();
// Create and queue all image decode tasks that this tile depends on.
ImageDecodeTask::Vector decode_tasks;
PixelRefTaskMap& existing_pixel_refs = image_decode_tasks_[tile->layer_id()];
- for (PicturePileImpl::PixelRefIterator iter(
- tile->content_rect(), tile->contents_scale(), tile->picture_pile());
- iter;
- ++iter) {
- SkPixelRef* pixel_ref = *iter;
+ std::vector<SkPixelRef*> pixel_refs;
+ tile->raster_source()->GatherPixelRefs(
+ tile->content_rect(), tile->contents_scale(), &pixel_refs);
+ for (SkPixelRef* pixel_ref : pixel_refs) {
uint32_t id = pixel_ref->getGenerationID();
// Append existing image decode task if available.
@@ -1024,10 +738,9 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(Tile* tile) {
return make_scoped_refptr(
new RasterTaskImpl(const_resource,
- tile->picture_pile(),
+ tile->raster_source(),
tile->content_rect(),
tile->contents_scale(),
- mts.raster_mode,
mts.resolution,
tile->layer_id(),
static_cast<const void*>(tile),
@@ -1037,8 +750,7 @@ scoped_refptr<RasterTask> TileManager::CreateRasterTask(Tile* tile) {
base::Bind(&TileManager::OnRasterTaskCompleted,
base::Unretained(this),
tile->id(),
- base::Passed(&resource),
- mts.raster_mode),
+ base::Passed(&resource)),
&decode_tasks));
}
@@ -1065,22 +777,15 @@ void TileManager::OnImageDecodeTaskCompleted(int layer_id,
void TileManager::OnRasterTaskCompleted(
Tile::Id tile_id,
scoped_ptr<ScopedResource> resource,
- RasterMode raster_mode,
- const PicturePileImpl::Analysis& analysis,
+ const RasterSource::SolidColorAnalysis& analysis,
bool was_canceled) {
- TileMap::iterator it = tiles_.find(tile_id);
- if (it == tiles_.end()) {
- ++update_visible_tiles_stats_.canceled_count;
- resource_pool_->ReleaseResource(resource.Pass());
- return;
- }
+ DCHECK(tiles_.find(tile_id) != tiles_.end());
- Tile* tile = it->second;
+ Tile* tile = tiles_[tile_id];
ManagedTileState& mts = tile->managed_state();
- ManagedTileState::TileVersion& tile_version = mts.tile_versions[raster_mode];
- DCHECK(tile_version.raster_task_);
- orphan_raster_tasks_.push_back(tile_version.raster_task_);
- tile_version.raster_task_ = NULL;
+ DCHECK(mts.raster_task.get());
+ orphan_raster_tasks_.push_back(mts.raster_task);
+ mts.raster_task = NULL;
if (was_canceled) {
++update_visible_tiles_stats_.canceled_count;
@@ -1091,495 +796,118 @@ void TileManager::OnRasterTaskCompleted(
++update_visible_tiles_stats_.completed_count;
if (analysis.is_solid_color) {
- tile_version.set_solid_color(analysis.solid_color);
+ mts.draw_info.set_solid_color(analysis.solid_color);
resource_pool_->ReleaseResource(resource.Pass());
} else {
- tile_version.set_use_resource();
- tile_version.resource_ = resource.Pass();
-
- bytes_releasable_ += BytesConsumedIfAllocated(tile);
- ++resources_releasable_;
+ mts.draw_info.set_use_resource();
+ mts.draw_info.resource_ = resource.Pass();
}
- FreeUnusedResourcesForTile(tile);
if (tile->priority(ACTIVE_TREE).distance_to_visible == 0.f)
did_initialize_visible_tile_ = true;
client_->NotifyTileStateChanged(tile);
}
-scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile,
+scoped_refptr<Tile> TileManager::CreateTile(RasterSource* raster_source,
const gfx::Size& tile_size,
const gfx::Rect& content_rect,
- const gfx::Rect& opaque_rect,
float contents_scale,
int layer_id,
int source_frame_number,
int flags) {
scoped_refptr<Tile> tile = make_scoped_refptr(new Tile(this,
- picture_pile,
+ raster_source,
tile_size,
content_rect,
- opaque_rect,
contents_scale,
layer_id,
source_frame_number,
flags));
DCHECK(tiles_.find(tile->id()) == tiles_.end());
- tiles_[tile->id()] = tile;
+ tiles_[tile->id()] = tile.get();
used_layer_counts_[tile->layer_id()]++;
- prioritized_tiles_dirty_ = true;
return tile;
}
-void TileManager::GetPairedPictureLayers(
- std::vector<PairedPictureLayer>* paired_layers) const {
- const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers();
+void TileManager::SetRasterizerForTesting(Rasterizer* rasterizer) {
+ rasterizer_ = rasterizer;
+ rasterizer_->SetClient(this);
+}
- paired_layers->clear();
- // Reserve a maximum possible paired layers.
- paired_layers->reserve(layers.size());
+bool TileManager::IsReadyToActivate() const {
+ TRACE_EVENT0("cc", "TileManager::IsReadyToActivate");
+ const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers();
for (std::vector<PictureLayerImpl*>::const_iterator it = layers.begin();
it != layers.end();
++it) {
- PictureLayerImpl* layer = *it;
-
- // TODO(vmpstr): Iterators and should handle this instead. crbug.com/381704
- if (!layer->HasValidTilePriorities())
- continue;
-
- PictureLayerImpl* twin_layer = layer->GetTwinLayer();
-
- // Ignore the twin layer when tile priorities are invalid.
- // TODO(vmpstr): Iterators should handle this instead. crbug.com/381704
- if (twin_layer && !twin_layer->HasValidTilePriorities())
- twin_layer = NULL;
-
- PairedPictureLayer paired_layer;
- WhichTree tree = layer->GetTree();
-
- // If the current tree is ACTIVE_TREE, then always generate a paired_layer.
- // If current tree is PENDING_TREE, then only generate a paired_layer if
- // there is no twin layer.
- if (tree == ACTIVE_TREE) {
- DCHECK(!twin_layer || twin_layer->GetTree() == PENDING_TREE);
- paired_layer.active_layer = layer;
- paired_layer.pending_layer = twin_layer;
- paired_layers->push_back(paired_layer);
- } else if (!twin_layer) {
- paired_layer.active_layer = NULL;
- paired_layer.pending_layer = layer;
- paired_layers->push_back(paired_layer);
- }
- }
-}
-
-TileManager::PairedPictureLayer::PairedPictureLayer()
- : active_layer(NULL), pending_layer(NULL) {}
-
-TileManager::PairedPictureLayer::~PairedPictureLayer() {}
-
-TileManager::RasterTileIterator::RasterTileIterator(TileManager* tile_manager,
- TreePriority tree_priority)
- : tree_priority_(tree_priority), comparator_(tree_priority) {
- std::vector<TileManager::PairedPictureLayer> paired_layers;
- tile_manager->GetPairedPictureLayers(&paired_layers);
- bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
-
- paired_iterators_.reserve(paired_layers.size());
- iterator_heap_.reserve(paired_layers.size());
- for (std::vector<TileManager::PairedPictureLayer>::iterator it =
- paired_layers.begin();
- it != paired_layers.end();
- ++it) {
- PairedPictureLayerIterator paired_iterator;
- if (it->active_layer) {
- paired_iterator.active_iterator =
- PictureLayerImpl::LayerRasterTileIterator(it->active_layer,
- prioritize_low_res);
- }
-
- if (it->pending_layer) {
- paired_iterator.pending_iterator =
- PictureLayerImpl::LayerRasterTileIterator(it->pending_layer,
- prioritize_low_res);
- }
-
- if (paired_iterator.PeekTile(tree_priority_) != NULL) {
- paired_iterators_.push_back(paired_iterator);
- iterator_heap_.push_back(&paired_iterators_.back());
- }
- }
-
- std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_);
-}
-
-TileManager::RasterTileIterator::~RasterTileIterator() {}
-
-TileManager::RasterTileIterator& TileManager::RasterTileIterator::operator++() {
- DCHECK(*this);
-
- std::pop_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_);
- PairedPictureLayerIterator* paired_iterator = iterator_heap_.back();
- iterator_heap_.pop_back();
-
- paired_iterator->PopTile(tree_priority_);
- if (paired_iterator->PeekTile(tree_priority_) != NULL) {
- iterator_heap_.push_back(paired_iterator);
- std::push_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_);
- }
- return *this;
-}
-
-TileManager::RasterTileIterator::operator bool() const {
- return !iterator_heap_.empty();
-}
-
-Tile* TileManager::RasterTileIterator::operator*() {
- DCHECK(*this);
- return iterator_heap_.front()->PeekTile(tree_priority_);
-}
-
-TileManager::RasterTileIterator::PairedPictureLayerIterator::
- PairedPictureLayerIterator() {}
-
-TileManager::RasterTileIterator::PairedPictureLayerIterator::
- ~PairedPictureLayerIterator() {}
-
-Tile* TileManager::RasterTileIterator::PairedPictureLayerIterator::PeekTile(
- TreePriority tree_priority) {
- PictureLayerImpl::LayerRasterTileIterator* next_iterator =
- NextTileIterator(tree_priority).first;
- if (!next_iterator)
- return NULL;
-
- DCHECK(*next_iterator);
- DCHECK(std::find(returned_shared_tiles.begin(),
- returned_shared_tiles.end(),
- **next_iterator) == returned_shared_tiles.end());
- return **next_iterator;
-}
-
-void TileManager::RasterTileIterator::PairedPictureLayerIterator::PopTile(
- TreePriority tree_priority) {
- PictureLayerImpl::LayerRasterTileIterator* next_iterator =
- NextTileIterator(tree_priority).first;
- DCHECK(next_iterator);
- DCHECK(*next_iterator);
- returned_shared_tiles.push_back(**next_iterator);
- ++(*next_iterator);
-
- next_iterator = NextTileIterator(tree_priority).first;
- while (next_iterator &&
- std::find(returned_shared_tiles.begin(),
- returned_shared_tiles.end(),
- **next_iterator) != returned_shared_tiles.end()) {
- ++(*next_iterator);
- next_iterator = NextTileIterator(tree_priority).first;
- }
-}
-
-std::pair<PictureLayerImpl::LayerRasterTileIterator*, WhichTree>
-TileManager::RasterTileIterator::PairedPictureLayerIterator::NextTileIterator(
- TreePriority tree_priority) {
- // If both iterators are out of tiles, return NULL.
- if (!active_iterator && !pending_iterator) {
- return std::pair<PictureLayerImpl::LayerRasterTileIterator*, WhichTree>(
- NULL, ACTIVE_TREE);
- }
-
- // If we only have one iterator with tiles, return it.
- if (!active_iterator)
- return std::make_pair(&pending_iterator, PENDING_TREE);
- if (!pending_iterator)
- return std::make_pair(&active_iterator, ACTIVE_TREE);
-
- // Now both iterators have tiles, so we have to decide based on tree priority.
- switch (tree_priority) {
- case SMOOTHNESS_TAKES_PRIORITY:
- return std::make_pair(&active_iterator, ACTIVE_TREE);
- case NEW_CONTENT_TAKES_PRIORITY:
- return std::make_pair(&pending_iterator, ACTIVE_TREE);
- case SAME_PRIORITY_FOR_BOTH_TREES: {
- Tile* active_tile = *active_iterator;
- Tile* pending_tile = *pending_iterator;
- if (active_tile == pending_tile)
- return std::make_pair(&active_iterator, ACTIVE_TREE);
-
- const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE);
- const TilePriority& pending_priority =
- pending_tile->priority(PENDING_TREE);
-
- if (active_priority.IsHigherPriorityThan(pending_priority))
- return std::make_pair(&active_iterator, ACTIVE_TREE);
- return std::make_pair(&pending_iterator, PENDING_TREE);
- }
- }
-
- NOTREACHED();
- // Keep the compiler happy.
- return std::pair<PictureLayerImpl::LayerRasterTileIterator*, WhichTree>(
- NULL, ACTIVE_TREE);
-}
-
-TileManager::RasterTileIterator::RasterOrderComparator::RasterOrderComparator(
- TreePriority tree_priority)
- : tree_priority_(tree_priority) {}
-
-bool TileManager::RasterTileIterator::RasterOrderComparator::operator()(
- PairedPictureLayerIterator* a,
- PairedPictureLayerIterator* b) const {
- std::pair<PictureLayerImpl::LayerRasterTileIterator*, WhichTree> a_pair =
- a->NextTileIterator(tree_priority_);
- DCHECK(a_pair.first);
- DCHECK(*a_pair.first);
-
- std::pair<PictureLayerImpl::LayerRasterTileIterator*, WhichTree> b_pair =
- b->NextTileIterator(tree_priority_);
- DCHECK(b_pair.first);
- DCHECK(*b_pair.first);
-
- Tile* a_tile = **a_pair.first;
- Tile* b_tile = **b_pair.first;
-
- const TilePriority& a_priority =
- a_tile->priority_for_tree_priority(tree_priority_);
- const TilePriority& b_priority =
- b_tile->priority_for_tree_priority(tree_priority_);
- bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
-
- // Now we have to return true iff b is higher priority than a.
-
- // If the bin is the same but the resolution is not, then the order will be
- // determined by whether we prioritize low res or not.
- // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile
- // class but instead produced by the iterators.
- if (b_priority.priority_bin == a_priority.priority_bin &&
- b_priority.resolution != a_priority.resolution) {
- // Non ideal resolution should be sorted lower than other resolutions.
- if (a_priority.resolution == NON_IDEAL_RESOLUTION)
- return true;
-
- if (b_priority.resolution == NON_IDEAL_RESOLUTION)
+ if (!(*it)->AllTilesRequiredForActivationAreReadyToDraw())
return false;
-
- if (prioritize_low_res)
- return b_priority.resolution == LOW_RESOLUTION;
-
- return b_priority.resolution == HIGH_RESOLUTION;
}
- return b_priority.IsHigherPriorityThan(a_priority);
-}
-
-TileManager::EvictionTileIterator::EvictionTileIterator()
- : comparator_(SAME_PRIORITY_FOR_BOTH_TREES) {}
-
-TileManager::EvictionTileIterator::EvictionTileIterator(
- TileManager* tile_manager,
- TreePriority tree_priority)
- : tree_priority_(tree_priority), comparator_(tree_priority) {
- std::vector<TileManager::PairedPictureLayer> paired_layers;
-
- tile_manager->GetPairedPictureLayers(&paired_layers);
-
- paired_iterators_.reserve(paired_layers.size());
- iterator_heap_.reserve(paired_layers.size());
- for (std::vector<TileManager::PairedPictureLayer>::iterator it =
- paired_layers.begin();
- it != paired_layers.end();
- ++it) {
- PairedPictureLayerIterator paired_iterator;
- if (it->active_layer) {
- paired_iterator.active_iterator =
- PictureLayerImpl::LayerEvictionTileIterator(it->active_layer,
- tree_priority_);
- }
-
- if (it->pending_layer) {
- paired_iterator.pending_iterator =
- PictureLayerImpl::LayerEvictionTileIterator(it->pending_layer,
- tree_priority_);
- }
-
- if (paired_iterator.PeekTile(tree_priority_) != NULL) {
- paired_iterators_.push_back(paired_iterator);
- iterator_heap_.push_back(&paired_iterators_.back());
- }
- }
-
- std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_);
+ return true;
}
-TileManager::EvictionTileIterator::~EvictionTileIterator() {}
+void TileManager::CheckIfReadyToActivate() {
+ TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate");
-TileManager::EvictionTileIterator& TileManager::EvictionTileIterator::
-operator++() {
- std::pop_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_);
- PairedPictureLayerIterator* paired_iterator = iterator_heap_.back();
- iterator_heap_.pop_back();
+ rasterizer_->CheckForCompletedTasks();
+ did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
- paired_iterator->PopTile(tree_priority_);
- if (paired_iterator->PeekTile(tree_priority_) != NULL) {
- iterator_heap_.push_back(paired_iterator);
- std::push_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_);
- }
- return *this;
+ if (IsReadyToActivate())
+ client_->NotifyReadyToActivate();
}
-TileManager::EvictionTileIterator::operator bool() const {
- return !iterator_heap_.empty();
+TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) {
}
-Tile* TileManager::EvictionTileIterator::operator*() {
- DCHECK(*this);
- return iterator_heap_.front()->PeekTile(tree_priority_);
+TileManager::MemoryUsage::MemoryUsage(int64 memory_bytes, int resource_count)
+ : memory_bytes_(memory_bytes), resource_count_(resource_count) {
}
-TileManager::EvictionTileIterator::PairedPictureLayerIterator::
- PairedPictureLayerIterator() {}
-
-TileManager::EvictionTileIterator::PairedPictureLayerIterator::
- ~PairedPictureLayerIterator() {}
-
-Tile* TileManager::EvictionTileIterator::PairedPictureLayerIterator::PeekTile(
- TreePriority tree_priority) {
- PictureLayerImpl::LayerEvictionTileIterator* next_iterator =
- NextTileIterator(tree_priority);
- if (!next_iterator)
- return NULL;
-
- DCHECK(*next_iterator);
- DCHECK(std::find(returned_shared_tiles.begin(),
- returned_shared_tiles.end(),
- **next_iterator) == returned_shared_tiles.end());
- return **next_iterator;
+// static
+TileManager::MemoryUsage TileManager::MemoryUsage::FromConfig(
+ const gfx::Size& size,
+ ResourceFormat format) {
+ return MemoryUsage(Resource::MemorySizeBytes(size, format), 1);
}
-void TileManager::EvictionTileIterator::PairedPictureLayerIterator::PopTile(
- TreePriority tree_priority) {
- PictureLayerImpl::LayerEvictionTileIterator* next_iterator =
- NextTileIterator(tree_priority);
- DCHECK(next_iterator);
- DCHECK(*next_iterator);
- returned_shared_tiles.push_back(**next_iterator);
- ++(*next_iterator);
-
- next_iterator = NextTileIterator(tree_priority);
- while (next_iterator &&
- std::find(returned_shared_tiles.begin(),
- returned_shared_tiles.end(),
- **next_iterator) != returned_shared_tiles.end()) {
- ++(*next_iterator);
- next_iterator = NextTileIterator(tree_priority);
+// static
+TileManager::MemoryUsage TileManager::MemoryUsage::FromTile(const Tile* tile) {
+ const ManagedTileState& mts = tile->managed_state();
+ if (mts.draw_info.resource_) {
+ return MemoryUsage::FromConfig(tile->size(),
+ mts.draw_info.resource_->format());
}
+ return MemoryUsage();
}
-PictureLayerImpl::LayerEvictionTileIterator*
-TileManager::EvictionTileIterator::PairedPictureLayerIterator::NextTileIterator(
- TreePriority tree_priority) {
- // If both iterators are out of tiles, return NULL.
- if (!active_iterator && !pending_iterator)
- return NULL;
-
- // If we only have one iterator with tiles, return it.
- if (!active_iterator)
- return &pending_iterator;
- if (!pending_iterator)
- return &active_iterator;
-
- Tile* active_tile = *active_iterator;
- Tile* pending_tile = *pending_iterator;
- if (active_tile == pending_tile)
- return &active_iterator;
-
- const TilePriority& active_priority =
- active_tile->priority_for_tree_priority(tree_priority);
- const TilePriority& pending_priority =
- pending_tile->priority_for_tree_priority(tree_priority);
-
- if (pending_priority.IsHigherPriorityThan(active_priority))
- return &active_iterator;
- return &pending_iterator;
+TileManager::MemoryUsage& TileManager::MemoryUsage::operator+=(
+ const MemoryUsage& other) {
+ memory_bytes_ += other.memory_bytes_;
+ resource_count_ += other.resource_count_;
+ return *this;
}
-TileManager::EvictionTileIterator::EvictionOrderComparator::
- EvictionOrderComparator(TreePriority tree_priority)
- : tree_priority_(tree_priority) {}
-
-bool TileManager::EvictionTileIterator::EvictionOrderComparator::operator()(
- PairedPictureLayerIterator* a,
- PairedPictureLayerIterator* b) const {
- PictureLayerImpl::LayerEvictionTileIterator* a_iterator =
- a->NextTileIterator(tree_priority_);
- DCHECK(a_iterator);
- DCHECK(*a_iterator);
-
- PictureLayerImpl::LayerEvictionTileIterator* b_iterator =
- b->NextTileIterator(tree_priority_);
- DCHECK(b_iterator);
- DCHECK(*b_iterator);
-
- Tile* a_tile = **a_iterator;
- Tile* b_tile = **b_iterator;
-
- const TilePriority& a_priority =
- a_tile->priority_for_tree_priority(tree_priority_);
- const TilePriority& b_priority =
- b_tile->priority_for_tree_priority(tree_priority_);
- bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
-
- // Now we have to return true iff b is lower priority than a.
-
- // If the bin is the same but the resolution is not, then the order will be
- // determined by whether we prioritize low res or not.
- // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile
- // class but instead produced by the iterators.
- if (b_priority.priority_bin == a_priority.priority_bin &&
- b_priority.resolution != a_priority.resolution) {
- // Non ideal resolution should be sorted higher than other resolutions.
- if (a_priority.resolution == NON_IDEAL_RESOLUTION)
- return false;
-
- if (b_priority.resolution == NON_IDEAL_RESOLUTION)
- return true;
-
- if (prioritize_low_res)
- return a_priority.resolution == LOW_RESOLUTION;
-
- return a_priority.resolution == HIGH_RESOLUTION;
- }
- return a_priority.IsHigherPriorityThan(b_priority);
+TileManager::MemoryUsage& TileManager::MemoryUsage::operator-=(
+ const MemoryUsage& other) {
+ memory_bytes_ -= other.memory_bytes_;
+ resource_count_ -= other.resource_count_;
+ return *this;
}
-void TileManager::SetRasterizerForTesting(Rasterizer* rasterizer) {
- rasterizer_ = rasterizer;
- rasterizer_->SetClient(this);
+TileManager::MemoryUsage TileManager::MemoryUsage::operator-(
+ const MemoryUsage& other) {
+ MemoryUsage result = *this;
+ result -= other;
+ return result;
}
-bool TileManager::IsReadyToActivate() const {
- const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers();
-
- for (std::vector<PictureLayerImpl*>::const_iterator it = layers.begin();
- it != layers.end();
- ++it) {
- if (!(*it)->AllTilesRequiredForActivationAreReadyToDraw())
- return false;
- }
-
- return true;
-}
-
-void TileManager::CheckIfReadyToActivate() {
- TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate");
-
- rasterizer_->CheckForCompletedTasks();
- did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
-
- if (IsReadyToActivate())
- client_->NotifyReadyToActivate();
+bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const {
+ return memory_bytes_ > limit.memory_bytes_ ||
+ resource_count_ > limit.resource_count_;
}
} // namespace cc
diff --git a/chromium/cc/resources/tile_manager.h b/chromium/cc/resources/tile_manager.h
index 5ad80910f8e..f5bea383141 100644
--- a/chromium/cc/resources/tile_manager.h
+++ b/chromium/cc/resources/tile_manager.h
@@ -17,22 +17,32 @@
#include "cc/base/ref_counted_managed.h"
#include "cc/base/unique_notifier.h"
#include "cc/debug/rendering_stats_instrumentation.h"
-#include "cc/layers/picture_layer_impl.h"
+#include "cc/resources/eviction_tile_priority_queue.h"
#include "cc/resources/managed_tile_state.h"
#include "cc/resources/memory_history.h"
-#include "cc/resources/picture_pile_impl.h"
-#include "cc/resources/prioritized_tile_set.h"
+#include "cc/resources/raster_source.h"
+#include "cc/resources/raster_tile_priority_queue.h"
#include "cc/resources/rasterizer.h"
#include "cc/resources/resource_pool.h"
#include "cc/resources/tile.h"
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
namespace cc {
+class PictureLayerImpl;
class ResourceProvider;
class CC_EXPORT TileManagerClient {
public:
// Returns the set of layers that the tile manager should consider for raster.
- virtual const std::vector<PictureLayerImpl*>& GetPictureLayers() = 0;
+ // TODO(vmpstr): Change the way we determine if we are ready to activate, so
+ // that this can be removed.
+ virtual const std::vector<PictureLayerImpl*>& GetPictureLayers() const = 0;
// Called when all tiles marked as required for activation are ready to draw.
virtual void NotifyReadyToActivate() = 0;
@@ -44,6 +54,18 @@ class CC_EXPORT TileManagerClient {
// - Tile marked for on-demand raster.
virtual void NotifyTileStateChanged(const Tile* tile) = 0;
+ // Given an empty raster tile priority queue, this will build a priority queue
+ // that will return tiles in order in which they should be rasterized.
+ // Note if the queue was previous built, Reset must be called on it.
+ virtual void BuildRasterQueue(RasterTilePriorityQueue* queue,
+ TreePriority tree_priority) = 0;
+
+ // Given an empty eviction tile priority queue, this will build a priority
+ // queue that will return tiles in order in which they should be evicted.
+ // Note if the queue was previous built, Reset must be called on it.
+ virtual void BuildEvictionQueue(EvictionTilePriorityQueue* queue,
+ TreePriority tree_priority) = 0;
+
protected:
virtual ~TileManagerClient() {}
};
@@ -54,8 +76,8 @@ struct RasterTaskCompletionStats {
size_t completed_count;
size_t canceled_count;
};
-scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
- const RasterTaskCompletionStats& stats);
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+ RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats);
// This class manages tiles, deciding which should get rasterized and which
// should no longer have any memory assigned to them. Tile objects are "owned"
@@ -64,103 +86,11 @@ scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
class CC_EXPORT TileManager : public RasterizerClient,
public RefCountedManager<Tile> {
public:
- struct CC_EXPORT PairedPictureLayer {
- PairedPictureLayer();
- ~PairedPictureLayer();
-
- PictureLayerImpl* active_layer;
- PictureLayerImpl* pending_layer;
- };
-
- class CC_EXPORT RasterTileIterator {
- public:
- RasterTileIterator(TileManager* tile_manager, TreePriority tree_priority);
- ~RasterTileIterator();
-
- RasterTileIterator& operator++();
- operator bool() const;
- Tile* operator*();
-
- private:
- struct PairedPictureLayerIterator {
- PairedPictureLayerIterator();
- ~PairedPictureLayerIterator();
-
- Tile* PeekTile(TreePriority tree_priority);
- void PopTile(TreePriority tree_priority);
-
- std::pair<PictureLayerImpl::LayerRasterTileIterator*, WhichTree>
- NextTileIterator(TreePriority tree_priority);
-
- PictureLayerImpl::LayerRasterTileIterator active_iterator;
- PictureLayerImpl::LayerRasterTileIterator pending_iterator;
-
- std::vector<Tile*> returned_shared_tiles;
- };
-
- class RasterOrderComparator {
- public:
- explicit RasterOrderComparator(TreePriority tree_priority);
-
- bool operator()(PairedPictureLayerIterator* a,
- PairedPictureLayerIterator* b) const;
-
- private:
- TreePriority tree_priority_;
- };
-
- std::vector<PairedPictureLayerIterator> paired_iterators_;
- std::vector<PairedPictureLayerIterator*> iterator_heap_;
- TreePriority tree_priority_;
- RasterOrderComparator comparator_;
-
- DISALLOW_COPY_AND_ASSIGN(RasterTileIterator);
- };
-
- struct CC_EXPORT EvictionTileIterator {
- public:
- EvictionTileIterator();
- EvictionTileIterator(TileManager* tile_manager, TreePriority tree_priority);
- ~EvictionTileIterator();
-
- EvictionTileIterator& operator++();
- operator bool() const;
- Tile* operator*();
-
- private:
- struct PairedPictureLayerIterator {
- PairedPictureLayerIterator();
- ~PairedPictureLayerIterator();
-
- Tile* PeekTile(TreePriority tree_priority);
- void PopTile(TreePriority tree_priority);
-
- PictureLayerImpl::LayerEvictionTileIterator* NextTileIterator(
- TreePriority tree_priority);
-
- PictureLayerImpl::LayerEvictionTileIterator active_iterator;
- PictureLayerImpl::LayerEvictionTileIterator pending_iterator;
-
- std::vector<Tile*> returned_shared_tiles;
- };
-
- class EvictionOrderComparator {
- public:
- explicit EvictionOrderComparator(TreePriority tree_priority);
-
- bool operator()(PairedPictureLayerIterator* a,
- PairedPictureLayerIterator* b) const;
-
- private:
- TreePriority tree_priority_;
- };
-
- std::vector<PairedPictureLayerIterator> paired_iterators_;
- std::vector<PairedPictureLayerIterator*> iterator_heap_;
- TreePriority tree_priority_;
- EvictionOrderComparator comparator_;
-
- DISALLOW_COPY_AND_ASSIGN(EvictionTileIterator);
+ enum NamedTaskSet {
+ REQUIRED_FOR_ACTIVATION = 0,
+ ALL = 1,
+ // Adding additional values requires increasing kNumberOfTaskSets in
+ // rasterizer.h
};
static scoped_ptr<TileManager> Create(
@@ -168,87 +98,85 @@ class CC_EXPORT TileManager : public RasterizerClient,
base::SequencedTaskRunner* task_runner,
ResourcePool* resource_pool,
Rasterizer* rasterizer,
- RenderingStatsInstrumentation* rendering_stats_instrumentation);
- virtual ~TileManager();
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ size_t scheduled_raster_task_limit);
+ ~TileManager() override;
void ManageTiles(const GlobalStateThatImpactsTilePriority& state);
// Returns true when visible tiles have been initialized.
bool UpdateVisibleTiles();
- scoped_refptr<Tile> CreateTile(PicturePileImpl* picture_pile,
+ scoped_refptr<Tile> CreateTile(RasterSource* raster_source,
const gfx::Size& tile_size,
const gfx::Rect& content_rect,
- const gfx::Rect& opaque_rect,
float contents_scale,
int layer_id,
int source_frame_number,
int flags);
- scoped_ptr<base::Value> BasicStateAsValue() const;
- scoped_ptr<base::Value> AllTilesAsValue() const;
+ scoped_refptr<base::debug::ConvertableToTraceFormat> BasicStateAsValue()
+ const;
+ void BasicStateAsValueInto(base::debug::TracedValue* dict) const;
const MemoryHistory::Entry& memory_stats_from_last_assign() const {
return memory_stats_from_last_assign_;
}
- void GetPairedPictureLayers(std::vector<PairedPictureLayer>* layers) const;
-
void InitializeTilesWithResourcesForTesting(const std::vector<Tile*>& tiles) {
for (size_t i = 0; i < tiles.size(); ++i) {
ManagedTileState& mts = tiles[i]->managed_state();
- ManagedTileState::TileVersion& tile_version =
- mts.tile_versions[HIGH_QUALITY_RASTER_MODE];
- tile_version.resource_ = resource_pool_->AcquireResource(gfx::Size(1, 1));
-
- bytes_releasable_ += BytesConsumedIfAllocated(tiles[i]);
- ++resources_releasable_;
+ mts.draw_info.resource_ =
+ resource_pool_->AcquireResource(tiles[i]->size());
}
}
void ReleaseTileResourcesForTesting(const std::vector<Tile*>& tiles) {
for (size_t i = 0; i < tiles.size(); ++i) {
Tile* tile = tiles[i];
- for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
- FreeResourceForTile(tile, static_cast<RasterMode>(mode));
- }
+ FreeResourcesForTile(tile);
}
}
void SetGlobalStateForTesting(
const GlobalStateThatImpactsTilePriority& state) {
- // Soft limit is used for resource pool such that
- // memory returns to soft limit after going over.
- if (state != global_state_) {
- global_state_ = state;
- prioritized_tiles_dirty_ = true;
- }
+ global_state_ = state;
}
void SetRasterizerForTesting(Rasterizer* rasterizer);
- void CleanUpReleasedTilesForTesting() { CleanUpReleasedTiles(); }
+ void FreeResourcesAndCleanUpReleasedTilesForTesting() {
+ FreeResourcesForReleasedTiles();
+ CleanUpReleasedTiles();
+ }
+
+ std::vector<Tile*> AllTilesForTesting() const {
+ std::vector<Tile*> tiles;
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end();
+ ++it) {
+ tiles.push_back(it->second);
+ }
+ return tiles;
+ }
protected:
TileManager(TileManagerClient* client,
- base::SequencedTaskRunner* task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
ResourcePool* resource_pool,
Rasterizer* rasterizer,
- RenderingStatsInstrumentation* rendering_stats_instrumentation);
-
- // Methods called by Tile
- friend class Tile;
- void DidChangeTilePriority(Tile* tile);
+ RenderingStatsInstrumentation* rendering_stats_instrumentation,
+ size_t scheduled_raster_task_limit);
+ void FreeResourcesForReleasedTiles();
void CleanUpReleasedTiles();
// Overriden from RefCountedManager<Tile>:
- virtual void Release(Tile* tile) OVERRIDE;
+ friend class Tile;
+ void Release(Tile* tile) override;
// Overriden from RasterizerClient:
- virtual bool ShouldForceTasksRequiredForActivationToComplete() const OVERRIDE;
- virtual void DidFinishRunningTasks() OVERRIDE;
- virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE;
+ void DidFinishRunningTasks(TaskSet task_set) override;
+ TaskSetCollection TasksThatShouldBeForcedToComplete() const override;
typedef std::vector<Tile*> TileVector;
typedef std::set<Tile*> TileSet;
@@ -257,34 +185,51 @@ class CC_EXPORT TileManager : public RasterizerClient,
virtual void ScheduleTasks(
const TileVector& tiles_that_need_to_be_rasterized);
- void AssignGpuMemoryToTiles(PrioritizedTileSet* tiles,
- TileVector* tiles_that_need_to_be_rasterized);
- void GetTilesWithAssignedBins(PrioritizedTileSet* tiles);
+ void AssignGpuMemoryToTiles(TileVector* tiles_that_need_to_be_rasterized);
private:
+ class MemoryUsage {
+ public:
+ MemoryUsage();
+ MemoryUsage(int64 memory_bytes, int resource_count);
+
+ static MemoryUsage FromConfig(const gfx::Size& size, ResourceFormat format);
+ static MemoryUsage FromTile(const Tile* tile);
+
+ MemoryUsage& operator+=(const MemoryUsage& other);
+ MemoryUsage& operator-=(const MemoryUsage& other);
+ MemoryUsage operator-(const MemoryUsage& other);
+
+ bool Exceeds(const MemoryUsage& limit) const;
+ int64 memory_bytes() const { return memory_bytes_; }
+
+ private:
+ int64 memory_bytes_;
+ int resource_count_;
+ };
+
void OnImageDecodeTaskCompleted(int layer_id,
SkPixelRef* pixel_ref,
bool was_canceled);
void OnRasterTaskCompleted(Tile::Id tile,
scoped_ptr<ScopedResource> resource,
- RasterMode raster_mode,
- const PicturePileImpl::Analysis& analysis,
+ const RasterSource::SolidColorAnalysis& analysis,
bool was_canceled);
- inline size_t BytesConsumedIfAllocated(const Tile* tile) const {
- return Resource::MemorySizeBytes(tile->size(),
- resource_pool_->resource_format());
- }
-
- void FreeResourceForTile(Tile* tile, RasterMode mode);
void FreeResourcesForTile(Tile* tile);
- void FreeUnusedResourcesForTile(Tile* tile);
void FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(Tile* tile);
scoped_refptr<ImageDecodeTask> CreateImageDecodeTask(Tile* tile,
SkPixelRef* pixel_ref);
scoped_refptr<RasterTask> CreateRasterTask(Tile* tile);
- void UpdatePrioritizedTileSetIfNeeded();
+ void RebuildEvictionQueueIfNeeded();
+ bool FreeTileResourcesUntilUsageIsWithinLimit(const MemoryUsage& limit,
+ MemoryUsage* usage);
+ bool FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
+ const MemoryUsage& limit,
+ const TilePriority& oother_priority,
+ MemoryUsage* usage);
+ bool TilePriorityViolatesMemoryPolicy(const TilePriority& priority);
bool IsReadyToActivate() const;
void CheckIfReadyToActivate();
@@ -293,28 +238,21 @@ class CC_EXPORT TileManager : public RasterizerClient,
ResourcePool* resource_pool_;
Rasterizer* rasterizer_;
GlobalStateThatImpactsTilePriority global_state_;
+ const size_t scheduled_raster_task_limit_;
typedef base::hash_map<Tile::Id, Tile*> TileMap;
TileMap tiles_;
- PrioritizedTileSet prioritized_tiles_;
- bool prioritized_tiles_dirty_;
-
- bool all_tiles_that_need_to_be_rasterized_have_memory_;
- bool all_tiles_required_for_activation_have_memory_;
-
- size_t bytes_releasable_;
- size_t resources_releasable_;
-
- bool ever_exceeded_memory_budget_;
+ bool all_tiles_that_need_to_be_rasterized_are_scheduled_;
MemoryHistory::Entry memory_stats_from_last_assign_;
RenderingStatsInstrumentation* rendering_stats_instrumentation_;
bool did_initialize_visible_tile_;
bool did_check_for_completed_tasks_since_last_schedule_tasks_;
+ bool did_oom_on_last_assign_;
- typedef base::hash_map<uint32_t, scoped_refptr<ImageDecodeTask> >
+ typedef base::hash_map<uint32_t, scoped_refptr<ImageDecodeTask>>
PixelRefTaskMap;
typedef base::hash_map<int, PixelRefTaskMap> LayerPixelRefTaskMap;
LayerPixelRefTaskMap image_decode_tasks_;
@@ -331,10 +269,14 @@ class CC_EXPORT TileManager : public RasterizerClient,
// Queue used when scheduling raster tasks.
RasterTaskQueue raster_queue_;
- std::vector<scoped_refptr<RasterTask> > orphan_raster_tasks_;
+ std::vector<scoped_refptr<RasterTask>> orphan_raster_tasks_;
UniqueNotifier ready_to_activate_check_notifier_;
+ RasterTilePriorityQueue raster_priority_queue_;
+ EvictionTilePriorityQueue eviction_priority_queue_;
+ bool eviction_priority_queue_is_up_to_date_;
+
DISALLOW_COPY_AND_ASSIGN(TileManager);
};
diff --git a/chromium/cc/resources/tile_manager_perftest.cc b/chromium/cc/resources/tile_manager_perftest.cc
index cc54fbb633c..43c10312cfb 100644
--- a/chromium/cc/resources/tile_manager_perftest.cc
+++ b/chromium/cc/resources/tile_manager_perftest.cc
@@ -4,8 +4,10 @@
#include "base/time/time.h"
#include "cc/debug/lap_timer.h"
+#include "cc/resources/raster_buffer.h"
#include "cc/resources/tile.h"
#include "cc/resources/tile_priority.h"
+#include "cc/test/begin_frame_args_test.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
@@ -22,6 +24,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
+#include "ui/gfx/frame_time.h"
+
namespace cc {
namespace {
@@ -33,9 +37,9 @@ static const int kTimeCheckInterval = 10;
class FakeRasterizerImpl : public Rasterizer, public RasterizerTaskClient {
public:
// Overridden from Rasterizer:
- virtual void SetClient(RasterizerClient* client) OVERRIDE {}
- virtual void Shutdown() OVERRIDE {}
- virtual void ScheduleTasks(RasterTaskQueue* queue) OVERRIDE {
+ void SetClient(RasterizerClient* client) override {}
+ void Shutdown() override {}
+ void ScheduleTasks(RasterTaskQueue* queue) override {
for (RasterTaskQueue::Item::Vector::const_iterator it =
queue->items.begin();
it != queue->items.end();
@@ -49,7 +53,7 @@ class FakeRasterizerImpl : public Rasterizer, public RasterizerTaskClient {
completed_tasks_.push_back(task);
}
}
- virtual void CheckForCompletedTasks() OVERRIDE {
+ void CheckForCompletedTasks() override {
for (RasterTask::Vector::iterator it = completed_tasks_.begin();
it != completed_tasks_.end();
++it) {
@@ -65,10 +69,11 @@ class FakeRasterizerImpl : public Rasterizer, public RasterizerTaskClient {
}
// Overridden from RasterizerTaskClient:
- virtual SkCanvas* AcquireCanvasForRaster(RasterTask* task) OVERRIDE {
- return NULL;
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) override {
+ return nullptr;
}
- virtual void ReleaseCanvasForRaster(RasterTask* task) OVERRIDE {}
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override {}
private:
RasterTask::Vector completed_tasks_;
@@ -106,31 +111,27 @@ class TileManagerPerfTest : public testing::Test {
host_impl_.tile_manager()->SetGlobalStateForTesting(state);
}
- virtual void SetUp() OVERRIDE {
- picture_pile_ = FakePicturePileImpl::CreateInfiniteFilledPile();
+ virtual void SetUp() override {
InitializeRenderer();
SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
}
virtual void InitializeRenderer() {
- host_impl_.InitializeRenderer(
- FakeOutputSurface::Create3d().PassAs<OutputSurface>());
+ host_impl_.InitializeRenderer(FakeOutputSurface::Create3d().Pass());
tile_manager()->SetRasterizerForTesting(g_fake_rasterizer.Pointer());
}
void SetupDefaultTrees(const gfx::Size& layer_bounds) {
- gfx::Size tile_size(100, 100);
-
scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ FakePicturePileImpl::CreateFilledPile(kDefaultTileSize, layer_bounds);
scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ FakePicturePileImpl::CreateFilledPile(kDefaultTileSize, layer_bounds);
SetupTrees(pending_pile, active_pile);
}
void ActivateTree() {
- host_impl_.ActivatePendingTree();
+ host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree());
pending_root_layer_ = NULL;
active_root_layer_ = static_cast<FakePictureLayerImpl*>(
@@ -160,7 +161,7 @@ class TileManagerPerfTest : public testing::Test {
scoped_ptr<FakePictureLayerImpl> pending_layer =
FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pile);
pending_layer->SetDrawsContent(true);
- pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>());
+ pending_tree->SetRootLayer(pending_layer.Pass());
pending_root_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.pending_tree()->LayerById(id_));
@@ -175,22 +176,100 @@ class TileManagerPerfTest : public testing::Test {
pending_root_layer_->SetAllTilesVisible();
}
- void RunRasterIteratorTest(const std::string& test_name,
- unsigned tile_count) {
+ void RunRasterQueueConstructTest(const std::string& test_name,
+ int layer_count) {
+ TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
+ SMOOTHNESS_TAKES_PRIORITY,
+ NEW_CONTENT_TAKES_PRIORITY};
+ int priority_count = 0;
+
+ std::vector<LayerImpl*> layers = CreateLayers(layer_count, 10);
+ bool resourceless_software_draw = false;
+ for (unsigned i = 0; i < layers.size(); ++i) {
+ layers[i]->UpdateTiles(Occlusion(), resourceless_software_draw);
+ }
+
+ timer_.Reset();
+ do {
+ RasterTilePriorityQueue queue;
+ host_impl_.BuildRasterQueue(&queue, priorities[priority_count]);
+ priority_count = (priority_count + 1) % arraysize(priorities);
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult("tile_manager_raster_tile_queue_construct",
+ "",
+ test_name,
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+ }
+
+ void RunRasterQueueConstructAndIterateTest(const std::string& test_name,
+ int layer_count,
+ unsigned tile_count) {
+ TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
+ SMOOTHNESS_TAKES_PRIORITY,
+ NEW_CONTENT_TAKES_PRIORITY};
+
+ std::vector<LayerImpl*> layers = CreateLayers(layer_count, 100);
+ bool resourceless_software_draw = false;
+ for (unsigned i = 0; i < layers.size(); ++i) {
+ layers[i]->UpdateTiles(Occlusion(), resourceless_software_draw);
+ }
+
+ int priority_count = 0;
timer_.Reset();
do {
int count = tile_count;
- for (TileManager::RasterTileIterator it(tile_manager(),
- SAME_PRIORITY_FOR_BOTH_TREES);
- it && count;
- ++it) {
- --count;
+ RasterTilePriorityQueue queue;
+ host_impl_.BuildRasterQueue(&queue, priorities[priority_count]);
+ while (count--) {
+ ASSERT_FALSE(queue.IsEmpty());
+ ASSERT_TRUE(queue.Top() != NULL);
+ queue.Pop();
+ }
+ priority_count = (priority_count + 1) % arraysize(priorities);
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult(
+ "tile_manager_raster_tile_queue_construct_and_iterate",
+ "",
+ test_name,
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+ }
+
+ void RunEvictionQueueConstructTest(const std::string& test_name,
+ int layer_count) {
+ TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
+ SMOOTHNESS_TAKES_PRIORITY,
+ NEW_CONTENT_TAKES_PRIORITY};
+ int priority_count = 0;
+
+ std::vector<LayerImpl*> layers = CreateLayers(layer_count, 10);
+ bool resourceless_software_draw = false;
+ for (unsigned i = 0; i < layers.size(); ++i) {
+ FakePictureLayerImpl* layer =
+ static_cast<FakePictureLayerImpl*>(layers[i]);
+ layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ for (size_t j = 0; j < layer->GetTilings()->num_tilings(); ++j) {
+ tile_manager()->InitializeTilesWithResourcesForTesting(
+ layer->GetTilings()->tiling_at(j)->AllTilesForTesting());
}
- ASSERT_EQ(0, count);
+ }
+
+ timer_.Reset();
+ do {
+ EvictionTilePriorityQueue queue;
+ host_impl_.BuildEvictionQueue(&queue, priorities[priority_count]);
+ priority_count = (priority_count + 1) % arraysize(priorities);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
- perf_test::PrintResult("tile_manager_raster_tile_iterator",
+ perf_test::PrintResult("tile_manager_eviction_tile_queue_construct",
"",
test_name,
timer_.LapsPerSecond(),
@@ -198,6 +277,49 @@ class TileManagerPerfTest : public testing::Test {
true);
}
+ void RunEvictionQueueConstructAndIterateTest(const std::string& test_name,
+ int layer_count,
+ unsigned tile_count) {
+ TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
+ SMOOTHNESS_TAKES_PRIORITY,
+ NEW_CONTENT_TAKES_PRIORITY};
+ int priority_count = 0;
+
+ std::vector<LayerImpl*> layers = CreateLayers(layer_count, tile_count);
+ bool resourceless_software_draw = false;
+ for (unsigned i = 0; i < layers.size(); ++i) {
+ FakePictureLayerImpl* layer =
+ static_cast<FakePictureLayerImpl*>(layers[i]);
+ layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ for (size_t j = 0; j < layer->GetTilings()->num_tilings(); ++j) {
+ tile_manager()->InitializeTilesWithResourcesForTesting(
+ layer->GetTilings()->tiling_at(j)->AllTilesForTesting());
+ }
+ }
+
+ timer_.Reset();
+ do {
+ int count = tile_count;
+ EvictionTilePriorityQueue queue;
+ host_impl_.BuildEvictionQueue(&queue, priorities[priority_count]);
+ while (count--) {
+ ASSERT_FALSE(queue.IsEmpty());
+ ASSERT_TRUE(queue.Top() != NULL);
+ queue.Pop();
+ }
+ priority_count = (priority_count + 1) % arraysize(priorities);
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ perf_test::PrintResult(
+ "tile_manager_eviction_tile_queue_construct_and_iterate",
+ "",
+ test_name,
+ timer_.LapsPerSecond(),
+ "runs/s",
+ true);
+ }
+
std::vector<LayerImpl*> CreateLayers(int layer_count,
int tiles_per_layer_count) {
// Compute the width/height required for high res to get
@@ -217,7 +339,7 @@ class TileManagerPerfTest : public testing::Test {
// Ensure that we start with blank trees and no tiles.
host_impl_.ResetTreesForTesting();
- tile_manager()->CleanUpReleasedTilesForTesting();
+ tile_manager()->FreeResourcesAndCleanUpReleasedTilesForTesting();
gfx::Size layer_bounds(width, height);
gfx::Size viewport(width / 5, height / 5);
@@ -235,13 +357,15 @@ class TileManagerPerfTest : public testing::Test {
int next_id = id_ + 1;
// Create the rest of the layers as children of the root layer.
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFilledPile(kDefaultTileSize, layer_bounds);
while (static_cast<int>(layers.size()) < layer_count) {
scoped_ptr<FakePictureLayerImpl> layer =
- FakePictureLayerImpl::CreateWithPile(
- host_impl_.pending_tree(), next_id, picture_pile_);
+ FakePictureLayerImpl::CreateWithPile(host_impl_.pending_tree(),
+ next_id, pile);
layer->SetBounds(layer_bounds);
layers.push_back(layer.get());
- pending_root_layer_->AddChild(layer.PassAs<LayerImpl>());
+ pending_root_layer_->AddChild(layer.Pass());
FakePictureLayerImpl* fake_layer =
static_cast<FakePictureLayerImpl*>(layers.back());
@@ -274,16 +398,19 @@ class TileManagerPerfTest : public testing::Test {
std::vector<LayerImpl*> layers =
CreateLayers(layer_count, approximate_tile_count_per_layer);
timer_.Reset();
+ bool resourceless_software_draw = false;
do {
- host_impl_.UpdateCurrentFrameTime();
- for (unsigned i = 0; i < layers.size(); ++i)
- layers[i]->UpdateTiles();
+ BeginFrameArgs args = CreateBeginFrameArgsForTesting();
+ host_impl_.UpdateCurrentBeginFrameArgs(args);
+ for (unsigned i = 0; i < layers.size(); ++i) {
+ layers[i]->UpdateTiles(Occlusion(), resourceless_software_draw);
+ }
GlobalStateThatImpactsTilePriority global_state(GlobalStateForTest());
tile_manager()->ManageTiles(global_state);
tile_manager()->UpdateVisibleTiles();
timer_.NextLap();
- host_impl_.ResetCurrentFrameTimeForNextFrame();
+ host_impl_.ResetCurrentBeginFrameArgsForNextFrame();
} while (!timer_.HasTimeLimitExpired());
perf_test::PrintResult(
@@ -304,34 +431,65 @@ class TileManagerPerfTest : public testing::Test {
FakePictureLayerImpl* pending_root_layer_;
FakePictureLayerImpl* active_root_layer_;
LapTimer timer_;
- scoped_refptr<FakePicturePileImpl> picture_pile_;
LayerTreeSettings settings_;
+
+ static const gfx::Size kDefaultTileSize;
};
+const gfx::Size TileManagerPerfTest::kDefaultTileSize(100, 100);
+
TEST_F(TileManagerPerfTest, ManageTiles) {
- RunManageTilesTest("1_100", 1, 100);
- RunManageTilesTest("1_500", 1, 500);
- RunManageTilesTest("1_1000", 1, 1000);
- RunManageTilesTest("5_100", 5, 100);
- RunManageTilesTest("5_500", 5, 500);
- RunManageTilesTest("5_1000", 5, 1000);
+ RunManageTilesTest("2_100", 2, 100);
+ RunManageTilesTest("2_500", 2, 500);
+ RunManageTilesTest("2_1000", 2, 1000);
RunManageTilesTest("10_100", 10, 100);
RunManageTilesTest("10_500", 10, 500);
RunManageTilesTest("10_1000", 10, 1000);
- RunManageTilesTest("100_100", 100, 100);
- RunManageTilesTest("100_500", 100, 500);
- RunManageTilesTest("100_1000", 100, 1000);
+ RunManageTilesTest("50_100", 100, 100);
+ RunManageTilesTest("50_500", 100, 500);
+ RunManageTilesTest("50_1000", 100, 1000);
+}
+
+TEST_F(TileManagerPerfTest, RasterTileQueueConstruct) {
+ RunRasterQueueConstructTest("2", 2);
+ RunRasterQueueConstructTest("10", 10);
+ RunRasterQueueConstructTest("50", 50);
}
-TEST_F(TileManagerPerfTest, RasterTileIterator) {
- SetupDefaultTrees(gfx::Size(10000, 10000));
- active_root_layer_->CreateDefaultTilingsAndTiles();
- pending_root_layer_->CreateDefaultTilingsAndTiles();
+TEST_F(TileManagerPerfTest, RasterTileQueueConstructAndIterate) {
+ RunRasterQueueConstructAndIterateTest("2_16", 2, 16);
+ RunRasterQueueConstructAndIterateTest("2_32", 2, 32);
+ RunRasterQueueConstructAndIterateTest("2_64", 2, 64);
+ RunRasterQueueConstructAndIterateTest("2_128", 2, 128);
+ RunRasterQueueConstructAndIterateTest("10_16", 10, 16);
+ RunRasterQueueConstructAndIterateTest("10_32", 10, 32);
+ RunRasterQueueConstructAndIterateTest("10_64", 10, 64);
+ RunRasterQueueConstructAndIterateTest("10_128", 10, 128);
+ RunRasterQueueConstructAndIterateTest("50_16", 50, 16);
+ RunRasterQueueConstructAndIterateTest("50_32", 50, 32);
+ RunRasterQueueConstructAndIterateTest("50_64", 50, 64);
+ RunRasterQueueConstructAndIterateTest("50_128", 50, 128);
+}
+
+TEST_F(TileManagerPerfTest, EvictionTileQueueConstruct) {
+ RunEvictionQueueConstructTest("2", 2);
+ RunEvictionQueueConstructTest("10", 10);
+ RunEvictionQueueConstructTest("50", 50);
+}
- RunRasterIteratorTest("2_16", 16);
- RunRasterIteratorTest("2_32", 32);
- RunRasterIteratorTest("2_64", 64);
- RunRasterIteratorTest("2_128", 128);
+TEST_F(TileManagerPerfTest, EvictionTileQueueConstructAndIterate) {
+ RunEvictionQueueConstructAndIterateTest("2_16", 2, 16);
+ RunEvictionQueueConstructAndIterateTest("2_32", 2, 32);
+ RunEvictionQueueConstructAndIterateTest("2_64", 2, 64);
+ RunEvictionQueueConstructAndIterateTest("2_128", 2, 128);
+ RunEvictionQueueConstructAndIterateTest("10_16", 10, 16);
+ RunEvictionQueueConstructAndIterateTest("10_32", 10, 32);
+ RunEvictionQueueConstructAndIterateTest("10_64", 10, 64);
+ RunEvictionQueueConstructAndIterateTest("10_128", 10, 128);
+ RunEvictionQueueConstructAndIterateTest("50_16", 50, 16);
+ RunEvictionQueueConstructAndIterateTest("50_32", 50, 32);
+ RunEvictionQueueConstructAndIterateTest("50_64", 50, 64);
+ RunEvictionQueueConstructAndIterateTest("50_128", 50, 128);
}
} // namespace
diff --git a/chromium/cc/resources/tile_manager_unittest.cc b/chromium/cc/resources/tile_manager_unittest.cc
index f894c4f9c98..2f0735c33d3 100644
--- a/chromium/cc/resources/tile_manager_unittest.cc
+++ b/chromium/cc/resources/tile_manager_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "cc/resources/eviction_tile_priority_queue.h"
+#include "cc/resources/raster_tile_priority_queue.h"
#include "cc/resources/tile.h"
#include "cc/resources/tile_priority.h"
#include "cc/test/fake_impl_proxy.h"
@@ -20,421 +22,20 @@
namespace cc {
namespace {
-class TileManagerTest : public testing::TestWithParam<bool>,
- public TileManagerClient {
+class LowResTilingsSettings : public ImplSidePaintingSettings {
public:
- typedef std::vector<scoped_refptr<Tile> > TileVector;
-
- TileManagerTest()
- : memory_limit_policy_(ALLOW_ANYTHING),
- max_tiles_(0),
- ready_to_activate_(false) {}
-
- void Initialize(int max_tiles,
- TileMemoryLimitPolicy memory_limit_policy,
- TreePriority tree_priority) {
- output_surface_ = FakeOutputSurface::Create3d();
- CHECK(output_surface_->BindToClient(&output_surface_client_));
-
- shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider_ = ResourceProvider::Create(
- output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false);
- resource_pool_ = ResourcePool::Create(
- resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
- tile_manager_ =
- make_scoped_ptr(new FakeTileManager(this, resource_pool_.get()));
-
- memory_limit_policy_ = memory_limit_policy;
- max_tiles_ = max_tiles;
- picture_pile_ = FakePicturePileImpl::CreateInfiniteFilledPile();
-
- SetTreePriority(tree_priority);
- }
-
- void SetTreePriority(TreePriority tree_priority) {
- GlobalStateThatImpactsTilePriority state;
- gfx::Size tile_size = settings_.default_tile_size;
-
- if (UsingMemoryLimit()) {
- state.soft_memory_limit_in_bytes =
- max_tiles_ * 4 * tile_size.width() * tile_size.height();
- state.num_resources_limit = 100;
- } else {
- state.soft_memory_limit_in_bytes = 100 * 1000 * 1000;
- state.num_resources_limit = max_tiles_;
- }
- state.hard_memory_limit_in_bytes = state.soft_memory_limit_in_bytes * 2;
- state.memory_limit_policy = memory_limit_policy_;
- state.tree_priority = tree_priority;
-
- global_state_ = state;
- resource_pool_->SetResourceUsageLimits(state.soft_memory_limit_in_bytes,
- state.soft_memory_limit_in_bytes,
- state.num_resources_limit);
- tile_manager_->SetGlobalStateForTesting(state);
- }
-
- virtual void TearDown() OVERRIDE {
- tile_manager_.reset(NULL);
- picture_pile_ = NULL;
-
- testing::Test::TearDown();
- }
-
- // TileManagerClient implementation.
- virtual const std::vector<PictureLayerImpl*>& GetPictureLayers() OVERRIDE {
- return picture_layers_;
- }
- virtual void NotifyReadyToActivate() OVERRIDE { ready_to_activate_ = true; }
- virtual void NotifyTileStateChanged(const Tile* tile) OVERRIDE {}
-
- TileVector CreateTilesWithSize(int count,
- TilePriority active_priority,
- TilePriority pending_priority,
- const gfx::Size& tile_size) {
- TileVector tiles;
- for (int i = 0; i < count; ++i) {
- scoped_refptr<Tile> tile = tile_manager_->CreateTile(picture_pile_.get(),
- tile_size,
- gfx::Rect(),
- gfx::Rect(),
- 1.0,
- 0,
- 0,
- 0);
- tile->SetPriority(ACTIVE_TREE, active_priority);
- tile->SetPriority(PENDING_TREE, pending_priority);
- tiles.push_back(tile);
- }
- return tiles;
- }
-
- TileVector CreateTiles(int count,
- TilePriority active_priority,
- TilePriority pending_priority) {
- return CreateTilesWithSize(
- count, active_priority, pending_priority, settings_.default_tile_size);
- }
-
- FakeTileManager* tile_manager() { return tile_manager_.get(); }
-
- int AssignedMemoryCount(const TileVector& tiles) {
- int has_memory_count = 0;
- for (TileVector::const_iterator it = tiles.begin(); it != tiles.end();
- ++it) {
- if (tile_manager_->HasBeenAssignedMemory(*it))
- ++has_memory_count;
- }
- return has_memory_count;
- }
-
- bool ready_to_activate() const { return ready_to_activate_; }
-
- // The parametrization specifies whether the max tile limit should
- // be applied to memory or resources.
- bool UsingResourceLimit() { return !GetParam(); }
- bool UsingMemoryLimit() { return GetParam(); }
-
- protected:
- GlobalStateThatImpactsTilePriority global_state_;
-
- private:
- LayerTreeSettings settings_;
- scoped_ptr<FakeTileManager> tile_manager_;
- scoped_refptr<FakePicturePileImpl> picture_pile_;
- FakeOutputSurfaceClient output_surface_client_;
- scoped_ptr<FakeOutputSurface> output_surface_;
- scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
- scoped_ptr<ResourceProvider> resource_provider_;
- scoped_ptr<ResourcePool> resource_pool_;
- TileMemoryLimitPolicy memory_limit_policy_;
- int max_tiles_;
- bool ready_to_activate_;
- std::vector<PictureLayerImpl*> picture_layers_;
+ LowResTilingsSettings() { create_low_res_tiling = true; }
};
-TEST_P(TileManagerTest, EnoughMemoryAllowAnything) {
- // A few tiles of each type of priority, with enough memory for all tiles.
-
- Initialize(10, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_now =
- CreateTiles(3, TilePriorityForNowBin(), TilePriority());
- TileVector pending_now =
- CreateTiles(3, TilePriority(), TilePriorityForNowBin());
- TileVector active_pending_soon =
- CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
- TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(3, AssignedMemoryCount(active_now));
- EXPECT_EQ(3, AssignedMemoryCount(pending_now));
- EXPECT_EQ(3, AssignedMemoryCount(active_pending_soon));
- EXPECT_EQ(0, AssignedMemoryCount(never_bin));
-}
-
-TEST_P(TileManagerTest, EnoughMemoryAllowPrepaintOnly) {
- // A few tiles of each type of priority, with enough memory for all tiles,
- // with the exception of never bin.
-
- Initialize(10, ALLOW_PREPAINT_ONLY, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_now =
- CreateTiles(3, TilePriorityForNowBin(), TilePriority());
- TileVector pending_now =
- CreateTiles(3, TilePriority(), TilePriorityForNowBin());
- TileVector active_pending_soon =
- CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
- TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(3, AssignedMemoryCount(active_now));
- EXPECT_EQ(3, AssignedMemoryCount(pending_now));
- EXPECT_EQ(3, AssignedMemoryCount(active_pending_soon));
- EXPECT_EQ(0, AssignedMemoryCount(never_bin));
-}
-
-TEST_P(TileManagerTest, EnoughMemoryPendingLowResAllowAbsoluteMinimum) {
- // A few low-res tiles required for activation, with enough memory for all
- // tiles.
-
- Initialize(5, ALLOW_ABSOLUTE_MINIMUM, SAME_PRIORITY_FOR_BOTH_TREES);
- TileVector pending_low_res =
- CreateTiles(5, TilePriority(), TilePriorityLowRes());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(5, AssignedMemoryCount(pending_low_res));
-}
-
-TEST_P(TileManagerTest, EnoughMemoryAllowAbsoluteMinimum) {
- // A few tiles of each type of priority, with enough memory for all tiles,
- // with the exception of never and soon bins.
-
- Initialize(10, ALLOW_ABSOLUTE_MINIMUM, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_now =
- CreateTiles(3, TilePriorityForNowBin(), TilePriority());
- TileVector pending_now =
- CreateTiles(3, TilePriority(), TilePriorityForNowBin());
- TileVector active_pending_soon =
- CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
- TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(3, AssignedMemoryCount(active_now));
- EXPECT_EQ(3, AssignedMemoryCount(pending_now));
- EXPECT_EQ(0, AssignedMemoryCount(active_pending_soon));
- EXPECT_EQ(0, AssignedMemoryCount(never_bin));
-}
-
-TEST_P(TileManagerTest, EnoughMemoryAllowNothing) {
- // A few tiles of each type of priority, with enough memory for all tiles,
- // but allow nothing should not assign any memory.
-
- Initialize(10, ALLOW_NOTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_now =
- CreateTiles(3, TilePriorityForNowBin(), TilePriority());
- TileVector pending_now =
- CreateTiles(3, TilePriority(), TilePriorityForNowBin());
- TileVector active_pending_soon =
- CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin());
- TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(0, AssignedMemoryCount(active_now));
- EXPECT_EQ(0, AssignedMemoryCount(pending_now));
- EXPECT_EQ(0, AssignedMemoryCount(active_pending_soon));
- EXPECT_EQ(0, AssignedMemoryCount(never_bin));
-}
-
-TEST_P(TileManagerTest, PartialOOMMemoryToPending) {
- // 5 tiles on active tree eventually bin, 5 tiles on pending tree that are
- // required for activation, but only enough memory for 8 tiles. The result
- // is all pending tree tiles get memory, and 3 of the active tree tiles
- // get memory. None of these tiles is needed to avoid calimity (flickering or
- // raster-on-demand) so the soft memory limit is used.
-
- Initialize(8, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_tree_tiles =
- CreateTiles(5, TilePriorityForEventualBin(), TilePriority());
- TileVector pending_tree_tiles =
- CreateTiles(5, TilePriority(), TilePriorityRequiredForActivation());
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(5, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(3, AssignedMemoryCount(pending_tree_tiles));
-
- SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(3, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(5, AssignedMemoryCount(pending_tree_tiles));
-}
-
-TEST_P(TileManagerTest, PartialOOMMemoryToActive) {
- // 5 tiles on active tree eventually bin, 5 tiles on pending tree now bin,
- // but only enough memory for 8 tiles. The result is all active tree tiles
- // get memory, and 3 of the pending tree tiles get memory.
- // The pending tiles are not needed to avoid calimity (flickering or
- // raster-on-demand) and the active tiles fit, so the soft limit is used.
-
- Initialize(8, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_tree_tiles =
- CreateTiles(5, TilePriorityForNowBin(), TilePriority());
- TileVector pending_tree_tiles =
- CreateTiles(5, TilePriority(), TilePriorityForNowBin());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(5, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(3, AssignedMemoryCount(pending_tree_tiles));
-}
-
-TEST_P(TileManagerTest, TotalOOMMemoryToPending) {
- // 10 tiles on active tree eventually bin, 10 tiles on pending tree that are
- // required for activation, but only enough tiles for 4 tiles. The result
- // is 4 pending tree tiles get memory, and none of the active tree tiles
- // get memory.
-
- Initialize(4, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_tree_tiles =
- CreateTiles(10, TilePriorityForEventualBin(), TilePriority());
- TileVector pending_tree_tiles =
- CreateTiles(10, TilePriority(), TilePriorityRequiredForActivation());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
-
- SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- if (UsingResourceLimit()) {
- EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(4, AssignedMemoryCount(pending_tree_tiles));
- } else {
- // Pending tiles are now required to avoid calimity (flickering or
- // raster-on-demand). Hard-limit is used and double the tiles fit.
- EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(8, AssignedMemoryCount(pending_tree_tiles));
- }
-}
-
-TEST_P(TileManagerTest, TotalOOMActiveSoonMemoryToPending) {
- // 10 tiles on active tree soon bin, 10 tiles on pending tree that are
- // required for activation, but only enough tiles for 4 tiles. The result
- // is 4 pending tree tiles get memory, and none of the active tree tiles
- // get memory.
-
- Initialize(4, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_tree_tiles =
- CreateTiles(10, TilePriorityForSoonBin(), TilePriority());
- TileVector pending_tree_tiles =
- CreateTiles(10, TilePriority(), TilePriorityRequiredForActivation());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
-
- SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- if (UsingResourceLimit()) {
- EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(4, AssignedMemoryCount(pending_tree_tiles));
- } else {
- // Pending tiles are now required to avoid calimity (flickering or
- // raster-on-demand). Hard-limit is used and double the tiles fit.
- EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(8, AssignedMemoryCount(pending_tree_tiles));
- }
-}
-
-TEST_P(TileManagerTest, TotalOOMMemoryToActive) {
- // 10 tiles on active tree eventually bin, 10 tiles on pending tree now bin,
- // but only enough memory for 4 tiles. The result is 4 active tree tiles
- // get memory, and none of the pending tree tiles get memory.
-
- Initialize(4, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_tree_tiles =
- CreateTiles(10, TilePriorityForNowBin(), TilePriority());
- TileVector pending_tree_tiles =
- CreateTiles(10, TilePriority(), TilePriorityForNowBin());
-
- tile_manager()->AssignMemoryToTiles(global_state_);
-
- if (UsingResourceLimit()) {
- EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
- } else {
- // Active tiles are required to avoid calimity (flickering or
- // raster-on-demand). Hard-limit is used and double the tiles fit.
- EXPECT_EQ(8, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
- }
-}
-
-TEST_P(TileManagerTest, TotalOOMMemoryToNewContent) {
- // 10 tiles on active tree now bin, 10 tiles on pending tree now bin,
- // but only enough memory for 8 tiles. Any tile missing would cause
- // a calamity (flickering or raster-on-demand). Depending on mode,
- // we should use varying amounts of the higher hard memory limit.
- if (UsingResourceLimit())
- return;
-
- Initialize(8, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY);
- TileVector active_tree_tiles =
- CreateTiles(10, TilePriorityForNowBin(), TilePriority());
- TileVector pending_tree_tiles =
- CreateTiles(10, TilePriority(), TilePriorityForNowBin());
-
- // Active tiles are required to avoid calimity. The hard-limit is used and all
- // active-tiles fit. No pending tiles are needed to avoid calamity so only 10
- // tiles total are used.
- tile_manager()->AssignMemoryToTiles(global_state_);
- EXPECT_EQ(10, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles));
-
- // Even the hard-limit won't save us now. All tiles are required to avoid
- // a clamity but we only have 16. The tiles will be distribted randomly
- // given they are identical, in practice depending on their screen location.
- SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
- tile_manager()->AssignMemoryToTiles(global_state_);
- EXPECT_EQ(16,
- AssignedMemoryCount(active_tree_tiles) +
- AssignedMemoryCount(pending_tree_tiles));
-
- // The pending tree is now more important. Active tiles will take higher
- // priority if they are ready-to-draw in practice. Importantly though,
- // pending tiles also utilize the hard-limit.
- SetTreePriority(NEW_CONTENT_TAKES_PRIORITY);
- tile_manager()->AssignMemoryToTiles(global_state_);
- EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles));
- EXPECT_EQ(10, AssignedMemoryCount(pending_tree_tiles));
-}
-
-// If true, the max tile limit should be applied as bytes; if false,
-// as num_resources_limit.
-INSTANTIATE_TEST_CASE_P(TileManagerTests,
- TileManagerTest,
- ::testing::Values(true, false));
-
-class TileManagerTileIteratorTest : public testing::Test {
+class TileManagerTilePriorityQueueTest : public testing::Test {
public:
- TileManagerTileIteratorTest()
+ TileManagerTilePriorityQueueTest()
: memory_limit_policy_(ALLOW_ANYTHING),
max_tiles_(10000),
ready_to_activate_(false),
id_(7),
proxy_(base::MessageLoopProxy::current()),
- host_impl_(ImplSidePaintingSettings(),
- &proxy_,
- &shared_bitmap_manager_) {}
+ host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_) {}
void SetTreePriority(TreePriority tree_priority) {
GlobalStateThatImpactsTilePriority state;
@@ -454,14 +55,13 @@ class TileManagerTileIteratorTest : public testing::Test {
host_impl_.tile_manager()->SetGlobalStateForTesting(state);
}
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
InitializeRenderer();
SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
}
virtual void InitializeRenderer() {
- host_impl_.InitializeRenderer(
- FakeOutputSurface::Create3d().PassAs<OutputSurface>());
+ host_impl_.InitializeRenderer(FakeOutputSurface::Create3d());
}
void SetupDefaultTrees(const gfx::Size& layer_bounds) {
@@ -476,7 +76,7 @@ class TileManagerTileIteratorTest : public testing::Test {
}
void ActivateTree() {
- host_impl_.ActivatePendingTree();
+ host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree());
pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>(
@@ -500,13 +100,24 @@ class TileManagerTileIteratorTest : public testing::Test {
void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) {
host_impl_.CreatePendingTree();
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
- // Clear recycled tree.
- pending_tree->DetachLayerTree();
- scoped_ptr<FakePictureLayerImpl> pending_layer =
- FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pile);
- pending_layer->SetDrawsContent(true);
- pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>());
+ // Steal from the recycled tree.
+ scoped_ptr<LayerImpl> old_pending_root = pending_tree->DetachLayerTree();
+ DCHECK_IMPLIES(old_pending_root, old_pending_root->id() == id_);
+
+ scoped_ptr<FakePictureLayerImpl> pending_layer;
+ if (old_pending_root) {
+ pending_layer.reset(
+ static_cast<FakePictureLayerImpl*>(old_pending_root.release()));
+ pending_layer->SetPile(pile);
+ } else {
+ pending_layer =
+ FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pile);
+ pending_layer->SetDrawsContent(true);
+ }
+ // The bounds() just mirror the pile size.
+ pending_layer->SetBounds(pending_layer->pile()->tiling_size());
+ pending_tree->SetRootLayer(pending_layer.Pass());
pending_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.pending_tree()->LayerById(id_));
@@ -537,121 +148,79 @@ class TileManagerTileIteratorTest : public testing::Test {
FakePictureLayerImpl* active_layer_;
};
-TEST_F(TileManagerTileIteratorTest, PairedPictureLayers) {
- host_impl_.CreatePendingTree();
- host_impl_.ActivatePendingTree();
- host_impl_.CreatePendingTree();
-
- LayerTreeImpl* active_tree = host_impl_.active_tree();
- LayerTreeImpl* pending_tree = host_impl_.pending_tree();
- EXPECT_NE(active_tree, pending_tree);
-
- scoped_ptr<FakePictureLayerImpl> active_layer =
- FakePictureLayerImpl::Create(active_tree, 10);
- scoped_ptr<FakePictureLayerImpl> pending_layer =
- FakePictureLayerImpl::Create(pending_tree, 10);
-
- TileManager* tile_manager = TileManagerTileIteratorTest::tile_manager();
- EXPECT_TRUE(tile_manager);
-
- std::vector<TileManager::PairedPictureLayer> paired_layers;
- tile_manager->GetPairedPictureLayers(&paired_layers);
-
- EXPECT_EQ(2u, paired_layers.size());
- if (paired_layers[0].active_layer) {
- EXPECT_EQ(active_layer.get(), paired_layers[0].active_layer);
- EXPECT_EQ(NULL, paired_layers[0].pending_layer);
- } else {
- EXPECT_EQ(pending_layer.get(), paired_layers[0].pending_layer);
- EXPECT_EQ(NULL, paired_layers[0].active_layer);
- }
-
- if (paired_layers[1].active_layer) {
- EXPECT_EQ(active_layer.get(), paired_layers[1].active_layer);
- EXPECT_EQ(NULL, paired_layers[1].pending_layer);
- } else {
- EXPECT_EQ(pending_layer.get(), paired_layers[1].pending_layer);
- EXPECT_EQ(NULL, paired_layers[1].active_layer);
- }
-
- active_layer->set_twin_layer(pending_layer.get());
- pending_layer->set_twin_layer(active_layer.get());
-
- tile_manager->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(1u, paired_layers.size());
-
- EXPECT_EQ(active_layer.get(), paired_layers[0].active_layer);
- EXPECT_EQ(pending_layer.get(), paired_layers[0].pending_layer);
-}
-
-TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
+TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueue) {
SetupDefaultTrees(gfx::Size(1000, 1000));
- TileManager* tile_manager = TileManagerTileIteratorTest::tile_manager();
- EXPECT_TRUE(tile_manager);
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
- std::vector<TileManager::PairedPictureLayer> paired_layers;
- tile_manager->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(1u, paired_layers.size());
-
- TileManager::RasterTileIterator it(tile_manager,
- SAME_PRIORITY_FOR_BOTH_TREES);
- EXPECT_TRUE(it);
+ RasterTilePriorityQueue queue;
+ host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_FALSE(queue.IsEmpty());
size_t tile_count = 0;
std::set<Tile*> all_tiles;
- for (; it; ++it) {
- EXPECT_TRUE(*it);
- all_tiles.insert(*it);
+ while (!queue.IsEmpty()) {
+ EXPECT_TRUE(queue.Top());
+ all_tiles.insert(queue.Top());
++tile_count;
+ queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
- EXPECT_EQ(17u, tile_count);
+ EXPECT_EQ(16u, tile_count);
// Sanity check, all tiles should be visible.
std::set<Tile*> smoothness_tiles;
- for (TileManager::RasterTileIterator it(tile_manager,
- SMOOTHNESS_TAKES_PRIORITY);
- it;
- ++it) {
- Tile* tile = *it;
+ queue.Reset();
+ host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
+ bool had_low_res = false;
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
EXPECT_TRUE(tile);
EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin);
- smoothness_tiles.insert(tile);
+ if (tile->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION)
+ had_low_res = true;
+ else
+ smoothness_tiles.insert(tile);
+ queue.Pop();
}
EXPECT_EQ(all_tiles, smoothness_tiles);
+ EXPECT_TRUE(had_low_res);
Region invalidation(gfx::Rect(0, 0, 500, 500));
// Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation);
- pending_layer_->HighResTiling()->Invalidate(invalidation);
- pending_layer_->LowResTiling()->Invalidate(invalidation);
+ pending_layer_->HighResTiling()->UpdateTilesToCurrentPile(
+ invalidation, gfx::Size(1000, 1000));
+ pending_layer_->LowResTiling()->UpdateTilesToCurrentPile(
+ invalidation, gfx::Size(1000, 1000));
active_layer_->ResetAllTilesPriorities();
pending_layer_->ResetAllTilesPriorities();
// Renew all of the tile priorities.
gfx::Rect viewport(50, 50, 100, 100);
- pending_layer_->HighResTiling()->UpdateTilePriorities(
- PENDING_TREE, viewport, 1.0f, 1.0);
- pending_layer_->LowResTiling()->UpdateTilePriorities(
- PENDING_TREE, viewport, 1.0f, 1.0);
- active_layer_->HighResTiling()->UpdateTilePriorities(
- ACTIVE_TREE, viewport, 1.0f, 1.0);
- active_layer_->LowResTiling()->UpdateTilePriorities(
- ACTIVE_TREE, viewport, 1.0f, 1.0);
+ pending_layer_->HighResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ pending_layer_->LowResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ active_layer_->HighResTiling()->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+ active_layer_->LowResTiling()->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
// Populate all tiles directly from the tilings.
all_tiles.clear();
+ std::set<Tile*> high_res_tiles;
std::vector<Tile*> pending_high_res_tiles =
pending_layer_->HighResTiling()->AllTilesForTesting();
- for (size_t i = 0; i < pending_high_res_tiles.size(); ++i)
+ for (size_t i = 0; i < pending_high_res_tiles.size(); ++i) {
all_tiles.insert(pending_high_res_tiles[i]);
+ high_res_tiles.insert(pending_high_res_tiles[i]);
+ }
std::vector<Tile*> pending_low_res_tiles =
pending_layer_->LowResTiling()->AllTilesForTesting();
@@ -660,8 +229,10 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
std::vector<Tile*> active_high_res_tiles =
active_layer_->HighResTiling()->AllTilesForTesting();
- for (size_t i = 0; i < active_high_res_tiles.size(); ++i)
+ for (size_t i = 0; i < active_high_res_tiles.size(); ++i) {
all_tiles.insert(active_high_res_tiles[i]);
+ high_res_tiles.insert(active_high_res_tiles[i]);
+ }
std::vector<Tile*> active_low_res_tiles =
active_layer_->LowResTiling()->AllTilesForTesting();
@@ -671,13 +242,12 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
Tile* last_tile = NULL;
smoothness_tiles.clear();
tile_count = 0;
- size_t increasing_distance_tiles = 0u;
+ size_t correct_order_tiles = 0u;
// Here we expect to get increasing ACTIVE_TREE priority_bin.
- for (TileManager::RasterTileIterator it(tile_manager,
- SMOOTHNESS_TAKES_PRIORITY);
- it;
- ++it) {
- Tile* tile = *it;
+ queue.Reset();
+ host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
EXPECT_TRUE(tile);
if (!last_tile)
@@ -685,11 +255,19 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
EXPECT_LE(last_tile->priority(ACTIVE_TREE).priority_bin,
tile->priority(ACTIVE_TREE).priority_bin);
+ bool skip_updating_last_tile = false;
if (last_tile->priority(ACTIVE_TREE).priority_bin ==
tile->priority(ACTIVE_TREE).priority_bin) {
- increasing_distance_tiles +=
+ correct_order_tiles +=
last_tile->priority(ACTIVE_TREE).distance_to_visible <=
tile->priority(ACTIVE_TREE).distance_to_visible;
+ } else if (tile->priority(ACTIVE_TREE).priority_bin ==
+ TilePriority::EVENTUALLY &&
+ tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW) {
+ // Since we'd return pending tree now tiles before the eventually tiles on
+ // the active tree, update the value.
+ ++correct_order_tiles;
+ skip_updating_last_tile = true;
}
if (tile->priority(ACTIVE_TREE).priority_bin == TilePriority::NOW &&
@@ -699,26 +277,28 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
EXPECT_EQ(LOW_RESOLUTION, last_tile->priority(ACTIVE_TREE).resolution);
}
- last_tile = tile;
+ if (!skip_updating_last_tile)
+ last_tile = tile;
++tile_count;
smoothness_tiles.insert(tile);
+ queue.Pop();
}
EXPECT_EQ(tile_count, smoothness_tiles.size());
EXPECT_EQ(all_tiles, smoothness_tiles);
// Since we don't guarantee increasing distance due to spiral iterator, we
// should check that we're _mostly_ right.
- EXPECT_GT(increasing_distance_tiles, 3 * tile_count / 4);
+ EXPECT_GT(correct_order_tiles, 3 * tile_count / 4);
std::set<Tile*> new_content_tiles;
last_tile = NULL;
- increasing_distance_tiles = 0u;
+ size_t increasing_distance_tiles = 0u;
// Here we expect to get increasing PENDING_TREE priority_bin.
- for (TileManager::RasterTileIterator it(tile_manager,
- NEW_CONTENT_TAKES_PRIORITY);
- it;
- ++it) {
- Tile* tile = *it;
+ queue.Reset();
+ host_impl_.BuildRasterQueue(&queue, NEW_CONTENT_TAKES_PRIORITY);
+ tile_count = 0;
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
EXPECT_TRUE(tile);
if (!last_tile)
@@ -742,86 +322,143 @@ TEST_F(TileManagerTileIteratorTest, RasterTileIterator) {
last_tile = tile;
new_content_tiles.insert(tile);
+ ++tile_count;
+ queue.Pop();
}
EXPECT_EQ(tile_count, new_content_tiles.size());
- EXPECT_EQ(all_tiles, new_content_tiles);
+ EXPECT_EQ(high_res_tiles, new_content_tiles);
// Since we don't guarantee increasing distance due to spiral iterator, we
// should check that we're _mostly_ right.
- EXPECT_GT(increasing_distance_tiles, 3 * tile_count / 4);
+ EXPECT_GE(increasing_distance_tiles, 3 * tile_count / 4);
}
-TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) {
+TEST_F(TileManagerTilePriorityQueueTest, ActivationComesBeforeEventually) {
SetupDefaultTrees(gfx::Size(1000, 1000));
- TileManager* tile_manager = TileManagerTileIteratorTest::tile_manager();
- EXPECT_TRUE(tile_manager);
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
- std::vector<TileManager::PairedPictureLayer> paired_layers;
- tile_manager->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(1u, paired_layers.size());
+ // Create a pending child layer.
+ gfx::Size tile_size(256, 256);
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000));
+ scoped_ptr<FakePictureLayerImpl> pending_child =
+ FakePictureLayerImpl::CreateWithPile(
+ host_impl_.pending_tree(), id_ + 1, pending_pile);
+ pending_layer_->AddChild(pending_child.Pass());
+ FakePictureLayerImpl* pending_child_raw = static_cast<FakePictureLayerImpl*>(
+ host_impl_.pending_tree()->LayerById(id_ + 1));
+ ASSERT_TRUE(pending_child_raw);
+
+ pending_child_raw->SetDrawsContent(true);
+ pending_child_raw->DoPostCommitInitializationIfNeeded();
+ pending_child_raw->CreateDefaultTilingsAndTiles();
+ ASSERT_TRUE(pending_child_raw->HighResTiling());
+
+ // Set a small viewport, so we have soon and eventually tiles.
+ gfx::Rect viewport(200, 200);
+ active_layer_->draw_properties().visible_content_rect = viewport;
+ active_layer_->UpdateTiles(Occlusion(), false);
+ pending_layer_->draw_properties().visible_content_rect = viewport;
+ pending_layer_->UpdateTiles(Occlusion(), false);
+ pending_child_raw->draw_properties().visible_content_rect = viewport;
+ pending_child_raw->UpdateTiles(Occlusion(), false);
+
+ RasterTilePriorityQueue queue;
+ host_impl_.SetRequiresHighResToDraw();
+ host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
+ EXPECT_FALSE(queue.IsEmpty());
+
+ // Get all the tiles that are NOW or SOON and make sure they are ready to
+ // draw.
+ std::vector<Tile*> all_tiles;
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
+ if (tile->combined_priority().priority_bin >= TilePriority::EVENTUALLY)
+ break;
+
+ all_tiles.push_back(tile);
+ queue.Pop();
+ }
+
+ tile_manager()->InitializeTilesWithResourcesForTesting(
+ std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
- TileManager::EvictionTileIterator empty_it(tile_manager,
- SAME_PRIORITY_FOR_BOTH_TREES);
- EXPECT_FALSE(empty_it);
+ // Ensure we can activate.
+ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+ EXPECT_TRUE(pending_child_raw->AllTilesRequiredForActivationAreReadyToDraw());
+}
+
+TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
+ SetupDefaultTrees(gfx::Size(1000, 1000));
+
+ active_layer_->CreateDefaultTilingsAndTiles();
+ pending_layer_->CreateDefaultTilingsAndTiles();
+
+ EvictionTilePriorityQueue empty_queue;
+ host_impl_.BuildEvictionQueue(&empty_queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_TRUE(empty_queue.IsEmpty());
std::set<Tile*> all_tiles;
size_t tile_count = 0;
- for (TileManager::RasterTileIterator raster_it(tile_manager,
- SAME_PRIORITY_FOR_BOTH_TREES);
- raster_it;
- ++raster_it) {
+ RasterTilePriorityQueue raster_queue;
+ host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ while (!raster_queue.IsEmpty()) {
++tile_count;
- EXPECT_TRUE(*raster_it);
- all_tiles.insert(*raster_it);
+ EXPECT_TRUE(raster_queue.Top());
+ all_tiles.insert(raster_queue.Top());
+ raster_queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
- EXPECT_EQ(17u, tile_count);
+ EXPECT_EQ(16u, tile_count);
- tile_manager->InitializeTilesWithResourcesForTesting(
+ tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
- TileManager::EvictionTileIterator it(tile_manager, SMOOTHNESS_TAKES_PRIORITY);
- EXPECT_TRUE(it);
+ EvictionTilePriorityQueue queue;
+ host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
+ EXPECT_FALSE(queue.IsEmpty());
// Sanity check, all tiles should be visible.
std::set<Tile*> smoothness_tiles;
- for (; it; ++it) {
- Tile* tile = *it;
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
EXPECT_TRUE(tile);
EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin);
EXPECT_TRUE(tile->HasResources());
smoothness_tiles.insert(tile);
+ queue.Pop();
}
EXPECT_EQ(all_tiles, smoothness_tiles);
- tile_manager->ReleaseTileResourcesForTesting(
+ tile_manager()->ReleaseTileResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
Region invalidation(gfx::Rect(0, 0, 500, 500));
// Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation);
- pending_layer_->HighResTiling()->Invalidate(invalidation);
- pending_layer_->LowResTiling()->Invalidate(invalidation);
+ pending_layer_->HighResTiling()->UpdateTilesToCurrentPile(
+ invalidation, gfx::Size(1000, 1000));
+ pending_layer_->LowResTiling()->UpdateTilesToCurrentPile(
+ invalidation, gfx::Size(1000, 1000));
active_layer_->ResetAllTilesPriorities();
pending_layer_->ResetAllTilesPriorities();
// Renew all of the tile priorities.
gfx::Rect viewport(50, 50, 100, 100);
- pending_layer_->HighResTiling()->UpdateTilePriorities(
- PENDING_TREE, viewport, 1.0f, 1.0);
- pending_layer_->LowResTiling()->UpdateTilePriorities(
- PENDING_TREE, viewport, 1.0f, 1.0);
- active_layer_->HighResTiling()->UpdateTilePriorities(
- ACTIVE_TREE, viewport, 1.0f, 1.0);
- active_layer_->LowResTiling()->UpdateTilePriorities(
- ACTIVE_TREE, viewport, 1.0f, 1.0);
+ pending_layer_->HighResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ pending_layer_->LowResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ active_layer_->HighResTiling()->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
+ active_layer_->LowResTiling()->ComputeTilePriorityRects(
+ ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
// Populate all tiles directly from the tilings.
all_tiles.clear();
@@ -845,18 +482,17 @@ TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) {
for (size_t i = 0; i < active_low_res_tiles.size(); ++i)
all_tiles.insert(active_low_res_tiles[i]);
- tile_manager->InitializeTilesWithResourcesForTesting(
+ tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
Tile* last_tile = NULL;
smoothness_tiles.clear();
tile_count = 0;
// Here we expect to get increasing ACTIVE_TREE priority_bin.
- for (TileManager::EvictionTileIterator it(tile_manager,
- SMOOTHNESS_TAKES_PRIORITY);
- it;
- ++it) {
- Tile* tile = *it;
+ queue.Reset();
+ host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
EXPECT_TRUE(tile);
EXPECT_TRUE(tile->HasResources());
@@ -867,13 +503,19 @@ TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) {
tile->priority(ACTIVE_TREE).priority_bin);
if (last_tile->priority(ACTIVE_TREE).priority_bin ==
tile->priority(ACTIVE_TREE).priority_bin) {
- EXPECT_GE(last_tile->priority(ACTIVE_TREE).distance_to_visible,
- tile->priority(ACTIVE_TREE).distance_to_visible);
+ EXPECT_LE(last_tile->required_for_activation(),
+ tile->required_for_activation());
+ if (last_tile->required_for_activation() ==
+ tile->required_for_activation()) {
+ EXPECT_GE(last_tile->priority(ACTIVE_TREE).distance_to_visible,
+ tile->priority(ACTIVE_TREE).distance_to_visible);
+ }
}
last_tile = tile;
++tile_count;
smoothness_tiles.insert(tile);
+ queue.Pop();
}
EXPECT_EQ(tile_count, smoothness_tiles.size());
@@ -882,11 +524,10 @@ TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) {
std::set<Tile*> new_content_tiles;
last_tile = NULL;
// Here we expect to get increasing PENDING_TREE priority_bin.
- for (TileManager::EvictionTileIterator it(tile_manager,
- NEW_CONTENT_TAKES_PRIORITY);
- it;
- ++it) {
- Tile* tile = *it;
+ queue.Reset();
+ host_impl_.BuildEvictionQueue(&queue, NEW_CONTENT_TAKES_PRIORITY);
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
EXPECT_TRUE(tile);
if (!last_tile)
@@ -896,16 +537,233 @@ TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) {
tile->priority(PENDING_TREE).priority_bin);
if (last_tile->priority(PENDING_TREE).priority_bin ==
tile->priority(PENDING_TREE).priority_bin) {
- EXPECT_GE(last_tile->priority(PENDING_TREE).distance_to_visible,
- tile->priority(PENDING_TREE).distance_to_visible);
+ EXPECT_LE(last_tile->required_for_activation(),
+ tile->required_for_activation());
+ if (last_tile->required_for_activation() ==
+ tile->required_for_activation()) {
+ EXPECT_GE(last_tile->priority(PENDING_TREE).distance_to_visible,
+ tile->priority(PENDING_TREE).distance_to_visible);
+ }
}
last_tile = tile;
new_content_tiles.insert(tile);
+ queue.Pop();
}
EXPECT_EQ(tile_count, new_content_tiles.size());
EXPECT_EQ(all_tiles, new_content_tiles);
}
+
+TEST_F(TileManagerTilePriorityQueueTest,
+ EvictionTilePriorityQueueWithOcclusion) {
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ pending_layer_->CreateDefaultTilingsAndTiles();
+
+ scoped_ptr<FakePictureLayerImpl> pending_child =
+ FakePictureLayerImpl::CreateWithPile(
+ host_impl_.pending_tree(), 2, pending_pile);
+ pending_layer_->AddChild(pending_child.Pass());
+
+ FakePictureLayerImpl* pending_child_layer =
+ static_cast<FakePictureLayerImpl*>(pending_layer_->children()[0]);
+ pending_child_layer->SetDrawsContent(true);
+ pending_child_layer->DoPostCommitInitializationIfNeeded();
+ pending_child_layer->CreateDefaultTilingsAndTiles();
+
+ std::set<Tile*> all_tiles;
+ size_t tile_count = 0;
+ RasterTilePriorityQueue raster_queue;
+ host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ while (!raster_queue.IsEmpty()) {
+ ++tile_count;
+ EXPECT_TRUE(raster_queue.Top());
+ all_tiles.insert(raster_queue.Top());
+ raster_queue.Pop();
+ }
+ EXPECT_EQ(tile_count, all_tiles.size());
+ EXPECT_EQ(32u, tile_count);
+
+ pending_layer_->ResetAllTilesPriorities();
+
+ // Renew all of the tile priorities.
+ gfx::Rect viewport(layer_bounds);
+ pending_layer_->HighResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ pending_layer_->LowResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ pending_child_layer->HighResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+ pending_child_layer->LowResTiling()->ComputeTilePriorityRects(
+ PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
+
+ // Populate all tiles directly from the tilings.
+ all_tiles.clear();
+ std::vector<Tile*> pending_high_res_tiles =
+ pending_layer_->HighResTiling()->AllTilesForTesting();
+ all_tiles.insert(pending_high_res_tiles.begin(),
+ pending_high_res_tiles.end());
+
+ std::vector<Tile*> pending_low_res_tiles =
+ pending_layer_->LowResTiling()->AllTilesForTesting();
+ all_tiles.insert(pending_low_res_tiles.begin(), pending_low_res_tiles.end());
+
+ // Set all tiles on the pending_child_layer as occluded on the pending tree.
+ std::vector<Tile*> pending_child_high_res_tiles =
+ pending_child_layer->HighResTiling()->AllTilesForTesting();
+ pending_child_layer->HighResTiling()->SetAllTilesOccludedForTesting();
+ all_tiles.insert(pending_child_high_res_tiles.begin(),
+ pending_child_high_res_tiles.end());
+
+ std::vector<Tile*> pending_child_low_res_tiles =
+ pending_child_layer->LowResTiling()->AllTilesForTesting();
+ pending_child_layer->LowResTiling()->SetAllTilesOccludedForTesting();
+ all_tiles.insert(pending_child_low_res_tiles.begin(),
+ pending_child_low_res_tiles.end());
+
+ tile_manager()->InitializeTilesWithResourcesForTesting(
+ std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
+
+ // Verify occlusion is considered by EvictionTilePriorityQueue.
+ TreePriority tree_priority = NEW_CONTENT_TAKES_PRIORITY;
+ size_t occluded_count = 0u;
+ Tile* last_tile = NULL;
+ EvictionTilePriorityQueue queue;
+ host_impl_.BuildEvictionQueue(&queue, tree_priority);
+ while (!queue.IsEmpty()) {
+ Tile* tile = queue.Top();
+ if (!last_tile)
+ last_tile = tile;
+
+ bool tile_is_occluded = tile->is_occluded_for_tree_priority(tree_priority);
+
+ // The only way we will encounter an occluded tile after an unoccluded
+ // tile is if the priorty bin decreased, the tile is required for
+ // activation, or the scale changed.
+ if (tile_is_occluded) {
+ occluded_count++;
+
+ bool last_tile_is_occluded =
+ last_tile->is_occluded_for_tree_priority(tree_priority);
+ if (!last_tile_is_occluded) {
+ TilePriority::PriorityBin tile_priority_bin =
+ tile->priority_for_tree_priority(tree_priority).priority_bin;
+ TilePriority::PriorityBin last_tile_priority_bin =
+ last_tile->priority_for_tree_priority(tree_priority).priority_bin;
+
+ EXPECT_TRUE((tile_priority_bin < last_tile_priority_bin) ||
+ tile->required_for_activation() ||
+ (tile->contents_scale() != last_tile->contents_scale()));
+ }
+ }
+ last_tile = tile;
+ queue.Pop();
+ }
+ size_t expected_occluded_count =
+ pending_child_high_res_tiles.size() + pending_child_low_res_tiles.size();
+ EXPECT_EQ(expected_occluded_count, occluded_count);
+}
+
+TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueEmptyLayers) {
+ SetupDefaultTrees(gfx::Size(1000, 1000));
+
+ active_layer_->CreateDefaultTilingsAndTiles();
+ pending_layer_->CreateDefaultTilingsAndTiles();
+
+ RasterTilePriorityQueue queue;
+ host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_FALSE(queue.IsEmpty());
+
+ size_t tile_count = 0;
+ std::set<Tile*> all_tiles;
+ while (!queue.IsEmpty()) {
+ EXPECT_TRUE(queue.Top());
+ all_tiles.insert(queue.Top());
+ ++tile_count;
+ queue.Pop();
+ }
+
+ EXPECT_EQ(tile_count, all_tiles.size());
+ EXPECT_EQ(16u, tile_count);
+
+ queue.Reset();
+ for (int i = 1; i < 10; ++i) {
+ scoped_ptr<FakePictureLayerImpl> pending_layer =
+ FakePictureLayerImpl::Create(host_impl_.pending_tree(), id_ + i);
+ pending_layer->SetDrawsContent(true);
+ pending_layer->DoPostCommitInitializationIfNeeded();
+ pending_layer->set_has_valid_tile_priorities(true);
+ pending_layer_->AddChild(pending_layer.Pass());
+ }
+
+ host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_FALSE(queue.IsEmpty());
+
+ tile_count = 0;
+ all_tiles.clear();
+ while (!queue.IsEmpty()) {
+ EXPECT_TRUE(queue.Top());
+ all_tiles.insert(queue.Top());
+ ++tile_count;
+ queue.Pop();
+ }
+ EXPECT_EQ(tile_count, all_tiles.size());
+ EXPECT_EQ(16u, tile_count);
+}
+
+TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueEmptyLayers) {
+ SetupDefaultTrees(gfx::Size(1000, 1000));
+
+ active_layer_->CreateDefaultTilingsAndTiles();
+ pending_layer_->CreateDefaultTilingsAndTiles();
+
+ RasterTilePriorityQueue raster_queue;
+ host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_FALSE(raster_queue.IsEmpty());
+
+ size_t tile_count = 0;
+ std::set<Tile*> all_tiles;
+ while (!raster_queue.IsEmpty()) {
+ EXPECT_TRUE(raster_queue.Top());
+ all_tiles.insert(raster_queue.Top());
+ ++tile_count;
+ raster_queue.Pop();
+ }
+ EXPECT_EQ(tile_count, all_tiles.size());
+ EXPECT_EQ(16u, tile_count);
+
+ std::vector<Tile*> tiles(all_tiles.begin(), all_tiles.end());
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+ EvictionTilePriorityQueue queue;
+ for (int i = 1; i < 10; ++i) {
+ scoped_ptr<FakePictureLayerImpl> pending_layer =
+ FakePictureLayerImpl::Create(host_impl_.pending_tree(), id_ + i);
+ pending_layer->SetDrawsContent(true);
+ pending_layer->DoPostCommitInitializationIfNeeded();
+ pending_layer->set_has_valid_tile_priorities(true);
+ pending_layer_->AddChild(pending_layer.Pass());
+ }
+
+ host_impl_.BuildEvictionQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_FALSE(queue.IsEmpty());
+
+ tile_count = 0;
+ all_tiles.clear();
+ while (!queue.IsEmpty()) {
+ EXPECT_TRUE(queue.Top());
+ all_tiles.insert(queue.Top());
+ ++tile_count;
+ queue.Pop();
+ }
+ EXPECT_EQ(tile_count, all_tiles.size());
+ EXPECT_EQ(16u, tile_count);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/resources/tile_priority.cc b/chromium/cc/resources/tile_priority.cc
index 3bf29680766..26826af450e 100644
--- a/chromium/cc/resources/tile_priority.cc
+++ b/chromium/cc/resources/tile_priority.cc
@@ -4,111 +4,95 @@
#include "cc/resources/tile_priority.h"
+#include "base/debug/trace_event_argument.h"
#include "base/values.h"
#include "cc/base/math_util.h"
namespace cc {
-scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) {
+std::string WhichTreeToString(WhichTree tree) {
switch (tree) {
case ACTIVE_TREE:
- return scoped_ptr<base::Value>(new base::StringValue("ACTIVE_TREE"));
+ return "ACTIVE_TREE";
case PENDING_TREE:
- return scoped_ptr<base::Value>(new base::StringValue("PENDING_TREE"));
+ return "PENDING_TREE";
default:
DCHECK(false) << "Unrecognized WhichTree value " << tree;
- return scoped_ptr<base::Value>(new base::StringValue(
- "<unknown WhichTree value>"));
+ return "<unknown WhichTree value>";
}
}
-scoped_ptr<base::Value> TileResolutionAsValue(
- TileResolution resolution) {
+std::string TileResolutionToString(TileResolution resolution) {
switch (resolution) {
case LOW_RESOLUTION:
- return scoped_ptr<base::Value>(new base::StringValue("LOW_RESOLUTION"));
+ return "LOW_RESOLUTION";
case HIGH_RESOLUTION:
- return scoped_ptr<base::Value>(new base::StringValue("HIGH_RESOLUTION"));
+ return "HIGH_RESOLUTION";
case NON_IDEAL_RESOLUTION:
- return scoped_ptr<base::Value>(new base::StringValue(
- "NON_IDEAL_RESOLUTION"));
+ return "NON_IDEAL_RESOLUTION";
}
DCHECK(false) << "Unrecognized TileResolution value " << resolution;
- return scoped_ptr<base::Value>(new base::StringValue(
- "<unknown TileResolution value>"));
+ return "<unknown TileResolution value>";
}
-scoped_ptr<base::Value> TilePriorityBinAsValue(TilePriority::PriorityBin bin) {
+std::string TilePriorityBinToString(TilePriority::PriorityBin bin) {
switch (bin) {
case TilePriority::NOW:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue("NOW"));
+ return "NOW";
case TilePriority::SOON:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue("SOON"));
+ return "SOON";
case TilePriority::EVENTUALLY:
- return scoped_ptr<base::Value>(
- base::Value::CreateStringValue("EVENTUALLY"));
+ return "EVENTUALLY";
}
DCHECK(false) << "Unrecognized TilePriority::PriorityBin value " << bin;
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "<unknown TilePriority::PriorityBin value>"));
+ return "<unknown TilePriority::PriorityBin value>";
}
-scoped_ptr<base::Value> TilePriority::AsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
- state->Set("resolution", TileResolutionAsValue(resolution).release());
- state->Set("priority_bin", TilePriorityBinAsValue(priority_bin).release());
- state->Set("distance_to_visible",
- MathUtil::AsValueSafely(distance_to_visible).release());
- return state.PassAs<base::Value>();
+void TilePriority::AsValueInto(base::debug::TracedValue* state) const {
+ state->SetString("resolution", TileResolutionToString(resolution));
+ state->SetString("priority_bin", TilePriorityBinToString(priority_bin));
+ state->SetDouble("distance_to_visible",
+ MathUtil::AsDoubleSafely(distance_to_visible));
}
-scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue(
- TileMemoryLimitPolicy policy) {
+std::string TileMemoryLimitPolicyToString(TileMemoryLimitPolicy policy) {
switch (policy) {
case ALLOW_NOTHING:
- return scoped_ptr<base::Value>(new base::StringValue("ALLOW_NOTHING"));
+ return "ALLOW_NOTHING";
case ALLOW_ABSOLUTE_MINIMUM:
- return scoped_ptr<base::Value>(new base::StringValue(
- "ALLOW_ABSOLUTE_MINIMUM"));
+ return "ALLOW_ABSOLUTE_MINIMUM";
case ALLOW_PREPAINT_ONLY:
- return scoped_ptr<base::Value>(new base::StringValue(
- "ALLOW_PREPAINT_ONLY"));
+ return "ALLOW_PREPAINT_ONLY";
case ALLOW_ANYTHING:
- return scoped_ptr<base::Value>(new base::StringValue(
- "ALLOW_ANYTHING"));
+ return "ALLOW_ANYTHING";
default:
DCHECK(false) << "Unrecognized policy value";
- return scoped_ptr<base::Value>(new base::StringValue(
- "<unknown>"));
+ return "<unknown>";
}
}
-scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) {
+std::string TreePriorityToString(TreePriority prio) {
switch (prio) {
case SAME_PRIORITY_FOR_BOTH_TREES:
- return scoped_ptr<base::Value>(new base::StringValue(
- "SAME_PRIORITY_FOR_BOTH_TREES"));
+ return "SAME_PRIORITY_FOR_BOTH_TREES";
case SMOOTHNESS_TAKES_PRIORITY:
- return scoped_ptr<base::Value>(new base::StringValue(
- "SMOOTHNESS_TAKES_PRIORITY"));
+ return "SMOOTHNESS_TAKES_PRIORITY";
case NEW_CONTENT_TAKES_PRIORITY:
- return scoped_ptr<base::Value>(new base::StringValue(
- "NEW_CONTENT_TAKES_PRIORITY"));
+ return "NEW_CONTENT_TAKES_PRIORITY";
+ default:
+ DCHECK(false) << "Unrecognized priority value " << prio;
+ return "<unknown>";
}
- DCHECK(false) << "Unrecognized priority value " << prio;
- return scoped_ptr<base::Value>(new base::StringValue(
- "<unknown>"));
}
-scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
- state->Set("memory_limit_policy",
- TileMemoryLimitPolicyAsValue(memory_limit_policy).release());
+void GlobalStateThatImpactsTilePriority::AsValueInto(
+ base::debug::TracedValue* state) const {
+ state->SetString("memory_limit_policy",
+ TileMemoryLimitPolicyToString(memory_limit_policy));
state->SetInteger("soft_memory_limit_in_bytes", soft_memory_limit_in_bytes);
state->SetInteger("hard_memory_limit_in_bytes", hard_memory_limit_in_bytes);
state->SetInteger("num_resources_limit", num_resources_limit);
- state->Set("tree_priority", TreePriorityAsValue(tree_priority).release());
- return state.PassAs<base::Value>();
+ state->SetString("tree_priority", TreePriorityToString(tree_priority));
}
} // namespace cc
diff --git a/chromium/cc/resources/tile_priority.h b/chromium/cc/resources/tile_priority.h
index f8ac9c6c7b0..d1610571863 100644
--- a/chromium/cc/resources/tile_priority.h
+++ b/chromium/cc/resources/tile_priority.h
@@ -7,13 +7,11 @@
#include <algorithm>
#include <limits>
+#include <string>
-#include "base/memory/ref_counted.h"
+#include "base/debug/trace_event_argument.h"
#include "base/memory/scoped_ptr.h"
-#include "cc/resources/picture_pile.h"
-#include "ui/gfx/quad_f.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
+#include "cc/base/cc_export.h"
namespace base {
class Value;
@@ -29,23 +27,20 @@ enum WhichTree {
NUM_TREES = 2
// Be sure to update WhichTreeAsValue when adding new fields.
};
-scoped_ptr<base::Value> WhichTreeAsValue(
- WhichTree tree);
+scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree);
enum TileResolution {
LOW_RESOLUTION = 0 ,
HIGH_RESOLUTION = 1,
NON_IDEAL_RESOLUTION = 2,
};
-scoped_ptr<base::Value> TileResolutionAsValue(
- TileResolution resolution);
+std::string TileResolutionToString(TileResolution resolution);
struct CC_EXPORT TilePriority {
enum PriorityBin { NOW, SOON, EVENTUALLY };
TilePriority()
: resolution(NON_IDEAL_RESOLUTION),
- required_for_activation(false),
priority_bin(EVENTUALLY),
distance_to_visible(std::numeric_limits<float>::infinity()) {}
@@ -53,7 +48,6 @@ struct CC_EXPORT TilePriority {
PriorityBin bin,
float distance_to_visible)
: resolution(resolution),
- required_for_activation(false),
priority_bin(bin),
distance_to_visible(distance_to_visible) {}
@@ -67,9 +61,6 @@ struct CC_EXPORT TilePriority {
else
resolution = NON_IDEAL_RESOLUTION;
- required_for_activation =
- active.required_for_activation || pending.required_for_activation;
-
if (active.priority_bin < pending.priority_bin) {
priority_bin = active.priority_bin;
distance_to_visible = active.distance_to_visible;
@@ -83,13 +74,12 @@ struct CC_EXPORT TilePriority {
}
}
- scoped_ptr<base::Value> AsValue() const;
+ void AsValueInto(base::debug::TracedValue* dict) const;
bool operator ==(const TilePriority& other) const {
return resolution == other.resolution &&
priority_bin == other.priority_bin &&
- distance_to_visible == other.distance_to_visible &&
- required_for_activation == other.required_for_activation;
+ distance_to_visible == other.distance_to_visible;
}
bool operator !=(const TilePriority& other) const {
@@ -103,15 +93,14 @@ struct CC_EXPORT TilePriority {
}
TileResolution resolution;
- bool required_for_activation;
PriorityBin priority_bin;
float distance_to_visible;
};
-scoped_ptr<base::Value> TilePriorityBinAsValue(TilePriority::PriorityBin bin);
+std::string TilePriorityBinToString(TilePriority::PriorityBin bin);
enum TileMemoryLimitPolicy {
- // Nothing.
+ // Nothing. This mode is used when visible is set to false.
ALLOW_NOTHING = 0,
// You might be made visible, but you're not being interacted with.
@@ -121,24 +110,18 @@ enum TileMemoryLimitPolicy {
ALLOW_PREPAINT_ONLY = 2, // Grande.
// You're the only thing in town. Go crazy.
- ALLOW_ANYTHING = 3, // Venti.
-
- NUM_TILE_MEMORY_LIMIT_POLICIES = 4,
-
- // NOTE: Be sure to update TreePriorityAsValue and kBinPolicyMap when adding
- // or reordering fields.
+ ALLOW_ANYTHING = 3 // Venti.
};
-scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue(
- TileMemoryLimitPolicy policy);
+std::string TileMemoryLimitPolicyToString(TileMemoryLimitPolicy policy);
enum TreePriority {
SAME_PRIORITY_FOR_BOTH_TREES,
SMOOTHNESS_TAKES_PRIORITY,
- NEW_CONTENT_TAKES_PRIORITY
-
+ NEW_CONTENT_TAKES_PRIORITY,
+ NUM_TREE_PRIORITIES
// Be sure to update TreePriorityAsValue when adding new fields.
};
-scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio);
+std::string TreePriorityToString(TreePriority prio);
class GlobalStateThatImpactsTilePriority {
public:
@@ -168,7 +151,7 @@ class GlobalStateThatImpactsTilePriority {
return !(*this == other);
}
- scoped_ptr<base::Value> AsValue() const;
+ void AsValueInto(base::debug::TracedValue* dict) const;
};
} // namespace cc
diff --git a/chromium/cc/resources/transferable_resource.cc b/chromium/cc/resources/transferable_resource.cc
index 30fa3169abd..558d6e87728 100644
--- a/chromium/cc/resources/transferable_resource.cc
+++ b/chromium/cc/resources/transferable_resource.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
#include "cc/resources/returned_resource.h"
#include "cc/resources/transferable_resource.h"
@@ -13,7 +12,8 @@ TransferableResource::TransferableResource()
format(RGBA_8888),
filter(0),
is_repeated(false),
- is_software(false) {
+ is_software(false),
+ allow_overlay(false) {
}
TransferableResource::~TransferableResource() {
diff --git a/chromium/cc/resources/transferable_resource.h b/chromium/cc/resources/transferable_resource.h
index 11651f2722d..03b47e616c8 100644
--- a/chromium/cc/resources/transferable_resource.h
+++ b/chromium/cc/resources/transferable_resource.h
@@ -11,7 +11,7 @@
#include "cc/base/cc_export.h"
#include "cc/resources/resource_format.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -35,6 +35,7 @@ struct CC_EXPORT TransferableResource {
gpu::MailboxHolder mailbox_holder;
bool is_repeated;
bool is_software;
+ bool allow_overlay;
};
} // namespace cc
diff --git a/chromium/cc/resources/ui_resource_bitmap.cc b/chromium/cc/resources/ui_resource_bitmap.cc
index 58df9d96272..e254cf71614 100644
--- a/chromium/cc/resources/ui_resource_bitmap.cc
+++ b/chromium/cc/resources/ui_resource_bitmap.cc
@@ -11,6 +11,26 @@
#include "third_party/skia/include/core/SkPixelRef.h"
namespace cc {
+namespace {
+
+UIResourceBitmap::UIResourceFormat SkColorTypeToUIResourceFormat(
+ SkColorType sk_type) {
+ UIResourceBitmap::UIResourceFormat format = UIResourceBitmap::RGBA8;
+ switch (sk_type) {
+ case kN32_SkColorType:
+ format = UIResourceBitmap::RGBA8;
+ break;
+ case kAlpha_8_SkColorType:
+ format = UIResourceBitmap::ALPHA_8;
+ break;
+ default:
+ NOTREACHED() << "Invalid SkColorType for UIResourceBitmap: " << sk_type;
+ break;
+ }
+ return format;
+}
+
+} // namespace
void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
const gfx::Size& size,
@@ -29,14 +49,14 @@ void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
}
UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) {
- DCHECK_EQ(skbitmap.colorType(), kPMColor_SkColorType);
DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels());
DCHECK(skbitmap.isImmutable());
skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef());
const SkImageInfo& info = pixel_ref->info();
- Create(
- pixel_ref, gfx::Size(info.fWidth, info.fHeight), UIResourceBitmap::RGBA8);
+ Create(pixel_ref,
+ gfx::Size(info.fWidth, info.fHeight),
+ SkColorTypeToUIResourceFormat(skbitmap.colorType()));
SetOpaque(skbitmap.isOpaque());
}
diff --git a/chromium/cc/resources/ui_resource_bitmap.h b/chromium/cc/resources/ui_resource_bitmap.h
index b8863d8e994..ec6511394d2 100644
--- a/chromium/cc/resources/ui_resource_bitmap.h
+++ b/chromium/cc/resources/ui_resource_bitmap.h
@@ -10,8 +10,7 @@
#include "cc/base/cc_export.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkPixelRef.h"
-#include "third_party/skia/include/core/SkTypes.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
class SkBitmap;
@@ -27,6 +26,7 @@ class CC_EXPORT UIResourceBitmap {
public:
enum UIResourceFormat {
RGBA8,
+ ALPHA_8,
ETC1
};
enum UIResourceWrapMode {
@@ -42,7 +42,7 @@ class CC_EXPORT UIResourceBitmap {
void SetOpaque(bool opaque) { opaque_ = opaque; }
// User must ensure that |skbitmap| is immutable. The SkBitmap Format should
- // be 32-bit RGBA.
+ // be 32-bit RGBA or 8-bit ALPHA.
explicit UIResourceBitmap(const SkBitmap& skbitmap);
UIResourceBitmap(const gfx::Size& size, bool is_opaque);
UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref,
diff --git a/chromium/cc/resources/ui_resource_request.cc b/chromium/cc/resources/ui_resource_request.cc
index 75680369c6d..b8dd50af117 100644
--- a/chromium/cc/resources/ui_resource_request.cc
+++ b/chromium/cc/resources/ui_resource_request.cc
@@ -26,7 +26,7 @@ UIResourceRequest& UIResourceRequest::operator=(
if (request.bitmap_) {
bitmap_ = make_scoped_ptr(new UIResourceBitmap(*request.bitmap_.get()));
} else {
- bitmap_.reset();
+ bitmap_ = nullptr;
}
return *this;
diff --git a/chromium/cc/resources/video_resource_updater.cc b/chromium/cc/resources/video_resource_updater.cc
index 1d93aebe3cc..01a6042ef3e 100644
--- a/chromium/cc/resources/video_resource_updater.cc
+++ b/chromium/cc/resources/video_resource_updater.cc
@@ -5,6 +5,7 @@
#include "cc/resources/video_resource_updater.h"
#include "base/bind.h"
+#include "base/debug/trace_event.h"
#include "cc/output/gl_renderer.h"
#include "cc/resources/resource_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -13,13 +14,32 @@
#include "media/filters/skcanvas_video_renderer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
namespace cc {
+namespace {
+
const ResourceFormat kYUVResourceFormat = LUMINANCE_8;
const ResourceFormat kRGBResourceFormat = RGBA_8888;
+class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
+ public:
+ explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
+ ~SyncPointClientImpl() override {}
+ uint32 InsertSyncPoint() override {
+ return GLC(gl_, gl_->InsertSyncPointCHROMIUM());
+ }
+ void WaitSyncPoint(uint32 sync_point) override {
+ GLC(gl_, gl_->WaitSyncPointCHROMIUM(sync_point));
+ }
+
+ private:
+ gpu::gles2::GLES2Interface* gl_;
+};
+
+} // namespace
+
VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {}
VideoFrameExternalResources::~VideoFrameExternalResources() {}
@@ -97,6 +117,7 @@ static gfx::Size SoftwarePlaneDimension(
VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
const scoped_refptr<media::VideoFrame>& video_frame) {
+ TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes");
media::VideoFrame::Format input_frame_format = video_frame->format();
#if defined(VIDEO_HOLE)
@@ -172,11 +193,11 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
if (resource_id == 0) {
// TODO(danakj): Abstract out hw/sw resource create/delete from
// ResourceProvider and stop using ResourceProvider in this class.
- resource_id =
- resource_provider_->CreateResource(output_plane_resource_size,
- GL_CLAMP_TO_EDGE,
- ResourceProvider::TextureUsageAny,
- output_resource_format);
+ resource_id = resource_provider_->CreateResource(
+ output_plane_resource_size,
+ GL_CLAMP_TO_EDGE,
+ ResourceProvider::TextureHintImmutable,
+ output_resource_format);
DCHECK(mailbox.IsZero());
@@ -188,9 +209,9 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name));
ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
resource_id);
- GLC(gl, gl->BindTexture(GL_TEXTURE_2D, lock.texture_id()));
- GLC(gl, gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
- GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
+ GLC(gl,
+ gl->ProduceTextureDirectCHROMIUM(
+ lock.texture_id(), GL_TEXTURE_2D, mailbox.name));
}
if (resource_id)
@@ -228,10 +249,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
{
ResourceProvider::ScopedWriteLockSoftware lock(
resource_provider_, plane_resources[0].resource_id);
- video_renderer_->Paint(video_frame.get(),
- lock.sk_canvas(),
- video_frame->visible_rect(),
- 0xff);
+ video_renderer_->Copy(video_frame, lock.sk_canvas());
}
RecycleResourceData recycle_data = {
@@ -283,14 +301,27 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
return external_resources;
}
-static void ReturnTexture(const scoped_refptr<media::VideoFrame>& frame,
- uint32 sync_point,
- bool lost_resource) {
- frame->AppendReleaseSyncPoint(sync_point);
+// static
+void VideoResourceUpdater::ReturnTexture(
+ base::WeakPtr<VideoResourceUpdater> updater,
+ const scoped_refptr<media::VideoFrame>& video_frame,
+ uint32 sync_point,
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner) {
+ // TODO(dshwang) this case should be forwarded to the decoder as lost
+ // resource.
+ if (lost_resource || !updater.get())
+ return;
+ // VideoFrame::UpdateReleaseSyncPoint() creates new sync point using the same
+ // GL context which created the given |sync_point|, so discard the
+ // |sync_point|.
+ SyncPointClientImpl client(updater->context_provider_->ContextGL());
+ video_frame->UpdateReleaseSyncPoint(&client);
}
VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
const scoped_refptr<media::VideoFrame>& video_frame) {
+ TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes");
media::VideoFrame::Format frame_format = video_frame->format();
DCHECK_EQ(frame_format, media::VideoFrame::NATIVE_TEXTURE);
@@ -323,7 +354,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
mailbox_holder->texture_target,
mailbox_holder->sync_point));
external_resources.release_callbacks.push_back(
- base::Bind(&ReturnTexture, video_frame));
+ base::Bind(&ReturnTexture, AsWeakPtr(), video_frame));
return external_resources;
}
@@ -332,7 +363,8 @@ void VideoResourceUpdater::RecycleResource(
base::WeakPtr<VideoResourceUpdater> updater,
RecycleResourceData data,
uint32 sync_point,
- bool lost_resource) {
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner) {
if (!updater.get()) {
// Resource was already deleted.
return;
diff --git a/chromium/cc/resources/video_resource_updater.h b/chromium/cc/resources/video_resource_updater.h
index eaaa8c10d69..99800b4c878 100644
--- a/chromium/cc/resources/video_resource_updater.h
+++ b/chromium/cc/resources/video_resource_updater.h
@@ -9,13 +9,12 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "cc/base/cc_export.h"
-#include "cc/resources/release_callback.h"
+#include "cc/resources/release_callback_impl.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/texture_mailbox.h"
-#include "ui/gfx/size.h"
+#include "ui/gfx/geometry/size.h"
namespace media {
class SkCanvasVideoRenderer;
@@ -50,11 +49,11 @@ class CC_EXPORT VideoFrameExternalResources {
ResourceType type;
std::vector<TextureMailbox> mailboxes;
- std::vector<ReleaseCallback> release_callbacks;
+ std::vector<ReleaseCallbackImpl> release_callbacks;
// TODO(danakj): Remove these too.
std::vector<unsigned> software_resources;
- ReleaseCallback software_release_callback;
+ ReleaseCallbackImpl software_release_callback;
VideoFrameExternalResources();
~VideoFrameExternalResources();
@@ -105,7 +104,13 @@ class CC_EXPORT VideoResourceUpdater
static void RecycleResource(base::WeakPtr<VideoResourceUpdater> updater,
RecycleResourceData data,
uint32 sync_point,
- bool lost_resource);
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner);
+ static void ReturnTexture(base::WeakPtr<VideoResourceUpdater> updater,
+ const scoped_refptr<media::VideoFrame>& video_frame,
+ uint32 sync_point,
+ bool lost_resource,
+ BlockingTaskRunner* main_thread_task_runner);
ContextProvider* context_provider_;
ResourceProvider* resource_provider_;
diff --git a/chromium/cc/resources/video_resource_updater_unittest.cc b/chromium/cc/resources/video_resource_updater_unittest.cc
index 05bcf221b4a..c0a4af402c4 100644
--- a/chromium/cc/resources/video_resource_updater_unittest.cc
+++ b/chromium/cc/resources/video_resource_updater_unittest.cc
@@ -10,6 +10,7 @@
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "cc/trees/blocking_task_runner.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,9 +28,14 @@ class VideoResourceUpdaterTest : public testing::Test {
FakeOutputSurface::Create3d(context3d.Pass());
CHECK(output_surface3d_->BindToClient(&client_));
shared_bitmap_manager_.reset(new TestSharedBitmapManager());
- resource_provider3d_ = ResourceProvider::Create(
- output_surface3d_.get(), shared_bitmap_manager_.get(), 0, false, 1,
- false);
+ resource_provider3d_ =
+ ResourceProvider::Create(output_surface3d_.get(),
+ shared_bitmap_manager_.get(),
+ NULL,
+ NULL,
+ 0,
+ false,
+ 1);
}
scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
@@ -62,7 +68,7 @@ class VideoResourceUpdaterTest : public testing::Test {
};
TEST_F(VideoResourceUpdaterTest, SoftwareFrame) {
- VideoResourceUpdater updater(output_surface3d_->context_provider().get(),
+ VideoResourceUpdater updater(output_surface3d_->context_provider(),
resource_provider3d_.get());
scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
diff --git a/chromium/cc/resources/zero_copy_raster_worker_pool.cc b/chromium/cc/resources/zero_copy_raster_worker_pool.cc
new file mode 100644
index 00000000000..ca2bc9b01e1
--- /dev/null
+++ b/chromium/cc/resources/zero_copy_raster_worker_pool.cc
@@ -0,0 +1,211 @@
+// 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/zero_copy_raster_worker_pool.h"
+
+#include <algorithm>
+
+#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
+#include "base/strings/stringprintf.h"
+#include "cc/debug/traced_value.h"
+#include "cc/resources/raster_buffer.h"
+#include "cc/resources/resource.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+namespace cc {
+namespace {
+
+class RasterBufferImpl : public RasterBuffer {
+ public:
+ RasterBufferImpl(ResourceProvider* resource_provider,
+ const Resource* resource)
+ : lock_(resource_provider, resource->id()), resource_(resource) {}
+
+ // Overridden from RasterBuffer:
+ void Playback(const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) override {
+ gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.GetGpuMemoryBuffer();
+ if (!gpu_memory_buffer)
+ return;
+
+ RasterWorkerPool::PlaybackToMemory(
+ gpu_memory_buffer->Map(), resource_->format(), resource_->size(),
+ gpu_memory_buffer->GetStride(), raster_source, rect, scale);
+ gpu_memory_buffer->Unmap();
+ }
+
+ private:
+ ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock_;
+ const Resource* resource_;
+
+ DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+};
+
+} // namespace
+
+// static
+scoped_ptr<RasterWorkerPool> ZeroCopyRasterWorkerPool::Create(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider) {
+ return make_scoped_ptr<RasterWorkerPool>(new ZeroCopyRasterWorkerPool(
+ task_runner, task_graph_runner, resource_provider));
+}
+
+ZeroCopyRasterWorkerPool::ZeroCopyRasterWorkerPool(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider)
+ : task_runner_(task_runner),
+ task_graph_runner_(task_graph_runner),
+ namespace_token_(task_graph_runner->GetNamespaceToken()),
+ resource_provider_(resource_provider),
+ raster_finished_weak_ptr_factory_(this) {
+}
+
+ZeroCopyRasterWorkerPool::~ZeroCopyRasterWorkerPool() {
+}
+
+Rasterizer* ZeroCopyRasterWorkerPool::AsRasterizer() {
+ return this;
+}
+
+void ZeroCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
+ client_ = client;
+}
+
+void ZeroCopyRasterWorkerPool::Shutdown() {
+ TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::Shutdown");
+
+ TaskGraph empty;
+ task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
+ task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
+}
+
+void ZeroCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
+ TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::ScheduleTasks");
+
+ if (raster_pending_.none())
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
+
+ // Mark all task sets as pending.
+ raster_pending_.set();
+
+ unsigned priority = kRasterTaskPriorityBase;
+
+ graph_.Reset();
+
+ // Cancel existing OnRasterFinished callbacks.
+ raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
+
+ scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
+
+ size_t task_count[kNumberOfTaskSets] = {0};
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
+ task_runner_.get(),
+ base::Bind(&ZeroCopyRasterWorkerPool::OnRasterFinished,
+ raster_finished_weak_ptr_factory_.GetWeakPtr(),
+ task_set));
+ }
+
+ for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
+ it != queue->items.end();
+ ++it) {
+ const RasterTaskQueue::Item& item = *it;
+ RasterTask* task = item.task;
+ DCHECK(!task->HasCompleted());
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ if (!item.task_sets[task_set])
+ continue;
+
+ ++task_count[task_set];
+
+ graph_.edges.push_back(
+ TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get()));
+ }
+
+ InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
+ }
+
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
+ InsertNodeForTask(&graph_,
+ new_raster_finished_tasks[task_set].get(),
+ kRasterFinishedTaskPriority,
+ task_count[task_set]);
+ }
+
+ ScheduleTasksOnOriginThread(this, &graph_);
+ task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
+
+ std::copy(new_raster_finished_tasks,
+ new_raster_finished_tasks + kNumberOfTaskSets,
+ raster_finished_tasks_);
+
+ TRACE_EVENT_ASYNC_STEP_INTO1(
+ "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
+}
+
+void ZeroCopyRasterWorkerPool::CheckForCompletedTasks() {
+ TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::CheckForCompletedTasks");
+
+ task_graph_runner_->CollectCompletedTasks(namespace_token_,
+ &completed_tasks_);
+ for (Task::Vector::const_iterator it = completed_tasks_.begin();
+ it != completed_tasks_.end();
+ ++it) {
+ RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
+
+ task->WillComplete();
+ task->CompleteOnOriginThread(this);
+ task->DidComplete();
+
+ task->RunReplyOnOriginThread();
+ }
+ completed_tasks_.clear();
+}
+
+scoped_ptr<RasterBuffer> ZeroCopyRasterWorkerPool::AcquireBufferForRaster(
+ const Resource* resource) {
+ return make_scoped_ptr<RasterBuffer>(
+ new RasterBufferImpl(resource_provider_, resource));
+}
+
+void ZeroCopyRasterWorkerPool::ReleaseBufferForRaster(
+ scoped_ptr<RasterBuffer> buffer) {
+ // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
+}
+
+void ZeroCopyRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
+ TRACE_EVENT1(
+ "cc", "ZeroCopyRasterWorkerPool::OnRasterFinished", "task_set", task_set);
+
+ DCHECK(raster_pending_[task_set]);
+ raster_pending_[task_set] = false;
+ if (raster_pending_.any()) {
+ TRACE_EVENT_ASYNC_STEP_INTO1(
+ "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
+ } else {
+ TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
+ }
+ client_->DidFinishRunningTasks(task_set);
+}
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+ZeroCopyRasterWorkerPool::StateAsValue() const {
+ scoped_refptr<base::debug::TracedValue> state =
+ new base::debug::TracedValue();
+
+ state->BeginArray("tasks_pending");
+ for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
+ state->AppendBoolean(raster_pending_[task_set]);
+ state->EndArray();
+ return state;
+}
+
+} // namespace cc
diff --git a/chromium/cc/resources/zero_copy_raster_worker_pool.h b/chromium/cc/resources/zero_copy_raster_worker_pool.h
new file mode 100644
index 00000000000..d1f583ee164
--- /dev/null
+++ b/chromium/cc/resources/zero_copy_raster_worker_pool.h
@@ -0,0 +1,79 @@
+// 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_ZERO_COPY_RASTER_WORKER_POOL_H_
+#define CC_RESOURCES_ZERO_COPY_RASTER_WORKER_POOL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "cc/resources/raster_worker_pool.h"
+#include "cc/resources/rasterizer.h"
+
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+}
+
+namespace cc {
+class ResourceProvider;
+
+class CC_EXPORT ZeroCopyRasterWorkerPool : public RasterWorkerPool,
+ public Rasterizer,
+ public RasterizerTaskClient {
+ public:
+ ~ZeroCopyRasterWorkerPool() override;
+
+ static scoped_ptr<RasterWorkerPool> Create(
+ base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider);
+
+ // Overridden from RasterWorkerPool:
+ Rasterizer* AsRasterizer() override;
+
+ // Overridden from Rasterizer:
+ void SetClient(RasterizerClient* client) override;
+ void Shutdown() override;
+ void ScheduleTasks(RasterTaskQueue* queue) override;
+ void CheckForCompletedTasks() override;
+
+ // Overridden from RasterizerTaskClient:
+ scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+ const Resource* resource) override;
+ void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override;
+
+ protected:
+ ZeroCopyRasterWorkerPool(base::SequencedTaskRunner* task_runner,
+ TaskGraphRunner* task_graph_runner,
+ ResourceProvider* resource_provider);
+
+ private:
+ void OnRasterFinished(TaskSet task_set);
+ scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ TaskGraphRunner* task_graph_runner_;
+ const NamespaceToken namespace_token_;
+ RasterizerClient* client_;
+ ResourceProvider* resource_provider_;
+
+ TaskSetCollection raster_pending_;
+
+ scoped_refptr<RasterizerTask> raster_finished_tasks_[kNumberOfTaskSets];
+
+ // Task graph used when scheduling tasks and vector used to gather
+ // completed tasks.
+ TaskGraph graph_;
+ Task::Vector completed_tasks_;
+
+ base::WeakPtrFactory<ZeroCopyRasterWorkerPool>
+ raster_finished_weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterWorkerPool);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_ZERO_COPY_RASTER_WORKER_POOL_H_