Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: cc/tiles/gpu_image_decode_controller.cc

Issue 1832573004: Gpu Image Decode Controller (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/tiles/gpu_image_decode_controller.h" 5 #include "cc/tiles/gpu_image_decode_controller.h"
6 6
7 #include "base/memory/discardable_memory_allocator.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/thread_task_runner_handle.h"
7 #include "cc/debug/devtools_instrumentation.h" 11 #include "cc/debug/devtools_instrumentation.h"
12 #include "cc/output/context_provider.h"
8 #include "cc/raster/tile_task_runner.h" 13 #include "cc/raster/tile_task_runner.h"
14 #include "gpu/command_buffer/client/context_support.h"
15 #include "gpu/command_buffer/client/gles2_interface.h"
16 #include "gpu_image_decode_controller.h"
9 #include "skia/ext/refptr.h" 17 #include "skia/ext/refptr.h"
18 #include "skia/ext/texture_handle.h"
19 #include "third_party/skia/include/core/SkCanvas.h"
20 #include "third_party/skia/include/core/SkSurface.h"
21 #include "third_party/skia/include/gpu/GrContext.h"
22 #include "third_party/skia/include/gpu/GrTexture.h"
23 #include "ui/gfx/skia_util.h"
24 #include "ui/gl/trace_util.h"
10 25
11 namespace cc { 26 namespace cc {
27 namespace {
12 28
29 static const int kMaxGpuImageBytes = 1024 * 1024 * 96;
30 static const int kMaxDiscardableItems = 1000;
31
32 // Returns true if an image would not be drawn and should therefore be
33 // skipped rather than decoded.
34 bool SkipImage(const DrawImage& draw_image) {
35 if (!SkIRect::Intersects(draw_image.src_rect(), draw_image.image()->bounds()))
36 return true;
37 if (draw_image.matrix_is_decomposable() &&
38 (draw_image.scale().width() == 0 || draw_image.scale().height() == 0))
vmpstr 2016/03/25 22:37:30 width() and height() are floats, so maybe check if
ericrk 2016/03/28 22:10:52 Done.
39 return true;
40 return false;
41 }
42
43 SkImage::DeferredTextureImageUsageParams ParamsFromDrawImage(
44 const DrawImage& draw_image) {
45 SkImage::DeferredTextureImageUsageParams params;
46 params.fMatrix = draw_image.matrix();
47 params.fQuality = draw_image.filter_quality();
48
49 return params;
50 }
51
52 SkImageInfo ImageInfoFromDrawImage(const DrawImage& draw_image) {
53 return SkImageInfo::MakeN32Premul(draw_image.image()->width(),
vmpstr 2016/03/25 22:37:29 The software idc changed to use different info dep
ericrk 2016/03/28 22:10:52 refactored both to use a new function in resource_
54 draw_image.image()->height());
55 }
56
57 } // namespace
58
59 // Task which decodes an image and stores the result in discardable memory.
60 // This task does not use GPU resources and can be run on any thread.
13 class ImageDecodeTaskImpl : public ImageDecodeTask { 61 class ImageDecodeTaskImpl : public ImageDecodeTask {
14 public: 62 public:
15 ImageDecodeTaskImpl(GpuImageDecodeController* controller, 63 ImageDecodeTaskImpl(GpuImageDecodeController* controller,
16 const DrawImage& image, 64 const DrawImage& draw_image,
17 uint64_t source_prepare_tiles_id) 65 uint64_t source_prepare_tiles_id)
18 : controller_(controller), 66 : controller_(controller),
19 image_(image), 67 image_(draw_image),
20 image_ref_(skia::SharePtr(image.image())), 68 image_ref_(skia::SharePtr(draw_image.image())),
21 source_prepare_tiles_id_(source_prepare_tiles_id) {} 69 source_prepare_tiles_id_(source_prepare_tiles_id) {}
22 70
23 // Overridden from Task: 71 // Overridden from Task:
24 void RunOnWorkerThread() override { 72 void RunOnWorkerThread() override {
25 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", "gpu", 73 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", "gpu",
26 "source_prepare_tiles_id", source_prepare_tiles_id_); 74 "source_prepare_tiles_id", source_prepare_tiles_id_);
27 devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
28 image_ref_.get());
29 controller_->DecodeImage(image_); 75 controller_->DecodeImage(image_);
30 } 76 }
31 77
32 // Overridden from TileTask: 78 // Overridden from TileTask:
33 void ScheduleOnOriginThread(TileTaskClient* client) override {} 79 void ScheduleOnOriginThread(TileTaskClient* client) override {}
34 void CompleteOnOriginThread(TileTaskClient* client) override { 80 void CompleteOnOriginThread(TileTaskClient* client) override {
35 controller_->RemovePendingTaskForImage(image_); 81 controller_->RemovePendingDecodeTaskForImage(image_);
36 } 82 }
37 83
38 protected: 84 protected:
39 ~ImageDecodeTaskImpl() override {} 85 ~ImageDecodeTaskImpl() override {}
40 86
41 private: 87 private:
42 GpuImageDecodeController* controller_; 88 GpuImageDecodeController* controller_;
43 DrawImage image_; 89 DrawImage image_;
44 skia::RefPtr<const SkImage> image_ref_; 90 skia::RefPtr<const SkImage> image_ref_;
91 const uint64_t source_prepare_tiles_id_;
92
93 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
94 };
95
96 // Task which creates an image from decoded data. Typically this involves
97 // uploading data to the GPU, which requires this task be run on the non-
98 // concurrent thread.
99 class ImageUploadTaskImpl : public ImageDecodeTask {
100 public:
101 ImageUploadTaskImpl(GpuImageDecodeController* controller,
102 const DrawImage& draw_image,
103 uint64_t source_prepare_tiles_id)
104 : ImageDecodeTask(controller->GetImageDecodeTaskAndRefLocked(
105 draw_image,
106 source_prepare_tiles_id)),
107 controller_(controller),
108 image_(draw_image),
109 image_ref_(skia::SharePtr(draw_image.image())),
110 source_prepare_tiles_id_(source_prepare_tiles_id) {}
111
112 // Override from Task:
113 void RunOnWorkerThread() override {
114 TRACE_EVENT2("cc", "ImageUploadTaskImpl::RunOnWorkerThread", "mode", "gpu",
115 "source_prepare_tiles_id", source_prepare_tiles_id_);
116 controller_->UploadImage(image_);
117 }
118
119 void ScheduleOnOriginThread(TileTaskClient* client) override {}
120 void CompleteOnOriginThread(TileTaskClient* client) override {
121 // We're done with the image decode, so un-ref it.
122 controller_->UnrefImageDecode(image_);
123 controller_->RemovePendingUploadTaskForImage(image_);
124 }
125
126 // Override from ImageDecodeTask:
127 bool SupportsConcurrentExecution() const override { return false; }
128
129 protected:
130 ~ImageUploadTaskImpl() override {}
131
132 private:
133 GpuImageDecodeController* controller_;
134 DrawImage image_;
135 skia::RefPtr<const SkImage> image_ref_;
45 uint64_t source_prepare_tiles_id_; 136 uint64_t source_prepare_tiles_id_;
46 137
47 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); 138 DISALLOW_COPY_AND_ASSIGN(ImageUploadTaskImpl);
48 }; 139 };
49 140
50 GpuImageDecodeController::GpuImageDecodeController() {} 141 GpuImageDecodeController::ImageData::ImageData(DecodedDataMode mode,
142 size_t size)
143 : mode(mode),
144 size(size),
145 decoded_data_ref_count(0),
146 decoded_data_is_locked(false),
147 image_pending(false),
148 image_ref_count(0),
149 is_at_raster(false) {}
150
151 GpuImageDecodeController::ImageData::~ImageData() = default;
152
153 GpuImageDecodeController::GpuImageDecodeController(ContextProvider* context)
154 : image_data_(decltype(image_data_)::NO_AUTO_EVICT),
vmpstr 2016/03/25 22:37:29 Can you typedef the map in the header instead :)
ericrk 2016/03/28 22:10:52 haha, forgot I had this :P - sure.
155 cached_items_limit_(kMaxDiscardableItems),
156 cached_bytes_limit_(kMaxGpuImageBytes),
157 bytes_used_(0),
158 context_(context),
159 context_threadsafe_proxy_(context->GrContext()->threadSafeProxy()) {}
51 160
52 GpuImageDecodeController::~GpuImageDecodeController() {} 161 GpuImageDecodeController::~GpuImageDecodeController() {}
53 162
54 bool GpuImageDecodeController::GetTaskForImageAndRef( 163 bool GpuImageDecodeController::GetTaskForImageAndRef(
55 const DrawImage& image, 164 const DrawImage& draw_image,
56 uint64_t prepare_tiles_id, 165 uint64_t prepare_tiles_id,
57 scoped_refptr<ImageDecodeTask>* task) { 166 scoped_refptr<ImageDecodeTask>* task) {
58 auto image_id = image.image()->uniqueID(); 167 if (SkipImage(draw_image)) {
59 base::AutoLock lock(lock_);
60 if (prerolled_images_.count(image_id) != 0) {
61 *task = nullptr; 168 *task = nullptr;
62 return false; 169 return false;
63 } 170 }
64 171
172 base::AutoLock lock(lock_);
173
174 const auto image_id = draw_image.image()->uniqueID();
175
176 auto found = image_data_.Get(image_id);
177 if (found != image_data_.end() && found->second->uploaded_image) {
178 // The image is already uploaded. If the image is not at raster, all we have
179 // to do is ref and return it. If the image is at raster, we should
180 // convert it to a non-at-raster image if possible. Otherwise we will
181 // continue using it in at-raster mode.
182 if (found->second->is_at_raster) {
183 if (EnsureCapacityLocked(found->second->size)) {
184 // Convert to non-at-raster, we have room now.
185 found->second->is_at_raster = false;
186 } else {
187 // Image won't fit in memory, Do at-raster decode.
188 *task = nullptr;
189 return false;
190 }
191 }
192 RefImageLocked(draw_image);
193 *task = nullptr;
194 return true;
195 }
196
197 // We didn't have a pre-uploaded image. Create or find the upload task.
65 scoped_refptr<ImageDecodeTask>& existing_task = 198 scoped_refptr<ImageDecodeTask>& existing_task =
66 pending_image_tasks_[image_id]; 199 pending_image_upload_tasks_[image_id];
200 if (!existing_task) {
vmpstr 2016/03/25 22:37:29 It might be less indentation to do if (existing_t
ericrk 2016/03/28 22:10:52 sure... less indentation is good.
201 // We will be decoding and uploading image data. Create a placeholder
202 // ImageData to hold the result.
203 scoped_ptr<ImageData> new_data;
204 ImageData* data;
205 if (found == image_data_.end()) {
206 new_data = NewImageData(draw_image);
207 data = new_data.get();
208 } else {
209 data = found->second.get();
210 }
211
212 if (!EnsureCapacityLocked(data->size)) {
213 // Image won't fit in memory. Do at-raster decode.
214 *task = nullptr;
215 return false;
216 }
217
218 if (new_data)
219 image_data_.Put(image_id, std::move(new_data));
220
221 bytes_used_ += data->size;
222 data->image_pending = true;
223 existing_task = make_scoped_refptr(
224 new ImageUploadTaskImpl(this, draw_image, prepare_tiles_id));
225 }
226
227 RefImageLocked(draw_image);
228 *task = existing_task;
229 return true;
230 }
231
232 void GpuImageDecodeController::UnrefImage(const DrawImage& draw_image) {
233 base::AutoLock lock(lock_);
234 UnrefImageLocked(draw_image);
vmpstr 2016/03/25 22:37:30 There's two different uses of Locked it seems. One
ericrk 2016/03/28 22:10:52 Ok... let me know how the new names are.
235 }
236
237 DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw(
238 const DrawImage& draw_image) {
239 TRACE_EVENT0("cc", "GpuImageDecodeController::GetDecodedImageForDraw");
240 if (SkipImage(draw_image))
241 return DecodedDrawImage(nullptr, draw_image.filter_quality());
242
243 const uint32_t unique_id = draw_image.image()->uniqueID();
244
245 context_->GetLock()->AssertAcquired();
246 base::AutoLock lock(lock_);
247 auto found = image_data_.Peek(unique_id);
248 if (found == image_data_.end()) {
249 auto data = NewImageData(draw_image);
250 if (!EnsureCapacityLocked(data->size)) {
vmpstr 2016/03/25 22:37:30 When would it be the case that we get to GetDecode
ericrk 2016/03/28 22:10:52 Likely not possible. Converting to a DCHECK, will
251 // Image won't fit in memory. Mark it as at-raster so it will not be
252 // retained longer than necessary.
253 data->is_at_raster = true;
254 }
255 bytes_used_ += data->size;
256 data->image_pending = true;
257 found = image_data_.Put(unique_id, std::move(data));
258 }
259 RefImageLocked(draw_image);
260
261 // We may or may not need to decode and upload the image we've found, the
262 // following functions early-out to if we already decoded.
263 DecodeImageIfNecessaryLocked(draw_image, found->second.get());
264 UploadImageIfNecessaryLocked(draw_image, found->second.get());
265 SkImage* image = found->second->uploaded_image.get();
vmpstr 2016/03/25 22:37:29 DCHECK(image)? or can it be null here?
ericrk 2016/03/28 22:10:52 Done.
266
267 DecodedDrawImage decoded_draw_image(image, draw_image.filter_quality());
268 decoded_draw_image.set_at_raster_decode(found->second->is_at_raster);
269 return decoded_draw_image;
270 }
271
272 void GpuImageDecodeController::DrawWithImageFinished(
273 const DrawImage& draw_image,
274 const DecodedDrawImage& decoded_draw_image) {
275 if (SkipImage(draw_image))
276 return;
277
278 UnrefImage(draw_image);
279
280 // We are mid-draw and holding the context lock, ensure we clean up any
281 // textures (especially at-raster), which may have just been marked for
282 // deletion by UnrefImage.
283 DeletePendingImagesLocked();
284 }
285
286 void GpuImageDecodeController::ReduceCacheUsage() {
287 base::AutoLock lock(lock_);
288 EnsureCapacityLocked(0);
289 }
290
291 void GpuImageDecodeController::DecodeImage(const DrawImage& draw_image) {
292 base::AutoLock lock(lock_);
293 auto found = image_data_.Peek(draw_image.image()->uniqueID());
294 if (found == image_data_.end() ||
295 found->second->decoded_data_ref_count == 0) {
296 // All references to this image decode were released before the task had a
297 // chance
298 // to run. Early out.
299 return;
300 }
301
302 // Take a ref on the image to ensure it stays alive while decode is in
303 // progress.
304 RefImageDecodeLocked(draw_image);
305 DecodeImageIfNecessaryLocked(draw_image, found->second.get());
306
307 // Remove the pending task before unreffing the image to ensure that
308 // the image is still alive while any caller might try to re-use this
309 // task.
310 RemovePendingDecodeTaskForImageLocked(draw_image);
311 UnrefImageDecodeLocked(draw_image);
312 }
313
314 void GpuImageDecodeController::UploadImage(const DrawImage& draw_image) {
315 ContextProvider::ScopedContextLock context_lock(context_);
316 base::AutoLock lock(lock_);
317 auto found = image_data_.Peek(draw_image.image()->uniqueID());
318 if (found == image_data_.end() || found->second->image_ref_count == 0) {
319 // All references to this image were released before the task had a chance
320 // to run. Early out.
321 return;
322 }
323 DCHECK(found != image_data_.end());
324
325 // We are about to upload a new image and are holding the context lock.
326 // Ensure that any images which have been marked for deletion are actually
327 // cleaned up so we don't exceed our memory limit during this upload.
328 DeletePendingImagesLocked();
329
330 // Take a ref on the image to ensure it stays alive while upload is in
331 // progress.
332 RefImageLocked(draw_image);
333 UploadImageIfNecessaryLocked(draw_image, found->second.get());
334
335 // Remove the pending task before unreffing the image to ensure that
336 // the image is still alive while any caller might try to re-use this
337 // task.
338 RemovePendingUploadTaskForImageLocked(draw_image);
339 UnrefImageLocked(draw_image);
340 }
341
342 void GpuImageDecodeController::RemovePendingDecodeTaskForImage(
343 const DrawImage& draw_image) {
344 base::AutoLock lock(lock_);
345 RemovePendingDecodeTaskForImageLocked(draw_image);
346 }
347
348 void GpuImageDecodeController::RemovePendingUploadTaskForImage(
349 const DrawImage& draw_image) {
350 base::AutoLock lock(lock_);
351 RemovePendingUploadTaskForImageLocked(draw_image);
352 }
353
354 scoped_refptr<ImageDecodeTask>
355 GpuImageDecodeController::GetImageDecodeTaskAndRefLocked(
356 const DrawImage& draw_image,
357 uint64_t prepare_tiles_id) {
358 lock_.AssertAcquired();
359 uint32_t image_id = draw_image.image()->uniqueID();
360 RefImageDecodeLocked(draw_image);
361
362 auto found = image_data_.Peek(image_id);
363 if (found != image_data_.end() && found->second->decoded_data_is_locked) {
364 // We should never be creating a decode task for an at raster image.
365 DCHECK(!found->second->is_at_raster);
366 return nullptr;
367 }
368
369 scoped_refptr<ImageDecodeTask>& existing_task =
370 pending_image_decode_tasks_[image_id];
67 if (!existing_task) { 371 if (!existing_task) {
68 existing_task = make_scoped_refptr( 372 existing_task = make_scoped_refptr(
69 new ImageDecodeTaskImpl(this, image, prepare_tiles_id)); 373 new ImageDecodeTaskImpl(this, draw_image, prepare_tiles_id));
70 } 374 }
71 *task = existing_task; 375 return existing_task;
376 }
377
378 void GpuImageDecodeController::UnrefImageDecode(const DrawImage& draw_image) {
379 base::AutoLock lock(lock_);
380 UnrefImageDecodeLocked(draw_image);
381 }
382
383 void GpuImageDecodeController::RefImageDecodeLocked(
384 const DrawImage& draw_image) {
385 lock_.AssertAcquired();
386 auto found = image_data_.Peek(draw_image.image()->uniqueID());
387 DCHECK(found != image_data_.end());
388 // At raster never uses Image Decode refs.
389 DCHECK(!found->second->is_at_raster);
390 ++found->second->decoded_data_ref_count;
vmpstr 2016/03/25 22:37:30 DCHECK that the memory is locked maybe?
ericrk 2016/03/28 22:10:52 We ref the image when we create a decode task - if
391 }
392
393 void GpuImageDecodeController::UnrefImageDecodeLocked(
394 const DrawImage& draw_image) {
395 lock_.AssertAcquired();
396 auto found = image_data_.Peek(draw_image.image()->uniqueID());
397 DCHECK(found != image_data_.end());
398 DCHECK_GT(found->second->decoded_data_ref_count, 0u);
399 // At raster never uses Image Decode refs.
400 DCHECK(!found->second->is_at_raster);
401 --found->second->decoded_data_ref_count;
402 if (found->second->decoded_data_ref_count == 0) {
403 if (found->second->decoded_data_is_locked) {
404 found->second->decoded_data_is_locked = false;
405 found->second->decoded_data->Unlock();
406 }
407 EnsureCapacityLocked(0);
408 }
409 }
410
411 void GpuImageDecodeController::RefImageLocked(const DrawImage& draw_image) {
412 lock_.AssertAcquired();
413 auto image_id = draw_image.image()->uniqueID();
414 auto found = image_data_.Peek(image_id);
415 DCHECK(found != image_data_.end());
416 ++found->second->image_ref_count;
417 if (found->second->image_ref_count == 1) {
vmpstr 2016/03/25 22:37:29 Dead code?
ericrk 2016/03/28 22:10:52 Done.
418 }
419 }
420
421 void GpuImageDecodeController::UnrefImageLocked(const DrawImage& draw_image) {
422 lock_.AssertAcquired();
423 auto image_id = draw_image.image()->uniqueID();
424 auto found = image_data_.Peek(image_id);
425 DCHECK(found != image_data_.end());
426 DCHECK_GT(found->second->image_ref_count, 0u);
427 uint32_t count = --found->second->image_ref_count;
428 if (count == 0) {
429 // Covert this image to not-at-raster. Its ref count is 0, so it will be
vmpstr 2016/03/25 22:37:30 Why are we converting this to not-at-raster?
ericrk 2016/03/28 22:10:52 Updated the comment.
430 // cleaned up in the next step if it doesn't fit anyway.
431 found->second->is_at_raster = false;
432 if (found->second->image_pending) {
433 found->second->image_pending = false;
vmpstr 2016/03/25 22:37:29 This is kind of weird for me. If the task is pendi
ericrk 2016/03/28 22:10:52 This was meant to mean that the image was budgeted
434 bytes_used_ -= found->second->size;
435 }
436 EnsureCapacityLocked(0);
437 }
438 }
439
440 bool GpuImageDecodeController::EnsureCapacityLocked(size_t new_size) {
441 lock_.AssertAcquired();
442 const size_t new_elements = new_size ? 1 : 0;
443 if (CanFitSize(new_size) && CanFitCount(new_elements))
444 return true;
445
446 // While we are over memory or item capacity, we iterate through our set of
447 // cached image data in LRU order. For each image, we can do two things:
448 // 1) We can free the uploaded image, reducing the memory usage of the cache
449 // and 2) we can remove the entry entirely, reducing the count of elements in
450 // the cache.
451 for (auto it = image_data_.rbegin(); it != image_data_.rend();) {
452 if (it->second->decoded_data_ref_count == 0 &&
vmpstr 2016/03/25 22:37:29 nit: Can you structure this as if (... != 0 || ..
ericrk 2016/03/28 22:10:52 Done.
ericrk 2016/03/28 22:10:52 Done.
453 it->second->image_ref_count == 0) {
454 if (it->second->uploaded_image) {
vmpstr 2016/03/25 22:37:30 uploaded_image implies that upload_pending is fals
ericrk 2016/03/28 22:10:52 Done.
ericrk 2016/03/28 22:10:52 Done.
455 DCHECK_GE(bytes_used_, it->second->size);
456 bytes_used_ -= it->second->size;
457 images_pending_deletion_.push_back(
458 std::move(it->second->uploaded_image));
459 it->second->uploaded_image = nullptr;
460 }
461 if (!CanFitCount(new_elements)) {
462 it = image_data_.Erase(it);
463 } else {
464 ++it;
465 }
466
467 if (CanFitSize(new_size) && CanFitCount(new_elements))
468 return true;
469 } else {
470 ++it;
471 }
472 }
473
474 // We couldn't reach a state where we are under our memory / count limites.
72 return false; 475 return false;
73 } 476 }
74 477
75 void GpuImageDecodeController::UnrefImage(const DrawImage& image) { 478 bool GpuImageDecodeController::CanFitSize(size_t size) const {
76 NOTREACHED(); 479 return bytes_used_ + size <= cached_bytes_limit_;
77 } 480 }
78 481
79 DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw( 482 bool GpuImageDecodeController::CanFitCount(size_t num_elements) const {
80 const DrawImage& draw_image) { 483 return image_data_.size() + num_elements <= cached_items_limit_;
81 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality()); 484 }
82 } 485
83 486 void GpuImageDecodeController::DecodeImageIfNecessaryLocked(
84 void GpuImageDecodeController::DrawWithImageFinished( 487 const DrawImage& draw_image,
85 const DrawImage& image, 488 ImageData* image_data) {
86 const DecodedDrawImage& decoded_image) {} 489 lock_.AssertAcquired();
87 490 if (image_data->uploaded_image) {
88 void GpuImageDecodeController::ReduceCacheUsage() {} 491 // We already have an uploaded image, no reason to decode.
89 492 return;
90 void GpuImageDecodeController::DecodeImage(const DrawImage& image) { 493 }
91 image.image()->preroll(); 494 if (image_data->decoded_data && (image_data->decoded_data_is_locked ||
92 base::AutoLock lock(lock_); 495 image_data->decoded_data->Lock())) {
93 prerolled_images_.insert(image.image()->uniqueID()); 496 // We already decoded this, or we just needed to lock, early out.
94 } 497 image_data->decoded_data_is_locked = true;
95 498 return;
96 void GpuImageDecodeController::RemovePendingTaskForImage( 499 }
97 const DrawImage& image) { 500
98 base::AutoLock lock(lock_); 501 TRACE_EVENT0("cc", "GpuImageDecodeController::DecodeImage");
99 pending_image_tasks_.erase(image.image()->uniqueID()); 502 scoped_ptr<base::DiscardableMemory> backing_memory;
503 {
504 base::AutoUnlock unlock(lock_);
505 if (image_data->mode == DECODED_DATA_MODE_CPU) {
vmpstr 2016/03/25 22:37:29 Can you make this a switch, so the "else" case is
ericrk 2016/03/28 22:10:52 Done.
506 backing_memory = base::DiscardableMemoryAllocator::GetInstance()
507 ->AllocateLockedDiscardableMemory(image_data->size);
508 memset(backing_memory->data(), 0, image_data->size);
vmpstr 2016/03/25 22:37:30 Why the clear?
ericrk 2016/03/28 22:10:52 This shouldn't be here.
509 SkImageInfo image_info = ImageInfoFromDrawImage(draw_image);
510 bool result = draw_image.image()->readPixels(
511 image_info, backing_memory->data(), image_info.minRowBytes(), 0, 0,
512 SkImage::kDisallow_CachingHint);
513 if (!result) {
514 backing_memory->Unlock();
515 return;
516 }
517 } else {
518 backing_memory = base::DiscardableMemoryAllocator::GetInstance()
519 ->AllocateLockedDiscardableMemory(image_data->size);
520 memset(backing_memory->data(), 0, image_data->size);
521 auto params = ParamsFromDrawImage(draw_image);
522 size_t data_size = draw_image.image()->getDeferredTextureImageData(
523 *context_threadsafe_proxy_, &params, 1, backing_memory->data());
524
525 if (!data_size) {
526 backing_memory->Unlock();
527 return;
528 }
529 }
530 }
531 image_data->decoded_data = std::move(backing_memory);
532 image_data->decoded_data_is_locked = true;
533 }
534
535 void GpuImageDecodeController::UploadImageIfNecessaryLocked(
536 const DrawImage& draw_image,
537 ImageData* image_data) {
538 lock_.AssertAcquired();
539 if (image_data->uploaded_image) {
540 // Someone has uploaded this image before us (at raster).
541 return;
542 }
543 TRACE_EVENT0("cc", "GpuImageDecodeController::UploadImage");
544 DCHECK(image_data->decoded_data_is_locked);
545
546 skia::RefPtr<SkImage> uploaded_image;
547 {
548 base::AutoUnlock unlock(lock_);
549 if (image_data->mode == DECODED_DATA_MODE_CPU) {
vmpstr 2016/03/25 22:37:29 switch here too please
ericrk 2016/03/28 22:10:52 Done.
550 SkImageInfo image_info = ImageInfoFromDrawImage(draw_image);
551 uploaded_image = skia::AdoptRef(SkImage::NewFromRaster(
552 image_info, image_data->decoded_data->data(),
553 image_info.minRowBytes(), [](const void*, void*) {}, nullptr));
554 } else {
555 uploaded_image = skia::AdoptRef(SkImage::NewFromDeferredTextureImageData(
556 context_->GrContext(), image_data->decoded_data->data(),
557 SkBudgeted::kNo));
558 }
559 }
560
561 image_data->uploaded_image = uploaded_image;
562 image_data->image_pending = false;
563 }
564
565 scoped_ptr<GpuImageDecodeController::ImageData>
566 GpuImageDecodeController::NewImageData(const DrawImage& draw_image) {
vmpstr 2016/03/25 22:37:30 maybe CreateImageData?
ericrk 2016/03/28 22:10:52 sure
567 DecodedDataMode mode;
568 SkImageInfo info = ImageInfoFromDrawImage(draw_image);
569 auto params = ParamsFromDrawImage(draw_image);
vmpstr 2016/03/25 22:37:30 SkImageInfo info ... auto params ... why auto? Is
ericrk 2016/03/28 22:10:52 I guess not :P
570 size_t data_size = draw_image.image()->getDeferredTextureImageData(
571 *context_threadsafe_proxy_, &params, 1, nullptr);
572
573 if (data_size == 0) {
vmpstr 2016/03/25 22:37:30 0 is returned in case of general failure, not just
ericrk 2016/03/28 22:10:52 Done.
574 // Can't upload image, too large. Use SW fallback.
575 data_size = info.getSafeSize(info.minRowBytes());
576 mode = GpuImageDecodeController::DECODED_DATA_MODE_CPU;
577 } else {
578 mode = GpuImageDecodeController::DECODED_DATA_MODE_GPU;
vmpstr 2016/03/25 22:37:29 s/GpuImageDecodeController:://
ericrk 2016/03/28 22:10:52 Done.
579 }
580
581 return make_scoped_ptr(new ImageData(mode, data_size));
582 }
583
584 void GpuImageDecodeController::RemovePendingDecodeTaskForImageLocked(
585 const DrawImage& draw_image) {
586 lock_.AssertAcquired();
587 pending_image_decode_tasks_.erase(draw_image.image()->uniqueID());
588 }
589
590 void GpuImageDecodeController::RemovePendingUploadTaskForImageLocked(
591 const DrawImage& draw_image) {
592 lock_.AssertAcquired();
593 pending_image_upload_tasks_.erase(draw_image.image()->uniqueID());
594 }
595
596 void GpuImageDecodeController::DeletePendingImagesLocked() {
597 context_->GetLock()->AssertAcquired();
598 lock_.AssertAcquired();
599 images_pending_deletion_.clear();
100 } 600 }
101 601
102 } // namespace cc 602 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698