blob: 3e00775bc8d51da494d3a874c880ed7e234c691a [file]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_PAINT_IMAGE_TRANSFER_CACHE_ENTRY_H_
#define CC_PAINT_IMAGE_TRANSFER_CACHE_ENTRY_H_
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <optional>
#include <vector>
#include "base/atomic_sequence_num.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "cc/paint/tone_map_util.h"
#include "cc/paint/transfer_cache_entry.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkYUVAInfo.h"
#include "third_party/skia/include/gpu/ganesh/GrTypes.h"
#include "third_party/skia/include/private/SkGainmapInfo.h"
#include "ui/gfx/color_space.h"
class GrDirectContext;
class SkColorSpace;
class SkImage;
class SkPixmap;
namespace cc {
static constexpr uint32_t kInvalidImageTransferCacheEntryId =
static_cast<uint32_t>(-1);
enum class YUVDecodeFormat {
kYUV3, // e.g., YUV 4:2:0, 4:2:2, or 4:4:4 as 3 planes.
kYUVA4, // e.g., YUV 4:2:0 as 3 planes plus an alpha plane.
kYVU3, // e.g., YVU 4:2:0, 4:2:2, or 4:4:4 as 3 planes.
kYUV2, // e.g., YUV 4:2:0 as NV12 (2 planes).
kUnknown,
kMaxValue = kUnknown,
};
CC_PAINT_EXPORT size_t NumberOfPlanesForYUVDecodeFormat(YUVDecodeFormat format);
// Client/ServiceImageTransferCacheEntry implement a transfer cache entry
// for transferring image data. On the client side, this is a CPU SkPixmap,
// on the service side the image is uploaded and is a GPU SkImage.
class CC_PAINT_EXPORT ClientImageTransferCacheEntry final
: public ClientTransferCacheEntryBase<TransferCacheEntryType::kImage> {
public:
// Abstraction around RGBA vs YUVA images.
struct CC_PAINT_EXPORT Image {
Image();
Image(const Image&);
Image& operator=(const Image&);
// Constructor for RGBA images.
explicit Image(const SkPixmap* pixmap);
// Constructor for YUVA images.
Image(base::span<const SkPixmap> yuva_pixmaps,
const SkYUVAInfo& yuva_info,
const SkColorSpace* color_space);
// The pixmaps for each plane.
std::array<const SkPixmap*, SkYUVAInfo::kMaxPlanes> pixmaps = {
nullptr, nullptr, nullptr, nullptr};
// The YUVA parameters. These should be unchanged for RGBA images.
SkYUVAInfo::PlaneConfig yuv_plane_config =
SkYUVAInfo::PlaneConfig::kUnknown;
SkYUVAInfo::Subsampling yuv_subsampling = SkYUVAInfo::Subsampling::kUnknown;
SkYUVColorSpace yuv_color_space = kIdentity_SkYUVColorSpace;
// The color space that will be assigned to the image when it is
// deserialized.
raw_ptr<const SkColorSpace> color_space = nullptr;
};
ClientImageTransferCacheEntry(
const Image& image,
bool needs_mips,
sk_sp<SkColorSpace> target_color_space = nullptr);
ClientImageTransferCacheEntry(const Image& image,
const Image& gainmap_image,
const SkGainmapInfo& gainmap_info,
bool needs_mips);
~ClientImageTransferCacheEntry() final;
uint32_t Id() const final;
// ClientTransferCacheEntry implementation:
uint32_t SerializedSize() const final;
bool Serialize(base::span<uint8_t> data) const final;
static uint32_t GetNextId() { return s_next_id_.GetNext(); }
bool IsYuv() const {
return image_.yuv_plane_config != SkYUVAInfo::PlaneConfig::kUnknown;
}
bool IsValid() const { return size_ > 0; }
private:
void ComputeSize();
const bool needs_mips_ = false;
sk_sp<SkColorSpace> target_color_space_;
const uint32_t id_;
uint32_t size_ = 0;
static base::AtomicSequenceNumber s_next_id_;
Image image_;
// The gainmap image and parameters. Either both or neither of these must
// be specified.
std::optional<Image> gainmap_image_;
std::optional<SkGainmapInfo> gainmap_info_;
};
class CC_PAINT_EXPORT ServiceImageTransferCacheEntry final
: public ServiceTransferCacheEntryBase<TransferCacheEntryType::kImage> {
public:
ServiceImageTransferCacheEntry();
~ServiceImageTransferCacheEntry() final;
ServiceImageTransferCacheEntry(ServiceImageTransferCacheEntry&& other);
ServiceImageTransferCacheEntry& operator=(
ServiceImageTransferCacheEntry&& other);
// ServiceTransferCacheEntry implementation:
size_t CachedSize() const final;
bool Deserialize(GrDirectContext* gr_context,
skgpu::graphite::Recorder* graphite_recorder,
base::span<const uint8_t> data) final;
const sk_sp<SkImage>& image() const { return image_; }
bool HasGainmap() const { return gainmap_image_ != nullptr; }
const sk_sp<SkImage>& gainmap_image() const { return gainmap_image_; }
const SkGainmapInfo& gainmap_info() const { return gainmap_info_; }
// Ensures the cached image has mips.
void EnsureMips();
// Used in tests and for registering each texture for memory dumps.
bool has_mips() const;
const std::vector<sk_sp<SkImage>>& plane_images() const {
return plane_images_;
}
const sk_sp<SkImage>& GetPlaneImage(size_t index) const;
const std::vector<size_t>& GetPlaneCachedSizes() const {
return plane_sizes_;
}
bool is_yuv() const { return !plane_images_.empty(); }
size_t num_planes() const { return plane_images_.size(); }
bool fits_on_gpu() const;
private:
raw_ptr<GrDirectContext> gr_context_ = nullptr;
raw_ptr<skgpu::graphite::Recorder> graphite_recorder_ = nullptr;
sk_sp<SkImage> image_;
// HDR local tone mapping may be done with a gainmap.
bool has_gainmap_ = false;
sk_sp<SkImage> gainmap_image_;
SkGainmapInfo gainmap_info_;
// The value of `size_` is computed during deserialization and never updated
// (even if the size of the image changes due to mipmaps being requested).
size_t size_ = 0;
// The individual planes that are used by `image_` when `image_` is a YUVA
// image. The planes are kept around for use in EnsureMips(), memory dumps,
// and unit tests.
std::optional<SkYUVAInfo> yuva_info_;
std::vector<sk_sp<SkImage>> plane_images_;
std::vector<size_t> plane_sizes_;
};
} // namespace cc
#endif // CC_PAINT_IMAGE_TRANSFER_CACHE_ENTRY_H_