Index: cc/raster_worker.cc |
diff --git a/cc/raster_worker.cc b/cc/raster_worker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a962035c8d6a371254d29c7c333799fab62b291b |
--- /dev/null |
+++ b/cc/raster_worker.cc |
@@ -0,0 +1,169 @@ |
+// Copyright 2012 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/raster_worker.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/bind.h" |
+#include "base/debug/trace_event.h" |
+#include "base/stringprintf.h" |
+#include "cc/picture_pile_impl.h" |
+#include "third_party/skia/include/core/SkDevice.h" |
+ |
+namespace cc { |
+ |
+namespace { |
+ |
+void RunRasterTask(PicturePileImpl* picture_pile, |
+ uint8_t* buffer, |
+ const gfx::Rect& rect, |
+ float contents_scale, |
+ RenderingStats* stats) { |
+ TRACE_EVENT0("cc", "RunRasterTask"); |
+ DCHECK(picture_pile); |
+ DCHECK(buffer); |
+ SkBitmap bitmap; |
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); |
+ bitmap.setPixels(buffer); |
+ SkDevice device(bitmap); |
+ SkCanvas canvas(&device); |
+ picture_pile->Raster(&canvas, rect, contents_scale, stats); |
+} |
+ |
+void OnRasterTaskCompleted(scoped_refptr<PicturePileImpl> picture_pile_clone, |
+ const base::Closure& reply) { |
+ reply.Run(); |
+} |
+ |
+void RunImageDecodeTask(skia::LazyPixelRef* pixel_ref, RenderingStats* stats) { |
+ TRACE_EVENT0("cc", "RunImageDecodeTask"); |
+ base::TimeTicks decode_begin_time = base::TimeTicks::Now(); |
+ pixel_ref->Decode(); |
+ stats->totalDeferredImageDecodeCount++; |
+ stats->totalDeferredImageDecodeTimeInSeconds += |
+ (base::TimeTicks::Now() - decode_begin_time).InSecondsF(); |
+} |
+ |
+const char* kRasterThreadNamePrefix = "CompositorRaster"; |
+ |
+// Allow two pending raster tasks per thread. This keeps resource usage |
+// low while making sure raster threads aren't unnecessarily idle. |
+const int kNumPendingRasterTasksPerThread = 2; |
+ |
+} // namespace |
+ |
+RasterWorker::Thread::Thread(const std::string name) |
+ : base::Thread(name.c_str()), |
+ num_pending_tasks_(0) { |
+ Start(); |
+} |
+ |
+RasterWorker::Thread::~Thread() { |
+ Stop(); |
+} |
+ |
+RasterWorker::RasterWorker(size_t num_raster_threads) { |
+ const std::string thread_name_prefix = kRasterThreadNamePrefix; |
+ while (raster_threads_.size() < num_raster_threads) { |
+ int thread_number = raster_threads_.size() + 1; |
+ raster_threads_.append( |
+ make_scoped_ptr( |
+ new Thread(thread_name_prefix + |
+ StringPrintf("Worker%d", thread_number).c_str()))); |
+ } |
+} |
+ |
+RasterWorker::~RasterWorker() { |
+} |
+ |
+bool RasterWorker::IsBusy() { |
+ Thread* thread = raster_threads_.first(); |
+ return thread->num_pending_tasks_ >= kNumPendingRasterTasksPerThread; |
+} |
+ |
+void RasterWorker::PostRasterTaskAndReply(PicturePileImpl* picture_pile, |
+ uint8_t* buffer, |
+ const gfx::Rect& rect, |
+ float contents_scale, |
+ const base::Closure& reply) { |
+ Thread* thread = raster_threads_.first(); |
+ |
+ scoped_refptr<PicturePileImpl> picture_pile_clone = |
+ picture_pile->GetCloneForDrawingOnThread(thread); |
+ |
+ PostTaskAndReply(base::Bind(&RunRasterTask, |
+ base::Unretained(picture_pile_clone.get()), |
+ buffer, |
+ rect, |
+ contents_scale), |
+ base::Bind(&OnRasterTaskCompleted, |
+ picture_pile_clone, |
+ reply)); |
+} |
+ |
+void RasterWorker::PostImageDecodingTaskAndReply( |
+ skia::LazyPixelRef* pixel_ref, |
+ const base::Closure& reply) { |
+ PostTaskAndReply(base::Bind(&RunImageDecodeTask, pixel_ref), reply); |
+} |
+ |
+void RasterWorker::PostTaskAndReply(const TaskCallback& task, |
+ const base::Closure& reply) { |
+ Thread* thread = raster_threads_.first(); |
+ DCHECK(thread->num_pending_tasks_ < kNumPendingRasterTasksPerThread); |
+ thread->num_pending_tasks_++; |
+ std::sort(raster_threads_.begin(), raster_threads_.end(), |
+ PendingTaskComparator()); |
+ |
+ RenderingStats* stats = new RenderingStats; |
+ thread->message_loop_proxy()->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind(&RasterWorker::RunTaskOnRasterThread, |
+ base::Unretained(this), |
+ task, |
+ stats), |
+ base::Bind(&RasterWorker::OnTaskCompleted, |
+ base::Unretained(this), |
+ thread, |
+ stats, |
+ reply)); |
+} |
+ |
+void RasterWorker::RunTaskOnRasterThread( |
+ const RasterWorker::TaskCallback& task, RenderingStats* stats) { |
+ task.Run(stats); |
+} |
+ |
+void RasterWorker::OnTaskCompleted(Thread* thread, |
+ RenderingStats* stats, |
+ const base::Closure& reply) { |
+ // Update rendering stats. |
+ rendering_stats_.totalRasterizeTimeInSeconds += |
+ stats->totalRasterizeTimeInSeconds; |
+ rendering_stats_.totalPixelsRasterized += stats->totalPixelsRasterized; |
+ rendering_stats_.totalDeferredImageDecodeTimeInSeconds += |
+ stats->totalDeferredImageDecodeTimeInSeconds; |
+ rendering_stats_.totalDeferredImageDecodeCount += |
+ stats->totalDeferredImageDecodeCount; |
+ delete stats; |
+ |
+ thread->num_pending_tasks_--; |
+ std::sort(raster_threads_.begin(), raster_threads_.end(), |
+ PendingTaskComparator()); |
+ |
+ reply.Run(); |
+} |
+ |
+void RasterWorker::GetRenderingStats(RenderingStats* stats) { |
+ stats->totalRasterizeTimeInSeconds = |
+ rendering_stats_.totalRasterizeTimeInSeconds; |
+ stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; |
+ stats->totalDeferredImageDecodeCount = |
+ rendering_stats_.totalDeferredImageDecodeCount; |
+ stats->totalDeferredImageDecodeTimeInSeconds = |
+ rendering_stats_.totalDeferredImageDecodeTimeInSeconds; |
+} |
+ |
+} // namespace cc |