blob: f59f5a276206acda1169fad4a746330d66c11a0d [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <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"
#include "third_party/skia/include/core/SkImage.h"
namespace cc {
class CC_EXPORT CheckerImageTrackerClient {
virtual ~CheckerImageTrackerClient() = default;
virtual void NeedsInvalidationForCheckerImagedTiles() = 0;
// CheckerImageTracker is used to track the set of images in a frame which are
// decoded asynchronously, using the ImageDecodeService, from the rasterization
// of tiles which depend on them. Once decoded, these images are stored for
// invalidation on the next sync tree. TakeImagesToInvalidateOnSyncTree will
// return this set and maintain a copy to keeps these images locked until the
// sync tree is activated.
// Note: It is illegal to call TakeImagesToInvalidateOnSyncTree for the next
// sync tree until the previous tree is activated.
class CC_EXPORT CheckerImageTracker {
// The priority type for a decode. Note we use int to specify a decreasing
// order of priority with higher values.
enum DecodeType : int {
// Priority for images on tiles being rasterized (visible or pre-paint).
kRaster = 0,
// Lowest priority for images on tiles in pre-decode region. These are tiles
// which are beyond the pre-paint region, but have their images decoded.
kPreDecode = 1,
kLast = kPreDecode
struct CC_EXPORT ImageDecodeRequest {
ImageDecodeRequest(PaintImage paint_image, DecodeType type);
PaintImage paint_image;
DecodeType type;
CheckerImageTracker(ImageController* image_controller,
CheckerImageTrackerClient* client,
bool enable_checker_imaging,
size_t min_image_bytes_to_checker);
CheckerImageTracker(const CheckerImageTracker&) = delete;
CheckerImageTracker& operator=(const CheckerImageTracker&) = delete;
// 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 DrawImage& image, WhichTree tree);
// Provides a prioritized queue of images to decode.
using ImageDecodeQueue = std::vector<ImageDecodeRequest>;
void ScheduleImageDecodeQueue(ImageDecodeQueue image_decode_queue);
// Disables scheduling any decode work by the tracker.
void SetNoDecodesAllowed();
// The max decode priority type that is allowed to run.
void SetMaxDecodePriorityAllowed(DecodeType decode_type);
// Returns the set of images to invalidate on the sync tree.
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);
// Informs the tracker to not checker the given image. This can be used to opt
// out of the checkering behavior for certain images, such as ones that were
// decoded using the img.decode api.
// Note that if the image is already being checkered, then it will continue to
// do so. This call is meant to be issued prior to the image appearing during
// raster.
void DisallowCheckeringForImage(const PaintImage& image);
void set_force_disabled(bool force_disabled) {
force_disabled_ = force_disabled;
void UpdateImageDecodingHints(
base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
bool has_locked_decodes_for_testing() const {
return !image_id_to_decode_.empty();
int decode_priority_allowed_for_testing() const {
return decode_priority_allowed_;
bool no_decodes_allowed_for_testing() const {
return decode_priority_allowed_ == kNoDecodeAllowedPriority;
PaintImage::DecodingMode get_decoding_mode_hint_for_testing(
PaintImage::Id id) {
CHECK(decoding_mode_map_.find(id) != decoding_mode_map_.end());
return decoding_mode_map_[id];
static const int kNoDecodeAllowedPriority;
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.
// The image has been decoded asynchronously once and should now be
// synchronously rasterized with the content or the image has been
// permanently vetoed from being decoded async.
// Contains the information to construct a DrawImage from PaintImage when
// queuing the image decode.
struct DecodeState {
DecodePolicy policy = DecodePolicy::SYNC;
SkFilterQuality filter_quality = kNone_SkFilterQuality;
SkSize scale = SkSize::MakeEmpty();
size_t frame_index = PaintImage::kDefaultFrameIndex;
// Wrapper to unlock an image decode requested from the ImageController on
// destruction.
class ScopedDecodeHolder {
ScopedDecodeHolder(ImageController* controller,
ImageController::ImageDecodeRequestId request_id)
: controller_(controller), request_id_(request_id) {}
ScopedDecodeHolder(const ScopedDecodeHolder&) = delete;
~ScopedDecodeHolder() { controller_->UnlockImageDecode(request_id_); }
ScopedDecodeHolder& operator=(const ScopedDecodeHolder&) = delete;
ImageController* controller_;
ImageController::ImageDecodeRequestId request_id_;
void DidFinishImageDecode(PaintImage::Id image_id,
ImageController::ImageDecodeRequestId request_id,
ImageController::ImageDecodeResult result);
// Called when the next request in the |image_decode_queue_| should be
// scheduled with the image decode service.
void ScheduleNextImageDecode();
void UpdateDecodeState(const DrawImage& draw_image,
PaintImage::Id paint_image_id,
DecodeState* decode_state);
ImageController* image_controller_;
CheckerImageTrackerClient* client_;
const bool enable_checker_imaging_;
const size_t min_image_bytes_to_checker_;
// Disables checkering of all images if set. As opposed to
// |enable_checker_imaging_|, this setting can be toggled.
bool force_disabled_ = false;
// A set of images which have been decoded and are pending invalidation for
// raster on the checkered tiles.
PaintImageIdFlatSet images_pending_invalidation_;
// A set of images which were invalidated on the 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_;
// The max decode type that is allowed to run, if decodes are allowed to run.
int decode_priority_allowed_ = kNoDecodeAllowedPriority;
// 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 map of ImageId to its DecodePolicy.
std::unordered_map<PaintImage::Id, DecodeState> image_async_decode_state_;
// A map of image id to image decode request id for images to be unlocked.
std::unordered_map<PaintImage::Id, std::unique_ptr<ScopedDecodeHolder>>
base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map_;
base::WeakPtrFactory<CheckerImageTracker> weak_factory_;
} // namespace cc