summaryrefslogtreecommitdiff
path: root/chromium/cc/tiles
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-17 13:57:45 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-19 13:44:40 +0000
commit6ec7b8da05d21a3878bd21c691b41e675d74bb1c (patch)
treeb87f250bc19413750b9bb9cdbf2da20ef5014820 /chromium/cc/tiles
parentec02ee4181c49b61fce1c8fb99292dbb8139cc90 (diff)
downloadqtwebengine-chromium-6ec7b8da05d21a3878bd21c691b41e675d74bb1c.tar.gz
BASELINE: Update Chromium to 60.0.3112.70
Change-Id: I9911c2280a014d4632f254857876a395d4baed2d Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/cc/tiles')
-rw-r--r--chromium/cc/tiles/checker_image_tracker.cc190
-rw-r--r--chromium/cc/tiles/checker_image_tracker.h95
-rw-r--r--chromium/cc/tiles/checker_image_tracker_unittest.cc375
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache.cc52
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache.h7
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache_unittest.cc678
-rw-r--r--chromium/cc/tiles/image_controller.cc13
-rw-r--r--chromium/cc/tiles/image_controller.h12
-rw-r--r--chromium/cc/tiles/image_controller_unittest.cc5
-rw-r--r--chromium/cc/tiles/image_decode_cache.h6
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.cc174
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.h9
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_set.h5
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_unittest.cc28
-rw-r--r--chromium/cc/tiles/prioritized_tile.cc7
-rw-r--r--chromium/cc/tiles/prioritized_tile.h7
-rw-r--r--chromium/cc/tiles/software_image_decode_cache.cc63
-rw-r--r--chromium/cc/tiles/software_image_decode_cache.h18
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_perftest.cc6
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_unittest.cc572
-rw-r--r--chromium/cc/tiles/tile.h14
-rw-r--r--chromium/cc/tiles/tile_draw_info.cc2
-rw-r--r--chromium/cc/tiles/tile_draw_info.h15
-rw-r--r--chromium/cc/tiles/tile_manager.cc208
-rw-r--r--chromium/cc/tiles/tile_manager.h36
-rw-r--r--chromium/cc/tiles/tile_manager_unittest.cc269
-rw-r--r--chromium/cc/tiles/tiling_set_raster_queue_all.cc17
-rw-r--r--chromium/cc/tiles/tiling_set_raster_queue_all.h3
28 files changed, 1864 insertions, 1022 deletions
diff --git a/chromium/cc/tiles/checker_image_tracker.cc b/chromium/cc/tiles/checker_image_tracker.cc
index 8bbcbebe839..022269d87a9 100644
--- a/chromium/cc/tiles/checker_image_tracker.cc
+++ b/chromium/cc/tiles/checker_image_tracker.cc
@@ -5,6 +5,7 @@
#include "cc/tiles/checker_image_tracker.h"
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
@@ -30,35 +31,23 @@ CheckerImageTracker::CheckerImageTracker(ImageController* image_controller,
enable_checker_imaging_(enable_checker_imaging),
weak_factory_(this) {}
-CheckerImageTracker::~CheckerImageTracker() {
- // Unlock all images pending decode requests.
- for (auto it : image_id_to_decode_request_id_)
- image_controller_->UnlockImageDecode(it.second);
-}
+CheckerImageTracker::~CheckerImageTracker() = default;
-void CheckerImageTracker::FilterImagesForCheckeringForTile(
- std::vector<DrawImage>* images,
- ImageIdFlatSet* checkered_images,
- WhichTree tree) {
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "CheckerImageTracker::FilterImagesForCheckeringForTile", "tree",
- tree);
- DCHECK(checkered_images->empty());
-
- base::EraseIf(*images,
- [this, tree, &checkered_images](const DrawImage& draw_image) {
- const sk_sp<const SkImage>& image = draw_image.image();
- DCHECK(image->isLazyGenerated());
- if (ShouldCheckerImage(image, tree)) {
- ScheduleImageDecodeIfNecessary(image);
- checkered_images->insert(image->uniqueID());
- return true;
- }
- return false;
- });
+void CheckerImageTracker::ScheduleImageDecodeQueue(
+ ImageDecodeQueue image_decode_queue) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+ "CheckerImageTracker::ScheduleImageDecodeQueue");
+ // Only checker-imaged (async updated) images are decoded using the image
+ // decode service. If |enable_checker_imaging_| is false, no image should
+ // be checkered.
+ DCHECK(image_decode_queue.empty() || enable_checker_imaging_);
+
+ image_decode_queue_ = std::move(image_decode_queue);
+ ScheduleNextImageDecode();
}
-const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() {
+const PaintImageIdFlatSet&
+CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"CheckerImageTracker::TakeImagesToInvalidateOnSyncTree");
DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u)
@@ -72,17 +61,45 @@ const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() {
void CheckerImageTracker::DidActivateSyncTree() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"CheckerImageTracker::DidActivateSyncTree");
- for (auto image_id : invalidated_images_on_current_sync_tree_) {
- auto it = image_id_to_decode_request_id_.find(image_id);
- image_controller_->UnlockImageDecode(it->second);
- image_id_to_decode_request_id_.erase(it);
- }
-
+ for (auto image_id : invalidated_images_on_current_sync_tree_)
+ image_id_to_decode_.erase(image_id);
invalidated_images_on_current_sync_tree_.clear();
}
+void CheckerImageTracker::ClearTracker(bool can_clear_decode_policy_tracking) {
+ // Unlock all images and tracking for images pending invalidation. The
+ // |images_invalidated_on_current_sync_tree_| will be cleared when the sync
+ // tree is activated.
+ //
+ // Note that we assume that any images with DecodePolicy::ASYNC, which may be
+ // checkered, are safe to stop tracking here and will either be re-checkered
+ // and invalidated when the decode completes or be invalidated externally.
+ // This is because the policy decision for checkering an image is based on
+ // inputs received from a PaintImage in the DisplayItemList. The policy chosen
+ // for a PaintImage should remain unchanged.
+ // If the external inputs for deciding the decode policy for an image change,
+ // they should be accompanied with an invalidation during paint.
+ image_id_to_decode_.clear();
+
+ if (can_clear_decode_policy_tracking) {
+ image_async_decode_state_.clear();
+ } else {
+ // If we can't clear the decode policy, we need to make sure we still
+ // re-decode and checker images that were pending invalidation.
+ for (auto image_id : images_pending_invalidation_) {
+ auto it = image_async_decode_state_.find(image_id);
+
+ DCHECK(it != image_async_decode_state_.end());
+ DCHECK_EQ(it->second, DecodePolicy::SYNC_DECODED_ONCE);
+
+ it->second = DecodePolicy::ASYNC;
+ }
+ }
+ images_pending_invalidation_.clear();
+}
+
void CheckerImageTracker::DidFinishImageDecode(
- ImageId image_id,
+ PaintImage::Id image_id,
ImageController::ImageDecodeRequestId request_id,
ImageController::ImageDecodeResult result) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
@@ -90,75 +107,114 @@ void CheckerImageTracker::DidFinishImageDecode(
TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode",
image_id);
- DCHECK_NE(result, ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED);
- DCHECK_NE(pending_image_decodes_.count(image_id), 0u);
- pending_image_decodes_.erase(image_id);
+ DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result);
+ DCHECK_EQ(outstanding_image_decode_.value().stable_id(), image_id);
+ outstanding_image_decode_.reset();
+
+ // The async decode state may have been cleared if the tracker was cleared
+ // before this decode could be finished.
+ auto it = image_async_decode_state_.find(image_id);
+ if (it == image_async_decode_state_.end()) {
+ DCHECK_EQ(image_id_to_decode_.count(image_id), 0u);
+ return;
+ }
- images_decoded_once_.insert(image_id);
+ it->second = DecodePolicy::SYNC_DECODED_ONCE;
images_pending_invalidation_.insert(image_id);
+ ScheduleNextImageDecode();
client_->NeedsInvalidationForCheckerImagedTiles();
}
-bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage>& image,
- WhichTree tree) const {
+bool CheckerImageTracker::ShouldCheckerImage(const PaintImage& image,
+ WhichTree tree) {
TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id",
- image->uniqueID());
+ image.stable_id());
if (!enable_checker_imaging_)
return false;
+ PaintImage::Id image_id = image.stable_id();
+
// If the image was invalidated on the current sync tree and the tile is
// for the active tree, continue checkering it on the active tree to ensure
// the image update is atomic for the frame.
- if (invalidated_images_on_current_sync_tree_.count(image->uniqueID()) != 0 &&
+ if (invalidated_images_on_current_sync_tree_.count(image_id) != 0 &&
tree == WhichTree::ACTIVE_TREE) {
return true;
}
- // If a decode request is pending for this image, continue checkering it.
- if (pending_image_decodes_.find(image->uniqueID()) !=
- pending_image_decodes_.end()) {
- return true;
- }
-
// If the image is pending invalidation, continue checkering it. All tiles
// for these images will be invalidated on the next pending tree.
- if (images_pending_invalidation_.find(image->uniqueID()) !=
+ if (images_pending_invalidation_.find(image_id) !=
images_pending_invalidation_.end()) {
return true;
}
- // If the image has been decoded once before, don't checker it again.
- if (images_decoded_once_.find(image->uniqueID()) !=
- images_decoded_once_.end()) {
- return false;
+ auto insert_result =
+ image_async_decode_state_.insert(std::pair<PaintImage::Id, DecodePolicy>(
+ image_id, DecodePolicy::SYNC_PERMANENT));
+ auto it = insert_result.first;
+ if (insert_result.second) {
+ bool can_checker_image =
+ image.animation_type() == PaintImage::AnimationType::STATIC &&
+ image.completion_state() == PaintImage::CompletionState::DONE;
+ if (can_checker_image) {
+ size_t size = SafeSizeOfImage(image.sk_image().get());
+ it->second = (size >= kMinImageSizeToCheckerBytes &&
+ size <= image_controller_->image_cache_max_limit_bytes())
+ ? DecodePolicy::ASYNC
+ : DecodePolicy::SYNC_PERMANENT;
+ }
}
- return SafeSizeOfImage(image.get()) >= kMinImageSizeToCheckerBytes;
+ return it->second == DecodePolicy::ASYNC;
}
-void CheckerImageTracker::ScheduleImageDecodeIfNecessary(
- const sk_sp<const SkImage>& image) {
+void CheckerImageTracker::ScheduleNextImageDecode() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- "CheckerImageTracker::ScheduleImageDecodeIfNecessary");
- ImageId image_id = image->uniqueID();
+ "CheckerImageTracker::ScheduleNextImageDecode");
+ // We can have only one outsanding decode pending completion with the decode
+ // service. We'll come back here when it is completed.
+ if (outstanding_image_decode_.has_value())
+ return;
+
+ while (!image_decode_queue_.empty()) {
+ auto candidate = std::move(image_decode_queue_.front());
+ image_decode_queue_.erase(image_decode_queue_.begin());
+
+ // Once an image has been decoded, it can still be present in the decode
+ // queue (duplicate entries), or while an image is still being skipped on
+ // the active tree. Check if the image is still ASYNC to see if a decode is
+ // needed.
+ PaintImage::Id image_id = candidate.stable_id();
+ auto it = image_async_decode_state_.find(image_id);
+ DCHECK(it != image_async_decode_state_.end());
+ if (it->second != DecodePolicy::ASYNC)
+ continue;
+
+ outstanding_image_decode_.emplace(candidate);
+ break;
+ }
- // If the image has already been decoded, or a decode request is pending, we
- // don't need to schedule another decode.
- if (images_decoded_once_.count(image_id) != 0 ||
- pending_image_decodes_.count(image_id) != 0) {
+ // We either found an image to decode or we reached the end of the queue. If
+ // we couldn't find an image, we're done.
+ if (!outstanding_image_decode_.has_value()) {
+ DCHECK(image_decode_queue_.empty());
return;
}
+ PaintImage::Id image_id = outstanding_image_decode_.value().stable_id();
+ DCHECK_EQ(image_id_to_decode_.count(image_id), 0u);
TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode",
image_id);
- DCHECK_EQ(image_id_to_decode_request_id_.count(image_id), 0U);
-
- image_id_to_decode_request_id_[image_id] =
+ ImageController::ImageDecodeRequestId request_id =
image_controller_->QueueImageDecode(
- image, base::Bind(&CheckerImageTracker::DidFinishImageDecode,
- weak_factory_.GetWeakPtr(), image_id));
- pending_image_decodes_.insert(image_id);
+ outstanding_image_decode_.value().sk_image(),
+ base::Bind(&CheckerImageTracker::DidFinishImageDecode,
+ weak_factory_.GetWeakPtr(), image_id));
+
+ image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>(
+ image_controller_, request_id));
}
} // namespace cc
diff --git a/chromium/cc/tiles/checker_image_tracker.h b/chromium/cc/tiles/checker_image_tracker.h
index 3bc29f55294..9f64d8d3f06 100644
--- a/chromium/cc/tiles/checker_image_tracker.h
+++ b/chromium/cc/tiles/checker_image_tracker.h
@@ -8,6 +8,7 @@
#include <unordered_map>
#include <vector>
+#include "base/optional.h"
#include "cc/cc_export.h"
#include "cc/paint/image_id.h"
#include "cc/tiles/image_controller.h"
@@ -37,33 +38,62 @@ class CC_EXPORT CheckerImageTracker {
bool enable_checker_imaging);
~CheckerImageTracker();
- // Given the |images| for a tile, filters the images which will be deferred
- // asynchronously using the image decoded service, eliminating them from
- // |images| adds them to the |checkered_images| set, so they can be skipped
- // during the rasterization of this tile.
- // The entries remaining in |images| are for images for which a cached decode
- // from the image decode service is available, or which must be decoded before
- // before this tile can be rasterized.
- void FilterImagesForCheckeringForTile(std::vector<DrawImage>* images,
- ImageIdFlatSet* checkered_images,
- WhichTree tree);
+ // Returns true if the decode for |image| will be deferred to the image decode
+ // service and it should be be skipped during raster.
+ bool ShouldCheckerImage(const PaintImage& image, WhichTree tree);
+
+ using ImageDecodeQueue = std::vector<PaintImage>;
+ void ScheduleImageDecodeQueue(ImageDecodeQueue image_decode_queue);
// Returns the set of images to invalidate on the sync tree.
- const ImageIdFlatSet& TakeImagesToInvalidateOnSyncTree();
+ const PaintImageIdFlatSet& TakeImagesToInvalidateOnSyncTree();
+ // Called when the sync tree is activated. Each call to
+ // TakeImagesToInvalidateOnSyncTree() must be followed by this when the
+ // invalidated sync tree is activated.
void DidActivateSyncTree();
+ // Called to reset the tracker state on navigation. This will release all
+ // cached images. Setting |can_clear_decode_policy_tracking| will also result
+ // in re-checkering any images already decoded by the tracker.
+ void ClearTracker(bool can_clear_decode_policy_tracking);
+
private:
- void DidFinishImageDecode(ImageId image_id,
+ enum class DecodePolicy {
+ // The image can be decoded asynchronously from raster. When set, the image
+ // is always skipped during rasterization of content that includes this
+ // image until it has been decoded using the decode service.
+ ASYNC,
+ // The image has been decoded asynchronously once and should now be
+ // synchronously rasterized with the content.
+ SYNC_DECODED_ONCE,
+ // The image has been permanently vetoed from being decoded async.
+ SYNC_PERMANENT,
+ };
+
+ // Wrapper to unlock an image decode requested from the ImageController on
+ // destruction.
+ class ScopedDecodeHolder {
+ public:
+ ScopedDecodeHolder(ImageController* controller,
+ ImageController::ImageDecodeRequestId request_id)
+ : controller_(controller), request_id_(request_id) {}
+ ~ScopedDecodeHolder() { controller_->UnlockImageDecode(request_id_); }
+
+ private:
+ ImageController* controller_;
+ ImageController::ImageDecodeRequestId request_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDecodeHolder);
+ };
+
+ void DidFinishImageDecode(PaintImage::Id image_id,
ImageController::ImageDecodeRequestId request_id,
ImageController::ImageDecodeResult result);
- // Returns true if the decode for |image| will be deferred to the image decode
- // service and it should be be skipped during raster.
- bool ShouldCheckerImage(const sk_sp<const SkImage>& image,
- WhichTree tree) const;
-
- void ScheduleImageDecodeIfNecessary(const sk_sp<const SkImage>& image);
+ // Called when the next request in the |image_decode_queue_| should be
+ // scheduled with the image decode service.
+ void ScheduleNextImageDecode();
ImageController* image_controller_;
CheckerImageTrackerClient* client_;
@@ -71,27 +101,26 @@ class CC_EXPORT CheckerImageTracker {
// A set of images which have been decoded and are pending invalidation for
// raster on the checkered tiles.
- ImageIdFlatSet images_pending_invalidation_;
+ PaintImageIdFlatSet images_pending_invalidation_;
// A set of images which were invalidated on the current sync tree.
- ImageIdFlatSet invalidated_images_on_current_sync_tree_;
+ PaintImageIdFlatSet invalidated_images_on_current_sync_tree_;
+
+ // The queue of images pending decode. We maintain a queue to ensure that the
+ // order in which images are decoded is aligned with the priority of the tiles
+ // dependent on these images.
+ ImageDecodeQueue image_decode_queue_;
- // A set of images which are currently pending decode from the image decode
- // service.
- // TODO(khushalsagar): This should be a queue that gets re-built each time we
- // do a PrepareTiles? See crbug.com/689184.
- ImageIdFlatSet pending_image_decodes_;
+ // The currently outstanding image decode that has been scheduled with the
+ // decode service. There can be only one outstanding decode at a time.
+ base::Optional<PaintImage> outstanding_image_decode_;
- // A set of images which have been decoded at least once from the
- // ImageDecodeService and should not be checkered again.
- // TODO(khushalsagar): Limit the size of this set.
- // TODO(khushalsagar): Plumb navigation changes here to reset this. See
- // crbug.com/693228.
- std::unordered_set<ImageId> images_decoded_once_;
+ // A map of ImageId to its DecodePolicy.
+ std::unordered_map<PaintImage::Id, DecodePolicy> image_async_decode_state_;
// A map of image id to image decode request id for images to be unlocked.
- std::unordered_map<ImageId, ImageController::ImageDecodeRequestId>
- image_id_to_decode_request_id_;
+ std::unordered_map<PaintImage::Id, std::unique_ptr<ScopedDecodeHolder>>
+ image_id_to_decode_;
base::WeakPtrFactory<CheckerImageTracker> weak_factory_;
};
diff --git a/chromium/cc/tiles/checker_image_tracker_unittest.cc b/chromium/cc/tiles/checker_image_tracker_unittest.cc
index 9ca8d39f344..38de60dfd80 100644
--- a/chromium/cc/tiles/checker_image_tracker_unittest.cc
+++ b/chromium/cc/tiles/checker_image_tracker_unittest.cc
@@ -15,8 +15,13 @@
namespace cc {
namespace {
+// 5MB max image cache size.
+const size_t kMaxImageCacheSizeBytes = 5 * 1024 * 1024;
+
const int kCheckerableImageDimension = 512;
-const int kNonCheckerableImageDimension = 16;
+// This size will result in an image just over kMaxImageCacheSizeBytes.
+const int kLargeNonCheckerableImageDimension = 1145;
+const int kSmallNonCheckerableImageDimension = 16;
class TestImageController : public ImageController {
public:
@@ -24,11 +29,16 @@ class TestImageController : public ImageController {
// the ImageController is over-ridden here.
TestImageController()
: ImageController(base::ThreadTaskRunnerHandle::Get().get(),
- base::ThreadTaskRunnerHandle::Get()) {}
+ base::ThreadTaskRunnerHandle::Get()) {
+ SetMaxImageCacheLimitBytesForTesting(kMaxImageCacheSizeBytes);
+ }
~TestImageController() override { DCHECK_EQ(locked_images_.size(), 0U); }
int num_of_locked_images() const { return locked_images_.size(); }
+ const PaintImageIdFlatSet& decodes_requested() const {
+ return decodes_requested_;
+ }
void UnlockImageDecode(ImageDecodeRequestId id) override {
DCHECK_EQ(locked_images_.count(id), 1U);
@@ -40,10 +50,7 @@ class TestImageController : public ImageController {
const ImageDecodedCallback& callback) override {
ImageDecodeRequestId request_id = next_image_request_id_++;
- // The tracker should request a decode only once.
- EXPECT_EQ(decodes_requested_.count(image->uniqueID()), 0u);
decodes_requested_.insert(image->uniqueID());
-
locked_images_.insert(request_id);
// Post the callback asynchronously to match the behaviour in
@@ -58,13 +65,17 @@ class TestImageController : public ImageController {
private:
ImageDecodeRequestId next_image_request_id_ = 1U;
std::unordered_set<ImageDecodeRequestId> locked_images_;
- ImageIdFlatSet decodes_requested_;
+ PaintImageIdFlatSet decodes_requested_;
};
class CheckerImageTrackerTest : public testing::Test,
public CheckerImageTrackerClient {
public:
- enum class ImageType { CHECKERABLE, NON_CHECKERABLE };
+ enum class ImageType {
+ CHECKERABLE,
+ SMALL_NON_CHECKERABLE,
+ LARGE_NON_CHECKERABLE
+ };
void SetUpTracker(bool checker_images_enabled) {
checker_image_tracker_ = base::MakeUnique<CheckerImageTracker>(
@@ -73,15 +84,38 @@ class CheckerImageTrackerTest : public testing::Test,
void TearDown() override { checker_image_tracker_.reset(); }
- DrawImage CreateImage(ImageType image_type) {
- int dimension = image_type == ImageType::CHECKERABLE
- ? kCheckerableImageDimension
- : kNonCheckerableImageDimension;
+ PaintImage CreateImage(
+ ImageType image_type,
+ PaintImage::AnimationType animation = PaintImage::AnimationType::STATIC,
+ PaintImage::CompletionState completion =
+ PaintImage::CompletionState::DONE) {
+ int dimension = 0;
+ switch (image_type) {
+ case ImageType::CHECKERABLE:
+ dimension = kCheckerableImageDimension;
+ break;
+ case ImageType::SMALL_NON_CHECKERABLE:
+ dimension = kSmallNonCheckerableImageDimension;
+ break;
+ case ImageType::LARGE_NON_CHECKERABLE:
+ dimension = kLargeNonCheckerableImageDimension;
+ break;
+ }
+
sk_sp<SkImage> image =
CreateDiscardableImage(gfx::Size(dimension, dimension));
- gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
- return DrawImage(image, SkIRect::MakeWH(image->width(), image->height()),
- kNone_SkFilterQuality, SkMatrix::I(), target_color_space);
+ return PaintImage(PaintImage::GetNextId(), image, animation, completion);
+ }
+
+ CheckerImageTracker::ImageDecodeQueue BuildImageDecodeQueue(
+ std::vector<PaintImage> images,
+ WhichTree tree) {
+ CheckerImageTracker::ImageDecodeQueue decode_queue;
+ for (const auto& image : images) {
+ if (checker_image_tracker_->ShouldCheckerImage(image, tree))
+ decode_queue.push_back(image);
+ }
+ return decode_queue;
}
// CheckerImageTrackerClient implementation.
@@ -101,13 +135,10 @@ TEST_F(CheckerImageTrackerTest, CheckerImagesDisabled) {
// disabled.
SetUpTracker(false);
- std::vector<DrawImage> draw_images;
- ImageIdFlatSet checkered_images;
- draw_images.push_back(CreateImage(ImageType::CHECKERABLE));
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 1U);
- EXPECT_EQ(checkered_images.size(), 0U);
+ PaintImageIdFlatSet checkered_images;
+ PaintImage paint_image = CreateImage(ImageType::CHECKERABLE);
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ paint_image, WhichTree::PENDING_TREE));
EXPECT_EQ(image_controller_.num_of_locked_images(), 0);
}
@@ -115,22 +146,25 @@ TEST_F(CheckerImageTrackerTest, UpdatesImagesAtomically) {
// Ensures that the tracker updates images atomically for each frame.
SetUpTracker(true);
- DrawImage checkerable_image = CreateImage(ImageType::CHECKERABLE);
- DrawImage non_checkerable_image = CreateImage(ImageType::NON_CHECKERABLE);
- ImageIdFlatSet checkered_images;
- std::vector<DrawImage> draw_images;
+ PaintImage checkerable_image = CreateImage(ImageType::CHECKERABLE);
+ PaintImage small_non_checkerable_image =
+ CreateImage(ImageType::SMALL_NON_CHECKERABLE);
+ PaintImage large_non_checkerable_image =
+ CreateImage(ImageType::LARGE_NON_CHECKERABLE);
+ CheckerImageTracker::ImageDecodeQueue image_decode_queue;
// First request to filter images.
- draw_images.push_back(checkerable_image);
- draw_images.push_back(non_checkerable_image);
- draw_images.push_back(checkerable_image);
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
-
- EXPECT_EQ(draw_images.size(), 1U);
- EXPECT_EQ(draw_images[0].image(), non_checkerable_image.image());
- EXPECT_EQ(checkered_images.size(), 1U);
- EXPECT_EQ(checkered_images.count(checkerable_image.image()->uniqueID()), 1U);
+ std::vector<PaintImage> paint_images = {
+ checkerable_image, small_non_checkerable_image,
+ large_non_checkerable_image, checkerable_image};
+ image_decode_queue =
+ BuildImageDecodeQueue(paint_images, WhichTree::PENDING_TREE);
+
+ ASSERT_EQ(2u, image_decode_queue.size());
+ EXPECT_EQ(checkerable_image, image_decode_queue[0]);
+ EXPECT_EQ(checkerable_image, image_decode_queue[1]);
+
+ checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue);
EXPECT_EQ(image_controller_.num_of_locked_images(), 1);
// Run pending task to indicate completion of decode request to the tracker.
@@ -143,44 +177,31 @@ TEST_F(CheckerImageTrackerTest, UpdatesImagesAtomically) {
// Continue checkering the image until the set of images to invalidate is
// pulled.
- draw_images.clear();
- draw_images.push_back(checkerable_image);
- checkered_images.clear();
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 0U);
- EXPECT_EQ(checkered_images.size(), 1U);
- EXPECT_EQ(image_controller_.num_of_locked_images(), 1);
+ EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image, WhichTree::PENDING_TREE));
- ImageIdFlatSet invalidated_images =
+ PaintImageIdFlatSet invalidated_images =
checker_image_tracker_->TakeImagesToInvalidateOnSyncTree();
EXPECT_EQ(invalidated_images.size(), 1U);
- EXPECT_EQ(invalidated_images.count(checkerable_image.image()->uniqueID()),
- 1U);
+ EXPECT_EQ(invalidated_images.count(checkerable_image.stable_id()), 1U);
// Use the same set of draw images to ensure that they are not checkered on
// the pending tree now.
- draw_images.clear();
- draw_images.push_back(checkerable_image);
- draw_images.push_back(non_checkerable_image);
- checkered_images.clear();
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 2U);
- EXPECT_EQ(checkered_images.size(), 0U);
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image, WhichTree::PENDING_TREE));
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ small_non_checkerable_image, WhichTree::PENDING_TREE));
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ large_non_checkerable_image, WhichTree::PENDING_TREE));
// Use this set to make the same request from the active tree, we should
// continue checkering this image on the active tree until activation.
- draw_images.clear();
- draw_images.push_back(checkerable_image);
- draw_images.push_back(non_checkerable_image);
- checkered_images.clear();
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::ACTIVE_TREE);
- EXPECT_EQ(draw_images.size(), 1U);
- EXPECT_EQ(draw_images[0].image(), non_checkerable_image.image());
- EXPECT_EQ(checkered_images.size(), 1U);
- EXPECT_EQ(checkered_images.count(checkerable_image.image()->uniqueID()), 1U);
+ EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image, WhichTree::ACTIVE_TREE));
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ small_non_checkerable_image, WhichTree::ACTIVE_TREE));
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ large_non_checkerable_image, WhichTree::ACTIVE_TREE));
// Activate the sync tree. The images should be unlocked upon activation.
EXPECT_EQ(image_controller_.num_of_locked_images(), 1);
@@ -192,18 +213,13 @@ TEST_F(CheckerImageTrackerTest, NoConsecutiveCheckeringForImage) {
// checkered again in subsequent frames.
SetUpTracker(true);
- DrawImage checkerable_image = CreateImage(ImageType::CHECKERABLE);
- DrawImage non_checkerable_image = CreateImage(ImageType::NON_CHECKERABLE);
- ImageIdFlatSet checkered_images;
- std::vector<DrawImage> draw_images;
+ PaintImage checkerable_image = CreateImage(ImageType::CHECKERABLE);
+ std::vector<PaintImage> paint_images = {checkerable_image};
- draw_images.clear();
- draw_images.push_back(checkerable_image);
- checkered_images.clear();
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 0U);
- EXPECT_EQ(checkered_images.size(), 1U);
+ CheckerImageTracker::ImageDecodeQueue image_decode_queue =
+ BuildImageDecodeQueue(paint_images, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+ checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue);
// Trigger decode completion, take images to invalidate and activate the sync
// tree.
@@ -212,13 +228,8 @@ TEST_F(CheckerImageTrackerTest, NoConsecutiveCheckeringForImage) {
checker_image_tracker_->DidActivateSyncTree();
// Subsequent requests for this image should not be checkered.
- draw_images.clear();
- draw_images.push_back(checkerable_image);
- checkered_images.clear();
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 1U);
- EXPECT_EQ(checkered_images.size(), 0U);
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image, WhichTree::PENDING_TREE));
}
TEST_F(CheckerImageTrackerTest,
@@ -227,72 +238,182 @@ TEST_F(CheckerImageTrackerTest,
// active tree are tracked correctly.
SetUpTracker(true);
- DrawImage checkerable_image1 = CreateImage(ImageType::CHECKERABLE);
- ImageIdFlatSet checkered_images;
- std::vector<DrawImage> draw_images;
+ PaintImage checkerable_image1 = CreateImage(ImageType::CHECKERABLE);
+ std::vector<PaintImage> paint_images;
+ CheckerImageTracker::ImageDecodeQueue image_decode_queue;
// First request to filter images on the pending and active tree.
- draw_images.push_back(checkerable_image1);
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 0U);
- EXPECT_EQ(checkered_images.size(), 1U);
+ paint_images.push_back(checkerable_image1);
+ image_decode_queue =
+ BuildImageDecodeQueue(paint_images, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+ checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue);
// The image is also checkered on the active tree while a decode request is
// pending.
- draw_images.clear();
- checkered_images.clear();
- draw_images.push_back(checkerable_image1);
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::ACTIVE_TREE);
- EXPECT_EQ(draw_images.size(), 0U);
- EXPECT_EQ(checkered_images.size(), 1U);
+ EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image1, WhichTree::ACTIVE_TREE));
// Trigger decode completion and take images to invalidate on the sync tree.
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(invalidation_request_pending_);
- ImageIdFlatSet invalidated_images =
+ PaintImageIdFlatSet invalidated_images =
checker_image_tracker_->TakeImagesToInvalidateOnSyncTree();
EXPECT_EQ(invalidated_images.size(), 1U);
- EXPECT_EQ(invalidated_images.count(checkerable_image1.image()->uniqueID()),
- 1U);
+ EXPECT_EQ(invalidated_images.count(checkerable_image1.stable_id()), 1U);
// Second request to filter the same image on the pending and active tree. It
// should be checkered on the active tree, but not the pending tree.
- draw_images.clear();
- checkered_images.clear();
- draw_images.push_back(checkerable_image1);
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 1U);
- EXPECT_EQ(checkered_images.size(), 0U);
-
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::ACTIVE_TREE);
- EXPECT_EQ(draw_images.size(), 0U);
- EXPECT_EQ(checkered_images.size(), 1U);
+ EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image1, WhichTree::ACTIVE_TREE));
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image1, WhichTree::PENDING_TREE));
// New checkerable image on the pending tree.
- DrawImage checkerable_image2 = CreateImage(ImageType::CHECKERABLE);
- draw_images.clear();
- checkered_images.clear();
- draw_images.push_back(checkerable_image2);
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::PENDING_TREE);
- EXPECT_EQ(draw_images.size(), 0U);
- EXPECT_EQ(checkered_images.size(), 1U);
+ PaintImage checkerable_image2 = CreateImage(ImageType::CHECKERABLE);
+ EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image2, WhichTree::PENDING_TREE));
// Activate the sync tree. The initial image should no longer be checkered on
// the active tree.
checker_image_tracker_->DidActivateSyncTree();
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ checkerable_image1, WhichTree::ACTIVE_TREE));
+}
+
+TEST_F(CheckerImageTrackerTest, CancelsScheduledDecodes) {
+ SetUpTracker(true);
+
+ PaintImage checkerable_image1 = CreateImage(ImageType::CHECKERABLE);
+ PaintImage checkerable_image2 = CreateImage(ImageType::CHECKERABLE);
+ std::vector<PaintImage> paint_images = {checkerable_image1,
+ checkerable_image2};
+
+ CheckerImageTracker::ImageDecodeQueue image_decode_queue;
+ image_decode_queue =
+ BuildImageDecodeQueue(paint_images, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 2U);
+ checker_image_tracker_->ScheduleImageDecodeQueue(
+ std::move(image_decode_queue));
+
+ // Only the first image in the queue should have been decoded.
+ EXPECT_EQ(image_controller_.decodes_requested().size(), 1U);
+ EXPECT_EQ(image_controller_.decodes_requested().count(
+ checkerable_image1.sk_image()->uniqueID()),
+ 1U);
+
+ // Rebuild the queue before the tracker is notified of decode completion,
+ // removing the second image and adding a new one.
+ PaintImage checkerable_image3 = CreateImage(ImageType::CHECKERABLE);
+ paint_images = {checkerable_image1, checkerable_image3};
+ image_decode_queue =
+ BuildImageDecodeQueue(paint_images, WhichTree::PENDING_TREE);
+
+ // The queue has 2 decodes because we are still checkering on the first one.
+ EXPECT_EQ(image_decode_queue.size(), 2U);
+ checker_image_tracker_->ScheduleImageDecodeQueue(
+ std::move(image_decode_queue));
+
+ // We still have only one decode because the tracker keeps only one decode
+ // pending at a time.
+ EXPECT_EQ(image_controller_.decodes_requested().size(), 1U);
+ EXPECT_EQ(image_controller_.decodes_requested().count(
+ checkerable_image1.sk_image()->uniqueID()),
+ 1U);
+
+ // Trigger completion for all decodes. Only 2 images should have been decoded
+ // since the second image was cancelled.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(image_controller_.decodes_requested().size(), 2U);
+ EXPECT_EQ(image_controller_.decodes_requested().count(
+ checkerable_image3.sk_image()->uniqueID()),
+ 1U);
+ EXPECT_EQ(image_controller_.num_of_locked_images(), 2);
+}
+
+TEST_F(CheckerImageTrackerTest, ClearsTracker) {
+ SetUpTracker(true);
+
+ PaintImage checkerable_image = CreateImage(ImageType::CHECKERABLE);
+ CheckerImageTracker::ImageDecodeQueue image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+ checker_image_tracker_->ScheduleImageDecodeQueue(
+ std::move(image_decode_queue));
+ base::RunLoop().RunUntilIdle();
+ checker_image_tracker_->TakeImagesToInvalidateOnSyncTree();
+
+ // The image is no longer checkered on the pending tree.
+ image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 0U);
+ EXPECT_EQ(image_controller_.num_of_locked_images(), 1);
+
+ // Clear the tracker without clearing the async decode tracking. This should
+ // drop the decode but the image should not be checkered.
+ bool can_clear_decode_policy_tracking = false;
+ checker_image_tracker_->ClearTracker(can_clear_decode_policy_tracking);
+ EXPECT_EQ(image_controller_.num_of_locked_images(), 0);
+ image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 0U);
+ checker_image_tracker_->DidActivateSyncTree();
+
+ // Now clear the decode tracking as well. The image will be re-checkered.
+ can_clear_decode_policy_tracking = true;
+ checker_image_tracker_->ClearTracker(can_clear_decode_policy_tracking);
+ image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+
+ // If an image had been decoded and tracker was cleared after it, we should
+ // continue checkering it.
+ PaintImage checkerable_image2 = CreateImage(ImageType::CHECKERABLE);
+ image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+ checker_image_tracker_->ScheduleImageDecodeQueue(
+ std::move(image_decode_queue));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(image_controller_.num_of_locked_images(), 1);
+ can_clear_decode_policy_tracking = false;
+ checker_image_tracker_->ClearTracker(can_clear_decode_policy_tracking);
+ EXPECT_EQ(image_controller_.num_of_locked_images(), 0);
+ image_decode_queue =
+ BuildImageDecodeQueue({checkerable_image}, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+}
+
+TEST_F(CheckerImageTrackerTest, CheckersOnlyStaticCompletedImages) {
+ SetUpTracker(true);
- draw_images.clear();
- checkered_images.clear();
- draw_images.push_back(checkerable_image1);
- checker_image_tracker_->FilterImagesForCheckeringForTile(
- &draw_images, &checkered_images, WhichTree::ACTIVE_TREE);
- EXPECT_EQ(draw_images.size(), 1U);
- EXPECT_EQ(checkered_images.size(), 0U);
+ PaintImage static_image = CreateImage(ImageType::CHECKERABLE);
+ PaintImage animated_image =
+ CreateImage(ImageType::CHECKERABLE, PaintImage::AnimationType::ANIMATED);
+ PaintImage partial_image =
+ CreateImage(ImageType::CHECKERABLE, PaintImage::AnimationType::STATIC,
+ PaintImage::CompletionState::PARTIALLY_DONE);
+ PaintImage video_image =
+ CreateImage(ImageType::CHECKERABLE, PaintImage::AnimationType::VIDEO);
+ std::vector<PaintImage> paint_images = {static_image, animated_image,
+ partial_image, video_image};
+
+ CheckerImageTracker::ImageDecodeQueue image_decode_queue =
+ BuildImageDecodeQueue(paint_images, WhichTree::PENDING_TREE);
+ EXPECT_EQ(image_decode_queue.size(), 1U);
+ EXPECT_EQ(image_decode_queue[0], static_image);
+
+ // Change the partial image to complete and try again. It should still not
+ // be checkered.
+ gfx::Size image_size = gfx::Size(partial_image.sk_image()->width(),
+ partial_image.sk_image()->height());
+ PaintImage completed_paint_image =
+ PaintImage(partial_image.stable_id(), CreateDiscardableImage(image_size));
+ EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage(
+ completed_paint_image, WhichTree::PENDING_TREE));
}
} // namespace
diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc
index 39a822617db..b30d9da1c6f 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache.cc
+++ b/chromium/cc/tiles/gpu_image_decode_cache.cc
@@ -110,6 +110,38 @@ gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image, int mip_level) {
return MipMapUtil::GetSizeForLevel(base_size, mip_level);
}
+// Draws and scales the provided |draw_image| into the |target_pixmap|. If the
+// draw/scale can be done directly, calls directly into SkImage::scalePixels,
+// if not, decodes to a compatible temporary pixmap and then converts that into
+// the |target_pixmap|.
+bool DrawAndScaleImage(const DrawImage& draw_image, SkPixmap* target_pixmap) {
+ const SkImage* image = draw_image.image().get();
+ if (image->dimensions() == target_pixmap->bounds().size() ||
+ target_pixmap->info().colorType() == kN32_SkColorType) {
+ // If no scaling is occurring, or if the target colortype is already N32,
+ // just scale directly.
+ return image->scalePixels(*target_pixmap,
+ CalculateUploadScaleFilterQuality(draw_image),
+ SkImage::kDisallow_CachingHint);
+ }
+
+ // If the target colortype is not N32, it may be impossible to scale
+ // directly. Instead scale into an N32 pixmap, and convert that into the
+ // |target_pixmap|.
+ SkImageInfo decode_info =
+ target_pixmap->info().makeColorType(kN32_SkColorType);
+ SkBitmap decode_bitmap;
+ if (!decode_bitmap.tryAllocPixels(decode_info))
+ return false;
+ SkPixmap decode_pixmap(decode_bitmap.info(), decode_bitmap.getPixels(),
+ decode_bitmap.rowBytes());
+ if (!image->scalePixels(decode_pixmap,
+ CalculateUploadScaleFilterQuality(draw_image),
+ SkImage::kDisallow_CachingHint))
+ return false;
+ return decode_pixmap.readPixels(*target_pixmap);
+}
+
} // namespace
// static
@@ -616,6 +648,10 @@ void GpuImageDecodeCache::ClearCache() {
}
}
+size_t GpuImageDecodeCache::GetMaximumMemoryLimitBytes() const {
+ return normal_max_cache_bytes_;
+}
+
bool GpuImageDecodeCache::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
@@ -1100,13 +1136,11 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image,
// In order to match GPU scaling quality (which uses mip-maps at high
// quality), we want to use at most medium filter quality for the
// scale.
- SkPixmap image_pixmap(image_info, backing_memory->data(),
- image_info.minRowBytes());
- // Note that scalePixels falls back to readPixels if the sale is 1x, so
+ SkPixmap image_pixmap(image_info.makeColorSpace(nullptr),
+ backing_memory->data(), image_info.minRowBytes());
+ // Note that scalePixels falls back to readPixels if the scale is 1x, so
// no need to special case that as an optimization.
- if (!draw_image.image()->scalePixels(
- image_pixmap, CalculateUploadScaleFilterQuality(draw_image),
- SkImage::kDisallow_CachingHint)) {
+ if (!DrawAndScaleImage(draw_image, &image_pixmap)) {
DLOG(ERROR) << "scalePixels failed.";
backing_memory->Unlock();
backing_memory.reset();
@@ -1119,7 +1153,8 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image,
// DCHECKs here to enforce this.
if (!draw_image.image()->getDeferredTextureImageData(
*context_threadsafe_proxy_.get(), &image_data->upload_params, 1,
- backing_memory->data(), nullptr)) {
+ backing_memory->data(), nullptr,
+ ResourceFormatToClosestSkColorType(format_))) {
DLOG(ERROR) << "getDeferredTextureImageData failed despite params "
<< "having validated.";
backing_memory->Unlock();
@@ -1219,7 +1254,8 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) {
draw_image.matrix(), CalculateUploadScaleFilterQuality(draw_image),
upload_scale_mip_level);
size_t data_size = draw_image.image()->getDeferredTextureImageData(
- *context_threadsafe_proxy_.get(), &params, 1, nullptr, nullptr);
+ *context_threadsafe_proxy_.get(), &params, 1, nullptr, nullptr,
+ ResourceFormatToClosestSkColorType(format_));
if (data_size == 0) {
// Can't upload image, too large or other failure. Try to use SW fallback.
diff --git a/chromium/cc/tiles/gpu_image_decode_cache.h b/chromium/cc/tiles/gpu_image_decode_cache.h
index 391f048c2e9..f60157742b4 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache.h
+++ b/chromium/cc/tiles/gpu_image_decode_cache.h
@@ -125,6 +125,7 @@ class CC_EXPORT GpuImageDecodeCache
void SetShouldAggressivelyFreeResources(
bool aggressively_free_resources) override;
void ClearCache() override;
+ size_t GetMaximumMemoryLimitBytes() const override;
// MemoryDumpProvider overrides.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
@@ -230,7 +231,7 @@ class CC_EXPORT GpuImageDecodeCache
UsageStats usage_stats_;
};
- struct ImageData : public base::RefCounted<ImageData> {
+ struct ImageData : public base::RefCountedThreadSafe<ImageData> {
ImageData(DecodedDataMode mode,
size_t size,
const gfx::ColorSpace& target_color_space,
@@ -250,7 +251,7 @@ class CC_EXPORT GpuImageDecodeCache
UploadedImageData upload;
private:
- friend class base::RefCounted<ImageData>;
+ friend class base::RefCountedThreadSafe<ImageData>;
~ImageData();
};
@@ -347,6 +348,8 @@ class CC_EXPORT GpuImageDecodeCache
sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_;
// All members below this point must only be accessed while holding |lock_|.
+ // The exception are const members like |normal_max_cache_bytes_| that can
+ // be accessed without a lock since they are thread safe.
base::Lock lock_;
// |persistent_cache_| represents the long-lived cache, keeping a certain
diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc
index 91a08d1f40c..fb2f91bceaf 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -8,6 +8,7 @@
#include "cc/test/test_context_provider.h"
#include "cc/test/test_tile_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace cc {
@@ -17,22 +18,48 @@ gfx::ColorSpace DefaultColorSpace() {
return gfx::ColorSpace::CreateSRGB();
}
+PaintImage::Id s_paint_image_id = PaintImage::GetNextId();
+
+PaintImage CreatePaintImage(sk_sp<SkImage> image) {
+ return PaintImage(s_paint_image_id, image);
+}
+
size_t kGpuMemoryLimitBytes = 96 * 1024 * 1024;
class TestGpuImageDecodeCache : public GpuImageDecodeCache {
public:
- explicit TestGpuImageDecodeCache(ContextProvider* context)
+ explicit TestGpuImageDecodeCache(ContextProvider* context,
+ ResourceFormat format)
: GpuImageDecodeCache(context,
- ResourceFormat::RGBA_8888,
+ format,
kGpuMemoryLimitBytes,
kGpuMemoryLimitBytes) {}
};
+class TestImageGenerator : public SkImageGenerator {
+ public:
+ explicit TestImageGenerator(const SkImageInfo& info)
+ : SkImageGenerator(info),
+ image_backing_memory_(info.getSafeSize(info.minRowBytes()), 0),
+ image_pixmap_(info, image_backing_memory_.data(), info.minRowBytes()) {}
+
+ protected:
+ bool onGetPixels(const SkImageInfo& info,
+ void* pixels,
+ size_t rowBytes,
+ const Options&) override {
+ return image_pixmap_.readPixels(info, pixels, rowBytes, 0, 0);
+ }
+
+ private:
+ std::vector<uint8_t> image_backing_memory_;
+ SkPixmap image_pixmap_;
+};
+
sk_sp<SkImage> CreateImage(int width, int height) {
- SkBitmap bitmap;
gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
- bitmap.allocPixels(
- SkImageInfo::MakeN32Premul(width, height, color_space.ToSkColorSpace()));
- return SkImage::MakeFromBitmap(bitmap);
+ std::unique_ptr<TestImageGenerator> generator(new TestImageGenerator(
+ SkImageInfo::MakeN32Premul(width, height, color_space.ToSkColorSpace())));
+ return SkImage::MakeFromGenerator(std::move(generator));
}
SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) {
@@ -47,18 +74,20 @@ SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) {
return matrix;
}
-TEST(GpuImageDecodeCacheTest, GetTaskForImageSameImage) {
+using GpuImageDecodeCacheTest = ::testing::TestWithParam<ResourceFormat>;
+
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageSameImage) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -66,8 +95,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSameImage) {
EXPECT_TRUE(task);
DrawImage another_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> another_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -82,18 +111,18 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSameImage) {
cache.UnrefImage(draw_image);
}
-TEST(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -101,8 +130,8 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) {
EXPECT_TRUE(task);
DrawImage another_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> another_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -117,21 +146,16 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageSmallerScale) {
cache.UnrefImage(another_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageLowerQuality DISABLED_GetTaskForImageLowerQuality
-#else
-#define MAYBE_GetTaskForImageLowerQuality GetTaskForImageLowerQuality
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLowerQuality) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageLowerQuality) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
SkMatrix matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f), is_decomposable);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
kHigh_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -140,7 +164,7 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLowerQuality) {
EXPECT_TRUE(task);
DrawImage another_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
kLow_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> another_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -155,24 +179,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLowerQuality) {
cache.UnrefImage(another_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageDifferentImage \
- DISABLED_GetTaskForImageDifferentImage
-#else
-#define MAYBE_GetTaskForImageDifferentImage GetTaskForImageDifferentImage
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentImage) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageDifferentImage) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -182,7 +200,7 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentImage) {
sk_sp<SkImage> second_image = CreateImage(100, 100);
DrawImage second_draw_image(
- second_image,
+ CreatePaintImage(second_image),
SkIRect::MakeWH(second_image->width(), second_image->height()), quality,
CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
DefaultColorSpace());
@@ -202,23 +220,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentImage) {
cache.UnrefImage(second_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageLargerScale DISABLED_GetTaskForImageLargerScale
-#else
-#define MAYBE_GetTaskForImageLargerScale GetTaskForImageLargerScale
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScale) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageLargerScale) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -232,8 +245,9 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScale) {
cache.UnrefImage(first_draw_image);
DrawImage second_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -243,8 +257,9 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScale) {
EXPECT_TRUE(first_task.get() != second_task.get());
DrawImage third_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> third_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -259,25 +274,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScale) {
cache.UnrefImage(third_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageLargerScaleNoReuse \
- DISABLED_GetTaskForImageLargerScaleNoReuse
-#else
-#define MAYBE_GetTaskForImageLargerScaleNoReuse \
- GetTaskForImageLargerScaleNoReuse
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScaleNoReuse) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageLargerScaleNoReuse) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -286,8 +294,9 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScaleNoReuse) {
EXPECT_TRUE(first_task);
DrawImage second_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -297,8 +306,9 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScaleNoReuse) {
EXPECT_TRUE(first_task.get() != second_task.get());
DrawImage third_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> third_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -316,22 +326,17 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageLargerScaleNoReuse) {
cache.UnrefImage(third_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageHigherQuality DISABLED_GetTaskForImageHigherQuality
-#else
-#define MAYBE_GetTaskForImageHigherQuality GetTaskForImageHigherQuality
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageHigherQuality) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkMatrix matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f), is_decomposable);
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()),
kLow_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -345,7 +350,8 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageHigherQuality) {
cache.UnrefImage(first_draw_image);
DrawImage second_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()),
kHigh_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -360,26 +366,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageHigherQuality) {
cache.UnrefImage(second_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageAlreadyDecodedAndLocked \
- DISABLED_GetTaskForImageAlreadyDecodedAndLocked
-#else
-#define MAYBE_GetTaskForImageAlreadyDecodedAndLocked \
- GetTaskForImageAlreadyDecodedAndLocked
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyDecodedAndLocked) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedAndLocked) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -414,26 +412,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyDecodedAndLocked) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageAlreadyDecodedNotLocked \
- DISABLED_GetTaskForImageAlreadyDecodedNotLocked
-#else
-#define MAYBE_GetTaskForImageAlreadyDecodedNotLocked \
- GetTaskForImageAlreadyDecodedNotLocked
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyDecodedNotLocked) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageAlreadyDecodedNotLocked) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -468,25 +458,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyDecodedNotLocked) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageAlreadyUploaded \
- DISABLED_GetTaskForImageAlreadyUploaded
-#else
-#define MAYBE_GetTaskForImageAlreadyUploaded GetTaskForImageAlreadyUploaded
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyUploaded) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageAlreadyUploaded) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -511,26 +494,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageAlreadyUploaded) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageCanceledGetsNewTask \
- DISABLED_GetTaskForImageCanceledGetsNewTask
-#else
-#define MAYBE_GetTaskForImageCanceledGetsNewTask \
- GetTaskForImageCanceledGetsNewTask
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageCanceledGetsNewTask) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -567,27 +542,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetTaskForImageCanceledGetsNewTask) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetTaskForImageCanceledWhileReffedGetsNewTask \
- DISABLED_GetTaskForImageCanceledWhileReffedGetsNewTask
-#else
-#define MAYBE_GetTaskForImageCanceledWhileReffedGetsNewTask \
- GetTaskForImageCanceledWhileReffedGetsNewTask
-#endif
-TEST(GpuImageDecodeCacheTest,
- MAYBE_GetTaskForImageCanceledWhileReffedGetsNewTask) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageCanceledWhileReffedGetsNewTask) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -628,26 +594,18 @@ TEST(GpuImageDecodeCacheTest,
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_NoTaskForImageAlreadyFailedDecoding \
- DISABLED_NoTaskForImageAlreadyFailedDecoding
-#else
-#define MAYBE_NoTaskForImageAlreadyFailedDecoding \
- NoTaskForImageAlreadyFailedDecoding
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_NoTaskForImageAlreadyFailedDecoding) {
+TEST_P(GpuImageDecodeCacheTest, NoTaskForImageAlreadyFailedDecoding) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -670,24 +628,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_NoTaskForImageAlreadyFailedDecoding) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetDecodedImageForDraw DISABLED_GetDecodedImageForDraw
-#else
-#define MAYBE_GetDecodedImageForDraw GetDecodedImageForDraw
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDraw) {
+TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDraw) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -711,18 +663,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDraw) {
cache.UnrefImage(draw_image);
}
-TEST(GpuImageDecodeCacheTest, GetLargeDecodedImageForDraw) {
+TEST_P(GpuImageDecodeCacheTest, GetLargeDecodedImageForDraw) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(1, 24000);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -747,20 +699,20 @@ TEST(GpuImageDecodeCacheTest, GetLargeDecodedImageForDraw) {
EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image));
}
-TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
+TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
cache.SetAllByteLimitsForTesting(0);
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -781,26 +733,18 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetDecodedImageForDrawLargerScale \
- DISABLED_GetDecodedImageForDrawLargerScale
-#else
-#define MAYBE_GetDecodedImageForDrawLargerScale \
- GetDecodedImageForDrawLargerScale
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawLargerScale) {
+TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawLargerScale) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -811,8 +755,8 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawLargerScale) {
TestTileTaskRunner::ProcessTask(task.get());
DrawImage larger_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> larger_task;
bool larger_need_unref = cache.GetTaskForImageAndRef(
@@ -848,23 +792,16 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawLargerScale) {
cache.UnrefImage(larger_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetDecodedImageForDrawHigherQuality \
- DISABLED_GetDecodedImageForDrawHigherQuality
-#else
-#define MAYBE_GetDecodedImageForDrawHigherQuality \
- GetDecodedImageForDrawHigherQuality
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawHigherQuality) {
+TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawHigherQuality) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkMatrix matrix = CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable);
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
kLow_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -876,7 +813,7 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawHigherQuality) {
TestTileTaskRunner::ProcessTask(task.get());
DrawImage higher_quality_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
kHigh_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> hq_task;
bool hq_needs_unref = cache.GetTaskForImageAndRef(
@@ -913,25 +850,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawHigherQuality) {
cache.UnrefImage(higher_quality_draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetDecodedImageForDrawNegative \
- DISABLED_GetDecodedImageForDrawNegative
-#else
-#define MAYBE_GetDecodedImageForDrawNegative GetDecodedImageForDrawNegative
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawNegative) {
+TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawNegative) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(-0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(-0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -957,26 +887,18 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetDecodedImageForDrawNegative) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetLargeScaledDecodedImageForDraw \
- DISABLED_GetLargeScaledDecodedImageForDraw
-#else
-#define MAYBE_GetLargeScaledDecodedImageForDraw \
- GetLargeScaledDecodedImageForDraw
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_GetLargeScaledDecodedImageForDraw) {
+TEST_P(GpuImageDecodeCacheTest, GetLargeScaledDecodedImageForDraw) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(1, 48000);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -1004,28 +926,20 @@ TEST(GpuImageDecodeCacheTest, MAYBE_GetLargeScaledDecodedImageForDraw) {
EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image));
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_AtRasterUsedDirectlyIfSpaceAllows \
- DISABLED_AtRasterUsedDirectlyIfSpaceAllows
-#else
-#define MAYBE_AtRasterUsedDirectlyIfSpaceAllows \
- AtRasterUsedDirectlyIfSpaceAllows
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_AtRasterUsedDirectlyIfSpaceAllows) {
+TEST_P(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
cache.SetAllByteLimitsForTesting(0);
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1057,29 +971,21 @@ TEST(GpuImageDecodeCacheTest, MAYBE_AtRasterUsedDirectlyIfSpaceAllows) {
cache.UnrefImage(draw_image);
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_GetDecodedImageForDrawAtRasterDecodeMultipleTimes \
- DISABLED_GetDecodedImageForDrawAtRasterDecodeMultipleTimes
-#else
-#define MAYBE_GetDecodedImageForDrawAtRasterDecodeMultipleTimes \
- GetDecodedImageForDrawAtRasterDecodeMultipleTimes
-#endif
-TEST(GpuImageDecodeCacheTest,
- MAYBE_GetDecodedImageForDrawAtRasterDecodeMultipleTimes) {
+TEST_P(GpuImageDecodeCacheTest,
+ GetDecodedImageForDrawAtRasterDecodeMultipleTimes) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
cache.SetAllByteLimitsForTesting(0);
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
// Must hold context lock before calling GetDecodedImageForDraw /
// DrawWithImageFinished.
@@ -1100,19 +1006,19 @@ TEST(GpuImageDecodeCacheTest,
cache.DrawWithImageFinished(draw_image, another_decoded_draw_image);
}
-TEST(GpuImageDecodeCacheTest,
- GetLargeDecodedImageForDrawAtRasterDecodeMultipleTimes) {
+TEST_P(GpuImageDecodeCacheTest,
+ GetLargeDecodedImageForDrawAtRasterDecodeMultipleTimes) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(1, 24000);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
// Must hold context lock before calling GetDecodedImageForDraw /
// DrawWithImageFinished.
@@ -1138,18 +1044,18 @@ TEST(GpuImageDecodeCacheTest,
EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image));
}
-TEST(GpuImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
+TEST_P(GpuImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1167,17 +1073,18 @@ TEST(GpuImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
}
-TEST(GpuImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
+TEST_P(GpuImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
DrawImage draw_image(
- image, SkIRect::MakeXYWH(150, 150, image->width(), image->height()),
- quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ CreatePaintImage(image),
+ SkIRect::MakeXYWH(150, 150, image->width(), image->height()), quality,
+ CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1196,18 +1103,19 @@ TEST(GpuImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
}
-TEST(GpuImageDecodeCacheTest, CanceledTasksDoNotCountAgainstBudget) {
+TEST_P(GpuImageDecodeCacheTest, CanceledTasksDoNotCountAgainstBudget) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(
- image, SkIRect::MakeXYWH(0, 0, image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeXYWH(0, 0, image->width(), image->height()),
+ quality,
+ CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1225,25 +1133,18 @@ TEST(GpuImageDecodeCacheTest, CanceledTasksDoNotCountAgainstBudget) {
EXPECT_EQ(0u, cache.GetBytesUsedForTesting());
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ShouldAggressivelyFreeResources \
- DISABLED_ShouldAggressivelyFreeResources
-#else
-#define MAYBE_ShouldAggressivelyFreeResources ShouldAggressivelyFreeResources
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_ShouldAggressivelyFreeResources) {
+TEST_P(GpuImageDecodeCacheTest, ShouldAggressivelyFreeResources) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
{
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1296,26 +1197,19 @@ TEST(GpuImageDecodeCacheTest, MAYBE_ShouldAggressivelyFreeResources) {
}
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_OrphanedImagesFreeOnReachingZeroRefs \
- DISABLED_OrphanedImagesFreeOnReachingZeroRefs
-#else
-#define MAYBE_OrphanedImagesFreeOnReachingZeroRefs \
- OrphanedImagesFreeOnReachingZeroRefs
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedImagesFreeOnReachingZeroRefs) {
+TEST_P(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
// Create a downscaled image.
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1330,8 +1224,9 @@ TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedImagesFreeOnReachingZeroRefs) {
// Create a larger version of |first_image|, this should immediately free the
// memory used by |first_image| for the smaller scale.
DrawImage second_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -1361,26 +1256,19 @@ TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedImagesFreeOnReachingZeroRefs) {
cache.GetDrawImageSizeForTesting(second_draw_image));
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_OrphanedZeroRefImagesImmediatelyDeleted \
- DISABLED_OrphanedZeroRefImagesImmediatelyDeleted
-#else
-#define MAYBE_OrphanedZeroRefImagesImmediatelyDeleted \
- OrphanedZeroRefImagesImmediatelyDeleted
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedZeroRefImagesImmediatelyDeleted) {
+TEST_P(GpuImageDecodeCacheTest, OrphanedZeroRefImagesImmediatelyDeleted) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
// Create a downscaled image.
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1399,8 +1287,9 @@ TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedZeroRefImagesImmediatelyDeleted) {
// Create a larger version of |first_image|, this should immediately free the
// memory used by |first_image| for the smaller scale.
DrawImage second_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -1419,22 +1308,16 @@ TEST(GpuImageDecodeCacheTest, MAYBE_OrphanedZeroRefImagesImmediatelyDeleted) {
cache.GetDrawImageSizeForTesting(second_draw_image));
}
-// crbug.com/709341.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_QualityCappedAtMedium DISABLED_QualityCappedAtMedium
-#else
-#define MAYBE_QualityCappedAtMedium QualityCappedAtMedium
-#endif
-TEST(GpuImageDecodeCacheTest, MAYBE_QualityCappedAtMedium) {
+TEST_P(GpuImageDecodeCacheTest, QualityCappedAtMedium) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
SkMatrix matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f), is_decomposable);
// Create an image with kLow_FilterQuality.
- DrawImage low_draw_image(image,
+ DrawImage low_draw_image(CreatePaintImage(image),
SkIRect::MakeWH(image->width(), image->height()),
kLow_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> low_task;
@@ -1446,7 +1329,7 @@ TEST(GpuImageDecodeCacheTest, MAYBE_QualityCappedAtMedium) {
// Get the same image at kMedium_FilterQuality. We can't re-use low, so we
// should get a new task/ref.
DrawImage medium_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
kMedium_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> medium_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -1457,7 +1340,7 @@ TEST(GpuImageDecodeCacheTest, MAYBE_QualityCappedAtMedium) {
// Get the same image at kHigh_FilterQuality. We should re-use medium.
DrawImage large_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
kHigh_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> large_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -1477,19 +1360,19 @@ TEST(GpuImageDecodeCacheTest, MAYBE_QualityCappedAtMedium) {
// Ensure that switching to a mipped version of an image after the initial
// cache entry creation doesn't cause a buffer overflow/crash.
-TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawMipUsageChange) {
+TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawMipUsageChange) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
// Create an image decode task and cache entry that does not need mips.
sk_sp<SkImage> image = CreateImage(4000, 4000);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -1510,24 +1393,25 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawMipUsageChange) {
// Do an at-raster decode of the above image that *does* require mips.
DrawImage draw_image_mips(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.6f, 0.6f), is_decomposable),
DefaultColorSpace());
DecodedDrawImage decoded_draw_image =
cache.GetDecodedImageForDraw(draw_image_mips);
cache.DrawWithImageFinished(draw_image_mips, decoded_draw_image);
}
-TEST(GpuImageDecodeCacheTest, MemoryStateSuspended) {
+TEST_P(GpuImageDecodeCacheTest, MemoryStateSuspended) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
// First Insert an image into our cache.
sk_sp<SkImage> image = CreateImage(1, 1);
bool is_decomposable = true;
SkMatrix matrix = CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
kLow_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1588,15 +1472,16 @@ TEST(GpuImageDecodeCacheTest, MemoryStateSuspended) {
cache.UnrefImage(draw_image);
}
-TEST(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) {
+TEST_P(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
sk_sp<SkImage> image = CreateImage(1, 1);
bool is_decomposable = true;
SkMatrix matrix = CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
kLow_SkFilterQuality, matrix, DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1614,7 +1499,7 @@ TEST(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) {
cache.UnrefImage(draw_image);
}
-TEST(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) {
+TEST_P(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) {
// Setup - Image cache has a normal working set, but zero cache size.
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
@@ -1626,10 +1511,10 @@ TEST(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) {
// Add an image to the cache. Due to normal working set, this should produce
// a task and a ref.
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -1669,7 +1554,7 @@ TEST(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) {
cache.UnrefImage(draw_image);
}
-TEST(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) {
+TEST_P(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) {
// Cache will fit one (but not two) 100x100 images.
size_t cache_size = 190 * 100 * 4;
@@ -1681,16 +1566,17 @@ TEST(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) {
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
sk_sp<SkImage> image2 = CreateImage(100, 100);
- DrawImage draw_image2(
- image2, SkIRect::MakeWH(image2->width(), image2->height()), quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image2(CreatePaintImage(image2),
+ SkIRect::MakeWH(image2->width(), image2->height()),
+ quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ DefaultColorSpace());
// Add an image to the cache and un-ref it.
{
@@ -1762,17 +1648,18 @@ TEST(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) {
}
}
-TEST(GpuImageDecodeCacheTest, ClearCache) {
+TEST_P(GpuImageDecodeCacheTest, ClearCache) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
for (int i = 0; i < 10; ++i) {
sk_sp<SkImage> image = CreateImage(100, 100);
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
+ CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()), quality,
CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1797,10 +1684,10 @@ TEST(GpuImageDecodeCacheTest, ClearCache) {
EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u);
}
-TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
+TEST_P(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
auto context_provider = TestContextProvider::Create();
context_provider->BindToCurrentThread();
- TestGpuImageDecodeCache cache(context_provider.get());
+ TestGpuImageDecodeCache cache(context_provider.get(), GetParam());
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
@@ -1809,9 +1696,9 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- color_space_a);
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_a);
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
first_draw_image, ImageDecodeCache::TracingInfo(), &first_task);
@@ -1819,9 +1706,9 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
EXPECT_TRUE(first_task);
DrawImage second_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- color_space_b);
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_b);
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
second_draw_image, ImageDecodeCache::TracingInfo(), &second_task);
@@ -1830,9 +1717,9 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
EXPECT_TRUE(first_task.get() != second_task.get());
DrawImage third_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
- color_space_a);
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_a);
scoped_refptr<TileTask> third_task;
need_unref = cache.GetTaskForImageAndRef(
third_draw_image, ImageDecodeCache::TracingInfo(), &third_task);
@@ -1849,5 +1736,10 @@ TEST(GpuImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
cache.UnrefImage(third_draw_image);
}
+INSTANTIATE_TEST_CASE_P(GpuImageDecodeCacheTests,
+ GpuImageDecodeCacheTest,
+ ::testing::Values(ResourceFormat::RGBA_8888,
+ ResourceFormat::RGBA_4444));
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/tiles/image_controller.cc b/chromium/cc/tiles/image_controller.cc
index ae81e64f96d..e8021e4264e 100644
--- a/chromium/cc/tiles/image_controller.cc
+++ b/chromium/cc/tiles/image_controller.cc
@@ -127,12 +127,15 @@ void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) {
SetPredecodeImages(std::vector<DrawImage>(),
ImageDecodeCache::TracingInfo());
StopWorkerTasks();
+ image_cache_max_limit_bytes_ = 0u;
}
cache_ = cache;
- if (cache_)
+ if (cache_) {
+ image_cache_max_limit_bytes_ = cache_->GetMaximumMemoryLimitBytes();
GenerateTasksForOrphanedRequests();
+ }
}
void ImageController::GetTasksForImagesAndRef(
@@ -192,8 +195,12 @@ ImageController::ImageDecodeRequestId ImageController::QueueImageDecode(
DCHECK(image);
bool is_image_lazy = image->isLazyGenerated();
auto image_bounds = image->bounds();
- DrawImage draw_image(std::move(image), image_bounds, kNone_SkFilterQuality,
- SkMatrix::I(), target_color_space);
+ // TODO(khushalsagar): Eliminate the use of an incorrect id here and have all
+ // call-sites provide PaintImage to the ImageController.
+ DrawImage draw_image(
+ PaintImage(PaintImage::kUnknownStableId,
+ sk_sp<SkImage>(const_cast<SkImage*>(image.release()))),
+ image_bounds, kNone_SkFilterQuality, SkMatrix::I(), target_color_space);
// Get the tasks for this decode.
scoped_refptr<TileTask> task;
diff --git a/chromium/cc/tiles/image_controller.h b/chromium/cc/tiles/image_controller.h
index d9253368bb8..30e93f68b18 100644
--- a/chromium/cc/tiles/image_controller.h
+++ b/chromium/cc/tiles/image_controller.h
@@ -9,9 +9,11 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
#include "base/threading/simple_thread.h"
#include "cc/base/unique_notifier.h"
#include "cc/cc_export.h"
@@ -55,6 +57,13 @@ class CC_EXPORT ImageController {
virtual ImageDecodeRequestId QueueImageDecode(
sk_sp<const SkImage> image,
const ImageDecodedCallback& callback);
+ size_t image_cache_max_limit_bytes() const {
+ return image_cache_max_limit_bytes_;
+ }
+
+ void SetMaxImageCacheLimitBytesForTesting(size_t bytes) {
+ image_cache_max_limit_bytes_ = bytes;
+ }
protected:
scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
@@ -93,9 +102,10 @@ class CC_EXPORT ImageController {
std::vector<DrawImage> predecode_locked_images_;
static ImageDecodeRequestId s_next_image_decode_queue_id_;
- std::unordered_map<ImageDecodeRequestId, DrawImage> requested_locked_images_;
+ base::flat_map<ImageDecodeRequestId, DrawImage> requested_locked_images_;
base::SequencedTaskRunner* origin_task_runner_ = nullptr;
+ size_t image_cache_max_limit_bytes_ = 0u;
// The variables defined below this lock (aside from weak_ptr_factory_) can
// only be accessed when the lock is acquired.
diff --git a/chromium/cc/tiles/image_controller_unittest.cc b/chromium/cc/tiles/image_controller_unittest.cc
index 3a89afb2b64..a4a565774a4 100644
--- a/chromium/cc/tiles/image_controller_unittest.cc
+++ b/chromium/cc/tiles/image_controller_unittest.cc
@@ -80,7 +80,7 @@ class WorkerTaskRunner : public base::SequencedTaskRunner {
return true;
}
- bool RunsTasksOnCurrentThread() const override { return false; }
+ bool RunsTasksInCurrentSequence() const override { return false; }
protected:
~WorkerTaskRunner() override {
@@ -129,6 +129,9 @@ class TestableCache : public ImageDecodeCache {
void SetShouldAggressivelyFreeResources(
bool aggressively_free_resources) override {}
void ClearCache() override {}
+ size_t GetMaximumMemoryLimitBytes() const override {
+ return 256 * 1024 * 1024;
+ }
int number_of_refs() const { return number_of_refs_; }
void SetTaskToUse(scoped_refptr<TileTask> task) { task_to_use_ = task; }
diff --git a/chromium/cc/tiles/image_decode_cache.h b/chromium/cc/tiles/image_decode_cache.h
index ca1f41e4cd9..1b550a6b06e 100644
--- a/chromium/cc/tiles/image_decode_cache.h
+++ b/chromium/cc/tiles/image_decode_cache.h
@@ -96,6 +96,12 @@ class CC_EXPORT ImageDecodeCache {
// Clears all elements from the cache.
virtual void ClearCache() = 0;
+
+ // Returns the maximum amount of memory we would be able to lock. This ignores
+ // any temporary states, such as throttled, and return the maximum possible
+ // memory. It is used as an esimate of whether an image can fit into the
+ // locked budget before creating a task.
+ virtual size_t GetMaximumMemoryLimitBytes() const = 0;
};
} // namespace cc
diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc
index 344cb32b6c0..2a20ddcc2e9 100644
--- a/chromium/cc/tiles/picture_layer_tiling.cc
+++ b/chromium/cc/tiles/picture_layer_tiling.cc
@@ -11,7 +11,7 @@
#include <limits>
#include <set>
-#include "base/containers/small_map.h"
+#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
@@ -257,12 +257,8 @@ void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation,
// twin, so it's slated for removal in the future.
if (live_tiles_rect_.IsEmpty())
return;
- // Pick 16 for the size of the SmallMap before it promotes to a unordered_map.
- // 4x4 tiles should cover most small invalidations, and walking a vector of
- // 16 is fast enough. If an invalidation is huge we will fall back to a
- // unordered_map instead of a vector in the SmallMap.
- base::SmallMap<std::unordered_map<TileMapKey, gfx::Rect, TileMapKeyHash>, 16>
- remove_tiles;
+
+ base::flat_map<TileMapKey, gfx::Rect> remove_tiles;
gfx::Rect expanded_live_tiles_rect =
tiling_data_.ExpandRectToTileBounds(live_tiles_rect_);
for (Region::Iterator iter(layer_invalidation); iter.has_rect();
@@ -380,9 +376,8 @@ PictureLayerTiling::CoverageIterator::CoverageIterator(
const gfx::Rect& coverage_rect)
: tiling_(tiling),
coverage_rect_(coverage_rect),
- coverage_to_content_(
- gfx::PreScaleAxisTransform2d(tiling->raster_transform(),
- 1.f / coverage_scale)) {
+ coverage_to_content_(tiling->raster_transform().scale() / coverage_scale,
+ tiling->raster_transform().translation()) {
DCHECK(tiling_);
// In order to avoid artifacts in geometry_rect scaling and clamping to ints,
// the |coverage_scale| should always be at least as big as the tiling's
@@ -439,25 +434,70 @@ PictureLayerTiling::CoverageIterator::operator++() {
return *this;
bool first_time = tile_i_ < left_;
- bool new_row = false;
- tile_i_++;
- if (tile_i_ > right_) {
- tile_i_ = left_;
- tile_j_++;
- new_row = true;
- if (tile_j_ > bottom_) {
- current_tile_ = NULL;
- return *this;
+ while (true) {
+ bool new_row = false;
+ tile_i_++;
+ if (tile_i_ > right_) {
+ tile_i_ = left_;
+ tile_j_++;
+ new_row = true;
+ if (tile_j_ > bottom_) {
+ current_tile_ = NULL;
+ break;
+ }
}
- }
- current_tile_ = tiling_->TileAt(tile_i_, tile_j_);
+ DCHECK_LT(tile_i_, tiling_->tiling_data_.num_tiles_x());
+ DCHECK_LT(tile_j_, tiling_->tiling_data_.num_tiles_y());
+ current_tile_ = tiling_->TileAt(tile_i_, tile_j_);
+
+ gfx::Rect geometry_rect_candidate = ComputeGeometryRect();
+
+ // This can happen due to floating point inprecision when calculating the
+ // |wanted_texels| area in the constructor.
+ if (geometry_rect_candidate.IsEmpty())
+ continue;
+
+ gfx::Rect last_geometry_rect = current_geometry_rect_;
+ current_geometry_rect_ = geometry_rect_candidate;
+
+ if (first_time)
+ break;
+
+ // Iteration happens left->right, top->bottom. Running off the bottom-right
+ // edge is handled by the intersection above with dest_rect_. Here we make
+ // sure that the new current geometry rect doesn't overlap with the last.
+ int min_left;
+ int min_top;
+ if (new_row) {
+ min_left = coverage_rect_.x();
+ min_top = last_geometry_rect.bottom();
+ } else {
+ min_left = last_geometry_rect.right();
+ min_top = last_geometry_rect.y();
+ }
+
+ int inset_left = std::max(0, min_left - current_geometry_rect_.x());
+ int inset_top = std::max(0, min_top - current_geometry_rect_.y());
+ current_geometry_rect_.Inset(inset_left, inset_top, 0, 0);
+
+#if DCHECK_IS_ON()
+ if (!new_row) {
+ DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x());
+ DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom());
+ DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y());
+ }
+#endif
+ break;
+ }
+ return *this;
+}
+
+gfx::Rect PictureLayerTiling::CoverageIterator::ComputeGeometryRect() const {
// Calculate the current geometry rect. As we reserved overlap between tiles
// to accommodate bilinear filtering and rounding errors in destination
// space, the geometry rect might overlap on the edges.
- gfx::Rect last_geometry_rect = current_geometry_rect_;
-
gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_);
{
// Adjust tile extent to accommodate numerical errors.
@@ -474,7 +514,7 @@ PictureLayerTiling::CoverageIterator::operator++() {
// Convert texel_extent to coverage scale, which is what we have to report
// geometry_rect in.
- current_geometry_rect_ =
+ gfx::Rect candidate =
gfx::ToEnclosedRect(coverage_to_content_.InverseMapRect(texel_extent));
{
// Adjust external edges to cover the whole layer in dest space.
@@ -486,48 +526,18 @@ PictureLayerTiling::CoverageIterator::operator++() {
// sampled as the AA fragment shader clamps sample coordinate and
// antialiasing itself.
const TilingData& data = tiling_->tiling_data_;
- current_geometry_rect_.Inset(tile_i_ ? 0 : -current_geometry_rect_.x(),
- tile_j_ ? 0 : -current_geometry_rect_.y(),
- (tile_i_ != data.num_tiles_x() - 1)
- ? 0
- : current_geometry_rect_.right() -
- coverage_rect_max_bounds_.width(),
- (tile_j_ != data.num_tiles_y() - 1)
- ? 0
- : current_geometry_rect_.bottom() -
- coverage_rect_max_bounds_.height());
+ candidate.Inset(
+ tile_i_ ? 0 : -candidate.x(), tile_j_ ? 0 : -candidate.y(),
+ (tile_i_ != data.num_tiles_x() - 1)
+ ? 0
+ : candidate.right() - coverage_rect_max_bounds_.width(),
+ (tile_j_ != data.num_tiles_y() - 1)
+ ? 0
+ : candidate.bottom() - coverage_rect_max_bounds_.height());
}
- current_geometry_rect_.Intersect(coverage_rect_);
- DCHECK(!current_geometry_rect_.IsEmpty());
-
- if (first_time)
- return *this;
-
- // Iteration happens left->right, top->bottom. Running off the bottom-right
- // edge is handled by the intersection above with dest_rect_. Here we make
- // sure that the new current geometry rect doesn't overlap with the last.
- int min_left;
- int min_top;
- if (new_row) {
- min_left = coverage_rect_.x();
- min_top = last_geometry_rect.bottom();
- } else {
- min_left = last_geometry_rect.right();
- min_top = last_geometry_rect.y();
- }
-
- int inset_left = std::max(0, min_left - current_geometry_rect_.x());
- int inset_top = std::max(0, min_top - current_geometry_rect_.y());
- current_geometry_rect_.Inset(inset_left, inset_top, 0, 0);
-
- if (!new_row) {
- DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x());
- DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom());
- DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y());
- }
-
- return *this;
+ candidate.Intersect(coverage_rect_);
+ return candidate;
}
gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const {
@@ -808,6 +818,39 @@ bool PictureLayerTiling::IsTileRequiredForDraw(const Tile* tile) const {
return true;
}
+bool PictureLayerTiling::ShouldDecodeCheckeredImagesForTile(
+ const Tile* tile) const {
+ // If this is the pending tree and the tile is not occluded, any checkered
+ // images on this tile should be decoded.
+ if (tree_ == PENDING_TREE)
+ return !IsTileOccludedOnCurrentTree(tile);
+
+ DCHECK_EQ(tree_, ACTIVE_TREE);
+ const PictureLayerTiling* pending_twin =
+ client_->GetPendingOrActiveTwinTiling(this);
+
+ // If we don't have a pending twin, then 2 cases are possible. Either we don't
+ // have a pending tree, in which case we should be decoding images for tiles
+ // which are unoccluded.
+ // If we do have a pending tree, then not having a twin implies that this
+ // tiling will be evicted upon activation. TODO(khushalsagar): Plumb this
+ // information here and return false for this case.
+ if (!pending_twin)
+ return !IsTileOccludedOnCurrentTree(tile);
+
+ // If the tile will be replaced upon activation, then we don't need to process
+ // it for checkered images. Since once the pending tree is activated, it is
+ // the new active tree's content that we will invalidate and replace once the
+ // decode finishes.
+ if (!TilingMatchesTileIndices(pending_twin) ||
+ pending_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index())) {
+ return false;
+ }
+
+ // Ask the pending twin if this tile will become occluded upon activation.
+ return !pending_twin->IsTileOccludedOnCurrentTree(tile);
+}
+
void PictureLayerTiling::UpdateRequiredStatesOnTile(Tile* tile) const {
tile->set_required_for_activation(IsTileRequiredForActivation(tile));
tile->set_required_for_draw(IsTileRequiredForDraw(tile));
@@ -836,7 +879,8 @@ PrioritizedTile PictureLayerTiling::MakePrioritizedTile(
tile_priority.distance_to_visible >
0.5f * max_skewport_extent_in_screen_space_);
return PrioritizedTile(tile, this, tile_priority, IsTileOccluded(tile),
- process_for_images_only);
+ process_for_images_only,
+ ShouldDecodeCheckeredImagesForTile(tile));
}
std::map<const Tile*, PrioritizedTile>
diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h
index ecf1974efa8..d49d22ed23f 100644
--- a/chromium/cc/tiles/picture_layer_tiling.h
+++ b/chromium/cc/tiles/picture_layer_tiling.h
@@ -63,6 +63,9 @@ struct TileMapKey {
bool operator==(const TileMapKey& other) const {
return index_x == other.index_x && index_y == other.index_y;
}
+ bool operator<(const TileMapKey& other) const {
+ return std::tie(index_x, index_y) < std::tie(other.index_x, other.index_y);
+ }
int index_x;
int index_y;
@@ -105,6 +108,10 @@ class CC_EXPORT PictureLayerTiling {
bool IsTileRequiredForActivation(const Tile* tile) const;
bool IsTileRequiredForDraw(const Tile* tile) const;
+ // Returns true if the tile should be processed for decoding images skipped
+ // during rasterization.
+ bool ShouldDecodeCheckeredImagesForTile(const Tile* tile) const;
+
void set_resolution(TileResolution resolution) {
resolution_ = resolution;
may_contain_low_resolution_tiles_ |= resolution == LOW_RESOLUTION;
@@ -230,6 +237,8 @@ class CC_EXPORT PictureLayerTiling {
int j() const { return tile_j_; }
private:
+ gfx::Rect ComputeGeometryRect() const;
+
const PictureLayerTiling* tiling_ = nullptr;
gfx::Size coverage_rect_max_bounds_;
gfx::Rect coverage_rect_;
diff --git a/chromium/cc/tiles/picture_layer_tiling_set.h b/chromium/cc/tiles/picture_layer_tiling_set.h
index 30c1d2967d7..ed71afa177d 100644
--- a/chromium/cc/tiles/picture_layer_tiling_set.h
+++ b/chromium/cc/tiles/picture_layer_tiling_set.h
@@ -107,6 +107,9 @@ class CC_EXPORT PictureLayerTilingSet {
// the aspect ratio.
float GetMaximumContentsScale() const;
+ // Remove one tiling.
+ void Remove(PictureLayerTiling* tiling);
+
// Removes all tilings with a contents scale key < |minimum_scale_key|.
void RemoveTilingsBelowScaleKey(float minimum_scale_key);
@@ -226,8 +229,6 @@ class CC_EXPORT PictureLayerTilingSet {
scoped_refptr<RasterSource> raster_source,
const Region& layer_invalidation);
- // Remove one tiling.
- void Remove(PictureLayerTiling* tiling);
void VerifyTilings(const PictureLayerTilingSet* pending_twin_set) const;
bool TilingsNeedUpdate(const gfx::Rect& required_rect_in_layer_space,
diff --git a/chromium/cc/tiles/picture_layer_tiling_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_unittest.cc
index f6185bf3638..39d5867a0a9 100644
--- a/chromium/cc/tiles/picture_layer_tiling_unittest.cc
+++ b/chromium/cc/tiles/picture_layer_tiling_unittest.cc
@@ -1255,5 +1255,33 @@ TEST_F(PictureLayerTilingIteratorTest, FractionalTranslatedTilingOverflow) {
EXPECT_FALSE(++iter);
}
+TEST_F(PictureLayerTilingIteratorTest, EdgeCaseLargeIntBounds) {
+ gfx::Size tile_size(256, 256);
+ float scale = 7352.331055f;
+ gfx::Size layer_bounds(292082, 26910);
+ gfx::Rect coverage_rect(2104641536, 522015, 29440, 66172);
+ Initialize(tile_size, scale, layer_bounds);
+ int count = 0;
+ for (PictureLayerTiling::CoverageIterator
+ iter(tiling_.get(), scale, coverage_rect);
+ iter && count < 200; ++count, ++iter) {
+ EXPECT_FALSE(iter.geometry_rect().IsEmpty());
+ }
+}
+
+TEST_F(PictureLayerTilingIteratorTest, EdgeCaseLargeIntBounds2) {
+ gfx::RectF rect(2104670720.f, 522014.5f, 192.f, 1.f);
+ gfx::Size tile_size(256, 256);
+ float scale = 7352.331055f;
+ gfx::Size layer_bounds(292082, 26910);
+ gfx::Rect coverage_rect(2104670720, 522015, 192, 1);
+ Initialize(tile_size, scale, layer_bounds);
+ for (PictureLayerTiling::CoverageIterator iter(tiling_.get(), scale,
+ coverage_rect);
+ iter; ++iter) {
+ EXPECT_FALSE(iter.geometry_rect().IsEmpty());
+ }
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/tiles/prioritized_tile.cc b/chromium/cc/tiles/prioritized_tile.cc
index a76963d340e..cd6e901959d 100644
--- a/chromium/cc/tiles/prioritized_tile.cc
+++ b/chromium/cc/tiles/prioritized_tile.cc
@@ -15,12 +15,15 @@ PrioritizedTile::PrioritizedTile(Tile* tile,
const PictureLayerTiling* source_tiling,
const TilePriority& priority,
bool is_occluded,
- bool is_process_for_images_only)
+ bool is_process_for_images_only,
+ bool should_decode_checkered_images_for_tile)
: tile_(tile),
source_tiling_(source_tiling),
priority_(priority),
is_occluded_(is_occluded),
- is_process_for_images_only_(is_process_for_images_only) {}
+ is_process_for_images_only_(is_process_for_images_only),
+ should_decode_checkered_images_for_tile_(
+ should_decode_checkered_images_for_tile) {}
PrioritizedTile::~PrioritizedTile() = default;
diff --git a/chromium/cc/tiles/prioritized_tile.h b/chromium/cc/tiles/prioritized_tile.h
index 7decc73cca1..a2996602c7f 100644
--- a/chromium/cc/tiles/prioritized_tile.h
+++ b/chromium/cc/tiles/prioritized_tile.h
@@ -24,7 +24,8 @@ class CC_EXPORT PrioritizedTile {
const PictureLayerTiling* source_tiling,
const TilePriority& priority,
bool is_occluded,
- bool is_process_for_images_only);
+ bool is_process_for_images_only,
+ bool should_decode_checkered_images_for_tile);
~PrioritizedTile();
Tile* tile() const { return tile_; }
@@ -36,6 +37,9 @@ class CC_EXPORT PrioritizedTile {
bool is_process_for_images_only() const {
return is_process_for_images_only_;
}
+ bool should_decode_checkered_images_for_tile() const {
+ return should_decode_checkered_images_for_tile_;
+ }
void AsValueInto(base::trace_event::TracedValue* value) const;
@@ -45,6 +49,7 @@ class CC_EXPORT PrioritizedTile {
TilePriority priority_;
bool is_occluded_ = false;
bool is_process_for_images_only_ = false;
+ bool should_decode_checkered_images_for_tile_ = false;
};
} // namespace cc
diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc
index 716d1f45ef3..c3b6eb7d4f0 100644
--- a/chromium/cc/tiles/software_image_decode_cache.cc
+++ b/chromium/cc/tiles/software_image_decode_cache.cc
@@ -250,7 +250,7 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal(
// image does not fit into the budget, then we don't ref this image, since it
// will be decoded at raster time which is when it will be temporarily put in
// the cache.
- ImageKey key = ImageKey::FromDrawImage(image);
+ ImageKey key = ImageKey::FromDrawImage(image, format_);
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::GetTaskForImageAndRef", "key",
key.ToString());
@@ -345,7 +345,7 @@ void SoftwareImageDecodeCache::UnrefImage(const DrawImage& image) {
// 2a. The image isn't in the locked cache because we didn't get to decode
// it yet (or failed to decode it).
// 2b. Unlock the image but keep it in list.
- const ImageKey& key = ImageKey::FromDrawImage(image);
+ const ImageKey& key = ImageKey::FromDrawImage(image, format_);
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::UnrefImage", "key", key.ToString());
@@ -445,11 +445,11 @@ SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key,
case kNone_SkFilterQuality:
case kLow_SkFilterQuality:
if (key.should_use_subrect())
- return GetSubrectImageDecode(key, std::move(image));
+ return GetSubrectImageDecode(key, draw_image.paint_image());
return GetOriginalSizeImageDecode(key, std::move(image));
case kMedium_SkFilterQuality:
case kHigh_SkFilterQuality:
- return GetScaledImageDecode(key, std::move(image));
+ return GetScaledImageDecode(key, draw_image.paint_image());
default:
NOTREACHED();
return nullptr;
@@ -458,7 +458,7 @@ SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key,
DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDraw(
const DrawImage& draw_image) {
- ImageKey key = ImageKey::FromDrawImage(draw_image);
+ ImageKey key = ImageKey::FromDrawImage(draw_image, format_);
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::GetDecodedImageForDraw", "key",
key.ToString());
@@ -611,15 +611,16 @@ SoftwareImageDecodeCache::GetOriginalSizeImageDecode(
std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key,
- sk_sp<const SkImage> image) {
+ const PaintImage& image) {
// Construct a key to use in GetDecodedImageForDrawInternal().
// This allows us to reuse an image in any cache if available.
- gfx::Rect full_image_rect(image->width(), image->height());
- DrawImage original_size_draw_image(
- std::move(image), gfx::RectToSkIRect(full_image_rect),
- kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space());
+ gfx::Rect full_image_rect(image.sk_image()->width(),
+ image.sk_image()->height());
+ DrawImage original_size_draw_image(image, gfx::RectToSkIRect(full_image_rect),
+ kNone_SkFilterQuality, SkMatrix::I(),
+ key.target_color_space());
ImageKey original_size_key =
- ImageKey::FromDrawImage(original_size_draw_image);
+ ImageKey::FromDrawImage(original_size_draw_image, format_);
sk_sp<SkColorSpace> target_color_space =
key.target_color_space().ToSkColorSpace();
@@ -674,15 +675,16 @@ SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key,
std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key,
- sk_sp<const SkImage> image) {
+ const PaintImage& image) {
// Construct a key to use in GetDecodedImageForDrawInternal().
// This allows us to reuse an image in any cache if available.
- gfx::Rect full_image_rect(image->width(), image->height());
- DrawImage original_size_draw_image(
- std::move(image), gfx::RectToSkIRect(full_image_rect),
- kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space());
+ gfx::Rect full_image_rect(image.sk_image()->width(),
+ image.sk_image()->height());
+ DrawImage original_size_draw_image(image, gfx::RectToSkIRect(full_image_rect),
+ kNone_SkFilterQuality, SkMatrix::I(),
+ key.target_color_space());
ImageKey original_size_key =
- ImageKey::FromDrawImage(original_size_draw_image);
+ ImageKey::FromDrawImage(original_size_draw_image, format_);
sk_sp<SkColorSpace> target_color_space =
key.target_color_space().ToSkColorSpace();
@@ -745,8 +747,8 @@ void SoftwareImageDecodeCache::DrawWithImageFinished(
const DecodedDrawImage& decoded_image) {
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::DrawWithImageFinished", "key",
- ImageKey::FromDrawImage(image).ToString());
- ImageKey key = ImageKey::FromDrawImage(image);
+ ImageKey::FromDrawImage(image, format_).ToString());
+ ImageKey key = ImageKey::FromDrawImage(image, format_);
if (!decoded_image.image())
return;
@@ -839,6 +841,10 @@ void SoftwareImageDecodeCache::ClearCache() {
ReduceCacheUsageUntilWithinLimit(0);
}
+size_t SoftwareImageDecodeCache::GetMaximumMemoryLimitBytes() const {
+ return locked_images_budget_.total_limit_bytes();
+}
+
void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key,
DecodeTaskType task_type) {
base::AutoLock lock(lock_);
@@ -898,7 +904,8 @@ void SoftwareImageDecodeCache::DumpImageMemoryForCache(
}
// SoftwareImageDecodeCacheKey
-ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) {
+ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image,
+ ResourceFormat format) {
const SkSize& scale = image.scale();
// If the src_rect falls outside of the image, we need to clip it since
// otherwise we might end up with uninitialized memory in the decode process.
@@ -915,16 +922,22 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) {
// If we're not going to do a scale, we can use low filter quality. Note that
// checking if the sizes are the same is better than checking if scale is 1.f,
// because even non-1 scale can result in the same (rounded) width/height.
- // If either dimension is a downscale, then use mipmaps (medium filter
- // quality).
+ // If either dimension is a downscale, and the quality is not None (in which
+ // case we need to preserve the pixelated scale), then use mipmaps (medium
+ // filter quality).
if (target_size.width() == src_rect.width() &&
target_size.height() == src_rect.height()) {
quality = std::min(quality, kLow_SkFilterQuality);
- } else if (target_size.width() < src_rect.width() ||
- target_size.height() < src_rect.height()) {
- quality = std::min(quality, kMedium_SkFilterQuality);
+ } else if (quality != kNone_SkFilterQuality &&
+ (target_size.width() < src_rect.width() ||
+ target_size.height() < src_rect.height())) {
+ quality = kMedium_SkFilterQuality;
}
+ // Skia doesn't scale an RGBA_4444 format, so always use the original decode.
+ if (format == RGBA_4444)
+ quality = std::min(quality, kLow_SkFilterQuality);
+
// Drop from high to medium if the the matrix we applied wasn't decomposable,
// or if the scaled image will be too large.
if (quality == kHigh_SkFilterQuality) {
diff --git a/chromium/cc/tiles/software_image_decode_cache.h b/chromium/cc/tiles/software_image_decode_cache.h
index 1d3e2ac75c4..755770b4bce 100644
--- a/chromium/cc/tiles/software_image_decode_cache.h
+++ b/chromium/cc/tiles/software_image_decode_cache.h
@@ -36,7 +36,8 @@ namespace cc {
// in the cache multiple times at different scales and filter qualities.
class CC_EXPORT ImageDecodeCacheKey {
public:
- static ImageDecodeCacheKey FromDrawImage(const DrawImage& image);
+ static ImageDecodeCacheKey FromDrawImage(const DrawImage& image,
+ ResourceFormat format);
ImageDecodeCacheKey(const ImageDecodeCacheKey& other);
@@ -140,6 +141,7 @@ class CC_EXPORT SoftwareImageDecodeCache
void SetShouldAggressivelyFreeResources(
bool aggressively_free_resources) override {}
void ClearCache() override;
+ size_t GetMaximumMemoryLimitBytes() const override;
// Decode the given image and store it in the cache. This is only called by an
// image decode task from a worker thread.
@@ -220,7 +222,7 @@ class CC_EXPORT SoftwareImageDecodeCache
size_t GetCurrentUsageSafe() const;
private:
- size_t limit_bytes_;
+ const size_t limit_bytes_;
base::CheckedNumeric<size_t> current_usage_bytes_;
};
@@ -263,17 +265,15 @@ class CC_EXPORT SoftwareImageDecodeCache
// data, which ensures that we cache an unlocked version of the original image
// in case we need to extract multiple subrects (as would be the case in an
// atlas).
- std::unique_ptr<DecodedImage> GetSubrectImageDecode(
- const ImageKey& key,
- sk_sp<const SkImage> image);
+ std::unique_ptr<DecodedImage> GetSubrectImageDecode(const ImageKey& key,
+ const PaintImage& image);
// GetScaledImageDecode is called by DecodeImageInternal when the quality
// requires the image be scaled. Like DecodeImageInternal, it should be
// called with no lock acquired and it returns nullptr if the decoding or
// scaling failed.
- std::unique_ptr<DecodedImage> GetScaledImageDecode(
- const ImageKey& key,
- sk_sp<const SkImage> image);
+ std::unique_ptr<DecodedImage> GetScaledImageDecode(const ImageKey& key,
+ const PaintImage& image);
void RefImage(const ImageKey& key);
void RefAtRasterImage(const ImageKey& key);
@@ -306,6 +306,8 @@ class CC_EXPORT SoftwareImageDecodeCache
// The members below this comment can only be accessed if the lock is held to
// ensure that they are safe to access on multiple threads.
+ // The exception is accessing |locked_images_budget_.total_limit_bytes()|,
+ // which is const and thread safe.
base::Lock lock_;
// Decoded images and ref counts (predecode path).
diff --git a/chromium/cc/tiles/software_image_decode_cache_perftest.cc b/chromium/cc/tiles/software_image_decode_cache_perftest.cc
index 0267f20d4f4..3a4b93ff28a 100644
--- a/chromium/cc/tiles/software_image_decode_cache_perftest.cc
+++ b/chromium/cc/tiles/software_image_decode_cache_perftest.cc
@@ -56,7 +56,9 @@ class SoftwareImageDecodeCachePerfTest : public testing::Test {
auto& subrect = rect_subrect.second;
for (auto& scale : scales) {
images.emplace_back(
- CreateImage(rect.width(), rect.height()), subrect, quality,
+ PaintImage(PaintImage::GetNextId(),
+ CreateImage(rect.width(), rect.height())),
+ subrect, quality,
CreateMatrix(SkSize::Make(scale.first, scale.second)),
gfx::ColorSpace());
}
@@ -66,7 +68,7 @@ class SoftwareImageDecodeCachePerfTest : public testing::Test {
timer_.Reset();
do {
for (auto& image : images)
- ImageDecodeCacheKey::FromDrawImage(image);
+ ImageDecodeCacheKey::FromDrawImage(image, RGBA_8888);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
diff --git a/chromium/cc/tiles/software_image_decode_cache_unittest.cc b/chromium/cc/tiles/software_image_decode_cache_unittest.cc
index 7d26359ba3d..90aa66e48a2 100644
--- a/chromium/cc/tiles/software_image_decode_cache_unittest.cc
+++ b/chromium/cc/tiles/software_image_decode_cache_unittest.cc
@@ -50,39 +50,116 @@ SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) {
return matrix;
}
-TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQuality) {
+PaintImage::Id s_paint_image_id = PaintImage::GetNextId();
+
+PaintImage CreatePaintImage(sk_sp<SkImage> image) {
+ return PaintImage(s_paint_image_id, image);
+}
+
+TEST(SoftwareImageDecodeCacheTest, ImageKeyNoneQuality) {
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality qualities[] = {kNone_SkFilterQuality, kLow_SkFilterQuality};
- for (auto quality : qualities) {
- DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
+ kNone_SkFilterQuality,
+ CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
- EXPECT_EQ(image->uniqueID(), key.image_id());
- EXPECT_EQ(quality, key.filter_quality());
- EXPECT_EQ(100, key.target_size().width());
- EXPECT_EQ(100, key.target_size().height());
- EXPECT_TRUE(key.can_use_original_size_decode());
- // Since the original decode will be used, the locked_bytes is that of the
- // original image.
- EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
- }
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
+ EXPECT_EQ(image->uniqueID(), key.image_id());
+ EXPECT_EQ(kNone_SkFilterQuality, key.filter_quality());
+ EXPECT_EQ(100, key.target_size().width());
+ EXPECT_EQ(100, key.target_size().height());
+ EXPECT_TRUE(key.can_use_original_size_decode());
+ // Since the original decode will be used, the locked_bytes is that of the
+ // original image.
+ EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
}
-TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) {
+TEST(SoftwareImageDecodeCacheTest,
+ ImageKeyLowQualityIncreasedToMediumIfDownscale) {
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
+ kLow_SkFilterQuality,
+ CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
+ EXPECT_EQ(image->uniqueID(), key.image_id());
+ EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality());
+ EXPECT_EQ(100, key.target_size().width());
+ EXPECT_EQ(100, key.target_size().height());
+ EXPECT_FALSE(key.can_use_original_size_decode());
+ EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
+}
+
+TEST(SoftwareImageDecodeCacheTest, LowUnscalableFormatStaysLow) {
+ sk_sp<SkImage> image = CreateImage(100, 100);
+ bool is_decomposable = true;
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
+ kLow_SkFilterQuality,
CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_4444);
+ EXPECT_EQ(image->uniqueID(), key.image_id());
+ EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
+ EXPECT_EQ(100, key.target_size().width());
+ EXPECT_EQ(100, key.target_size().height());
+ EXPECT_TRUE(key.can_use_original_size_decode());
+ EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
+}
+
+TEST(SoftwareImageDecodeCacheTest, HighUnscalableFormatBecomesLow) {
+ sk_sp<SkImage> image = CreateImage(100, 100);
+ bool is_decomposable = true;
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
+ kHigh_SkFilterQuality,
+ CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
+
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_4444);
+ EXPECT_EQ(image->uniqueID(), key.image_id());
+ EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
+ EXPECT_EQ(100, key.target_size().width());
+ EXPECT_EQ(100, key.target_size().height());
+ EXPECT_TRUE(key.can_use_original_size_decode());
+ EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
+}
+
+TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityKeptLowIfUpscale) {
+ sk_sp<SkImage> image = CreateImage(100, 100);
+ bool is_decomposable = true;
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()),
+ kLow_SkFilterQuality,
+ CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
+
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
+ EXPECT_EQ(image->uniqueID(), key.image_id());
+ EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
+ EXPECT_EQ(100, key.target_size().width());
+ EXPECT_EQ(100, key.target_size().height());
+ EXPECT_TRUE(key.can_use_original_size_decode());
+ EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
+}
+
+TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) {
+ sk_sp<SkImage> image = CreateImage(100, 100);
+ bool is_decomposable = true;
+ SkFilterQuality quality = kMedium_SkFilterQuality;
+
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
+
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -96,12 +173,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfEnlarging) {
bool is_decomposable = true;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -115,12 +192,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfIdentity) {
bool is_decomposable = true;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -136,11 +213,11 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kMedium_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -156,11 +233,11 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kMedium_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -175,12 +252,12 @@ TEST(SoftwareImageDecodeCacheTest,
bool is_decomposable = false;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -194,12 +271,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_5Scale) {
bool is_decomposable = true;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(500, key.target_size().width());
@@ -213,12 +290,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_0cale) {
bool is_decomposable = true;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(500, key.target_size().width());
@@ -233,11 +310,11 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_75Scale) {
SkFilterQuality quality = kMedium_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(500, key.target_size().width());
@@ -251,12 +328,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_5Scale) {
bool is_decomposable = true;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(250, key.target_size().width());
@@ -271,11 +348,11 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_49Scale) {
SkFilterQuality quality = kMedium_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(250, key.target_size().width());
@@ -289,12 +366,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) {
bool is_decomposable = true;
SkFilterQuality quality = kMedium_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(62, key.target_size().width());
@@ -309,11 +386,11 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) {
SkFilterQuality quality = kMedium_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(7, key.target_size().width());
@@ -328,12 +405,12 @@ TEST(SoftwareImageDecodeCacheTest,
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -348,12 +425,12 @@ TEST(SoftwareImageDecodeCacheTest,
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality());
EXPECT_EQ(50, key.target_size().width());
@@ -367,12 +444,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyDowscalesHighQuality) {
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(quality, key.filter_quality());
EXPECT_EQ(250, key.target_size().width());
@@ -389,12 +466,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) {
// At least one dimension should scale down, so that medium quality doesn't
// become low.
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.9f, 2.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.9f, 2.f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality());
EXPECT_EQ(4555, key.target_size().width());
@@ -409,12 +486,12 @@ TEST(SoftwareImageDecodeCacheTest,
bool is_decomposable = false;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -428,12 +505,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToLowIfIdentity) {
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -449,11 +526,11 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kHigh_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -469,11 +546,11 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kHigh_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -485,29 +562,30 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, OriginalDecodesAreEqual) {
sk_sp<SkImage> image = CreateImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kLow_SkFilterQuality;
+ SkFilterQuality quality = kNone_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
+ DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
- EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
+ EXPECT_EQ(kNone_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
EXPECT_EQ(100, key.target_size().height());
EXPECT_TRUE(key.can_use_original_size_decode());
EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
DrawImage another_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
DefaultColorSpace());
- auto another_key = ImageDecodeCacheKey::FromDrawImage(another_draw_image);
+ auto another_key =
+ ImageDecodeCacheKey::FromDrawImage(another_draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), another_key.image_id());
- EXPECT_EQ(kLow_SkFilterQuality, another_key.filter_quality());
+ EXPECT_EQ(kNone_SkFilterQuality, another_key.filter_quality());
EXPECT_EQ(100, another_key.target_size().width());
EXPECT_EQ(100, another_key.target_size().height());
EXPECT_TRUE(another_key.can_use_original_size_decode());
@@ -522,11 +600,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRect) {
SkFilterQuality quality = kHigh_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeXYWH(25, 35, image->width(), image->height()),
- quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ CreatePaintImage(image),
+ SkIRect::MakeXYWH(25, 35, image->width(), image->height()), quality,
+ CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kLow_SkFilterQuality, key.filter_quality());
EXPECT_EQ(100, key.target_size().width());
@@ -541,11 +620,12 @@ TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRectWithScale) {
SkFilterQuality quality = kHigh_SkFilterQuality;
DrawImage draw_image(
- image, SkIRect::MakeXYWH(20, 30, image->width(), image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(image),
+ SkIRect::MakeXYWH(20, 30, image->width(), image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
- auto key = ImageDecodeCacheKey::FromDrawImage(draw_image);
+ auto key = ImageDecodeCacheKey::FromDrawImage(draw_image, RGBA_8888);
EXPECT_EQ(image->uniqueID(), key.image_id());
EXPECT_EQ(kMedium_SkFilterQuality, key.filter_quality());
EXPECT_EQ(40, key.target_size().width());
@@ -560,10 +640,10 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) {
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -571,8 +651,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) {
EXPECT_TRUE(task);
DrawImage another_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> another_task;
need_unref = cache.GetTaskForImageAndRef(
@@ -592,7 +672,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) {
bool is_decomposable = true;
DrawImage high_quality_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
kHigh_SkFilterQuality,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
@@ -603,24 +683,24 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) {
EXPECT_TRUE(need_unref);
EXPECT_TRUE(high_quality_task);
- DrawImage low_quality_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()),
- kLow_SkFilterQuality,
+ DrawImage none_quality_draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ kNone_SkFilterQuality,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
- scoped_refptr<TileTask> low_quality_task;
- need_unref = cache.GetTaskForImageAndRef(low_quality_draw_image,
+ scoped_refptr<TileTask> none_quality_task;
+ need_unref = cache.GetTaskForImageAndRef(none_quality_draw_image,
ImageDecodeCache::TracingInfo(),
- &low_quality_task);
+ &none_quality_task);
EXPECT_TRUE(need_unref);
- EXPECT_TRUE(low_quality_task);
- EXPECT_TRUE(high_quality_task.get() != low_quality_task.get());
+ EXPECT_TRUE(none_quality_task);
+ EXPECT_TRUE(high_quality_task.get() != none_quality_task.get());
TestTileTaskRunner::ProcessTask(high_quality_task.get());
- TestTileTaskRunner::ProcessTask(low_quality_task.get());
+ TestTileTaskRunner::ProcessTask(none_quality_task.get());
cache.UnrefImage(high_quality_draw_image);
- cache.UnrefImage(low_quality_draw_image);
+ cache.UnrefImage(none_quality_draw_image);
}
TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
@@ -630,8 +710,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
SkFilterQuality quality = kHigh_SkFilterQuality;
DrawImage half_size_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> half_size_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -640,8 +720,8 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
EXPECT_TRUE(half_size_task);
DrawImage quarter_size_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> quarter_size_task;
need_unref = cache.GetTaskForImageAndRef(quarter_size_draw_image,
@@ -665,8 +745,9 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
sk_sp<SkImage> first_image = CreateImage(100, 100);
DrawImage first_draw_image(
- first_image, SkIRect::MakeWH(first_image->width(), first_image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(first_image),
+ SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -676,7 +757,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
sk_sp<SkImage> second_image = CreateImage(100, 100);
DrawImage second_draw_image(
- second_image,
+ CreatePaintImage(second_image),
SkIRect::MakeWH(second_image->width(), second_image->height()), quality,
CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
DefaultColorSpace());
@@ -694,7 +775,15 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
cache.UnrefImage(second_draw_image);
}
-TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
+// crbug.com/709341
+#if defined(MEMORY_SANITIZER)
+#define MAYBE_GetTaskForImageDifferentColorSpace \
+ DISABLED_GetTaskForImageDifferentColorSpace
+#else
+#define MAYBE_GetTaskForImageDifferentColorSpace \
+ GetTaskForImageDifferentColorSpace
+#endif
+TEST(SoftwareImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentColorSpace) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
@@ -707,8 +796,9 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
sk_sp<SkImage> image = CreateImageWithColorSpace(100, 100, color_space_a);
DrawImage first_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_b);
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ color_space_b);
scoped_refptr<TileTask> first_task;
bool need_unref = cache.GetTaskForImageAndRef(
first_draw_image, ImageDecodeCache::TracingInfo(), &first_task);
@@ -716,8 +806,9 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
EXPECT_TRUE(first_task);
DrawImage second_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_c);
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ color_space_c);
scoped_refptr<TileTask> second_task;
need_unref = cache.GetTaskForImageAndRef(
second_draw_image, ImageDecodeCache::TracingInfo(), &second_task);
@@ -726,8 +817,9 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentColorSpace) {
EXPECT_TRUE(first_task.get() != second_task.get());
DrawImage third_draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), color_space_b);
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
+ color_space_b);
scoped_refptr<TileTask> third_task;
need_unref = cache.GetTaskForImageAndRef(
third_draw_image, ImageDecodeCache::TracingInfo(), &third_task);
@@ -749,10 +841,10 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) {
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -780,10 +872,10 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyPrerolled) {
SkFilterQuality quality = kLow_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -818,10 +910,10 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) {
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -862,10 +954,10 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -905,10 +997,10 @@ TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDraw) {
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
@@ -940,8 +1032,9 @@ TEST(SoftwareImageDecodeCacheTest,
sk_sp<SkImage> image = CreateImage(100, 100);
DrawImage draw_image(
- image, SkIRect::MakeXYWH(20, 30, image->width(), image->height()),
- quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(image),
+ SkIRect::MakeXYWH(20, 30, image->width(), image->height()), quality,
+ CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -972,10 +1065,10 @@ TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
DecodedDrawImage decoded_draw_image =
cache.GetDecodedImageForDraw(draw_image);
@@ -998,10 +1091,10 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
DecodedDrawImage decoded_draw_image =
cache.GetDecodedImageForDraw(draw_image);
@@ -1030,10 +1123,10 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
DecodedDrawImage decoded_draw_image =
cache.GetDecodedImageForDraw(draw_image);
@@ -1076,10 +1169,10 @@ TEST(SoftwareImageDecodeCacheTest,
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
DecodedDrawImage decoded_draw_image =
cache.GetDecodedImageForDraw(draw_image);
@@ -1122,10 +1215,10 @@ TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
SkFilterQuality quality = kHigh_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1147,8 +1240,9 @@ TEST(SoftwareImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
sk_sp<SkImage> image = CreateImage(100, 100);
DrawImage draw_image(
- image, SkIRect::MakeXYWH(150, 150, image->width(), image->height()),
- quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ CreatePaintImage(image),
+ SkIRect::MakeXYWH(150, 150, image->width(), image->height()), quality,
+ CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1170,10 +1264,10 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityFilterIsHandled) {
SkFilterQuality quality = kLow_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1200,7 +1294,8 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
SkFilterQuality quality = kLow_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeXYWH(10, 10, 80, 80), quality,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
@@ -1219,7 +1314,10 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
// SkImage object.
EXPECT_TRUE(decoded_draw_image.image() != image);
EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
- EXPECT_TRUE(decoded_draw_image.is_scale_adjustment_identity());
+ // Low quality will be upgraded to medium and mip-mapped.
+ EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
+ EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
+ EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
cache.UnrefImage(draw_image);
@@ -1231,7 +1329,8 @@ TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) {
SkFilterQuality quality = kNone_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(100, 100);
- DrawImage draw_image(image, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
+ DrawImage draw_image(CreatePaintImage(image),
+ SkIRect::MakeXYWH(10, 10, 80, 80), quality,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
@@ -1262,10 +1361,10 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) {
SkFilterQuality quality = kMedium_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(500, 200);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1295,10 +1394,10 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) {
SkFilterQuality quality = kMedium_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(500, 200);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1329,8 +1428,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) {
sk_sp<SkImage> image = CreateImage(500, 200);
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1361,10 +1460,10 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) {
SkFilterQuality quality = kMedium_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(500, 200);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1395,8 +1494,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) {
sk_sp<SkImage> image = CreateImage(500, 200);
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1427,10 +1526,10 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
SkFilterQuality quality = kMedium_SkFilterQuality;
sk_sp<SkImage> image = CreateImage(500, 200);
- DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
- quality,
- CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
- DefaultColorSpace());
+ DrawImage draw_image(
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
+ DefaultColorSpace());
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
@@ -1461,8 +1560,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
sk_sp<SkImage> image = CreateImage(500, 200);
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1494,8 +1593,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_001ScaleIsHandled) {
sk_sp<SkImage> image = CreateImage(500, 200);
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
@@ -1519,12 +1618,12 @@ TEST(SoftwareImageDecodeCacheTest,
sk_sp<SkImage> image = CreateImage(500, 200);
DrawImage draw_image_50(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
DefaultColorSpace());
DrawImage draw_image_49(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
- CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
+ CreatePaintImage(image), SkIRect::MakeWH(image->width(), image->height()),
+ quality, CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task_50;
@@ -1573,7 +1672,8 @@ TEST(SoftwareImageDecodeCacheTest, ClearCache) {
for (int i = 0; i < 10; ++i) {
sk_sp<SkImage> image = CreateImage(100, 100);
DrawImage draw_image(
- image, SkIRect::MakeWH(image->width(), image->height()), quality,
+ CreatePaintImage(image),
+ SkIRect::MakeWH(image->width(), image->height()), quality,
CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
scoped_refptr<TileTask> task;
diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h
index 435d5f0552e..66dfadae0a6 100644
--- a/chromium/cc/tiles/tile.h
+++ b/chromium/cc/tiles/tile.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "cc/paint/draw_image.h"
#include "cc/raster/tile_task.h"
#include "cc/tiles/tile_draw_info.h"
#include "ui/gfx/geometry/axis_transform2d.h"
@@ -117,6 +118,15 @@ class CC_EXPORT Tile {
return is_solid_color_analysis_performed_;
}
+ bool set_raster_task_scheduled_with_checker_images(bool has_checker_images) {
+ bool previous_value = raster_task_scheduled_with_checker_images_;
+ raster_task_scheduled_with_checker_images_ = has_checker_images;
+ return previous_value;
+ }
+ bool raster_task_scheduled_with_checker_images() const {
+ return raster_task_scheduled_with_checker_images_;
+ }
+
const PictureLayerTiling* tiling() const { return tiling_; }
void set_tiling(const PictureLayerTiling* tiling) { tiling_ = tiling; }
@@ -158,6 +168,10 @@ class CC_EXPORT Tile {
Id invalidated_id_;
unsigned scheduled_priority_;
+
+ // Set to true if there is a raster task scheduled for this tile that will
+ // rasterize a resource with checker images.
+ bool raster_task_scheduled_with_checker_images_ = false;
scoped_refptr<TileTask> raster_task_;
DISALLOW_COPY_AND_ASSIGN(Tile);
diff --git a/chromium/cc/tiles/tile_draw_info.cc b/chromium/cc/tiles/tile_draw_info.cc
index 2e4eebb726c..d27059f5949 100644
--- a/chromium/cc/tiles/tile_draw_info.cc
+++ b/chromium/cc/tiles/tile_draw_info.cc
@@ -22,7 +22,7 @@ void TileDrawInfo::AsValueInto(base::trace_event::TracedValue* state) const {
Resource* TileDrawInfo::TakeResource() {
Resource* resource = resource_;
- set_resource(nullptr);
+ set_resource(nullptr, false);
return resource;
}
diff --git a/chromium/cc/tiles/tile_draw_info.h b/chromium/cc/tiles/tile_draw_info.h
index 8ba08857dd2..dc1a8855506 100644
--- a/chromium/cc/tiles/tile_draw_info.h
+++ b/chromium/cc/tiles/tile_draw_info.h
@@ -77,6 +77,11 @@ class CC_EXPORT TileDrawInfo {
return resource_ ? IsResourceFormatCompressed(resource_->format()) : false;
}
+ bool is_checker_imaged() const {
+ DCHECK(!resource_is_checker_imaged_ || resource_);
+ return resource_is_checker_imaged_;
+ }
+
void SetSolidColorForTesting(SkColor color) { set_solid_color(color); }
void AsValueInto(base::trace_event::TracedValue* state) const;
@@ -87,9 +92,13 @@ class CC_EXPORT TileDrawInfo {
const Resource* resource() const { return resource_; }
- void set_resource(Resource* resource) {
+ void set_resource(Resource* resource, bool resource_is_checker_imaged) {
+ DCHECK(!resource_is_checker_imaged || resource)
+ << "Need to have a resource for it to be checker-imaged";
+
mode_ = RESOURCE_MODE;
is_resource_ready_to_draw_ = false;
+ resource_is_checker_imaged_ = resource_is_checker_imaged;
resource_ = resource;
}
@@ -111,6 +120,10 @@ class CC_EXPORT TileDrawInfo {
Resource* resource_ = nullptr;
bool contents_swizzled_ = false;
bool is_resource_ready_to_draw_ = false;
+
+ // Set to true if |resource_| was rasterized with checker-imaged content. The
+ // flag can only be true iff we have a valid |resource_|.
+ bool resource_is_checker_imaged_ = false;
};
} // namespace cc
diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc
index 5639661f713..b34cbb8f2e4 100644
--- a/chromium/cc/tiles/tile_manager.cc
+++ b/chromium/cc/tiles/tile_manager.cc
@@ -425,6 +425,10 @@ void TileManager::SetResources(ResourcePool* resource_pool,
}
void TileManager::Release(Tile* tile) {
+ if (tile->raster_task_scheduled_with_checker_images())
+ num_of_tiles_with_checker_images_--;
+ DCHECK_GE(num_of_tiles_with_checker_images_, 0);
+
FreeResourcesForTile(tile);
tiles_.erase(tile->id());
}
@@ -522,6 +526,10 @@ void TileManager::Flush() {
tile_task_manager_->CheckForCompletedTasks();
did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
+
+ // Actually flush.
+ raster_buffer_provider_->Flush();
+
CheckPendingGpuWorkTiles(true /* issue_signals */);
TRACE_EVENT_INSTANT1("cc", "DidFlush", TRACE_EVENT_SCOPE_THREAD, "stats",
@@ -639,6 +647,8 @@ TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() {
MemoryUsage memory_usage(resource_pool_->memory_usage_bytes(),
resource_pool_->resource_count());
+ gfx::ColorSpace raster_color_space = client_->GetRasterColorSpace();
+
std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue(
client_->BuildRasterQueue(global_state_.tree_priority,
RasterTilePriorityQueue::Type::ALL));
@@ -684,6 +694,21 @@ TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() {
continue;
}
+ // Tiles in the raster queue should either require raster or decode for
+ // checker-images. If this tile does not need raster, process it only to
+ // build the decode queue for checkered images.
+ // Note that performing this check after the solid color analysis is not
+ // necessary for correctness.
+ if (!tile->draw_info().NeedsRaster()) {
+ DCHECK(tile->draw_info().is_checker_imaged());
+ DCHECK(prioritized_tile.should_decode_checkered_images_for_tile());
+
+ AddCheckeredImagesToDecodeQueue(
+ prioritized_tile, raster_color_space,
+ &work_to_schedule.checker_image_decode_queue);
+ continue;
+ }
+
// We won't be able to schedule this tile, so break out early.
if (work_to_schedule.tiles_to_raster.size() >=
scheduled_raster_task_limit_) {
@@ -729,6 +754,25 @@ TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() {
break;
}
+ // If the tile has a scheduled task that will rasterize a resource with
+ // checker-imaged content, add those images to the decode queue. Note that
+ // we add all images as we process the raster priority queue to ensure that
+ // images are added to the decode queue in raster priority order.
+ if (tile->HasRasterTask()) {
+ if (tile->raster_task_scheduled_with_checker_images() &&
+ prioritized_tile.should_decode_checkered_images_for_tile()) {
+ AddCheckeredImagesToDecodeQueue(
+ prioritized_tile, raster_color_space,
+ &work_to_schedule.checker_image_decode_queue);
+ }
+ } else {
+ // Creating the raster task here will acquire resources, but
+ // this resource usage has already been accounted for above.
+ tile->raster_task_ =
+ CreateRasterTask(prioritized_tile, client_->GetRasterColorSpace(),
+ &work_to_schedule.checker_image_decode_queue);
+ }
+
memory_usage += memory_required_by_tile_to_be_scheduled;
work_to_schedule.tiles_to_raster.push_back(prioritized_tile);
}
@@ -739,6 +783,33 @@ TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() {
eviction_priority_queue = FreeTileResourcesUntilUsageIsWithinLimit(
std::move(eviction_priority_queue), hard_memory_limit, &memory_usage);
+ // At this point, if we ran out of memory when allocating resources and we
+ // couldn't go past even the NOW bin, this means we have evicted resources
+ // from all tiles with a lower priority while we still might have resources
+ // holding checker-imaged content. The invalidations for these resources will
+ // be generated only if the skipped images are decoded. So we must schedule
+ // decodes for these tiles to update their content.
+ if (!had_enough_memory_to_schedule_tiles_needed_now &&
+ num_of_tiles_with_checker_images_ > 0) {
+ for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
+ const PrioritizedTile& prioritized_tile = raster_priority_queue->Top();
+
+ if (prioritized_tile.priority().priority_bin > TilePriority::NOW)
+ break;
+
+ if (!prioritized_tile.should_decode_checkered_images_for_tile())
+ continue;
+
+ Tile* tile = prioritized_tile.tile();
+ if (tile->draw_info().is_checker_imaged() ||
+ tile->raster_task_scheduled_with_checker_images()) {
+ AddCheckeredImagesToDecodeQueue(
+ prioritized_tile, raster_color_space,
+ &work_to_schedule.checker_image_decode_queue);
+ }
+ }
+ }
+
UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget",
!had_enough_memory_to_schedule_tiles_needed_now);
did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now;
@@ -760,6 +831,11 @@ TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() {
void TileManager::FreeResourcesForTile(Tile* tile) {
TileDrawInfo& draw_info = tile->draw_info();
+
+ if (draw_info.is_checker_imaged())
+ num_of_tiles_with_checker_images_--;
+ DCHECK_GE(num_of_tiles_with_checker_images_, 0);
+
Resource* resource = draw_info.TakeResource();
if (resource) {
resource_pool_->ReleaseResource(resource);
@@ -775,6 +851,45 @@ void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(
client_->NotifyTileStateChanged(tile);
}
+void TileManager::PartitionImagesForCheckering(
+ const PrioritizedTile& prioritized_tile,
+ const gfx::ColorSpace& raster_color_space,
+ std::vector<DrawImage>* sync_decoded_images,
+ std::vector<PaintImage>* checkered_images) {
+ Tile* tile = prioritized_tile.tile();
+ std::vector<DrawImage> images_in_tile;
+ prioritized_tile.raster_source()->GetDiscardableImagesInRect(
+ tile->enclosing_layer_rect(), tile->raster_transform().scale(),
+ raster_color_space, &images_in_tile);
+ WhichTree tree = tile->tiling()->tree();
+
+ for (auto& draw_image : images_in_tile) {
+ if (checker_image_tracker_.ShouldCheckerImage(draw_image.paint_image(),
+ tree))
+ checkered_images->push_back(draw_image.paint_image());
+ else
+ sync_decoded_images->push_back(draw_image);
+ }
+}
+
+void TileManager::AddCheckeredImagesToDecodeQueue(
+ const PrioritizedTile& prioritized_tile,
+ const gfx::ColorSpace& raster_color_space,
+ CheckerImageTracker::ImageDecodeQueue* image_decode_queue) {
+ Tile* tile = prioritized_tile.tile();
+ std::vector<DrawImage> images_in_tile;
+ prioritized_tile.raster_source()->GetDiscardableImagesInRect(
+ tile->enclosing_layer_rect(), tile->raster_transform().scale(),
+ raster_color_space, &images_in_tile);
+ WhichTree tree = tile->tiling()->tree();
+
+ for (auto& draw_image : images_in_tile) {
+ if (checker_image_tracker_.ShouldCheckerImage(draw_image.paint_image(),
+ tree))
+ image_decode_queue->push_back(draw_image.paint_image());
+ }
+}
+
void TileManager::ScheduleTasks(
const PrioritizedWorkToSchedule& work_to_schedule) {
const std::vector<PrioritizedTile>& tiles_that_need_to_be_rasterized =
@@ -823,11 +938,7 @@ void TileManager::ScheduleTasks(
DCHECK(tile->draw_info().requires_resource());
DCHECK(!tile->draw_info().resource());
-
- if (!tile->raster_task_) {
- tile->raster_task_ =
- CreateRasterTask(prioritized_tile, raster_color_space);
- }
+ DCHECK(tile->HasRasterTask());
TileTask* task = tile->raster_task_.get();
@@ -880,7 +991,6 @@ void TileManager::ScheduleTasks(
std::vector<scoped_refptr<TileTask>> new_locked_image_tasks =
image_controller_.SetPredecodeImages(std::move(new_locked_images),
tracing_info);
-
for (auto& task : new_locked_image_tasks) {
auto decode_it = std::find_if(graph_.nodes.begin(), graph_.nodes.end(),
[&task](const TaskGraph::Node& node) {
@@ -929,6 +1039,12 @@ void TileManager::ScheduleTasks(
// in |raster_queue_|.
tile_task_manager_->ScheduleTasks(&graph_);
+ // Schedule running of the checker-image decode queue. This replaces the
+ // previously scheduled queue and effectively cancels image decodes from the
+ // previous queue, if not already started.
+ checker_image_tracker_.ScheduleImageDecodeQueue(
+ std::move(work_to_schedule.checker_image_decode_queue));
+
did_check_for_completed_tasks_since_last_schedule_tasks_ = false;
TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", "state",
@@ -937,8 +1053,13 @@ void TileManager::ScheduleTasks(
scoped_refptr<TileTask> TileManager::CreateRasterTask(
const PrioritizedTile& prioritized_tile,
- const gfx::ColorSpace& color_space) {
+ const gfx::ColorSpace& color_space,
+ CheckerImageTracker::ImageDecodeQueue* checker_image_decode_queue) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+ "TileManager::CreateRasterTask");
Tile* tile = prioritized_tile.tile();
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+ "TileManager::CreateRasterTask", "Tile", tile->id());
// Get the resource.
uint64_t resource_content_id = 0;
@@ -964,29 +1085,44 @@ scoped_refptr<TileTask> TileManager::CreateRasterTask(
playback_settings.skip_images =
prioritized_tile.priority().resolution == LOW_RESOLUTION;
- // Create and queue all image decode tasks that this tile depends on.
+ // Create and queue all image decode tasks that this tile depends on. Note
+ // that we need to store the images for decode tasks in
+ // |scheduled_draw_images_| since the tile might have been destroyed by the
+ // time the raster task finishes.
TileTask::Vector decode_tasks;
- std::vector<DrawImage>& images = scheduled_draw_images_[tile->id()];
- ImageIdFlatSet images_to_skip;
- images.clear();
+ std::vector<DrawImage>& sync_decoded_images =
+ scheduled_draw_images_[tile->id()];
+ sync_decoded_images.clear();
if (!playback_settings.skip_images) {
- prioritized_tile.raster_source()->GetDiscardableImagesInRect(
- tile->enclosing_layer_rect(), tile->raster_transform().scale(),
- color_space, &images);
- checker_image_tracker_.FilterImagesForCheckeringForTile(
- &images, &images_to_skip, prioritized_tile.tile()->tiling()->tree());
+ std::vector<PaintImage> checkered_images;
+ PartitionImagesForCheckering(prioritized_tile, color_space,
+ &sync_decoded_images, &checkered_images);
+ for (const auto& image : checkered_images) {
+ playback_settings.images_to_skip.insert(image.sk_image()->uniqueID());
+
+ // This can be the case for tiles on the active tree that will be replaced
+ // or are occluded on the pending tree. While we still need to continue
+ // skipping images for these tiles, we don't need to decode them since
+ // they will not be required on the next active tree.
+ if (prioritized_tile.should_decode_checkered_images_for_tile())
+ checker_image_decode_queue->push_back(image);
+ }
}
// We can skip the image hijack canvas if we have no images, or no images to
// skip during raster.
playback_settings.use_image_hijack_canvas =
- !images.empty() || !images_to_skip.empty();
- playback_settings.images_to_skip = std::move(images_to_skip);
+ !sync_decoded_images.empty() || !playback_settings.images_to_skip.empty();
+
+ bool has_checker_images = !playback_settings.images_to_skip.empty();
+ tile->set_raster_task_scheduled_with_checker_images(has_checker_images);
+ if (has_checker_images)
+ num_of_tiles_with_checker_images_++;
// Get the tasks for the required images.
ImageDecodeCache::TracingInfo tracing_info(
prepare_tiles_count_, prioritized_tile.priority().priority_bin);
- image_controller_.GetTasksForImagesAndRef(&images, &decode_tasks,
+ image_controller_.GetTasksForImagesAndRef(&sync_decoded_images, &decode_tasks,
tracing_info);
std::unique_ptr<RasterBuffer> raster_buffer =
@@ -1012,10 +1148,15 @@ void TileManager::OnRasterTaskCompleted(
auto found = tiles_.find(tile_id);
Tile* tile = nullptr;
+ bool raster_task_was_scheduled_with_checker_images = false;
if (found != tiles_.end()) {
tile = found->second;
DCHECK(tile->raster_task_.get());
tile->raster_task_ = nullptr;
+ raster_task_was_scheduled_with_checker_images =
+ tile->set_raster_task_scheduled_with_checker_images(false);
+ if (raster_task_was_scheduled_with_checker_images)
+ num_of_tiles_with_checker_images_--;
}
// Unref all the images.
@@ -1038,8 +1179,11 @@ void TileManager::OnRasterTaskCompleted(
}
TileDrawInfo& draw_info = tile->draw_info();
- draw_info.set_resource(resource);
+ draw_info.set_resource(resource,
+ raster_task_was_scheduled_with_checker_images);
draw_info.contents_swizzled_ = DetermineResourceRequiresSwizzle(tile);
+ if (raster_task_was_scheduled_with_checker_images)
+ num_of_tiles_with_checker_images_++;
// In SMOOTHNESS_TAKES_PRIORITY mode, we wait for GPU work to complete for a
// tile before setting it as ready to draw.
@@ -1248,7 +1392,7 @@ void TileManager::MarkTilesOutOfMemory(
}
}
-const ImageIdFlatSet& TileManager::TakeImagesToInvalidateOnSyncTree() {
+const PaintImageIdFlatSet& TileManager::TakeImagesToInvalidateOnSyncTree() {
return checker_image_tracker_.TakeImagesToInvalidateOnSyncTree();
}
@@ -1256,6 +1400,11 @@ void TileManager::DidActivateSyncTree() {
checker_image_tracker_.DidActivateSyncTree();
}
+void TileManager::ClearCheckerImageTracking(
+ bool can_clear_decode_policy_tracking) {
+ checker_image_tracker_.ClearTracker(can_clear_decode_policy_tracking);
+}
+
void TileManager::NeedsInvalidationForCheckerImagedTiles() {
client_->RequestImplSideInvalidation();
}
@@ -1287,6 +1436,11 @@ bool TileManager::UsePartialRaster() const {
}
void TileManager::CheckPendingGpuWorkTiles(bool issue_signals) {
+ TRACE_EVENT2("cc", "TileManager::CheckPendingGpuWorkTiles",
+ "pending_gpu_work_tiles", pending_gpu_work_tiles_.size(),
+ "tree_priority",
+ TreePriorityToString(global_state_.tree_priority));
+
ResourceProvider::ResourceIdArray required_for_activation_ids;
ResourceProvider::ResourceIdArray required_for_draw_ids;
@@ -1364,6 +1518,12 @@ scoped_refptr<TileTask> TileManager::CreateTaskSetFinishedTask(
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
TileManager::ActivationStateAsValue() {
auto state = base::MakeUnique<base::trace_event::TracedValue>();
+ ActivationStateAsValueInto(state.get());
+ return std::move(state);
+}
+
+void TileManager::ActivationStateAsValueInto(
+ base::trace_event::TracedValue* state) {
state->SetString("tree_priority",
TreePriorityToString(global_state_.tree_priority));
state->SetInteger("soft_memory_limit",
@@ -1402,7 +1562,7 @@ TileManager::ActivationStateAsValue() {
state->BeginArray("raster_tiles");
for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
state->BeginDictionary();
- tile_as_value(raster_priority_queue->Top(), state.get());
+ tile_as_value(raster_priority_queue->Top(), state);
state->EndDictionary();
}
state->EndArray();
@@ -1414,12 +1574,10 @@ TileManager::ActivationStateAsValue() {
state->BeginArray("activation_tiles");
for (; !required_priority_queue->IsEmpty(); required_priority_queue->Pop()) {
state->BeginDictionary();
- tile_as_value(required_priority_queue->Top(), state.get());
+ tile_as_value(required_priority_queue->Top(), state);
state->EndDictionary();
}
state->EndArray();
-
- return std::move(state);
}
TileManager::MemoryUsage::MemoryUsage()
diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h
index 3327cf1bf99..9b503e6af37 100644
--- a/chromium/cc/tiles/tile_manager.h
+++ b/chromium/cc/tiles/tile_manager.h
@@ -15,6 +15,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/sequenced_task_runner.h"
#include "base/values.h"
#include "cc/base/unique_notifier.h"
#include "cc/raster/raster_buffer_provider.h"
@@ -150,8 +151,9 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient {
bool IsReadyToActivate() const;
bool IsReadyToDraw() const;
- const ImageIdFlatSet& TakeImagesToInvalidateOnSyncTree();
+ const PaintImageIdFlatSet& TakeImagesToInvalidateOnSyncTree();
void DidActivateSyncTree();
+ void ClearCheckerImageTracking(bool can_clear_decode_policy_tracking);
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
BasicStateAsValue() const;
@@ -164,10 +166,12 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient {
void InitializeTilesWithResourcesForTesting(const std::vector<Tile*>& tiles) {
for (size_t i = 0; i < tiles.size(); ++i) {
TileDrawInfo& draw_info = tiles[i]->draw_info();
- draw_info.set_resource(resource_pool_->AcquireResource(
- tiles[i]->desired_texture_size(),
- raster_buffer_provider_->GetResourceFormat(false),
- client_->GetRasterColorSpace()));
+ draw_info.set_resource(
+ resource_pool_->AcquireResource(
+ tiles[i]->desired_texture_size(),
+ raster_buffer_provider_->GetResourceFormat(false),
+ client_->GetRasterColorSpace()),
+ false);
draw_info.set_resource_ready_for_draw();
}
}
@@ -234,6 +238,11 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient {
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
ActivationStateAsValue();
+ void ActivationStateAsValueInto(base::trace_event::TracedValue* state);
+ int num_of_tiles_with_checker_images() const {
+ return num_of_tiles_with_checker_images_;
+ }
+
protected:
friend class Tile;
// Must be called by tile during destruction.
@@ -281,13 +290,15 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient {
std::vector<PrioritizedTile> tiles_to_raster;
std::vector<PrioritizedTile> tiles_to_process_for_images;
+ CheckerImageTracker::ImageDecodeQueue checker_image_decode_queue;
};
void FreeResourcesForTile(Tile* tile);
void FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(Tile* tile);
scoped_refptr<TileTask> CreateRasterTask(
const PrioritizedTile& prioritized_tile,
- const gfx::ColorSpace& color_space);
+ const gfx::ColorSpace& color_space,
+ CheckerImageTracker::ImageDecodeQueue* checker_image_decode_queue);
std::unique_ptr<EvictionTilePriorityQueue>
FreeTileResourcesUntilUsageIsWithinLimit(
@@ -319,6 +330,15 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient {
PrioritizedWorkToSchedule AssignGpuMemoryToTiles();
void ScheduleTasks(const PrioritizedWorkToSchedule& work_to_schedule);
+ void PartitionImagesForCheckering(const PrioritizedTile& prioritized_tile,
+ const gfx::ColorSpace& raster_color_space,
+ std::vector<DrawImage>* sync_decoded_images,
+ std::vector<PaintImage>* checkered_images);
+ void AddCheckeredImagesToDecodeQueue(
+ const PrioritizedTile& prioritized_tile,
+ const gfx::ColorSpace& raster_color_space,
+ CheckerImageTracker::ImageDecodeQueue* image_decode_queue);
+
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
ScheduledTasksStateAsValue() const;
@@ -373,6 +393,10 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient {
std::unordered_map<Tile::Id, std::vector<DrawImage>> scheduled_draw_images_;
std::vector<scoped_refptr<TileTask>> locked_image_tasks_;
+ // Number of tiles with a checker-imaged resource or active raster tasks which
+ // will create a checker-imaged resource.
+ int num_of_tiles_with_checker_images_ = 0;
+
// We need two WeakPtrFactory objects as the invalidation pattern of each is
// different. The |task_set_finished_weak_ptr_factory_| is invalidated any
// time new tasks are scheduled, preventing a race when the callback has
diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc
index b410cc006af..4cfe0123e32 100644
--- a/chromium/cc/tiles/tile_manager_unittest.cc
+++ b/chromium/cc/tiles/tile_manager_unittest.cc
@@ -29,6 +29,7 @@
#include "cc/test/fake_recording_source.h"
#include "cc/test/fake_tile_manager.h"
#include "cc/test/fake_tile_task_manager.h"
+#include "cc/test/skia_common.h"
#include "cc/test/test_layer_tree_host_base.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/test/test_tile_priorities.h"
@@ -1493,7 +1494,7 @@ TEST_F(TileManagerTilePriorityQueueTest, NoRasterTasksforSolidColorTiles) {
std::unique_ptr<PictureLayerImpl> layer_impl = PictureLayerImpl::Create(
host_impl()->active_tree(), 1, Layer::LayerMaskType::NOT_MASK);
- layer_impl->set_is_drawn_render_surface_layer_list_member(true);
+ layer_impl->set_contributes_to_drawn_render_surface(true);
PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set();
PictureLayerTiling* tiling =
@@ -1698,7 +1699,7 @@ TEST_F(TileManagerTest, LowResHasNoImage) {
std::unique_ptr<PictureLayerImpl> layer = PictureLayerImpl::Create(
host_impl()->active_tree(), 1, Layer::LayerMaskType::NOT_MASK);
PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set();
- layer->set_is_drawn_render_surface_layer_list_member(true);
+ layer->set_contributes_to_drawn_render_surface(true);
auto* tiling = tiling_set->AddTiling(gfx::AxisTransform2d(), raster);
tiling->set_resolution(resolutions[i]);
@@ -2320,14 +2321,14 @@ class CheckerImagingTileManagerTest : public TestLayerTreeHostBase {
SkImageInfo::MakeN32Premul(size.width(), size.height())) {}
protected:
- MOCK_METHOD5(onGetPixels,
- bool(const SkImageInfo&, void*, size_t, SkPMColor[], int*));
+ MOCK_METHOD4(onGetPixels,
+ bool(const SkImageInfo&, void*, size_t, const Options&));
};
void TearDown() override {
// Allow all tasks on the image worker to run now. Any scheduled decodes
// will be aborted.
- image_worker_task_runner()->set_run_tasks_synchronously(true);
+ task_runner_->set_run_tasks_synchronously(true);
}
LayerTreeSettings CreateSettings() override {
@@ -2351,8 +2352,11 @@ class CheckerImagingTileManagerTest : public TestLayerTreeHostBase {
return base::MakeUnique<SynchronousTaskGraphRunner>();
}
- SynchronousSimpleTaskRunner* image_worker_task_runner() const {
- return task_runner_.get();
+ void FlushDecodeTasks() {
+ while (task_runner_->HasPendingTask()) {
+ task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ }
}
private:
@@ -2366,7 +2370,7 @@ TEST_F(CheckerImagingTileManagerTest,
std::unique_ptr<FakeRecordingSource> recording_source =
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
- recording_source->SetGenerateDiscardableImagesMetadata(true);
+ recording_source->set_fill_with_nonsolid_color(true);
sk_sp<SkImage> image = SkImage::MakeFromGenerator(
base::MakeUnique<testing::StrictMock<MockImageGenerator>>(
@@ -2379,7 +2383,7 @@ TEST_F(CheckerImagingTileManagerTest,
std::unique_ptr<PictureLayerImpl> layer_impl = PictureLayerImpl::Create(
host_impl()->active_tree(), 1, Layer::LayerMaskType::NOT_MASK);
- layer_impl->set_is_drawn_render_surface_layer_list_member(true);
+ layer_impl->set_contributes_to_drawn_render_surface(true);
PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set();
PictureLayerTiling* tiling =
@@ -2402,5 +2406,252 @@ TEST_F(CheckerImagingTileManagerTest,
EXPECT_FALSE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting());
}
+TEST_F(CheckerImagingTileManagerTest, BuildsImageDecodeQueueAsExpected) {
+ const gfx::Size layer_bounds(900, 900);
+
+ std::unique_ptr<FakeRecordingSource> recording_source =
+ FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
+ recording_source->set_fill_with_nonsolid_color(true);
+
+ int dimension = 450;
+ sk_sp<SkImage> image1 =
+ CreateDiscardableImage(gfx::Size(dimension, dimension));
+ sk_sp<SkImage> image2 =
+ CreateDiscardableImage(gfx::Size(dimension, dimension));
+ sk_sp<SkImage> image3 =
+ CreateDiscardableImage(gfx::Size(dimension, dimension));
+ recording_source->add_draw_image(image1, gfx::Point(0, 0));
+ recording_source->add_draw_image(image2, gfx::Point(600, 0));
+ recording_source->add_draw_image(image3, gfx::Point(0, 600));
+
+ recording_source->Rerecord();
+ scoped_refptr<RasterSource> raster_source =
+ RasterSource::CreateFromRecordingSource(recording_source.get(), false);
+
+ gfx::Size tile_size(500, 500);
+ Region invalidation((gfx::Rect(layer_bounds)));
+ SetupPendingTree(raster_source, tile_size, invalidation);
+
+ PictureLayerTilingSet* tiling_set =
+ pending_layer()->picture_layer_tiling_set();
+ PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0);
+ pending_tiling->set_resolution(HIGH_RESOLUTION);
+ pending_tiling->CreateAllTilesForTesting();
+ pending_tiling->SetTilePriorityRectsForTesting(
+ gfx::Rect(layer_bounds), // Visible rect.
+ gfx::Rect(layer_bounds), // Skewport rect.
+ gfx::Rect(layer_bounds), // Soon rect.
+ gfx::Rect(layer_bounds)); // Eventually rect.
+
+ // PrepareTiles and make sure we account correctly for tiles that have been
+ // scheduled with checkered images.
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+ EXPECT_TRUE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting());
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ const Tile* tile = pending_tiling->TileAt(i, j);
+ EXPECT_TRUE(tile->HasRasterTask());
+ if (i == 1 && j == 1)
+ EXPECT_FALSE(tile->raster_task_scheduled_with_checker_images());
+ else
+ EXPECT_TRUE(tile->raster_task_scheduled_with_checker_images());
+ }
+ }
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 3);
+
+ // Now raster all the tiles and make sure these tiles are still accounted for
+ // with checkered images.
+ static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting());
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ const Tile* tile = pending_tiling->TileAt(i, j);
+ EXPECT_FALSE(tile->HasRasterTask());
+ EXPECT_FALSE(tile->raster_task_scheduled_with_checker_images());
+ EXPECT_TRUE(tile->draw_info().has_resource());
+ if (i == 1 && j == 1)
+ EXPECT_FALSE(tile->draw_info().is_checker_imaged());
+ else
+ EXPECT_TRUE(tile->draw_info().is_checker_imaged());
+ }
+ }
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 3);
+
+ // Activate the pending tree.
+ ActivateTree();
+
+ // Set empty tile priority rects so an empty image decode queue is used.
+ gfx::Rect empty_rect;
+ PictureLayerTiling* active_tiling =
+ active_layer()->picture_layer_tiling_set()->tiling_at(0);
+ active_tiling->SetTilePriorityRectsForTesting(
+ gfx::Rect(empty_rect), // Visible rect.
+ gfx::Rect(empty_rect), // Skewport rect.
+ gfx::Rect(empty_rect), // Soon rect.
+ gfx::Rect(empty_rect)); // Eventually rect.
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+
+ // Run the decode tasks. Since the first decode is always scheduled, the
+ // completion for it should be triggered.
+ FlushDecodeTasks();
+
+ // Create a new pending tree to invalidate tiles for decoded images and verify
+ // that only tiles for |image1| are invalidated.
+ EXPECT_TRUE(host_impl()->client()->did_request_impl_side_invalidation());
+ PerformImplSideInvalidation();
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ const Tile* tile = pending_tiling->TileAt(i, j);
+ if (i == 0 && j == 0)
+ EXPECT_TRUE(tile);
+ else
+ EXPECT_FALSE(tile);
+ }
+ }
+ host_impl()->client()->reset_did_request_impl_side_invalidation();
+
+ // Activating the tree replaces the checker-imaged tile.
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 3);
+ ActivateTree();
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 2);
+
+ // Set the tile priority rects such that only the tile with the second image
+ // is scheduled for decodes, since it is checker-imaged.
+ gfx::Rect rect_to_raster(600, 0, 300, 900);
+ active_tiling->SetTilePriorityRectsForTesting(
+ gfx::Rect(rect_to_raster), // Visible rect.
+ gfx::Rect(rect_to_raster), // Skewport rect.
+ gfx::Rect(rect_to_raster), // Soon rect.
+ gfx::Rect(rect_to_raster)); // Eventually rect.
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+
+ // Run decode tasks to trigger completion of any pending decodes.
+ FlushDecodeTasks();
+
+ // Create a new pending tree to invalidate tiles for decoded images and verify
+ // that only tiles for |image2| are invalidated.
+ EXPECT_TRUE(host_impl()->client()->did_request_impl_side_invalidation());
+ PerformImplSideInvalidation();
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ const Tile* tile = pending_tiling->TileAt(i, j);
+ if (i == 1 && j == 0)
+ EXPECT_TRUE(tile);
+ else
+ EXPECT_FALSE(tile);
+ }
+ }
+ host_impl()->client()->reset_did_request_impl_side_invalidation();
+
+ // Activating the tree replaces the checker-imaged tile.
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 2);
+ ActivateTree();
+ EXPECT_EQ(host_impl()->tile_manager()->num_of_tiles_with_checker_images(), 1);
+
+ // Set the tile priority rects to cover the complete tiling and change the
+ // visibility. While |image3| has not yet been decoded, since we are
+ // invisible no decodes should have been scheduled.
+ active_tiling->SetTilePriorityRectsForTesting(
+ gfx::Rect(layer_bounds), // Visible rect.
+ gfx::Rect(layer_bounds), // Skewport rect.
+ gfx::Rect(layer_bounds), // Soon rect.
+ gfx::Rect(layer_bounds)); // Eventually rect.
+ host_impl()->SetVisible(false);
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+ FlushDecodeTasks();
+ EXPECT_FALSE(host_impl()->client()->did_request_impl_side_invalidation());
+}
+
+class CheckerImagingTileManagerMemoryTest
+ : public CheckerImagingTileManagerTest {
+ public:
+ std::unique_ptr<FakeLayerTreeHostImpl> CreateHostImpl(
+ const LayerTreeSettings& settings,
+ TaskRunnerProvider* task_runner_provider,
+ TaskGraphRunner* task_graph_runner) override {
+ LayerTreeSettings new_settings = settings;
+ new_settings.gpu_memory_policy.num_resources_limit = 4;
+ return CheckerImagingTileManagerTest::CreateHostImpl(
+ new_settings, task_runner_provider, task_graph_runner);
+ }
+};
+
+TEST_F(CheckerImagingTileManagerMemoryTest, AddsAllNowTilesToImageDecodeQueue) {
+ const gfx::Size layer_bounds(900, 1400);
+
+ std::unique_ptr<FakeRecordingSource> recording_source =
+ FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
+ recording_source->set_fill_with_nonsolid_color(true);
+
+ int dimension = 450;
+ sk_sp<SkImage> image1 =
+ CreateDiscardableImage(gfx::Size(dimension, dimension));
+ sk_sp<SkImage> image2 =
+ CreateDiscardableImage(gfx::Size(dimension, dimension));
+ recording_source->add_draw_image(image1, gfx::Point(0, 515));
+ recording_source->add_draw_image(image2, gfx::Point(515, 515));
+
+ recording_source->Rerecord();
+ scoped_refptr<RasterSource> raster_source =
+ RasterSource::CreateFromRecordingSource(recording_source.get(), false);
+
+ gfx::Size tile_size(500, 500);
+ Region invalidation((gfx::Rect(layer_bounds)));
+ SetupPendingTree(raster_source, tile_size, invalidation);
+
+ PictureLayerTilingSet* tiling_set =
+ pending_layer()->picture_layer_tiling_set();
+ PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0);
+ pending_tiling->set_resolution(HIGH_RESOLUTION);
+ pending_tiling->CreateAllTilesForTesting();
+
+ // Use a rect that only rasterizes the bottom 2 rows of tiles.
+ gfx::Rect rect_to_raster(0, 500, 900, 900);
+ pending_tiling->SetTilePriorityRectsForTesting(
+ rect_to_raster, // Visible rect.
+ rect_to_raster, // Skewport rect.
+ rect_to_raster, // Soon rect.
+ rect_to_raster); // Eventually rect.
+
+ // PrepareTiles, rasterize all scheduled tiles and activate while no images
+ // have been decoded.
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+ static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ ActivateTree();
+
+ // Expand the visible rect to include the complete tiling. The tile iteration
+ // will not go beyond the first tile since there are no resources with a lower
+ // priority that can be evicted. But we should still see image decodes
+ // scheduled for all visible tiles.
+ gfx::Rect complete_tiling_rect(layer_bounds);
+ PictureLayerTiling* active_tiling =
+ active_layer()->picture_layer_tiling_set()->tiling_at(0);
+ active_tiling->SetTilePriorityRectsForTesting(
+ complete_tiling_rect, // Visible rect.
+ complete_tiling_rect, // Skewport rect.
+ complete_tiling_rect, // Soon rect.
+ complete_tiling_rect); // Eventually rect.
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+
+ // Flush all decode tasks. The tiles with checkered images should be
+ // invalidated.
+ FlushDecodeTasks();
+ EXPECT_TRUE(host_impl()->client()->did_request_impl_side_invalidation());
+ PerformImplSideInvalidation();
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 3; j++) {
+ const Tile* tile = pending_tiling->TileAt(i, j);
+ if (j == 1)
+ EXPECT_TRUE(tile);
+ else
+ EXPECT_FALSE(tile);
+ }
+ }
+ host_impl()->client()->reset_did_request_impl_side_invalidation();
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.cc b/chromium/cc/tiles/tiling_set_raster_queue_all.cc
index 74bf1b2f144..adae8a8dfbe 100644
--- a/chromium/cc/tiles/tiling_set_raster_queue_all.cc
+++ b/chromium/cc/tiles/tiling_set_raster_queue_all.cc
@@ -200,8 +200,23 @@ bool TilingSetRasterQueueAll::OnePriorityRectIterator::
bool TilingSetRasterQueueAll::OnePriorityRectIterator::IsTileValid(
const Tile* tile) const {
- if (!tile || !TileNeedsRaster(tile))
+ if (!tile)
return false;
+
+ // A tile is valid for raster if it needs raster and is unoccluded.
+ bool tile_is_valid_for_raster =
+ tile->draw_info().NeedsRaster() && !tiling_->IsTileOccluded(tile);
+
+ // A tile is not valid for the raster queue if it is not valid for raster or
+ // processing for checker-images.
+ if (!tile_is_valid_for_raster) {
+ bool tile_is_valid_for_checker_images =
+ tile->draw_info().is_checker_imaged() &&
+ tiling_->ShouldDecodeCheckeredImagesForTile(tile);
+ if (!tile_is_valid_for_checker_images)
+ return false;
+ }
+
// After the pending visible rect has been processed, we must return false
// for pending visible rect tiles as tiling iterators do not ignore those
// tiles.
diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.h b/chromium/cc/tiles/tiling_set_raster_queue_all.h
index 318156380a1..73bb4c9e17b 100644
--- a/chromium/cc/tiles/tiling_set_raster_queue_all.h
+++ b/chromium/cc/tiles/tiling_set_raster_queue_all.h
@@ -44,9 +44,6 @@ class CC_EXPORT TilingSetRasterQueueAll {
protected:
~OnePriorityRectIterator() = default;
- bool TileNeedsRaster(const Tile* tile) const {
- return tile->draw_info().NeedsRaster() && !tiling_->IsTileOccluded(tile);
- }
template <typename TilingIteratorType>
void AdvanceToNextTile(TilingIteratorType* iterator);