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

Side by Side Diff: ui/gfx/image/image_skia.cc

Issue 2922463002: Replace deprecated base::NonThreadSafe in ui\gfx\image_skia.cc in favor of SequenceChecker. (Closed)
Patch Set: Created 3 years, 6 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
« no previous file with comments | « ui/gfx/image/image_skia.h ('k') | ui/gfx/image/image_skia_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/gfx/image/image_skia.h" 5 #include "ui/gfx/image/image_skia.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
11 #include <limits> 11 #include <limits>
12 #include <memory> 12 #include <memory>
13 13
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/threading/non_thread_safe.h" 17 #include "base/sequence_checker.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "ui/gfx/geometry/rect.h" 19 #include "ui/gfx/geometry/rect.h"
20 #include "ui/gfx/geometry/size.h" 20 #include "ui/gfx/geometry/size.h"
21 #include "ui/gfx/geometry/size_conversions.h" 21 #include "ui/gfx/geometry/size_conversions.h"
22 #include "ui/gfx/image/image_skia_operations.h" 22 #include "ui/gfx/image/image_skia_operations.h"
23 #include "ui/gfx/image/image_skia_source.h" 23 #include "ui/gfx/image/image_skia_source.h"
24 #include "ui/gfx/skia_util.h" 24 #include "ui/gfx/skia_util.h"
25 #include "ui/gfx/switches.h" 25 #include "ui/gfx/switches.h"
26 26
27 namespace gfx { 27 namespace gfx {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 rep.sk_bitmap(), 67 rep.sk_bitmap(),
68 skia::ImageOperations::RESIZE_LANCZOS3, 68 skia::ImageOperations::RESIZE_LANCZOS3,
69 scaled_size.width(), 69 scaled_size.width(),
70 scaled_size.height()), target_scale); 70 scaled_size.height()), target_scale);
71 } 71 }
72 72
73 } // namespace 73 } // namespace
74 74
75 // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a 75 // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a
76 // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's 76 // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's
77 // information. Having both |base::RefCountedThreadSafe| and 77 // information. Using a |base::SequenceChecker| on a
78 // |base::NonThreadSafe| may sound strange but is necessary to turn 78 // |base::RefCountedThreadSafe| subclass may sound strange but is necessary to
79 // the 'thread-non-safe modifiable ImageSkiaStorage' into 79 // turn the 'thread-non-safe modifiable ImageSkiaStorage' into the 'thread-safe
80 // the 'thread-safe read-only ImageSkiaStorage'. 80 // read-only ImageSkiaStorage'.
81 class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>, 81 class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage> {
82 public base::NonThreadSafe {
83 public: 82 public:
84 ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size); 83 ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size);
85 ImageSkiaStorage(ImageSkiaSource* source, float scale); 84 ImageSkiaStorage(ImageSkiaSource* source, float scale);
86 85
87 bool has_source() const { return source_ != nullptr; } 86 bool has_source() const { return source_ != nullptr; }
88 std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; } 87 std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; }
89 const gfx::Size& size() const { return size_; } 88 const gfx::Size& size() const { return size_; }
90 bool read_only() const { return read_only_; } 89 bool read_only() const { return read_only_; }
91 90
92 void DeleteSource(); 91 void DeleteSource();
93 void SetReadOnly(); 92 void SetReadOnly();
94 void DetachFromThread(); 93 void DetachFromSequence();
95 94
96 // Checks if the current thread can safely modify the storage. 95 // Checks if the current thread can safely modify the storage.
97 bool CanModify() const; 96 bool CanModify() const;
98 97
99 // Checks if the current thread can safely read the storage. 98 // Checks if the current thread can safely read the storage.
100 bool CanRead() const; 99 bool CanRead() const;
101 100
102 // Add a new representation. This checks if the scale of the added image 101 // Add a new representation. This checks if the scale of the added image
103 // is not 1.0f, and mark the existing rep as scaled to make 102 // is not 1.0f, and mark the existing rep as scaled to make
104 // the image high DPI aware. 103 // the image high DPI aware.
(...skipping 28 matching lines...) Expand all
133 // Vector of bitmaps and their associated scale. 132 // Vector of bitmaps and their associated scale.
134 std::vector<gfx::ImageSkiaRep> image_reps_; 133 std::vector<gfx::ImageSkiaRep> image_reps_;
135 134
136 std::unique_ptr<ImageSkiaSource> source_; 135 std::unique_ptr<ImageSkiaSource> source_;
137 136
138 // Size of the image in DIP. 137 // Size of the image in DIP.
139 gfx::Size size_; 138 gfx::Size size_;
140 139
141 bool read_only_; 140 bool read_only_;
142 141
142 base::SequenceChecker sequence_checker_;
143
143 DISALLOW_COPY_AND_ASSIGN(ImageSkiaStorage); 144 DISALLOW_COPY_AND_ASSIGN(ImageSkiaStorage);
144 }; 145 };
145 146
146 ImageSkiaStorage::ImageSkiaStorage(ImageSkiaSource* source, 147 ImageSkiaStorage::ImageSkiaStorage(ImageSkiaSource* source,
147 const gfx::Size& size) 148 const gfx::Size& size)
148 : source_(source), size_(size), read_only_(false) {} 149 : source_(source), size_(size), read_only_(false) {}
149 150
150 ImageSkiaStorage::ImageSkiaStorage(ImageSkiaSource* source, float scale) 151 ImageSkiaStorage::ImageSkiaStorage(ImageSkiaSource* source, float scale)
151 : source_(source), read_only_(false) { 152 : source_(source), read_only_(false) {
152 ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true); 153 ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true);
153 if (it == image_reps_.end() || it->is_null()) 154 if (it == image_reps_.end() || it->is_null())
154 source_.reset(); 155 source_.reset();
155 else 156 else
156 size_.SetSize(it->GetWidth(), it->GetHeight()); 157 size_.SetSize(it->GetWidth(), it->GetHeight());
157 } 158 }
158 159
159 void ImageSkiaStorage::DeleteSource() { 160 void ImageSkiaStorage::DeleteSource() {
160 source_.reset(); 161 source_.reset();
161 } 162 }
162 163
163 void ImageSkiaStorage::SetReadOnly() { 164 void ImageSkiaStorage::SetReadOnly() {
164 read_only_ = true; 165 read_only_ = true;
165 } 166 }
166 167
167 void ImageSkiaStorage::DetachFromThread() { 168 void ImageSkiaStorage::DetachFromSequence() {
168 base::NonThreadSafe::DetachFromThread(); 169 sequence_checker_.DetachFromSequence();
169 } 170 }
170 171
171 bool ImageSkiaStorage::CanModify() const { 172 bool ImageSkiaStorage::CanModify() const {
172 return !read_only_ && CalledOnValidThread(); 173 return !read_only_ && sequence_checker_.CalledOnValidSequence();
173 } 174 }
174 175
175 bool ImageSkiaStorage::CanRead() const { 176 bool ImageSkiaStorage::CanRead() const {
176 return (read_only_ && !source_) || CalledOnValidThread(); 177 return (read_only_ && !source_) || sequence_checker_.CalledOnValidSequence();
177 } 178 }
178 179
179 void ImageSkiaStorage::AddRepresentation(const ImageSkiaRep& image) { 180 void ImageSkiaStorage::AddRepresentation(const ImageSkiaRep& image) {
180 // Explicitly adding a representation makes no sense for images that 181 // Explicitly adding a representation makes no sense for images that
181 // inherently have representations at all scales already. 182 // inherently have representations at all scales already.
182 DCHECK(!HasRepresentationAtAllScales()); 183 DCHECK(!HasRepresentationAtAllScales());
183 184
184 if (image.scale() != 1.0f) { 185 if (image.scale() != 1.0f) {
185 for (ImageSkia::ImageSkiaReps::iterator it = image_reps_.begin(); 186 for (ImageSkia::ImageSkiaReps::iterator it = image_reps_.begin();
186 it < image_reps_.end(); ++it) { 187 it < image_reps_.end(); ++it) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 break; 219 break;
219 } 220 }
220 float diff = std::abs(it->scale() - scale); 221 float diff = std::abs(it->scale() - scale);
221 if (diff < smallest_diff && !it->is_null()) { 222 if (diff < smallest_diff && !it->is_null()) {
222 closest_iter = it; 223 closest_iter = it;
223 smallest_diff = diff; 224 smallest_diff = diff;
224 } 225 }
225 } 226 }
226 227
227 if (fetch_new_image && source_.get()) { 228 if (fetch_new_image && source_.get()) {
228 DCHECK(CalledOnValidThread()) 229 DCHECK(sequence_checker_.CalledOnValidSequence())
229 << "An ImageSkia with the source must be accessed by the same thread."; 230 << "An ImageSkia with the source must be accessed by the same "
231 "sequence.";
230 232
231 ImageSkiaRep image; 233 ImageSkiaRep image;
232 float resource_scale = scale; 234 float resource_scale = scale;
233 if (!HasRepresentationAtAllScales() && g_supported_scales) 235 if (!HasRepresentationAtAllScales() && g_supported_scales)
234 resource_scale = MapToSupportedScale(scale); 236 resource_scale = MapToSupportedScale(scale);
235 if (scale != resource_scale) { 237 if (scale != resource_scale) {
236 std::vector<ImageSkiaRep>::iterator iter = 238 std::vector<ImageSkiaRep>::iterator iter =
237 FindRepresentation(resource_scale, fetch_new_image); 239 FindRepresentation(resource_scale, fetch_new_image);
238 CHECK(iter != image_reps_.end()); 240 CHECK(iter != image_reps_.end());
239 image = iter->unscaled() ? (*iter) : ScaleImageSkiaRep(*iter, scale); 241 image = iter->unscaled() ? (*iter) : ScaleImageSkiaRep(*iter, scale);
(...skipping 21 matching lines...) Expand all
261 if (image.is_null() || image.scale() != scale) { 263 if (image.is_null() || image.scale() != scale) {
262 non_const->image_reps().push_back(ImageSkiaRep(SkBitmap(), scale)); 264 non_const->image_reps().push_back(ImageSkiaRep(SkBitmap(), scale));
263 } 265 }
264 266
265 // image_reps_ must have the exact much now, so find again. 267 // image_reps_ must have the exact much now, so find again.
266 return FindRepresentation(scale, false); 268 return FindRepresentation(scale, false);
267 } 269 }
268 return exact_iter != image_reps_.end() ? exact_iter : closest_iter; 270 return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
269 } 271 }
270 272
271 ImageSkiaStorage::~ImageSkiaStorage() { 273 ImageSkiaStorage::~ImageSkiaStorage() = default;
272 // We only care if the storage is modified by the same thread. Don't blow up
273 // even if someone else deleted the ImageSkia.
274 DetachFromThread();
275 }
276 274
277 } // internal 275 } // internal
278 276
279 ImageSkia::ImageSkia() : storage_(NULL) { 277 ImageSkia::ImageSkia() : storage_(NULL) {
280 } 278 }
281 279
282 ImageSkia::ImageSkia(ImageSkiaSource* source, const gfx::Size& size) 280 ImageSkia::ImageSkia(ImageSkiaSource* source, const gfx::Size& size)
283 : storage_(new internal::ImageSkiaStorage(source, size)) { 281 : storage_(new internal::ImageSkiaStorage(source, size)) {
284 DCHECK(source); 282 DCHECK(source);
285 // No other thread has reference to this, so it's safe to detach the thread. 283 // No other thread has reference to this, so it's safe to detach the sequence.
286 DetachStorageFromThread(); 284 DetachStorageFromSequence();
287 } 285 }
288 286
289 ImageSkia::ImageSkia(ImageSkiaSource* source, float scale) 287 ImageSkia::ImageSkia(ImageSkiaSource* source, float scale)
290 : storage_(new internal::ImageSkiaStorage(source, scale)) { 288 : storage_(new internal::ImageSkiaStorage(source, scale)) {
291 DCHECK(source); 289 DCHECK(source);
292 if (!storage_->has_source()) 290 if (!storage_->has_source())
293 storage_ = NULL; 291 storage_ = NULL;
294 // No other thread has reference to this, so it's safe to detach the thread. 292 // No other thread has reference to this, so it's safe to detach the sequence.
295 DetachStorageFromThread(); 293 DetachStorageFromSequence();
296 } 294 }
297 295
298 ImageSkia::ImageSkia(const ImageSkiaRep& image_rep) { 296 ImageSkia::ImageSkia(const ImageSkiaRep& image_rep) {
299 Init(image_rep); 297 Init(image_rep);
300 // No other thread has reference to this, so it's safe to detach the thread. 298 // No other thread has reference to this, so it's safe to detach the sequence.
301 DetachStorageFromThread(); 299 DetachStorageFromSequence();
302 } 300 }
303 301
304 ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) { 302 ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) {
305 } 303 }
306 304
307 ImageSkia& ImageSkia::operator=(const ImageSkia& other) { 305 ImageSkia& ImageSkia::operator=(const ImageSkia& other) {
308 storage_ = other.storage_; 306 storage_ = other.storage_;
309 return *this; 307 return *this;
310 } 308 }
311 309
(...skipping 30 matching lines...) Expand all
342 return base::WrapUnique(copy); 340 return base::WrapUnique(copy);
343 341
344 CHECK(CanRead()); 342 CHECK(CanRead());
345 343
346 std::vector<gfx::ImageSkiaRep>& reps = storage_->image_reps(); 344 std::vector<gfx::ImageSkiaRep>& reps = storage_->image_reps();
347 for (std::vector<gfx::ImageSkiaRep>::iterator iter = reps.begin(); 345 for (std::vector<gfx::ImageSkiaRep>::iterator iter = reps.begin();
348 iter != reps.end(); ++iter) { 346 iter != reps.end(); ++iter) {
349 copy->AddRepresentation(*iter); 347 copy->AddRepresentation(*iter);
350 } 348 }
351 // The copy has its own storage. Detach the copy from the current 349 // The copy has its own storage. Detach the copy from the current
352 // thread so that other thread can use this. 350 // sequence so that other sequences can use this.
353 if (!copy->isNull()) 351 if (!copy->isNull())
354 copy->storage_->DetachFromThread(); 352 copy->storage_->DetachFromSequence();
355 return base::WrapUnique(copy); 353 return base::WrapUnique(copy);
356 } 354 }
357 355
358 bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const { 356 bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const {
359 return storage_.get() == other.storage_.get(); 357 return storage_.get() == other.storage_.get();
360 } 358 }
361 359
362 void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) { 360 void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) {
363 DCHECK(!image_rep.is_null()); 361 DCHECK(!image_rep.is_null());
364 362
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, true); 413 ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, true);
416 if (it == storage_->image_reps().end()) 414 if (it == storage_->image_reps().end())
417 return NullImageRep(); 415 return NullImageRep();
418 416
419 return *it; 417 return *it;
420 } 418 }
421 419
422 void ImageSkia::SetReadOnly() { 420 void ImageSkia::SetReadOnly() {
423 CHECK(storage_.get()); 421 CHECK(storage_.get());
424 storage_->SetReadOnly(); 422 storage_->SetReadOnly();
425 DetachStorageFromThread(); 423 DetachStorageFromSequence();
426 } 424 }
427 425
428 void ImageSkia::MakeThreadSafe() { 426 void ImageSkia::MakeThreadSafe() {
429 CHECK(storage_.get()); 427 CHECK(storage_.get());
430 EnsureRepsForSupportedScales(); 428 EnsureRepsForSupportedScales();
431 // Delete source as we no longer needs it. 429 // Delete source as we no longer needs it.
432 if (storage_.get()) 430 if (storage_.get())
433 storage_->DeleteSource(); 431 storage_->DeleteSource();
434 storage_->SetReadOnly(); 432 storage_->SetReadOnly();
435 CHECK(IsThreadSafe()); 433 CHECK(IsThreadSafe());
(...skipping 29 matching lines...) Expand all
465 it != internal_image_reps.end(); ++it) { 463 it != internal_image_reps.end(); ++it) {
466 if (!it->is_null()) 464 if (!it->is_null())
467 image_reps.push_back(*it); 465 image_reps.push_back(*it);
468 } 466 }
469 467
470 return image_reps; 468 return image_reps;
471 } 469 }
472 470
473 void ImageSkia::EnsureRepsForSupportedScales() const { 471 void ImageSkia::EnsureRepsForSupportedScales() const {
474 DCHECK(g_supported_scales != NULL); 472 DCHECK(g_supported_scales != NULL);
475 // Don't check ReadOnly because the source may generate images 473 // Don't check ReadOnly because the source may generate images even for read
476 // even for read only ImageSkia. Concurrent access will be protected 474 // only ImageSkia. Concurrent access will be protected by
477 // by |DCHECK(CalledOnValidThread())| in FindRepresentation. 475 // |DCHECK(sequence_checker_.CalledOnValidSequence())| in FindRepresentation.
478 if (storage_.get() && storage_->has_source()) { 476 if (storage_.get() && storage_->has_source()) {
479 for (std::vector<float>::const_iterator it = g_supported_scales->begin(); 477 for (std::vector<float>::const_iterator it = g_supported_scales->begin();
480 it != g_supported_scales->end(); ++it) 478 it != g_supported_scales->end(); ++it)
481 storage_->FindRepresentation(*it, true); 479 storage_->FindRepresentation(*it, true);
482 } 480 }
483 } 481 }
484 482
485 void ImageSkia::RemoveUnsupportedRepresentationsForScale(float scale) { 483 void ImageSkia::RemoveUnsupportedRepresentationsForScale(float scale) {
486 for (const ImageSkiaRep& image_rep_to_test : image_reps()) { 484 for (const ImageSkiaRep& image_rep_to_test : image_reps()) {
487 const float test_scale = image_rep_to_test.scale(); 485 const float test_scale = image_rep_to_test.scale();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 } 519 }
522 520
523 bool ImageSkia::CanRead() const { 521 bool ImageSkia::CanRead() const {
524 return !storage_.get() || storage_->CanRead(); 522 return !storage_.get() || storage_->CanRead();
525 } 523 }
526 524
527 bool ImageSkia::CanModify() const { 525 bool ImageSkia::CanModify() const {
528 return !storage_.get() || storage_->CanModify(); 526 return !storage_.get() || storage_->CanModify();
529 } 527 }
530 528
531 void ImageSkia::DetachStorageFromThread() { 529 void ImageSkia::DetachStorageFromSequence() {
532 if (storage_.get()) 530 if (storage_.get())
533 storage_->DetachFromThread(); 531 storage_->DetachFromSequence();
534 } 532 }
535 533
536 } // namespace gfx 534 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/image/image_skia.h ('k') | ui/gfx/image/image_skia_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698