Index: cc/tiles/image_decode_controller.cc |
diff --git a/cc/tiles/image_decode_controller.cc b/cc/tiles/image_decode_controller.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bc1dfef7e920f356703f0a1a5bc0bb9e00d8cf63 |
--- /dev/null |
+++ b/cc/tiles/image_decode_controller.cc |
@@ -0,0 +1,124 @@ |
+// Copyright 2015 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/tiles/image_decode_controller.h" |
+ |
+#include "cc/debug/devtools_instrumentation.h" |
+ |
+namespace cc { |
+namespace { |
+ |
+class ImageDecodeTaskImpl : public ImageDecodeTask { |
+ public: |
+ ImageDecodeTaskImpl(ImageDecodeController* controller, |
+ SkPixelRef* pixel_ref, |
+ int layer_id, |
+ uint64_t source_prepare_tiles_id) |
+ : controller_(controller), |
+ pixel_ref_(skia::SharePtr(pixel_ref)), |
+ layer_id_(layer_id), |
+ source_prepare_tiles_id_(source_prepare_tiles_id) {} |
+ |
+ // Overridden from Task: |
+ void RunOnWorkerThread() override { |
+ TRACE_EVENT1("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", |
+ "source_prepare_tiles_id", source_prepare_tiles_id_); |
+ devtools_instrumentation::ScopedImageDecodeTask image_decode_task( |
+ pixel_ref_.get()); |
+ controller_->DecodePixelRef(pixel_ref_.get()); |
+ |
+ // Release the reference after decoding image to ensure that it is not kept |
+ // alive unless needed. |
+ pixel_ref_.clear(); |
+ } |
+ |
+ // Overridden from TileTask: |
+ void ScheduleOnOriginThread(TileTaskClient* client) override {} |
+ void CompleteOnOriginThread(TileTaskClient* client) override {} |
+ void RunReplyOnOriginThread() override { |
+ controller_->OnImageDecodeTaskCompleted(layer_id_, pixel_ref_.get(), |
+ !HasFinishedRunning()); |
+ } |
+ |
+ protected: |
+ ~ImageDecodeTaskImpl() override {} |
+ |
+ private: |
+ ImageDecodeController* controller_; |
+ skia::RefPtr<SkPixelRef> pixel_ref_; |
+ int layer_id_; |
+ uint64_t source_prepare_tiles_id_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
+}; |
+ |
+} // namespace |
+ |
+ImageDecodeController::ImageDecodeController() {} |
+ |
+ImageDecodeController::~ImageDecodeController() {} |
+ |
+scoped_refptr<ImageDecodeTask> ImageDecodeController::GetTaskForPixelRef( |
+ SkPixelRef* pixel_ref, |
+ int layer_id, |
+ uint64_t prepare_tiles_id) { |
+ uint32_t generation_id = pixel_ref->getGenerationID(); |
+ scoped_refptr<ImageDecodeTask>& decode_task = |
+ image_decode_tasks_[layer_id][generation_id]; |
+ if (!decode_task) |
+ decode_task = CreateTaskForPixelRef(pixel_ref, layer_id, prepare_tiles_id); |
+ return decode_task; |
+} |
+ |
+scoped_refptr<ImageDecodeTask> ImageDecodeController::CreateTaskForPixelRef( |
+ SkPixelRef* pixel_ref, |
+ int layer_id, |
+ uint64_t prepare_tiles_id) { |
+ return make_scoped_refptr( |
+ new ImageDecodeTaskImpl(this, pixel_ref, layer_id, prepare_tiles_id)); |
+} |
+ |
+void ImageDecodeController::DecodePixelRef(SkPixelRef* pixel_ref) { |
+ // This will cause the image referred to by pixel ref to be decoded. |
+ pixel_ref->lockPixels(); |
+ pixel_ref->unlockPixels(); |
+} |
+ |
+void ImageDecodeController::AddLayerUsedCount(int layer_id) { |
+ ++used_layer_counts_[layer_id]; |
+} |
+ |
+void ImageDecodeController::SubtractLayerUsedCount(int layer_id) { |
+ if (--used_layer_counts_[layer_id]) |
+ return; |
+ |
+ // Clean up decode tasks once a layer is no longer used. |
+ used_layer_counts_.erase(layer_id); |
+ image_decode_tasks_.erase(layer_id); |
+} |
+ |
+void ImageDecodeController::OnImageDecodeTaskCompleted(int layer_id, |
+ SkPixelRef* pixel_ref, |
+ bool was_canceled) { |
+ // If the task has successfully finished, then keep the task until the layer |
+ // is no longer in use. This ensures that we only decode a pixel ref once. |
+ // TODO(vmpstr): Remove this when decode lifetime is controlled by cc. |
+ if (!was_canceled) |
+ return; |
+ |
+ // Otherwise, we have to clean up the task so that a new one can be created if |
+ // we need to decode the pixel ref again. |
+ LayerPixelRefTaskMap::iterator layer_it = image_decode_tasks_.find(layer_id); |
+ if (layer_it == image_decode_tasks_.end()) |
+ return; |
+ |
+ PixelRefTaskMap& pixel_ref_tasks = layer_it->second; |
+ PixelRefTaskMap::iterator task_it = |
+ pixel_ref_tasks.find(pixel_ref->getGenerationID()); |
+ if (task_it == pixel_ref_tasks.end()) |
+ return; |
+ pixel_ref_tasks.erase(task_it); |
+} |
+ |
+} // namespace cc |