Chromium Code Reviews| Index: cc/tiles/gpu_image_decode_cache.cc |
| diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc |
| index 3ae2645f4b50695e545c5cabd4228115e8d3aa4f..7f75c888d8adc413831e88726b609c0cd00a0d1e 100644 |
| --- a/cc/tiles/gpu_image_decode_cache.cc |
| +++ b/cc/tiles/gpu_image_decode_cache.cc |
| @@ -149,11 +149,13 @@ class ImageDecodeTaskImpl : public TileTask { |
| public: |
| ImageDecodeTaskImpl(GpuImageDecodeCache* cache, |
| const DrawImage& draw_image, |
| - const ImageDecodeCache::TracingInfo& tracing_info) |
| + const ImageDecodeCache::TracingInfo& tracing_info, |
| + GpuImageDecodeCache::DecodeTaskType task_type) |
| : TileTask(true), |
| cache_(cache), |
| image_(draw_image), |
| - tracing_info_(tracing_info) { |
| + tracing_info_(tracing_info), |
| + task_type_(task_type) { |
| DCHECK(!SkipImage(draw_image)); |
| } |
| @@ -169,7 +171,7 @@ class ImageDecodeTaskImpl : public TileTask { |
| // Overridden from TileTask: |
| void OnTaskCompleted() override { |
| - cache_->OnImageDecodeTaskCompleted(image_); |
| + cache_->OnImageDecodeTaskCompleted(image_, task_type_); |
| } |
| protected: |
| @@ -179,6 +181,7 @@ class ImageDecodeTaskImpl : public TileTask { |
| GpuImageDecodeCache* cache_; |
| DrawImage image_; |
| const ImageDecodeCache::TracingInfo tracing_info_; |
| + const GpuImageDecodeCache::DecodeTaskType task_type_; |
| DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
| }; |
| @@ -380,6 +383,22 @@ GpuImageDecodeCache::~GpuImageDecodeCache() { |
| bool GpuImageDecodeCache::GetTaskForImageAndRef(const DrawImage& draw_image, |
| const TracingInfo& tracing_info, |
| scoped_refptr<TileTask>* task) { |
| + return GetTaskForImageAndRefInternal( |
| + draw_image, tracing_info, DecodeTaskType::PART_OF_UPLOAD_TASK, task); |
| +} |
| + |
| +bool GpuImageDecodeCache::GetOutOfRasterDecodeTaskForImageAndRef( |
| + const DrawImage& draw_image, |
| + scoped_refptr<TileTask>* task) { |
| + return GetTaskForImageAndRefInternal( |
| + draw_image, TracingInfo(), DecodeTaskType::STAND_ALONE_DECODE_TASK, task); |
| +} |
| + |
| +bool GpuImageDecodeCache::GetTaskForImageAndRefInternal( |
| + const DrawImage& draw_image, |
| + const TracingInfo& tracing_info, |
| + DecodeTaskType task_type, |
| + scoped_refptr<TileTask>* task) { |
| TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| "GpuImageDecodeCache::GetTaskForImageAndRef"); |
| if (SkipImage(draw_image)) { |
| @@ -408,11 +427,18 @@ bool GpuImageDecodeCache::GetTaskForImageAndRef(const DrawImage& draw_image, |
| RefImage(draw_image); |
| *task = nullptr; |
| return true; |
| - } else if (image_data->upload.task) { |
| + } else if (task_type == DecodeTaskType::PART_OF_UPLOAD_TASK && |
| + image_data->upload.task) { |
| // We had an existing upload task, ref the image and return the task. |
| RefImage(draw_image); |
| *task = image_data->upload.task; |
| return true; |
| + } else if (task_type == DecodeTaskType::STAND_ALONE_DECODE_TASK && |
| + image_data->decode.stand_alone_task) { |
| + // We had an existing out of raster task, ref the image and return the task. |
| + RefImage(draw_image); |
| + *task = image_data->decode.stand_alone_task; |
| + return true; |
| } |
| // Ensure that the image we're about to decode/upload will fit in memory. |
| @@ -427,13 +453,18 @@ bool GpuImageDecodeCache::GetTaskForImageAndRef(const DrawImage& draw_image, |
| if (new_data) |
| persistent_cache_.Put(image_id, std::move(new_data)); |
| - // Ref image and create a upload and decode tasks. We will release this ref |
| - // in UploadTaskCompleted. |
| - RefImage(draw_image); |
| - *task = make_scoped_refptr(new ImageUploadTaskImpl( |
| - this, draw_image, GetImageDecodeTaskAndRef(draw_image, tracing_info), |
| - tracing_info)); |
| - image_data->upload.task = *task; |
| + if (task_type == DecodeTaskType::PART_OF_UPLOAD_TASK) { |
| + // Ref image and create a upload and decode tasks. We will release this ref |
| + // in UploadTaskCompleted. |
| + RefImage(draw_image); |
| + *task = make_scoped_refptr(new ImageUploadTaskImpl( |
| + this, draw_image, |
| + GetImageDecodeTaskAndRef(draw_image, tracing_info, task_type), |
| + tracing_info)); |
| + image_data->upload.task = *task; |
| + } else { |
| + *task = GetImageDecodeTaskAndRef(draw_image, tracing_info, task_type); |
| + } |
| // Ref the image again - this ref is owned by the caller, and it is their |
| // responsibility to release it by calling UnrefImage. |
| @@ -647,15 +678,22 @@ void GpuImageDecodeCache::UploadImage(const DrawImage& draw_image) { |
| } |
| void GpuImageDecodeCache::OnImageDecodeTaskCompleted( |
| - const DrawImage& draw_image) { |
| + const DrawImage& draw_image, |
| + DecodeTaskType task_type) { |
| TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| "GpuImageDecodeCache::OnImageDecodeTaskCompleted"); |
| base::AutoLock lock(lock_); |
| // Decode task is complete, remove our reference to it. |
| ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| DCHECK(image_data); |
| - DCHECK(image_data->decode.task); |
| - image_data->decode.task = nullptr; |
| + if (task_type == DecodeTaskType::PART_OF_UPLOAD_TASK) { |
| + DCHECK(image_data->decode.task); |
| + image_data->decode.task = nullptr; |
| + } else { |
| + DCHECK(task_type == DecodeTaskType::STAND_ALONE_DECODE_TASK); |
| + DCHECK(image_data->decode.stand_alone_task); |
| + image_data->decode.stand_alone_task = nullptr; |
| + } |
| // While the decode task is active, we keep a ref on the decoded data. |
| // Release that ref now. |
| @@ -684,14 +722,16 @@ void GpuImageDecodeCache::OnImageUploadTaskCompleted( |
| // the requested decode. |
| scoped_refptr<TileTask> GpuImageDecodeCache::GetImageDecodeTaskAndRef( |
| const DrawImage& draw_image, |
| - const TracingInfo& tracing_info) { |
| + const TracingInfo& tracing_info, |
| + DecodeTaskType task_type) { |
| TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| "GpuImageDecodeCache::GetImageDecodeTaskAndRef"); |
| lock_.AssertAcquired(); |
| // This ref is kept alive while an upload task may need this decode. We |
| // release this ref in UploadTaskCompleted. |
| - RefImageDecode(draw_image); |
| + if (task_type == DecodeTaskType::PART_OF_UPLOAD_TASK) |
| + RefImageDecode(draw_image); |
| ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| DCHECK(image_data); |
| @@ -704,13 +744,16 @@ scoped_refptr<TileTask> GpuImageDecodeCache::GetImageDecodeTaskAndRef( |
| } |
| // We didn't have an existing locked image, create a task to lock or decode. |
| - scoped_refptr<TileTask>& existing_task = image_data->decode.task; |
| + scoped_refptr<TileTask>& existing_task = |
|
ericrk
2017/01/04 07:48:31
I assume we can't end up decoding an image twice i
vmpstr
2017/01/06 01:19:03
That's not necessarily true, since which image is
ericrk
2017/01/09 21:07:27
Sounds good to me - there's probably something we
|
| + (task_type == DecodeTaskType::PART_OF_UPLOAD_TASK) |
| + ? image_data->decode.task |
| + : image_data->decode.stand_alone_task; |
| if (!existing_task) { |
| // Ref image decode and create a decode task. This ref will be released in |
| // DecodeTaskCompleted. |
| RefImageDecode(draw_image); |
| existing_task = make_scoped_refptr( |
| - new ImageDecodeTaskImpl(this, draw_image, tracing_info)); |
| + new ImageDecodeTaskImpl(this, draw_image, tracing_info, task_type)); |
| } |
| return existing_task; |
| } |
| @@ -857,10 +900,11 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, |
| // We should unlock the discardable memory for the image in two cases: |
| // 1) The image is no longer being used (no decode or upload refs). |
| // 2) This is a GPU backed image that has already been uploaded (no decode |
| - // refs). |
| + // refs, and we actually already have an image). |
| bool should_unlock_discardable = |
| - !has_any_refs || (image_data->mode == DecodedDataMode::GPU && |
| - !image_data->decode.ref_count); |
| + !has_any_refs || |
| + (image_data->mode == DecodedDataMode::GPU && |
| + !image_data->decode.ref_count && image_data->upload.image()); |
| if (should_unlock_discardable && image_data->decode.is_locked()) { |
| DCHECK(image_data->decode.data()); |