diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc index 140365b0304089..4f1bdc1e600be7 100644 --- a/cc/paint/paint_image.cc +++ b/cc/paint/paint_image.cc @@ -212,19 +212,14 @@ bool PaintImage::Decode(void* memory, client_id); } -bool PaintImage::DecodeYuv( - void* planes[SkYUVASizeInfo::kMaxCount], - size_t frame_index, - GeneratorClientId client_id, - const SkYUVASizeInfo& yuva_size_info, - SkColorType color_type, - SkYUVAIndex plane_indices[SkYUVAIndex::kIndexCount]) const { - DCHECK(plane_indices != nullptr); +bool PaintImage::DecodeYuv(const SkYUVAPixmaps& pixmaps, + size_t frame_index, + GeneratorClientId client_id) const { + DCHECK(pixmaps.isValid()); DCHECK(paint_image_generator_); const uint32_t lazy_pixel_ref = unique_id(); - return paint_image_generator_->GetYUVAPlanes(yuva_size_info, color_type, - plane_indices, planes, - frame_index, lazy_pixel_ref); + return paint_image_generator_->GetYUVAPlanes(pixmaps, frame_index, + lazy_pixel_ref); } bool PaintImage::DecodeFromGenerator(void* memory, @@ -347,31 +342,16 @@ const ImageHeaderMetadata* PaintImage::GetImageHeaderMetadata() const { return nullptr; } -bool PaintImage::IsYuv(SkYUVASizeInfo* yuva_size_info, - SkYUVAIndex* plane_indices, - SkYUVColorSpace* yuv_color_space, - uint8_t* bit_depth) const { - SkYUVASizeInfo temp_yuva_size_info; - SkYUVAIndex temp_plane_indices[SkYUVAIndex::kIndexCount]; - SkYUVColorSpace temp_yuv_color_space; - uint8_t temp_bit_depth; - if (!yuva_size_info) { - yuva_size_info = &temp_yuva_size_info; - } - if (!plane_indices) { - plane_indices = temp_plane_indices; - } - if (!yuv_color_space) { - yuv_color_space = &temp_yuv_color_space; - } - if (!bit_depth) { - bit_depth = &temp_bit_depth; - } - // ImageDecoder will fill out the value of |yuv_color_space| depending on - // the codec's specification. +bool PaintImage::IsYuv( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* info) const { + SkYUVAPixmapInfo temp_info; + if (!info) + info = &temp_info; + // ImageDecoder will fill out the SkYUVColorSpace in |info| depending on the + // codec's specification. return paint_image_generator_ && - paint_image_generator_->QueryYUVA(yuva_size_info, plane_indices, - yuv_color_space, bit_depth); + paint_image_generator_->QueryYUVA(supported_data_types, info); } const std::vector& PaintImage::GetFrameMetadata() const { @@ -421,7 +401,8 @@ std::string PaintImage::ToString() const { << " id_: " << id_ << " animation_type_: " << static_cast(animation_type_) << " completion_state_: " << static_cast(completion_state_) - << " is_multipart_: " << is_multipart_ << " is YUV: " << IsYuv(); + << " is_multipart_: " << is_multipart_ + << " is YUV: " << IsYuv(SkYUVAPixmapInfo::SupportedDataTypes::All()); return str.str(); } diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index 0e9c31e869e602..d9f18fba1a3ac7 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h @@ -16,8 +16,7 @@ #include "cc/paint/paint_export.h" #include "gpu/command_buffer/common/mailbox.h" #include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/core/SkYUVAIndex.h" -#include "third_party/skia/include/core/SkYUVASizeInfo.h" +#include "third_party/skia/include/core/SkYUVAPixmaps.h" #include "ui/gfx/display_color_spaces.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -34,6 +33,11 @@ enum class ImageType { kPNG, kJPEG, kWEBP, kGIF, kICO, kBMP, kAVIF, kInvalid }; enum class YUVSubsampling { k410, k411, k420, k422, k440, k444, kUnknown }; +enum class YUVIndex { kY, kU, kV }; + +// Should match the number of YUVIndex values. +static constexpr int kNumYUVPlanes = 3; + struct CC_PAINT_EXPORT ImageHeaderMetadata { public: ImageHeaderMetadata(); @@ -206,29 +210,16 @@ class CC_PAINT_EXPORT PaintImage { size_t frame_index, GeneratorClientId client_id) const; - // Decode the image into YUV into |planes| for the given SkYUVASizeInfo. - // - Elements of the |planes| array are pointers to some underlying memory - // for each plane. It is assumed to have been split up by a call to - // SkYUVASizeInfo::computePlanes with the given |yuva_size_info|. - // - The amount of memory allocated must be at least - // |yuva_size_info|.computeTotalBytes(), though there are places in the - // code that assume YUV420 without alpha because it is currently the only - // subsampling supported for direct YUV rendering. - // - The dimensions of YUV planes are tracked in |yuva_size_info|. - // This struct is initialized by QueryYUVA in calls to - // PaintImage::IsYuv(), including within this method. + // Decode the image into YUV into |pixmaps|. + // - SkPixmaps owned by |pixmaps| are preallocated to store the + // planar data. They must have have color types, row bytes, + // and sizes as indicated by PaintImage::IsYuv(). // - The |frame_index| parameter will be passed along to // ImageDecoder::DecodeToYUV but for multi-frame YUV support, ImageDecoder // needs a separate YUV frame buffer cache. - // - The mapping of source planes to channels is tracked by |plane_indices|. - // This struct is initialized by QueryYUVA in calls to - // PaintImage::IsYuv(), including within this method. - bool DecodeYuv(void* planes[SkYUVASizeInfo::kMaxCount], + bool DecodeYuv(const SkYUVAPixmaps& pixmaps, size_t frame_index, - GeneratorClientId client_id, - const SkYUVASizeInfo& yuva_size_info, - SkColorType yuva_color_type, - SkYUVAIndex* plane_indices) const; + GeneratorClientId client_id) const; // Returns the SkImage associated with this PaintImage. If PaintImage is // texture backed, this API will always do a readback from GPU to CPU memory, @@ -284,13 +275,12 @@ class CC_PAINT_EXPORT PaintImage { gfx::ContentColorUsage GetContentColorUsage() const; // Returns whether this image will be decoded and rendered from YUV data - // and fills out plane size info, plane index info, and the matrix for - // conversion from YUV to RGB in, respectively, |yuva_size_info|, - // |plane_indices|, and |yuv_color_space| if any are provided. - bool IsYuv(SkYUVASizeInfo* yuva_size_info = nullptr, - SkYUVAIndex* plane_indices = nullptr, - SkYUVColorSpace* yuv_color_space = nullptr, - uint8_t* bit_depth = nullptr) const; + // and fills out |info|. |supported_data_types| indicates the bit depths and + // data types allowed. If successful, the caller can use |info| to allocate + // SkPixmaps to pass DecodeYuv() and render with the correct YUV->RGB + // transformation. + bool IsYuv(const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* info = nullptr) const; // Get metadata associated with this image. SkColorType GetColorType() const; diff --git a/cc/paint/paint_image_generator.h b/cc/paint/paint_image_generator.h index 7e46f2d2511534..7c52f61681fff3 100644 --- a/cc/paint/paint_image_generator.h +++ b/cc/paint/paint_image_generator.h @@ -13,8 +13,7 @@ #include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkYUVAIndex.h" -#include "third_party/skia/include/core/SkYUVASizeInfo.h" +#include "third_party/skia/include/core/SkYUVAPixmaps.h" namespace cc { @@ -45,29 +44,24 @@ class CC_PAINT_EXPORT PaintImageGenerator : public SkRefCnt { PaintImage::GeneratorClientId client_id, uint32_t lazy_pixel_ref) = 0; - // Returns true if the generator supports YUV decoding, providing the output - // information in |info| and |color_space|. - virtual bool QueryYUVA(SkYUVASizeInfo* info, - SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - SkYUVColorSpace* color_space, - uint8_t* bit_depth) const = 0; - - // Decodes to YUV into the provided |planes| for each of the Y, U, and V - // planes, and returns true on success. The method should only be used if - // QueryYUVA returns true. - // |info| and |indices| need to exactly match the values returned by the - // query, except the info.fWidthBytes may be larger than the recommendation - // (but not smaller). + // Returns true if the generator supports YUV decoding, providing the details + // about planar configuration and conversion to RGB in |info|. + // |supported_data_types| indicates the allowed bit depth and types allowed + // for Y, U, V, and A values. + virtual bool QueryYUVA( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* info) const = 0; + + // Decodes to YUV, storing planar data in the SkPixmaps in the provided + // |pixmaps|. The method should only be used if QueryYUVA returns true. + // SkPixmaps owned by |pixmaps| have been configured as indicated by + // QueryYUVA. // // TODO(khushalsagar): |lazy_pixel_ref| is only present for // DecodingImageGenerator tracing needs. Remove it. - virtual bool GetYUVAPlanes( - const SkYUVASizeInfo& info, - SkColorType color_type, - const SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - void* planes[3], - size_t frame_index, - uint32_t lazy_pixel_ref) = 0; + virtual bool GetYUVAPlanes(const SkYUVAPixmaps& pixmaps, + size_t frame_index, + uint32_t lazy_pixel_ref) = 0; // Returns the smallest size that is at least as big as the requested size, // such that we can decode to exactly that scale. diff --git a/cc/paint/paint_image_unittest.cc b/cc/paint/paint_image_unittest.cc index dfda9aa18e90cf..6de36fe986bf1d 100644 --- a/cc/paint/paint_image_unittest.cc +++ b/cc/paint/paint_image_unittest.cc @@ -74,44 +74,30 @@ TEST(PaintImageTest, GetSkImageForFrameNotGeneratorBacked) { TEST(PaintImageTest, DecodeToYuv420NoAlpha) { const SkISize full_size = SkISize::Make(10, 10); - const SkISize uv_size = SkISize::Make(5, 5); - SkYUVASizeInfo yuva_size_info; - yuva_size_info.fSizes[SkYUVAIndex::kY_Index] = full_size; - yuva_size_info.fWidthBytes[SkYUVAIndex::kY_Index] = - base::checked_cast(full_size.width()); - - yuva_size_info.fSizes[SkYUVAIndex::kU_Index] = uv_size; - yuva_size_info.fWidthBytes[SkYUVAIndex::kU_Index] = - base::checked_cast(uv_size.width()); - - yuva_size_info.fSizes[SkYUVAIndex::kV_Index] = uv_size; - yuva_size_info.fWidthBytes[SkYUVAIndex::kV_Index] = - base::checked_cast(uv_size.width()); - - yuva_size_info.fSizes[SkYUVAIndex::kA_Index] = SkISize::MakeEmpty(); - yuva_size_info.fWidthBytes[SkYUVAIndex::kA_Index] = 0u; - + SkYUVAInfo yuva_info(full_size, SkYUVAInfo::PlanarConfig::kY_U_V_420, + kJPEG_Full_SkYUVColorSpace); + SkYUVAPixmapInfo yuva_pixmap_info(yuva_info, + SkYUVAPixmapInfo::DataType::kUnorm8, + /*row bytes*/ nullptr); sk_sp yuv_generator = sk_make_sp(SkImageInfo::MakeN32Premul(full_size), - yuva_size_info); + yuva_pixmap_info); PaintImage image = PaintImageBuilder::WithDefault() .set_id(PaintImage::GetNextId()) .set_paint_image_generator(yuv_generator) .TakePaintImage(); - std::vector memory(yuva_size_info.computeTotalBytes()); - void* planes[SkYUVASizeInfo::kMaxCount]; - yuva_size_info.computePlanes(memory.data(), planes); + std::vector memory(yuva_pixmap_info.computeTotalBytes()); + auto pixmaps = + SkYUVAPixmaps::FromExternalMemory(yuva_pixmap_info, memory.data()); - SkYUVASizeInfo image_yuv_size_info; - SkYUVAIndex image_plane_indices[SkYUVAIndex::kIndexCount]; - ASSERT_TRUE(image.IsYuv(&image_yuv_size_info, image_plane_indices)); - ASSERT_EQ(yuva_size_info, image_yuv_size_info); + SkYUVAPixmapInfo image_yuva_pixmap_info; + ASSERT_TRUE(image.IsYuv(SkYUVAPixmapInfo::SupportedDataTypes::All(), + &image_yuva_pixmap_info)); + ASSERT_EQ(yuva_pixmap_info, image_yuva_pixmap_info); - SkYUVAIndex plane_indices[SkYUVAIndex::kIndexCount]; - image.DecodeYuv(planes, 1u /* frame_index */, - PaintImage::kDefaultGeneratorClientId, yuva_size_info, - kGray_8_SkColorType /* color_type */, plane_indices); + image.DecodeYuv(pixmaps, 1u /* frame_index */, + PaintImage::kDefaultGeneratorClientId); ASSERT_EQ(yuv_generator->frames_decoded().size(), 1u); EXPECT_EQ(yuv_generator->frames_decoded().count(1u), 1u); yuv_generator->reset_frames_decoded(); diff --git a/cc/paint/skia_paint_image_generator.cc b/cc/paint/skia_paint_image_generator.cc index c92416f919f30d..a66916d38b995c 100644 --- a/cc/paint/skia_paint_image_generator.cc +++ b/cc/paint/skia_paint_image_generator.cc @@ -33,23 +33,20 @@ bool SkiaPaintImageGenerator::onGetPixels(const SkImageInfo& info, info, pixels, row_bytes, frame_index_, client_id_, uniqueID()); } -bool SkiaPaintImageGenerator::onQueryYUVA8( - SkYUVASizeInfo* size_info, - SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - SkYUVColorSpace* color_space) const { - // Only 8-bit YUV is supported by the SkImageGenerator. - uint8_t bit_depth = 8; - const bool result = paint_image_generator_->QueryYUVA( - size_info, indices, color_space, &bit_depth); - return result && bit_depth == 8; +bool SkiaPaintImageGenerator::onQueryYUVAInfo( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* yuva_pixmap_info) const { + if (!paint_image_generator_->QueryYUVA(supported_data_types, + yuva_pixmap_info)) { + return false; + } + // TODO(skbug.com/10632): Enable other bit depths now that they are supported + // by SkImageGenerator. There's no known reason that this should not work. + return yuva_pixmap_info->dataType() == SkYUVAPixmapInfo::DataType::kUnorm8; } -bool SkiaPaintImageGenerator::onGetYUVA8Planes( - const SkYUVASizeInfo& size_info, - const SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - void* planes[4]) { - return paint_image_generator_->GetYUVAPlanes(size_info, kGray_8_SkColorType, - indices, planes, frame_index_, +bool SkiaPaintImageGenerator::onGetYUVAPlanes(const SkYUVAPixmaps& planes) { + return paint_image_generator_->GetYUVAPlanes(planes, frame_index_, uniqueID()); } diff --git a/cc/paint/skia_paint_image_generator.h b/cc/paint/skia_paint_image_generator.h index a3c2cedc957244..49a438c03d3ae8 100644 --- a/cc/paint/skia_paint_image_generator.h +++ b/cc/paint/skia_paint_image_generator.h @@ -27,12 +27,12 @@ class CC_PAINT_EXPORT SkiaPaintImageGenerator final : public SkImageGenerator { void* pixels, size_t row_bytes, const Options& options) override; - bool onQueryYUVA8(SkYUVASizeInfo* size_info, - SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - SkYUVColorSpace* color_space) const override; - bool onGetYUVA8Planes(const SkYUVASizeInfo& size_info, - const SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - void* planes[3]) override; + + bool onQueryYUVAInfo( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* yuva_pixmap_info) const override; + + bool onGetYUVAPlanes(const SkYUVAPixmaps& planes) override; private: sk_sp paint_image_generator_; diff --git a/cc/test/fake_paint_image_generator.cc b/cc/test/fake_paint_image_generator.cc index 5a32e1c9db6b46..9ad1d8e6770d8a 100644 --- a/cc/test/fake_paint_image_generator.cc +++ b/cc/test/fake_paint_image_generator.cc @@ -22,19 +22,18 @@ FakePaintImageGenerator::FakePaintImageGenerator( FakePaintImageGenerator::FakePaintImageGenerator( const SkImageInfo& info, - const SkYUVASizeInfo& yuva_size_info, - uint8_t yuva_bit_depth, + const SkYUVAPixmapInfo& yuva_pixmap_info, std::vector frames, bool allocate_discardable_memory, std::vector supported_sizes) : PaintImageGenerator(info, std::move(frames)), - image_backing_memory_( - allocate_discardable_memory ? yuva_size_info.computeTotalBytes() : 0, - 0), + image_backing_memory_(allocate_discardable_memory + ? yuva_pixmap_info.computeTotalBytes() + : 0, + 0), supported_sizes_(std::move(supported_sizes)), is_yuv_(true), - yuva_size_info_(yuva_size_info), - yuva_bit_depth_(yuva_bit_depth) {} + yuva_pixmap_info_(yuva_pixmap_info) {} FakePaintImageGenerator::~FakePaintImageGenerator() = default; @@ -66,35 +65,30 @@ bool FakePaintImageGenerator::GetPixels(const SkImageInfo& info, return true; } -bool FakePaintImageGenerator::QueryYUVA(SkYUVASizeInfo* yuv_info, - SkYUVAIndex indices[], - SkYUVColorSpace* color_space, - uint8_t* bit_depth) const { +bool FakePaintImageGenerator::QueryYUVA( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* yuva_pixmap_info) const { if (!is_yuv_) return false; - *yuv_info = yuva_size_info_; - *bit_depth = yuva_bit_depth_; - return true; + + *yuva_pixmap_info = yuva_pixmap_info_; + return yuva_pixmap_info->isSupported(supported_data_types); } -bool FakePaintImageGenerator::GetYUVAPlanes(const SkYUVASizeInfo& yuv_info, - SkColorType color_type, - const SkYUVAIndex indices[], - void* planes[4], +bool FakePaintImageGenerator::GetYUVAPlanes(const SkYUVAPixmaps& pixmaps, size_t frame_index, uint32_t lazy_pixel_ref) { CHECK(is_yuv_); CHECK(!expect_fallback_to_rgb_); if (image_backing_memory_.empty()) return false; - int numPlanes = SkYUVASizeInfo::kMaxCount; - void* src_planes[numPlanes]; - yuv_info.computePlanes(image_backing_memory_.data(), src_planes); - for (int i = 0; i < numPlanes; ++i) { - size_t bytes_for_plane_i = - yuv_info.fWidthBytes[i] * - base::checked_cast(yuv_info.fSizes[i].height()); - memcpy(planes[i], src_planes[i], bytes_for_plane_i); + size_t plane_sizes[SkYUVAInfo::kMaxPlanes]; + yuva_pixmap_info_.computeTotalBytes(plane_sizes); + uint8_t* src_plane_memory = image_backing_memory_.data(); + int num_planes = pixmaps.numPlanes(); + for (int i = 0; i < num_planes; ++i) { + memcpy(pixmaps.plane(i).writable_addr(), src_plane_memory, plane_sizes[i]); + src_plane_memory += plane_sizes[i]; } if (frames_decoded_count_.find(frame_index) == frames_decoded_count_.end()) frames_decoded_count_[frame_index] = 1; diff --git a/cc/test/fake_paint_image_generator.h b/cc/test/fake_paint_image_generator.h index 935f6e2e03a84c..420808e7871a9f 100644 --- a/cc/test/fake_paint_image_generator.h +++ b/cc/test/fake_paint_image_generator.h @@ -9,6 +9,7 @@ #include "base/containers/flat_map.h" #include "cc/paint/paint_image_generator.h" +#include "third_party/skia/include/core/SkYUVAPixmaps.h" namespace cc { @@ -23,8 +24,7 @@ class FakePaintImageGenerator : public PaintImageGenerator { // YUV decoding mode constructor. explicit FakePaintImageGenerator( const SkImageInfo& info, - const SkYUVASizeInfo& yuva_size_info, - uint8_t yuva_bit_depth = 8, + const SkYUVAPixmapInfo& yuva_pixmap_info, std::vector frames = {FrameMetadata()}, bool allocate_discardable_memory = true, std::vector supported_sizes = {}); @@ -41,14 +41,10 @@ class FakePaintImageGenerator : public PaintImageGenerator { size_t frame_index, PaintImage::GeneratorClientId client_id, uint32_t lazy_pixel_ref) override; - bool QueryYUVA(SkYUVASizeInfo* info, - SkYUVAIndex indices[], - SkYUVColorSpace* color_space, - uint8_t* bit_depth) const override; - bool GetYUVAPlanes(const SkYUVASizeInfo& info, - SkColorType color_type, - const SkYUVAIndex indices[], - void* planes[4], + bool QueryYUVA( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* yuva_pixmap_info) const override; + bool GetYUVAPlanes(const SkYUVAPixmaps& pixmaps, size_t frame_index, uint32_t lazy_pixel_ref) override; SkISize GetSupportedDecodeSize(const SkISize& requested_size) const override; @@ -74,8 +70,7 @@ class FakePaintImageGenerator : public PaintImageGenerator { std::vector supported_sizes_; std::vector decode_infos_; bool is_yuv_ = false; - SkYUVASizeInfo yuva_size_info_; - uint8_t yuva_bit_depth_; + SkYUVAPixmapInfo yuva_pixmap_info_; // TODO(skbug.com/8564): After Skia supports rendering from software YUV // planes and after Chrome implements it, we should no longer expect RGB // fallback. diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc index 32a825df2bc4f1..50a77285841b9c 100644 --- a/cc/test/skia_common.cc +++ b/cc/test/skia_common.cc @@ -100,52 +100,33 @@ PaintImage CreatePaintWorkletPaintImage( return paint_image; } -SkYUVASizeInfo GetYUVASizeInfo(const gfx::Size& image_size, - YUVSubsampling format, - uint8_t bytes_per_pixel, - bool has_alpha) { - SkISize uv_size; +SkYUVAPixmapInfo GetYUVAPixmapInfo(const gfx::Size& image_size, + YUVSubsampling format, + SkYUVAPixmapInfo::DataType yuv_data_type, + bool has_alpha) { + // TODO(skbug.com/10632): Update this when we have planar configs with alpha. + if (has_alpha) { + NOTREACHED(); + return SkYUVAPixmapInfo(); + } + SkYUVAInfo::PlanarConfig planar_config; switch (format) { case YUVSubsampling::k420: - // 4:2:0 has half sized width and height. - uv_size = SkISize::Make((image_size.width() + 1) / 2, - (image_size.height() + 1) / 2); + planar_config = SkYUVAInfo::PlanarConfig::kY_U_V_420; break; case YUVSubsampling::k422: - // 4:2:2 has half sized width. - uv_size = - SkISize::Make((image_size.width() + 1) / 2, image_size.height()); + planar_config = SkYUVAInfo::PlanarConfig::kY_U_V_422; break; case YUVSubsampling::k444: - // 4:4:4 has the same size for all planes. - uv_size = SkISize::Make(image_size.width(), image_size.height()); + planar_config = SkYUVAInfo::PlanarConfig::kY_U_V_444; break; default: NOTREACHED(); - return SkYUVASizeInfo(); - } - const size_t uv_width = base::checked_cast(uv_size.width()); - SkYUVASizeInfo yuva_size_info; - yuva_size_info.fSizes[SkYUVAIndex::kY_Index].set(image_size.width(), - image_size.height()); - yuva_size_info.fWidthBytes[SkYUVAIndex::kY_Index] = - base::checked_cast(image_size.width()) * bytes_per_pixel; - yuva_size_info.fSizes[SkYUVAIndex::kU_Index] = uv_size; - yuva_size_info.fWidthBytes[SkYUVAIndex::kU_Index] = - uv_width * bytes_per_pixel; - yuva_size_info.fSizes[SkYUVAIndex::kV_Index] = uv_size; - yuva_size_info.fWidthBytes[SkYUVAIndex::kV_Index] = - uv_width * bytes_per_pixel; - if (has_alpha) { - yuva_size_info.fSizes[SkYUVAIndex::kA_Index].set(image_size.width(), - image_size.height()); - yuva_size_info.fWidthBytes[SkYUVAIndex::kA_Index] = - base::checked_cast(image_size.width()) * bytes_per_pixel; - } else { - yuva_size_info.fSizes[SkYUVAIndex::kA_Index] = SkISize::MakeEmpty(); - yuva_size_info.fWidthBytes[SkYUVAIndex::kA_Index] = 0u; + return SkYUVAPixmapInfo(); } - return yuva_size_info; + SkYUVAInfo yuva_info({image_size.width(), image_size.height()}, planar_config, + kJPEG_Full_SkYUVColorSpace); + return SkYUVAPixmapInfo(yuva_info, yuv_data_type, /*row bytes*/ nullptr); } PaintImage CreateDiscardablePaintImage( @@ -155,7 +136,7 @@ PaintImage CreateDiscardablePaintImage( PaintImage::Id id, SkColorType color_type, base::Optional yuv_format, - uint8_t yuv_bytes_per_pixel) { + SkYUVAPixmapInfo::DataType yuv_data_type) { if (!color_space) color_space = SkColorSpace::MakeSRGB(); if (id == PaintImage::kInvalidId) @@ -165,9 +146,10 @@ PaintImage CreateDiscardablePaintImage( kPremul_SkAlphaType, color_space); sk_sp generator; if (yuv_format) { + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(size, *yuv_format, yuv_data_type); generator = sk_make_sp( - info, GetYUVASizeInfo(size, *yuv_format, yuv_bytes_per_pixel), - yuv_bytes_per_pixel * 8, std::vector{FrameMetadata()}, + info, yuva_pixmap_info, std::vector{FrameMetadata()}, allocate_encoded_data); } else { generator = sk_make_sp( diff --git a/cc/test/skia_common.h b/cc/test/skia_common.h index 8ec895e639edaf..eac05ad838f923 100644 --- a/cc/test/skia_common.h +++ b/cc/test/skia_common.h @@ -43,10 +43,10 @@ sk_sp CreatePaintImageGenerator(const gfx::Size& size); PaintImage CreatePaintWorkletPaintImage(scoped_refptr input); -SkYUVASizeInfo GetYUVASizeInfo(const gfx::Size& image_size, - YUVSubsampling yuv_format, - uint8_t bytes_per_pixel, - bool has_alpha = false); +SkYUVAPixmapInfo GetYUVAPixmapInfo(const gfx::Size& image_size, + YUVSubsampling yuv_format, + SkYUVAPixmapInfo::DataType yuv_data_type, + bool has_alpha = false); PaintImage CreateDiscardablePaintImage( const gfx::Size& size, @@ -55,7 +55,8 @@ PaintImage CreateDiscardablePaintImage( PaintImage::Id id = PaintImage::kInvalidId, SkColorType color_type = kN32_SkColorType, base::Optional yuv_format = base::nullopt, - uint8_t yuv_bytes_per_pixel = 1); + SkYUVAPixmapInfo::DataType yuv_data_type = + SkYUVAPixmapInfo::DataType::kUnorm8); DrawImage CreateDiscardableDrawImage(const gfx::Size& size, sk_sp color_space, diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index 1bb3886bdd47fd..b00bb6a26a7c0f 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc @@ -171,49 +171,6 @@ bool ShouldGenerateMips(const DrawImage& draw_image, return false; } -// This helper method takes in -// - |yuva_size_info| corresponding to the plane dimensions of a YUV image -// - |info| indicating SkAlphaType and SkColorSpace per plane (though the final -// image color space is currently indicated through other means at creation -// of the YUV SkImage) -// - |memory_ptr| pointing to sufficient contiguous memory for the planes -// -// It then sets each SkPixmap to have the dimensions specified by its respective -// SkYUVAIndex within |yuva_size_info| and to point to bytes in memory at -// |planes[index]|. -void SetYuvPixmapsFromSizeInfo(SkPixmap* pixmap_y, - SkPixmap* pixmap_u, - SkPixmap* pixmap_v, - const SkYUVASizeInfo& yuva_size_info, - void* planes[SkYUVASizeInfo::kMaxCount], - const SkImageInfo& info, - SkColorType color_type, - void* memory_ptr) { - DCHECK(pixmap_y); - DCHECK(pixmap_u); - DCHECK(pixmap_v); - const size_t y_width_bytes = - yuva_size_info.fWidthBytes[SkYUVAIndex::kY_Index]; - const size_t y_width = yuva_size_info.fSizes[SkYUVAIndex::kY_Index].width(); - const size_t y_height = yuva_size_info.fSizes[SkYUVAIndex::kY_Index].height(); - const size_t u_width_bytes = - yuva_size_info.fWidthBytes[SkYUVAIndex::kU_Index]; - const size_t u_width = yuva_size_info.fSizes[SkYUVAIndex::kU_Index].width(); - const size_t u_height = yuva_size_info.fSizes[SkYUVAIndex::kU_Index].height(); - const size_t v_width_bytes = - yuva_size_info.fWidthBytes[SkYUVAIndex::kV_Index]; - const size_t v_width = yuva_size_info.fSizes[SkYUVAIndex::kV_Index].width(); - const size_t v_height = yuva_size_info.fSizes[SkYUVAIndex::kV_Index].height(); - const SkImageInfo y_decode_info = - info.makeColorType(color_type).makeWH(y_width, y_height); - const SkImageInfo u_decode_info = y_decode_info.makeWH(u_width, u_height); - const SkImageInfo v_decode_info = y_decode_info.makeWH(v_width, v_height); - yuva_size_info.computePlanes(memory_ptr, planes); - pixmap_y->reset(y_decode_info, planes[SkYUVAIndex::kY_Index], y_width_bytes); - pixmap_u->reset(u_decode_info, planes[SkYUVAIndex::kU_Index], u_width_bytes); - pixmap_v->reset(v_decode_info, planes[SkYUVAIndex::kV_Index], v_width_bytes); -} - // Estimates the byte size of the decoded data for an image that goes through // hardware decode acceleration. The actual byte size is only known once the // image is decoded in the service side because different drivers have different @@ -268,16 +225,19 @@ size_t EstimateHardwareDecodedDataSize( // // The |do_yuv_decode| parameter indicates whether YUV decoding can and should // be done, which is a combination of the underlying data requesting YUV and the -// cache mode (i.e. OOP-R or not) supporting it. The |yuva_color_type| field -// indicates which SkColorType should be used for each plane. -bool DrawAndScaleImage(const DrawImage& draw_image, - SkPixmap* target_pixmap, - PaintImage::GeneratorClientId client_id, - const bool do_yuv_decode, - const SkColorType yuva_color_type = kGray_8_SkColorType, - SkPixmap* pixmap_y = nullptr, - SkPixmap* pixmap_u = nullptr, - SkPixmap* pixmap_v = nullptr) { +// cache mode (i.e. OOP-R or not) supporting it. The |yuva_data_type| field +// indicates the bit depth and type that should be used for Y, U, and V values. +bool DrawAndScaleImage( + const DrawImage& draw_image, + SkPixmap* target_pixmap, + PaintImage::GeneratorClientId client_id, + const bool do_yuv_decode, + const SkYUVAPixmapInfo::SupportedDataTypes& yuva_supported_data_types, + const SkYUVAPixmapInfo::DataType yuva_data_type = + SkYUVAPixmapInfo::DataType::kUnorm8, + SkPixmap* pixmap_y = nullptr, + SkPixmap* pixmap_u = nullptr, + SkPixmap* pixmap_v = nullptr) { // We will pass color_space explicitly to PaintImage::Decode, so pull it out // of the pixmap and populate a stand-alone value. // Note: To pull colorspace out of the pixmap, we create a new pixmap with @@ -297,13 +257,18 @@ bool DrawAndScaleImage(const DrawImage& draw_image, const bool is_nearest_neighbor = draw_image.filter_quality() == kNone_SkFilterQuality; SkImageInfo info = pixmap.info(); - SkYUVASizeInfo yuva_size_info; - SkYUVAIndex plane_indices[SkYUVAIndex::kIndexCount]; + SkYUVAPixmapInfo yuva_pixmap_info; if (do_yuv_decode) { + DCHECK(pixmap_y); + DCHECK(pixmap_u); + DCHECK(pixmap_v); // If |do_yuv_decode| is true, IsYuv() must be true. const bool yuva_info_initialized = - paint_image.IsYuv(&yuva_size_info, plane_indices); + paint_image.IsYuv(yuva_supported_data_types, &yuva_pixmap_info); DCHECK(yuva_info_initialized); + DCHECK_EQ(yuva_pixmap_info.dataType(), yuva_data_type); + // Only tri-planar YUV with no alpha is currently supported. + DCHECK_EQ(yuva_pixmap_info.numPlanes(), 3); } SkISize supported_size = paint_image.GetSupportedDecodeSize(pixmap.bounds().size()); @@ -315,13 +280,15 @@ bool DrawAndScaleImage(const DrawImage& draw_image, is_original_decode || (!is_nearest_neighbor && !do_yuv_decode); if (supported_size == pixmap.bounds().size() && can_directly_decode) { if (do_yuv_decode) { - void* planes[SkYUVASizeInfo::kMaxCount]; - SetYuvPixmapsFromSizeInfo(pixmap_y, pixmap_u, pixmap_v, yuva_size_info, - planes, info, yuva_color_type, - pixmap.writable_addr()); - return paint_image.DecodeYuv(planes, draw_image.frame_index(), client_id, - yuva_size_info, yuva_color_type, - plane_indices); + SkYUVAPixmaps yuva_pixmaps = SkYUVAPixmaps::FromExternalMemory( + yuva_pixmap_info, pixmap.writable_addr()); + // Only tri-planar YUV with no alpha is currently supported. + DCHECK_EQ(yuva_pixmaps.numPlanes(), 3); + *pixmap_y = yuva_pixmaps.plane(0); + *pixmap_u = yuva_pixmaps.plane(1); + *pixmap_v = yuva_pixmaps.plane(2); + return paint_image.DecodeYuv(yuva_pixmaps, draw_image.frame_index(), + client_id); } return paint_image.Decode(pixmap.writable_addr(), &info, color_space, draw_image.frame_index(), client_id); @@ -336,15 +303,17 @@ bool DrawAndScaleImage(const DrawImage& draw_image, // YUV420 and the dimensions of |pixmap|. Resizing happens on a plane-by-plane // basis. SkImageInfo decode_info; + SkColorType yuva_color_type; if (do_yuv_decode) { - const size_t yuva_bytes = yuva_size_info.computeTotalBytes(); + const size_t yuva_bytes = yuva_pixmap_info.computeTotalBytes(); if (SkImageInfo::ByteSizeOverflowed(yuva_bytes)) { return false; } // We temporarily abuse the dimensions of the pixmap to ensure we allocate // the proper number of bytes, but the actual plane dimensions are stored in - // |yuva_size_info| and accessed within PaintImage::DecodeYuv() and below. - + // |yuva_pixmap_info| and accessed within PaintImage::DecodeYuv() and below. + yuva_color_type = SkYUVAPixmapInfo::DefaultColorTypeForDataType( + yuva_pixmap_info.dataType(), 1); decode_info = info.makeColorType(yuva_color_type).makeWH(yuva_bytes, 1); } else { SkISize decode_size = @@ -365,17 +334,18 @@ bool DrawAndScaleImage(const DrawImage& draw_image, return false; SkPixmap decode_pixmap = decode_bitmap.pixmap(); - void* planes[SkYUVASizeInfo::kMaxCount]; + SkYUVAPixmaps unscaled_yuva_pixmaps; if (do_yuv_decode) { - yuva_size_info.computePlanes(decode_pixmap.writable_addr(), planes); + unscaled_yuva_pixmaps = SkYUVAPixmaps::FromExternalMemory( + yuva_pixmap_info, decode_pixmap.writable_addr()); } bool initial_decode_failed = - do_yuv_decode ? !paint_image.DecodeYuv(planes, draw_image.frame_index(), - client_id, yuva_size_info, - yuva_color_type, plane_indices) - : !paint_image.Decode(decode_pixmap.writable_addr(), - &decode_info, color_space, - draw_image.frame_index(), client_id); + do_yuv_decode + ? !paint_image.DecodeYuv(unscaled_yuva_pixmaps, + draw_image.frame_index(), client_id) + : !paint_image.Decode(decode_pixmap.writable_addr(), &decode_info, + color_space, draw_image.frame_index(), + client_id); if (initial_decode_failed) return false; @@ -384,18 +354,7 @@ bool DrawAndScaleImage(const DrawImage& draw_image, decode_pixmap, &pixmap, filter_quality); } if (do_yuv_decode) { - SkPixmap unscaled_pixmap_y; - SkPixmap unscaled_pixmap_u; - SkPixmap unscaled_pixmap_v; - SetYuvPixmapsFromSizeInfo(&unscaled_pixmap_y, &unscaled_pixmap_u, - &unscaled_pixmap_v, yuva_size_info, planes, - decode_info, yuva_color_type, - decode_pixmap.writable_addr()); - const SkImageInfo y_info_scaled = info.makeColorType(yuva_color_type); - const auto& yuva_sizes = yuva_size_info.fSizes; - DCHECK(yuva_sizes[SkYUVAIndex::kU_Index] == - yuva_sizes[SkYUVAIndex::kV_Index]); // Always promote scaled images to 4:4:4 to avoid blurriness. By using the // same dimensions for the UV planes, we can avoid scaling them completely @@ -420,9 +379,9 @@ bool DrawAndScaleImage(const DrawImage& draw_image, v_info_scaled.minRowBytes()); const bool all_planes_scaled_successfully = - unscaled_pixmap_y.scalePixels(*pixmap_y, filter_quality) && - unscaled_pixmap_u.scalePixels(*pixmap_u, filter_quality) && - unscaled_pixmap_v.scalePixels(*pixmap_v, filter_quality); + unscaled_yuva_pixmaps.plane(0).scalePixels(*pixmap_y, filter_quality) && + unscaled_yuva_pixmaps.plane(1).scalePixels(*pixmap_u, filter_quality) && + unscaled_yuva_pixmaps.plane(2).scalePixels(*pixmap_v, filter_quality); return all_planes_scaled_successfully; } return decode_pixmap.scalePixels(pixmap, filter_quality); @@ -753,10 +712,10 @@ void GpuImageDecodeCache::DecodedImageData::SetLockedData( DCHECK(image_v); DCHECK(!image_yuv_planes_); data_ = std::move(data); - image_yuv_planes_ = std::array, SkYUVASizeInfo::kMaxCount>(); - image_yuv_planes_->at(SkYUVAIndex::kY_Index) = std::move(image_y); - image_yuv_planes_->at(SkYUVAIndex::kU_Index) = std::move(image_u); - image_yuv_planes_->at(SkYUVAIndex::kV_Index) = std::move(image_v); + image_yuv_planes_ = std::array, kNumYUVPlanes>(); + image_yuv_planes_->at(static_cast(YUVIndex::kY)) = std::move(image_y); + image_yuv_planes_->at(static_cast(YUVIndex::kU)) = std::move(image_u); + image_yuv_planes_->at(static_cast(YUVIndex::kV)) = std::move(image_v); OnSetLockedData(out_of_raster); } @@ -778,9 +737,9 @@ void GpuImageDecodeCache::DecodedImageData::ResetData() { if (data_) { if (is_yuv()) { DCHECK(image_yuv_planes_); - DCHECK(image_yuv_planes_->at(SkYUVAIndex::kY_Index)); - DCHECK(image_yuv_planes_->at(SkYUVAIndex::kU_Index)); - DCHECK(image_yuv_planes_->at(SkYUVAIndex::kV_Index)); + DCHECK(image_yuv_planes_->at(static_cast(YUVIndex::kY))); + DCHECK(image_yuv_planes_->at(static_cast(YUVIndex::kU))); + DCHECK(image_yuv_planes_->at(static_cast(YUVIndex::kV))); } else { DCHECK(image_); } @@ -850,16 +809,22 @@ void GpuImageDecodeCache::UploadedImageData::SetYuvImage( DCHECK(v_image_input); mode_ = Mode::kSkImage; - image_yuv_planes_ = std::array, SkYUVASizeInfo::kMaxCount>(); - image_yuv_planes_->at(SkYUVAIndex::kY_Index) = std::move(y_image_input); - image_yuv_planes_->at(SkYUVAIndex::kU_Index) = std::move(u_image_input); - image_yuv_planes_->at(SkYUVAIndex::kV_Index) = std::move(v_image_input); + image_yuv_planes_ = std::array, kNumYUVPlanes>(); + image_yuv_planes_->at(static_cast(YUVIndex::kY)) = + std::move(y_image_input); + image_yuv_planes_->at(static_cast(YUVIndex::kU)) = + std::move(u_image_input); + image_yuv_planes_->at(static_cast(YUVIndex::kV)) = + std::move(v_image_input); if (y_image()->isTextureBacked() && u_image()->isTextureBacked() && v_image()->isTextureBacked()) { - gl_plane_ids_ = std::array(); - gl_plane_ids_->at(SkYUVAIndex::kY_Index) = GlIdFromSkImage(y_image().get()); - gl_plane_ids_->at(SkYUVAIndex::kU_Index) = GlIdFromSkImage(u_image().get()); - gl_plane_ids_->at(SkYUVAIndex::kV_Index) = GlIdFromSkImage(v_image().get()); + gl_plane_ids_ = std::array(); + gl_plane_ids_->at(static_cast(YUVIndex::kY)) = + GlIdFromSkImage(y_image().get()); + gl_plane_ids_->at(static_cast(YUVIndex::kU)) = + GlIdFromSkImage(u_image().get()); + gl_plane_ids_->at(static_cast(YUVIndex::kV)) = + GlIdFromSkImage(v_image().get()); } } @@ -907,7 +872,7 @@ GpuImageDecodeCache::ImageData::ImageData( bool do_hardware_accelerated_decode, bool is_yuv_format, SkYUVColorSpace yuv_cs, - SkColorType yuv_ct) + SkYUVAPixmapInfo::DataType yuv_dt) : paint_image_id(paint_image_id), mode(mode), size(size), @@ -925,7 +890,7 @@ GpuImageDecodeCache::ImageData::ImageData( if (is_yuv) { DCHECK_LE(yuv_cs, SkYUVColorSpace::kLastEnum_SkYUVColorSpace); yuv_color_space = yuv_cs; - yuv_color_type = yuv_ct; + yuv_data_type = yuv_dt; } } @@ -1022,8 +987,15 @@ GpuImageDecodeCache::GpuImageDecodeCache( if (context_->GetLock()) context_lock.emplace(context_); const auto& caps = context_->ContextCapabilities(); - allow_yuv_r16_ext_decoding_ = caps.texture_norm16; - allow_yuv_luminance_f16_decoding_ = caps.texture_half_float_linear; + yuva_supported_data_types_.enableDataType( + SkYUVAPixmapInfo::DataType::kUnorm8, 1); + if (caps.texture_norm16) { + yuva_supported_data_types_.enableDataType( + SkYUVAPixmapInfo::DataType::kUnorm16, 1); + } else if (caps.texture_half_float_linear) { + yuva_supported_data_types_.enableDataType( + SkYUVAPixmapInfo::DataType::kFloat16, 1); + } } // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). @@ -1960,8 +1932,8 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image, SkPixmap pixmap_u; SkPixmap pixmap_v; if (!DrawAndScaleImage(draw_image, &pixmap, generator_client_id_, - image_data->is_yuv, - image_data->yuv_color_type.value(), &pixmap_y, + image_data->is_yuv, yuva_supported_data_types_, + image_data->yuv_data_type.value(), &pixmap_y, &pixmap_u, &pixmap_v)) { DLOG(ERROR) << "DrawAndScaleImage failed."; backing_memory->Unlock(); @@ -1973,7 +1945,7 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image, } } else { // RGBX decoding is the default path. if (!DrawAndScaleImage(draw_image, &pixmap, generator_client_id_, - image_data->is_yuv)) { + image_data->is_yuv, yuva_supported_data_types_)) { DLOG(ERROR) << "DrawAndScaleImage failed."; backing_memory->Unlock(); backing_memory.reset(); @@ -2374,42 +2346,26 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image, } } - SkYUVASizeInfo target_yuva_size_info; - // We fill out a default value for |yuv_color_space| and |yuv_color_type| but - // only fill out the base::Optional members in ImageData if it is YUV. - SkYUVColorSpace yuv_color_space = SkYUVColorSpace::kIdentity_SkYUVColorSpace; - SkColorType yuv_color_type = kGray_8_SkColorType; - uint8_t yuv_bit_depth = 8; - const bool is_yuv = - !do_hardware_accelerated_decode && - draw_image.paint_image().IsYuv(&target_yuva_size_info, - nullptr /* plane_indices */, - &yuv_color_space, &yuv_bit_depth) && - mode != DecodedDataMode::kCpu && !image_larger_than_max_texture && - (yuv_bit_depth == 8 || allow_yuv_r16_ext_decoding_ || - allow_yuv_luminance_f16_decoding_); + SkYUVAPixmapInfo yuva_pixmap_info; + const bool is_yuv = !do_hardware_accelerated_decode && + draw_image.paint_image().IsYuv(yuva_supported_data_types_, + &yuva_pixmap_info) && + mode != DecodedDataMode::kCpu && + !image_larger_than_max_texture; // TODO(crbug.com/910276): Change after alpha support. if (is_yuv) { - DCHECK_GE(yuv_bit_depth, 8u); - DCHECK_LE(yuv_bit_depth, 16); - if (yuv_bit_depth == 8) - yuv_color_type = kGray_8_SkColorType; - else if (allow_yuv_r16_ext_decoding_) - yuv_color_type = kA16_unorm_SkColorType; - else if (allow_yuv_luminance_f16_decoding_) - yuv_color_type = kA16_float_SkColorType; - if (upload_scale_mip_level > 0) { // Scaled decode. We always promote to 4:4:4 when scaling YUV to avoid // blurriness. See comment in DrawAndScaleImage() for details. const base::CheckedNumeric y_plane_size = - image_info.makeColorType(yuv_color_type).computeMinByteSize(); + image_info.makeColorType(yuva_pixmap_info.planeInfo(0).colorType()) + .computeMinByteSize(); DCHECK(!SkImageInfo::ByteSizeOverflowed(y_plane_size.ValueOrDie())); data_size = (3 * y_plane_size).ValueOrDie(); } else { // Original size decode. - data_size = target_yuva_size_info.computeTotalBytes(); + data_size = yuva_pixmap_info.computeTotalBytes(); DCHECK(!SkImageInfo::ByteSizeOverflowed(data_size)); } } @@ -2419,7 +2375,8 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image, draw_image.target_color_space(), CalculateDesiredFilterQuality(draw_image), upload_scale_mip_level, needs_mips, is_bitmap_backed, can_do_hardware_accelerated_decode, - do_hardware_accelerated_decode, is_yuv, yuv_color_space, yuv_color_type)); + do_hardware_accelerated_decode, is_yuv, yuva_pixmap_info.yuvColorSpace(), + yuva_pixmap_info.dataType())); } void GpuImageDecodeCache::WillAddCacheEntry(const DrawImage& draw_image) { @@ -2804,18 +2761,18 @@ sk_sp GpuImageDecodeCache::GetSWImageDecodeForTesting( // the YUV SkImage may flatten it to RGB or not be possible to request. sk_sp GpuImageDecodeCache::GetUploadedPlaneForTesting( const DrawImage& draw_image, - size_t index) { + YUVIndex index) { base::AutoLock lock(lock_); ImageData* image_data = GetImageDataForDrawImage( draw_image, InUseCacheKey::FromDrawImage(draw_image)); if (!image_data->is_yuv) return nullptr; switch (index) { - case SkYUVAIndex::kY_Index: + case YUVIndex::kY: return image_data->upload.y_image(); - case SkYUVAIndex::kU_Index: + case YUVIndex::kU: return image_data->upload.u_image(); - case SkYUVAIndex::kV_Index: + case YUVIndex::kV: return image_data->upload.v_image(); default: return nullptr; diff --git a/cc/tiles/gpu_image_decode_cache.h b/cc/tiles/gpu_image_decode_cache.h index a65ba52602752e..468b43ca12ec53 100644 --- a/cc/tiles/gpu_image_decode_cache.h +++ b/cc/tiles/gpu_image_decode_cache.h @@ -22,7 +22,7 @@ #include "cc/paint/image_transfer_cache_entry.h" #include "cc/tiles/image_decode_cache.h" #include "third_party/skia/include/core/SkRefCnt.h" -#include "third_party/skia/include/core/SkYUVAIndex.h" +#include "third_party/skia/include/core/SkYUVAInfo.h" #include "third_party/skia/include/gpu/gl/GrGLTypes.h" namespace viz { @@ -204,7 +204,7 @@ class CC_EXPORT GpuImageDecodeCache bool IsInPersistentCacheForTesting(const DrawImage& image) const; sk_sp GetSWImageDecodeForTesting(const DrawImage& image); sk_sp GetUploadedPlaneForTesting(const DrawImage& draw_image, - size_t index); + YUVIndex index); size_t paint_image_entries_count_for_testing() const { return paint_image_entries_.size(); } @@ -232,7 +232,7 @@ class CC_EXPORT GpuImageDecodeCache scoped_refptr task; protected: - using YUVSkImages = std::array, SkYUVASizeInfo::kMaxCount>; + using YUVSkImages = std::array, kNumYUVPlanes>; struct UsageStats { int lock_count = 1; @@ -278,15 +278,15 @@ class CC_EXPORT GpuImageDecodeCache } sk_sp y_image() const { - return plane_image_internal(SkYUVAIndex::kY_Index); + return plane_image_internal(YUVIndex::kY); } sk_sp u_image() const { - return plane_image_internal(SkYUVAIndex::kU_Index); + return plane_image_internal(YUVIndex::kU); } sk_sp v_image() const { - return plane_image_internal(SkYUVAIndex::kV_Index); + return plane_image_internal(YUVIndex::kV); } bool is_yuv() const { return image_yuv_planes_.has_value(); } @@ -310,12 +310,12 @@ class CC_EXPORT GpuImageDecodeCache private: void ReportUsageStats() const; - sk_sp plane_image_internal(const size_t plane_id) const { + sk_sp plane_image_internal(const YUVIndex yuv_index) const { DCHECK(is_locked()); DCHECK(image_yuv_planes_); - DCHECK_GT(image_yuv_planes_->size(), plane_id) + DCHECK_GT(image_yuv_planes_->size(), static_cast(yuv_index)) << "Requested reference to a plane_id that is not set"; - return image_yuv_planes_->at(plane_id); + return image_yuv_planes_->at(static_cast(yuv_index)); } const bool is_bitmap_backed_; @@ -358,33 +358,25 @@ class CC_EXPORT GpuImageDecodeCache return image_; } const sk_sp& y_image() const { - return plane_image_internal(SkYUVAIndex::kY_Index); + return plane_image_internal(YUVIndex::kY); } const sk_sp& u_image() const { - return plane_image_internal(SkYUVAIndex::kU_Index); + return plane_image_internal(YUVIndex::kU); } const sk_sp& v_image() const { - return plane_image_internal(SkYUVAIndex::kV_Index); + return plane_image_internal(YUVIndex::kV); } GrGLuint gl_id() const { DCHECK(mode_ == Mode::kSkImage || mode_ == Mode::kNone); return gl_id_; } - GrGLuint gl_y_id() const { - return gl_plane_id_internal(SkYUVAIndex::kY_Index); - } - GrGLuint gl_u_id() const { - return gl_plane_id_internal(SkYUVAIndex::kU_Index); - } - GrGLuint gl_v_id() const { - return gl_plane_id_internal(SkYUVAIndex::kV_Index); - } + GrGLuint gl_y_id() const { return gl_plane_id_internal(YUVIndex::kY); } + GrGLuint gl_u_id() const { return gl_plane_id_internal(YUVIndex::kU); } + GrGLuint gl_v_id() const { return gl_plane_id_internal(YUVIndex::kV); } // We consider an image to be valid YUV if all planes are non-null. bool has_yuv_planes() const { - static_assert(SkYUVAIndex::kLast_Index == SkYUVAIndex::kA_Index, - "Alpha plane isn't last in the YUV plane array"); if (!image_yuv_planes_) { return false; } @@ -422,27 +414,31 @@ class CC_EXPORT GpuImageDecodeCache if (!unmipped_yuv_images_) { unmipped_yuv_images_ = YUVSkImages(); } - unmipped_yuv_images_->at(SkYUVAIndex::kY_Index) = std::move(y_image); - unmipped_yuv_images_->at(SkYUVAIndex::kU_Index) = std::move(u_image); - unmipped_yuv_images_->at(SkYUVAIndex::kV_Index) = std::move(v_image); + unmipped_yuv_images_->at(static_cast(YUVIndex::kY)) = + std::move(y_image); + unmipped_yuv_images_->at(static_cast(YUVIndex::kU)) = + std::move(u_image); + unmipped_yuv_images_->at(static_cast(YUVIndex::kV)) = + std::move(v_image); } sk_sp take_unmipped_y_image() { - return take_unmipped_yuv_image_internal(SkYUVAIndex::kY_Index); + return take_unmipped_yuv_image_internal(YUVIndex::kY); } sk_sp take_unmipped_u_image() { - return take_unmipped_yuv_image_internal(SkYUVAIndex::kU_Index); + return take_unmipped_yuv_image_internal(YUVIndex::kU); } sk_sp take_unmipped_v_image() { - return take_unmipped_yuv_image_internal(SkYUVAIndex::kV_Index); + return take_unmipped_yuv_image_internal(YUVIndex::kV); } - sk_sp take_unmipped_yuv_image_internal(const size_t plane_id) { + sk_sp take_unmipped_yuv_image_internal(const YUVIndex yuv_index) { DCHECK(!is_locked_); - if (unmipped_yuv_images_ && unmipped_yuv_images_->size() > plane_id) { - return std::move(unmipped_yuv_images_->at(plane_id)); + const size_t index = static_cast(yuv_index); + if (unmipped_yuv_images_ && unmipped_yuv_images_->size() > index) { + return std::move(unmipped_yuv_images_->at(index)); } return nullptr; } @@ -457,20 +453,22 @@ class CC_EXPORT GpuImageDecodeCache void ReportUsageStats() const; - const sk_sp& plane_image_internal(const size_t plane_id) const { + const sk_sp& plane_image_internal(const YUVIndex yuv_index) const { DCHECK(mode_ == Mode::kSkImage || mode_ == Mode::kNone); DCHECK(image_yuv_planes_); - DCHECK_GT(image_yuv_planes_->size(), plane_id) + const size_t index = static_cast(yuv_index); + DCHECK_GT(image_yuv_planes_->size(), index) << "Requested reference to a plane_id that is not set"; - return image_yuv_planes_->at(plane_id); + return image_yuv_planes_->at(index); } - GrGLuint gl_plane_id_internal(const size_t plane_id) const { + GrGLuint gl_plane_id_internal(const YUVIndex yuv_index) const { DCHECK(mode_ == Mode::kSkImage || mode_ == Mode::kNone); DCHECK(gl_plane_ids_); - DCHECK_GT(gl_plane_ids_->size(), plane_id) + const size_t index = static_cast(yuv_index); + DCHECK_GT(gl_plane_ids_->size(), index) << "Requested GL id for a plane texture that is not uploaded"; - return gl_plane_ids_->at(plane_id); + return gl_plane_ids_->at(index); } Mode mode_ = Mode::kNone; @@ -482,8 +480,7 @@ class CC_EXPORT GpuImageDecodeCache // TODO(crbug/910276): Change after alpha support. bool is_alpha_ = false; GrGLuint gl_id_ = 0; - base::Optional> - gl_plane_ids_; + base::Optional> gl_plane_ids_; // Used if |mode_| == kTransferCache. base::Optional transfer_cache_id_; @@ -509,7 +506,7 @@ class CC_EXPORT GpuImageDecodeCache bool do_hardware_accelerated_decode, bool is_yuv_format, SkYUVColorSpace yuv_cs, - SkColorType yuv_ct); + SkYUVAPixmapInfo::DataType yuv_dt); bool IsGpuOrTransferCache() const; bool HasUploadedData() const; @@ -526,7 +523,7 @@ class CC_EXPORT GpuImageDecodeCache bool is_yuv; bool is_budgeted = false; base::Optional yuv_color_space; - base::Optional yuv_color_type; + base::Optional yuv_data_type; // If true, this image is no longer in our |persistent_cache_| and will be // deleted as soon as its ref count reaches zero. @@ -720,8 +717,7 @@ class CC_EXPORT GpuImageDecodeCache const PaintImage::GeneratorClientId generator_client_id_; bool allow_accelerated_jpeg_decodes_ = false; bool allow_accelerated_webp_decodes_ = false; - bool allow_yuv_r16_ext_decoding_ = false; - bool allow_yuv_luminance_f16_decoding_ = false; + SkYUVAPixmapInfo::SupportedDataTypes yuva_supported_data_types_; // All members below this point must only be accessed while holding |lock_|. // The exception are const members like |normal_max_cache_bytes_| that can diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc index 0cf832569102d3..812db27e58a3fa 100644 --- a/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/cc/tiles/gpu_image_decode_cache_unittest.cc @@ -418,7 +418,7 @@ class GpuImageDecodeCacheTest if (do_yuv_decode_) { return CreateDiscardablePaintImage( size, color_space, allocate_encoded_memory, id, color_type_, - yuv_format_, yuv_bytes_per_pixel_); + yuv_format_, yuv_data_type_); } return CreateDiscardablePaintImage( size, color_space, allocate_encoded_memory, id, color_type_); @@ -436,10 +436,9 @@ class GpuImageDecodeCacheTest kPremul_SkAlphaType, SkColorSpace::MakeSRGB()); sk_sp generator; if (do_yuv_decode_) { - generator = sk_make_sp( - info, - GetYUVASizeInfo(test_image_size, yuv_format_, yuv_bytes_per_pixel_), - yuv_bytes_per_pixel_ * 8); + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(test_image_size, yuv_format_, yuv_data_type_); + generator = sk_make_sp(info, yuva_pixmap_info); generator->SetExpectFallbackToRGB(); } else { generator = sk_make_sp(info); @@ -491,9 +490,10 @@ class GpuImageDecodeCacheTest size_t GetBytesNeededForSingleImage(gfx::Size image_dimensions) { if (do_yuv_decode_) { - return GetYUVASizeInfo(image_dimensions, yuv_format_, - yuv_bytes_per_pixel_) - .computeTotalBytes(); + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(image_dimensions, yuv_format_, yuv_data_type_); + + return yuva_pixmap_info.computeTotalBytes(); } const size_t test_image_area_bytes = base::checked_cast(image_dimensions.GetArea()); @@ -544,28 +544,24 @@ class GpuImageDecodeCacheTest const DrawImage& draw_image, const base::Optional transfer_cache_id, bool should_have_mips) { - for (size_t i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) { - // TODO(crbug.com/910276): Skip alpha plane until supported in cache. - if (i != SkYUVAIndex::kA_Index) { - sk_sp original_uploaded_plane; - if (use_transfer_cache_) { - DCHECK(transfer_cache_id.has_value()); - const uint32_t id = transfer_cache_id.value(); - auto* image_entry = - transfer_cache_helper_.GetEntryAs( - id); - original_uploaded_plane = image_entry->GetPlaneImage(i); - } else { - original_uploaded_plane = - cache->GetUploadedPlaneForTesting(draw_image, i); - } - - ASSERT_TRUE(original_uploaded_plane); - auto plane_with_mips = original_uploaded_plane->makeTextureImage( - context_provider()->GrContext(), GrMipMapped::kYes); - ASSERT_TRUE(plane_with_mips); - EXPECT_EQ(should_have_mips, original_uploaded_plane == plane_with_mips); + for (size_t i = 0; i < kNumYUVPlanes; ++i) { + sk_sp original_uploaded_plane; + if (use_transfer_cache_) { + DCHECK(transfer_cache_id.has_value()); + const uint32_t id = transfer_cache_id.value(); + auto* image_entry = + transfer_cache_helper_.GetEntryAs( + id); + original_uploaded_plane = image_entry->GetPlaneImage(i); + } else { + original_uploaded_plane = cache->GetUploadedPlaneForTesting( + draw_image, static_cast(i)); } + ASSERT_TRUE(original_uploaded_plane); + auto plane_with_mips = original_uploaded_plane->makeTextureImage( + context_provider()->GrContext(), GrMipMapped::kYes); + ASSERT_TRUE(plane_with_mips); + EXPECT_EQ(should_have_mips, original_uploaded_plane == plane_with_mips); } } @@ -573,32 +569,33 @@ class GpuImageDecodeCacheTest GpuImageDecodeCache* cache, const DrawImage& draw_image, const base::Optional transfer_cache_id, - const SkISize plane_sizes[SkYUVASizeInfo::kMaxCount], - SkColorType expected_type = kGray_8_SkColorType, + const SkISize plane_sizes[SkYUVAInfo::kMaxPlanes], + SkYUVAPixmapInfo::DataType expected_type = + SkYUVAPixmapInfo::DataType::kUnorm8, const SkColorSpace* expected_cs = nullptr) { - for (size_t i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) { - // TODO(crbug.com/910276): Skip alpha plane until supported in cache. - if (i != SkYUVAIndex::kA_Index) { - sk_sp uploaded_plane; - if (use_transfer_cache_) { - DCHECK(transfer_cache_id.has_value()); - const uint32_t id = transfer_cache_id.value(); - auto* image_entry = - transfer_cache_helper_.GetEntryAs( - id); - uploaded_plane = image_entry->GetPlaneImage(i); - } else { - uploaded_plane = cache->GetUploadedPlaneForTesting(draw_image, i); - } - ASSERT_TRUE(uploaded_plane); - EXPECT_EQ(plane_sizes[i], uploaded_plane->dimensions()); - EXPECT_EQ(expected_type, uploaded_plane->colorType()); - if (expected_cs && use_transfer_cache_) { - EXPECT_TRUE( - SkColorSpace::Equals(expected_cs, uploaded_plane->colorSpace())); - } else if (expected_cs) { - // In-process raster sets the ColorSpace on the composite SkImage. - } + SkColorType expected_color_type = + SkYUVAPixmapInfo::DefaultColorTypeForDataType(expected_type, 1); + for (size_t i = 0; i < kNumYUVPlanes; ++i) { + sk_sp uploaded_plane; + if (use_transfer_cache_) { + DCHECK(transfer_cache_id.has_value()); + const uint32_t id = transfer_cache_id.value(); + auto* image_entry = + transfer_cache_helper_.GetEntryAs( + id); + uploaded_plane = image_entry->GetPlaneImage(i); + } else { + uploaded_plane = cache->GetUploadedPlaneForTesting( + draw_image, static_cast(i)); + } + ASSERT_TRUE(uploaded_plane); + EXPECT_EQ(plane_sizes[i], uploaded_plane->dimensions()); + EXPECT_EQ(expected_color_type, uploaded_plane->colorType()); + if (expected_cs && use_transfer_cache_) { + EXPECT_TRUE( + SkColorSpace::Equals(expected_cs, uploaded_plane->colorSpace())); + } else if (expected_cs) { + // In-process raster sets the ColorSpace on the composite SkImage. } } } @@ -613,7 +610,8 @@ class GpuImageDecodeCacheTest scoped_refptr context_provider_; // Only used when |do_yuv_decode_| is true. - uint8_t yuv_bytes_per_pixel_ = 1; + SkYUVAPixmapInfo::DataType yuv_data_type_ = + SkYUVAPixmapInfo::DataType::kUnorm8; YUVSubsampling yuv_format_ = YUVSubsampling::k420; bool use_transfer_cache_; @@ -2067,13 +2065,15 @@ TEST_P(GpuImageDecodeCacheTest, CacheDecodesExpectedFrames) { SkImageInfo info = SkImageInfo::Make(test_image_size.width(), test_image_size.height(), color_type_, kPremul_SkAlphaType); - sk_sp generator = - do_yuv_decode_ ? sk_make_sp( - info, - GetYUVASizeInfo(test_image_size, yuv_format_, - yuv_bytes_per_pixel_), - yuv_bytes_per_pixel_ * 8, frames) - : sk_make_sp(info, frames); + sk_sp generator; + if (do_yuv_decode_) { + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(test_image_size, yuv_format_, yuv_data_type_); + generator = + sk_make_sp(info, yuva_pixmap_info, frames); + } else { + generator = sk_make_sp(info, frames); + } PaintImage image = PaintImageBuilder::WithDefault() .set_id(PaintImage::GetNextId()) .set_paint_image_generator(generator) @@ -2886,15 +2886,13 @@ TEST_P(GpuImageDecodeCacheTest, MipsAddedWhileOriginalInUse) { if (!use_transfer_cache_) { if (do_yuv_decode_) { DrawImage draw_image = draw_and_decoded_draw_image.image; - for (size_t i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) { - // TODO(crbug.com/910276): Skip alpha plane until supported in - // cache. - if (i != SkYUVAIndex::kA_Index) { - SkImage* plane_image = - cache->GetUploadedPlaneForTesting(draw_image, i).get(); - discardable_manager_.ExpectLocked( - GpuImageDecodeCache::GlIdFromSkImage(plane_image)); - } + for (size_t i = 0; i < kNumYUVPlanes; ++i) { + SkImage* plane_image = cache + ->GetUploadedPlaneForTesting( + draw_image, static_cast(i)) + .get(); + discardable_manager_.ExpectLocked( + GpuImageDecodeCache::GlIdFromSkImage(plane_image)); } } else { discardable_manager_.ExpectLocked( @@ -2958,10 +2956,12 @@ TEST_P(GpuImageDecodeCacheTest, // uploaded planes. CompareAllPlanesToMippedVersions(cache, draw_image, transfer_cache_entry_id, true /* should_have_mips */); - SkYUVASizeInfo yuv_size_info = GetYUVASizeInfo( - GetNormalImageSize(), yuv_format_, yuv_bytes_per_pixel_); + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(GetNormalImageSize(), yuv_format_, yuv_data_type_); + SkISize plane_sizes[SkYUVAInfo::kMaxPlanes]; + yuva_pixmap_info.yuvaInfo().planeDimensions(plane_sizes); VerifyUploadedPlaneSizes(cache, draw_image, transfer_cache_entry_id, - yuv_size_info.fSizes); + plane_sizes); cache->DrawWithImageFinished(draw_image, decoded_draw_image); cache->UnrefImage(draw_image); @@ -2989,9 +2989,14 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { return; } - auto decode_and_check_plane_sizes = [this](GpuImageDecodeCache* cache, - SkColorType yuv_color_type, - gfx::ColorSpace target_cs) { + auto decode_and_check_plane_sizes = [this]( + GpuImageDecodeCache* cache, + bool decodes_to_yuv, + SkYUVAPixmapInfo::DataType + yuv_data_type = SkYUVAPixmapInfo:: + DataType::kUnorm8, + gfx::ColorSpace target_cs = + gfx::ColorSpace::CreateSRGB()) { SkFilterQuality filter_quality = kMedium_SkFilterQuality; SkSize requires_decode_at_original_scale = SkSize::Make(0.8f, 0.8f); @@ -3003,10 +3008,9 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { // An unknown SkColorType means we expect fallback to RGB. PaintImage image = - yuv_color_type == kUnknown_SkColorType - ? CreatePaintImageForFallbackToRGB(GetNormalImageSize()) - : CreatePaintImageInternal(GetNormalImageSize(), - decoded_cs.ToSkColorSpace()); + decodes_to_yuv ? CreatePaintImageInternal(GetNormalImageSize(), + decoded_cs.ToSkColorSpace()) + : CreatePaintImageForFallbackToRGB(GetNormalImageSize()); float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel; if (target_cs.IsHDR()) @@ -3038,15 +3042,15 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { EXPECT_TRUE(decoded_draw_image.image()); EXPECT_TRUE(decoded_draw_image.image()->isTextureBacked()); - if (yuv_color_type != kUnknown_SkColorType) { + if (decodes_to_yuv) { // Skia will flatten a YUV SkImage upon calling makeTextureImage. Thus, we // must separately request mips for each plane and compare to the original // uploaded planes. CompareAllPlanesToMippedVersions(cache, draw_image, transfer_cache_entry_id, true /* should_have_mips */); - SkYUVASizeInfo yuv_size_info = GetYUVASizeInfo( - GetNormalImageSize(), yuv_format_, yuv_bytes_per_pixel_); + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(GetNormalImageSize(), yuv_format_, yuv_data_type_); // Decoded HDR images should have their SDR white level adjusted to match // the display so we avoid scaling them by variable SDR brightness levels. @@ -3054,8 +3058,10 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { ? decoded_cs.GetWithSDRWhiteLevel(sdr_white_level) : decoded_cs; + SkISize plane_sizes[SkYUVAInfo::kMaxPlanes]; + yuva_pixmap_info.yuvaInfo().planeDimensions(plane_sizes); VerifyUploadedPlaneSizes(cache, draw_image, transfer_cache_entry_id, - yuv_size_info.fSizes, yuv_color_type, + plane_sizes, yuv_data_type, expected_cs.ToSkColorSpace().get()); if (expected_cs.IsValid()) { @@ -3070,8 +3076,9 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { *transfer_cache_entry_id) ->is_yuv()); } else { - for (size_t plane = 0; plane < SkYUVASizeInfo::kMaxCount; ++plane) - EXPECT_FALSE(cache->GetUploadedPlaneForTesting(draw_image, plane)); + for (size_t plane = 0; plane < kNumYUVPlanes; ++plane) + EXPECT_FALSE(cache->GetUploadedPlaneForTesting( + draw_image, static_cast(plane))); } } @@ -3079,9 +3086,6 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { cache->UnrefImage(draw_image); }; - // Setup paint images and associated YUV info structs to be uint16_t based. - yuv_bytes_per_pixel_ = 2; - gpu::Capabilities original_caps; { // TODO(crbug.com/1110007): We shouldn't need to lock to get capabilities. @@ -3100,30 +3104,35 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { context_provider_->SetContextCapabilitiesOverride(r16_caps); auto r16_cache = CreateCache(); + yuv_data_type_ = SkYUVAPixmapInfo::DataType::kUnorm16; + yuv_format_ = YUVSubsampling::k420; - decode_and_check_plane_sizes(r16_cache.get(), kA16_unorm_SkColorType, + decode_and_check_plane_sizes(r16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kUnorm16, DefaultColorSpace()); yuv_format_ = YUVSubsampling::k422; - decode_and_check_plane_sizes(r16_cache.get(), kA16_unorm_SkColorType, + decode_and_check_plane_sizes(r16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kUnorm16, DefaultColorSpace()); yuv_format_ = YUVSubsampling::k444; - decode_and_check_plane_sizes(r16_cache.get(), kA16_unorm_SkColorType, + decode_and_check_plane_sizes(r16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kUnorm16, DefaultColorSpace()); // Verify HDR decoding has white level adjustment. yuv_format_ = YUVSubsampling::k420; - decode_and_check_plane_sizes(r16_cache.get(), kA16_unorm_SkColorType, - hdr_cs); + decode_and_check_plane_sizes(r16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kUnorm16, hdr_cs); yuv_format_ = YUVSubsampling::k422; - decode_and_check_plane_sizes(r16_cache.get(), kA16_unorm_SkColorType, - hdr_cs); + decode_and_check_plane_sizes(r16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kUnorm16, hdr_cs); yuv_format_ = YUVSubsampling::k444; - decode_and_check_plane_sizes(r16_cache.get(), kA16_unorm_SkColorType, - hdr_cs); + decode_and_check_plane_sizes(r16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kUnorm16, hdr_cs); } // Verify that half-float is used when R16 is not available. @@ -3134,30 +3143,35 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { context_provider_->SetContextCapabilitiesOverride(f16_caps); auto f16_cache = CreateCache(); + yuv_data_type_ = SkYUVAPixmapInfo::DataType::kFloat16; + yuv_format_ = YUVSubsampling::k420; - decode_and_check_plane_sizes(f16_cache.get(), kA16_float_SkColorType, + decode_and_check_plane_sizes(f16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kFloat16, DefaultColorSpace()); yuv_format_ = YUVSubsampling::k422; - decode_and_check_plane_sizes(f16_cache.get(), kA16_float_SkColorType, + decode_and_check_plane_sizes(f16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kFloat16, DefaultColorSpace()); yuv_format_ = YUVSubsampling::k444; - decode_and_check_plane_sizes(f16_cache.get(), kA16_float_SkColorType, + decode_and_check_plane_sizes(f16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kFloat16, DefaultColorSpace()); // Verify HDR decoding has white level adjustment. yuv_format_ = YUVSubsampling::k420; - decode_and_check_plane_sizes(f16_cache.get(), kA16_float_SkColorType, - hdr_cs); + decode_and_check_plane_sizes(f16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kFloat16, hdr_cs); yuv_format_ = YUVSubsampling::k422; - decode_and_check_plane_sizes(f16_cache.get(), kA16_float_SkColorType, - hdr_cs); + decode_and_check_plane_sizes(f16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kFloat16, hdr_cs); yuv_format_ = YUVSubsampling::k444; - decode_and_check_plane_sizes(f16_cache.get(), kA16_float_SkColorType, - hdr_cs); + decode_and_check_plane_sizes(f16_cache.get(), true, + SkYUVAPixmapInfo::DataType::kFloat16, hdr_cs); } // Verify YUV16 is unsupported when neither R16 or half-float are available. @@ -3168,17 +3182,16 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) { context_provider_->SetContextCapabilitiesOverride(no_yuv16_caps); auto no_yuv16_cache = CreateCache(); + yuv_data_type_ = SkYUVAPixmapInfo::DataType::kUnorm16; + yuv_format_ = YUVSubsampling::k420; - decode_and_check_plane_sizes(no_yuv16_cache.get(), kUnknown_SkColorType, - DefaultColorSpace()); + decode_and_check_plane_sizes(no_yuv16_cache.get(), false); yuv_format_ = YUVSubsampling::k422; - decode_and_check_plane_sizes(no_yuv16_cache.get(), kUnknown_SkColorType, - DefaultColorSpace()); + decode_and_check_plane_sizes(no_yuv16_cache.get(), false); yuv_format_ = YUVSubsampling::k444; - decode_and_check_plane_sizes(no_yuv16_cache.get(), kUnknown_SkColorType, - DefaultColorSpace()); + decode_and_check_plane_sizes(no_yuv16_cache.get(), false); } } @@ -3197,7 +3210,7 @@ TEST_P(GpuImageDecodeCacheTest, ScaledYUVDecodeScaledDrawCorrectlyMipsPlanes) { auto decode_and_check_plane_sizes = [this, cache = owned_cache.get()]( SkSize scaled_size, - const SkISize mipped_plane_sizes[SkYUVASizeInfo::kMaxCount]) { + const SkISize mipped_plane_sizes[SkYUVAInfo::kMaxPlanes]) { SkFilterQuality filter_quality = kMedium_SkFilterQuality; gfx::Size image_size = GetNormalImageSize(); @@ -3243,18 +3256,18 @@ TEST_P(GpuImageDecodeCacheTest, ScaledYUVDecodeScaledDrawCorrectlyMipsPlanes) { }; gfx::Size image_size = GetNormalImageSize(); - SkISize mipped_plane_sizes[SkYUVASizeInfo::kMaxCount]; + SkISize mipped_plane_sizes[kNumYUVPlanes]; SkSize less_than_half_scale = SkSize::Make(0.45f, 0.45f); // Because we intend to draw this image at 0.45 x 0.45 scale, we will upload // the Y plane at mip level 1 (corresponding to 1/2 the original size). - mipped_plane_sizes[SkYUVAIndex::kY_Index] = SkISize::Make( + mipped_plane_sizes[static_cast(YUVIndex::kY)] = SkISize::Make( (image_size.width() + 1) / 2, (image_size.height() + 1) / 2); - mipped_plane_sizes[SkYUVAIndex::kU_Index] = - mipped_plane_sizes[SkYUVAIndex::kY_Index]; - mipped_plane_sizes[SkYUVAIndex::kV_Index] = - mipped_plane_sizes[SkYUVAIndex::kY_Index]; + mipped_plane_sizes[static_cast(YUVIndex::kU)] = + mipped_plane_sizes[static_cast(YUVIndex::kY)]; + mipped_plane_sizes[static_cast(YUVIndex::kV)] = + mipped_plane_sizes[static_cast(YUVIndex::kY)]; // For 4:2:0, the chroma planes (U and V) should be uploaded at the same size // as the Y plane since they get promoted to 4:4:4 to avoid blurriness from @@ -3275,12 +3288,12 @@ TEST_P(GpuImageDecodeCacheTest, ScaledYUVDecodeScaledDrawCorrectlyMipsPlanes) { // Because we intend to draw this image at 0.20 x 0.20 scale, we will upload // the Y plane at mip level 2 (corresponding to 1/4 the original size). - mipped_plane_sizes[SkYUVAIndex::kY_Index] = SkISize::Make( + mipped_plane_sizes[static_cast(YUVIndex::kY)] = SkISize::Make( (image_size.width() + 1) / 4, (image_size.height() + 1) / 4); - mipped_plane_sizes[SkYUVAIndex::kU_Index] = - mipped_plane_sizes[SkYUVAIndex::kY_Index]; - mipped_plane_sizes[SkYUVAIndex::kV_Index] = - mipped_plane_sizes[SkYUVAIndex::kY_Index]; + mipped_plane_sizes[static_cast(YUVIndex::kU)] = + mipped_plane_sizes[static_cast(YUVIndex::kY)]; + mipped_plane_sizes[static_cast(YUVIndex::kV)] = + mipped_plane_sizes[static_cast(YUVIndex::kY)]; // For 4:2:0, the chroma planes (U and V) should be uploaded at the same size // as the Y plane since they get promoted to 4:4:4 to avoid blurriness from @@ -3392,11 +3405,9 @@ class GpuImageDecodeCacheWithAcceleratedDecodesTest color_type_, kPremul_SkAlphaType, SkColorSpace::MakeSRGB()); sk_sp generator; if (do_yuv_decode_) { - generator = sk_make_sp( - info, - GetYUVASizeInfo(image_data.image_size, yuv_format_, - yuv_bytes_per_pixel_), - yuv_bytes_per_pixel_ * 8); + SkYUVAPixmapInfo yuva_pixmap_info = + GetYUVAPixmapInfo(image_data.image_size, yuv_format_, yuv_data_type_); + generator = sk_make_sp(info, yuva_pixmap_info); } else { generator = sk_make_sp(info); } diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc index f6e682699d33c3..04e3061f74df65 100644 --- a/gpu/command_buffer/service/raster_decoder.cc +++ b/gpu/command_buffer/service/raster_decoder.cc @@ -65,6 +65,7 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurfaceProps.h" #include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/core/SkYUVAIndex.h" #include "third_party/skia/include/gpu/GrBackendSemaphore.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index bccd716ba0daf5..5242c00a0471b9 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc @@ -611,6 +611,34 @@ bool ValidFormatForDirectUploading(GrGLenum format, unsigned int type) { } } +bool VideoPixelFormatAsSkYUVAInfoPlanarConfig( + VideoPixelFormat format, + SkYUVAInfo::PlanarConfig* config) { + // TODO(skbug.com/10632): Add more formats, e.g. I420A, NV12, NV21 when Skia + // equivalents are added. + // The 9, 10, and 12 bit formats could be added here if GetYUVAPlanes() were + // updated to convert data to unorm16/float16. + switch (format) { + case PIXEL_FORMAT_I420: + if (config) { + *config = SkYUVAInfo::PlanarConfig::kY_U_V_420; + } + return true; + case PIXEL_FORMAT_I422: + if (config) { + *config = SkYUVAInfo::PlanarConfig::kY_U_V_422; + } + return true; + case PIXEL_FORMAT_I444: + if (config) { + *config = SkYUVAInfo::PlanarConfig::kY_U_V_444; + } + return true; + default: + return false; + } +} + } // anonymous namespace // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. @@ -641,75 +669,51 @@ class VideoImageGenerator : public cc::PaintImageGenerator { return true; } - bool QueryYUVA(SkYUVASizeInfo* sizeInfo, - SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - SkYUVColorSpace* color_space, - uint8_t* bit_depth) const override { + bool QueryYUVA(const SkYUVAPixmapInfo::SupportedDataTypes&, + SkYUVAPixmapInfo* info) const override { // Temporarily disabling this path to avoid creating YUV ImageData in // GpuImageDecodeCache. // TODO(crbug.com/921636): Restore the code below once YUV rendering support // is added for VideoImageGenerator. return false; #if 0 - if (!media::IsYuvPlanar(frame_->format()) || - // TODO(rileya): Skia currently doesn't support YUVA conversion. Remove - // this case once it does. As-is we will fall back on the pure-software - // path in this case. - frame_->format() == PIXEL_FORMAT_I420A) { + SkYUVAInfo::PlanarConfig planar_config; + if (!VideoPixelFormatAsSkYUVAInfoPlanarConfig(frame_->format(), + &planar_config)) { return false; } - - if (color_space) { - if (!frame_->ColorSpace().ToSkYUVColorSpace(color_space)) { + if (info) { + SkYUVColorSpace yuv_color_space; + if (!frame_->ColorSpace().ToSkYUVColorSpace(&yuv_color_space)) { // TODO(hubbe): This really should default to rec709 // https://crbug.com/828599 - *color_space = kRec601_SkYUVColorSpace; + yuv_color_space = kRec601_SkYUVColorSpace; } - } - - for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane; - ++plane) { - const gfx::Size size = - VideoFrame::PlaneSize(frame_->format(), plane, + // We use the Y plane size because it may get rounded up to an even size. + // Our implementation of GetYUVAPlanes expects this. + gfx::Size y_size = + VideoFrame::PlaneSize(frame_->format(), VideoFrame::kYPlane, gfx::Size(frame_->visible_rect().width(), frame_->visible_rect().height())); - sizeInfo->fSizes[plane].set(size.width(), size.height()); - sizeInfo->fWidthBytes[plane] = size.width(); + SkYUVAInfo yuva_info = SkYUVAInfo({y_size.width(), y_size.height()}, + planar_config, yuv_color_space); + *info = SkYUVAPixmapInfo(yuva_info, SkYUVAPixmapInfo::DataType::kUnorm8, + /* row bytes */ nullptr); } - sizeInfo->fSizes[VideoFrame::kAPlane] = SkISize::MakeEmpty(); - sizeInfo->fWidthBytes[VideoFrame::kAPlane] = 0; - - indices[SkYUVAIndex::kY_Index] = {VideoFrame::kYPlane, SkColorChannel::kR}; - indices[SkYUVAIndex::kU_Index] = {VideoFrame::kUPlane, SkColorChannel::kR}; - indices[SkYUVAIndex::kV_Index] = {VideoFrame::kVPlane, SkColorChannel::kR}; - indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR}; - return true; #endif } - bool GetYUVAPlanes(const SkYUVASizeInfo& sizeInfo, - SkColorType color_type, - const SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - void* planes[4], + bool GetYUVAPlanes(const SkYUVAPixmaps& pixmaps, size_t frame_index, uint32_t lazy_pixel_ref) override { DCHECK_EQ(frame_index, 0u); - media::VideoPixelFormat format = frame_->format(); - DCHECK(media::IsYuvPlanar(format) && format != PIXEL_FORMAT_I420A); - - for (int i = 0; i <= VideoFrame::kVPlane; ++i) { - if (sizeInfo.fSizes[i].isEmpty() || !sizeInfo.fWidthBytes[i]) { - return false; - } - } - if (!sizeInfo.fSizes[VideoFrame::kAPlane].isEmpty() || - sizeInfo.fWidthBytes[VideoFrame::kAPlane]) { + if (!VideoPixelFormatAsSkYUVAInfoPlanarConfig(frame_->format(), nullptr)) { return false; } - int numPlanes; - if (!SkYUVAIndex::AreValidIndices(indices, &numPlanes) || numPlanes != 3) { + + if (!pixmaps.plane(3).dimensions().isEmpty()) { return false; } @@ -719,8 +723,8 @@ class VideoImageGenerator : public cc::PaintImageGenerator { VideoFrame::PlaneSize(frame_->format(), plane, gfx::Size(frame_->visible_rect().width(), frame_->visible_rect().height())); - if (size.width() != sizeInfo.fSizes[plane].width() || - size.height() != sizeInfo.fSizes[plane].height()) { + if (size.width() != pixmaps.plane(plane).width() || + size.height() != pixmaps.plane(plane).height()) { return false; } @@ -739,11 +743,12 @@ class VideoImageGenerator : public cc::PaintImageGenerator { // Copy the frame to the supplied memory. // TODO: Find a way (API change?) to avoid this copy. - uint8_t* out_line = static_cast(planes[plane]); - int out_line_stride = sizeInfo.fWidthBytes[plane]; + uint8_t* out_line = + static_cast(pixmaps.plane(plane).writable_addr()); + int out_line_stride = static_cast(pixmaps.plane(plane).rowBytes()); uint8_t* in_line = frame_->data(plane) + offset; int in_line_stride = frame_->stride(plane); - int plane_height = sizeInfo.fSizes[plane].height(); + int plane_height = pixmaps.plane(plane).height(); int bytes_to_copy_per_line = std::min(out_line_stride, in_line_stride); libyuv::CopyPlane(in_line, in_line_stride, out_line, out_line_stride, bytes_to_copy_per_line, plane_height); diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc index 4656734f9fc597..a22f12f13d1dc3 100644 --- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc +++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc @@ -218,30 +218,19 @@ bool DecodingImageGenerator::GetPixels(const SkImageInfo& dst_info, } bool DecodingImageGenerator::QueryYUVA( - SkYUVASizeInfo* size_info, - SkYUVAIndex indices[SkYUVAIndex::kIndexCount], - SkYUVColorSpace* color_space, - uint8_t* bit_depth) const { + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* yuva_pixmap_info) const { if (!can_yuv_decode_) return false; - TRACE_EVENT0("blink", "DecodingImageGenerator::queryYUVA"); - - // Indicate that we have three separate planes - indices[SkYUVAIndex::kY_Index] = {0, SkColorChannel::kR}; - indices[SkYUVAIndex::kU_Index] = {1, SkColorChannel::kR}; - indices[SkYUVAIndex::kV_Index] = {2, SkColorChannel::kR}; - indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR}; + TRACE_EVENT0("blink", "DecodingImageGenerator::QueryYUVAInfo"); DCHECK(all_data_received_); - return frame_generator_->GetYUVComponentSizes(data_.get(), size_info, - color_space, bit_depth); + return frame_generator_->GetYUVAInfo(data_.get(), supported_data_types, + yuva_pixmap_info); } -bool DecodingImageGenerator::GetYUVAPlanes(const SkYUVASizeInfo& size_info, - SkColorType color_type, - const SkYUVAIndex indices[4], - void* planes[3], +bool DecodingImageGenerator::GetYUVAPlanes(const SkYUVAPixmaps& pixmaps, size_t frame_index, uint32_t lazy_pixel_ref) { // TODO(crbug.com/943519): YUV decoding does not currently support incremental @@ -249,27 +238,32 @@ bool DecodingImageGenerator::GetYUVAPlanes(const SkYUVASizeInfo& size_info, DCHECK(can_yuv_decode_); DCHECK(all_data_received_); - TRACE_EVENT0("blink", "DecodingImageGenerator::getYUVAPlanes"); + TRACE_EVENT0("blink", "DecodingImageGenerator::GetYUVAPlanes"); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Decode LazyPixelRef", "LazyPixelRef", lazy_pixel_ref); - // Verify sizes and indices + SkISize plane_sizes[3]; + size_t plane_row_bytes[3]; + void* plane_addrs[3]; + + // Verify sizes and extract DecodeToYUV parameters for (int i = 0; i < 3; ++i) { - if (size_info.fSizes[i].isEmpty() || !size_info.fWidthBytes[i]) { + const SkPixmap& plane = pixmaps.plane(i); + if (plane.dimensions().isEmpty() || !plane.rowBytes()) return false; - } - } - if (!size_info.fSizes[3].isEmpty() || size_info.fWidthBytes[3]) { - return false; + if (plane.colorType() != pixmaps.plane(0).colorType()) + return false; + plane_sizes[i] = plane.dimensions(); + plane_row_bytes[i] = plane.rowBytes(); + plane_addrs[i] = plane.writable_addr(); } - int numPlanes; - if (!SkYUVAIndex::AreValidIndices(indices, &numPlanes) || numPlanes != 3) { + if (!pixmaps.plane(3).dimensions().isEmpty()) { return false; } - return frame_generator_->DecodeToYUV(data_.get(), frame_index, color_type, - size_info.fSizes, planes, - size_info.fWidthBytes); + return frame_generator_->DecodeToYUV( + data_.get(), frame_index, pixmaps.plane(0).colorType(), plane_sizes, + plane_addrs, plane_row_bytes); } SkISize DecodingImageGenerator::GetSupportedDecodeSize( diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.h b/third_party/blink/renderer/platform/graphics/decoding_image_generator.h index 73d5b103e2bb26..134e30bbef36ef 100644 --- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.h +++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.h @@ -34,7 +34,7 @@ #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/skia/include/core/SkImageInfo.h" -#include "third_party/skia/include/core/SkYUVAIndex.h" +#include "third_party/skia/include/core/SkYUVAPixmaps.h" class SkData; @@ -76,16 +76,15 @@ class PLATFORM_EXPORT DecodingImageGenerator final size_t frame_index, PaintImage::GeneratorClientId client_id, uint32_t lazy_pixel_ref) override; - bool QueryYUVA(SkYUVASizeInfo*, - SkYUVAIndex[SkYUVAIndex::kIndexCount], - SkYUVColorSpace*, - uint8_t* bit_depth) const override; - bool GetYUVAPlanes(const SkYUVASizeInfo&, - SkColorType color_type, - const SkYUVAIndex[SkYUVAIndex::kIndexCount], - void* planes[4], + + bool QueryYUVA( + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* yuva_pixmap_info) const override; + + bool GetYUVAPlanes(const SkYUVAPixmaps& pixmaps, size_t frame_index, uint32_t lazy_pixel_ref) override; + SkISize GetSupportedDecodeSize(const SkISize& requested_size) const override; PaintImage::ContentId GetContentIdForFrame(size_t frame_index) const override; const cc::ImageHeaderMetadata* GetMetadataForDecodeAcceleration() diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc index 9d5b3ba13a019b..372482a738d596 100644 --- a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc +++ b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc @@ -38,23 +38,37 @@ namespace blink { -static bool UpdateYUVComponentSizes(ImageDecoder* decoder, - SkISize component_sizes[4], - size_t component_width_bytes[4]) { - DCHECK(decoder->CanDecodeToYUV()); - // Initialize sizes for decoder if not already set. - bool size_available = decoder->IsSizeAvailable(); - DCHECK(size_available); - - for (int yuv_index = 0; yuv_index < 3; ++yuv_index) { - IntSize size = decoder->DecodedYUVSize(yuv_index); - component_sizes[yuv_index].set(size.Width(), size.Height()); - component_width_bytes[yuv_index] = decoder->DecodedYUVWidthBytes(yuv_index); +static bool UpdateYUVAInfoPlanarConfigAndWidthBytes( + ImageDecoder* decoder, + SkYUVAInfo::PlanarConfig* config, + size_t component_width_bytes[SkYUVAInfo::kMaxPlanes]) { + switch (decoder->GetYUVSubsampling()) { + case cc::YUVSubsampling::k410: + *config = SkYUVAInfo::PlanarConfig::kY_U_V_410; + break; + case cc::YUVSubsampling::k411: + *config = SkYUVAInfo::PlanarConfig::kY_U_V_411; + break; + case cc::YUVSubsampling::k420: + *config = SkYUVAInfo::PlanarConfig::kY_U_V_420; + break; + case cc::YUVSubsampling::k422: + *config = SkYUVAInfo::PlanarConfig::kY_U_V_422; + break; + case cc::YUVSubsampling::k440: + *config = SkYUVAInfo::PlanarConfig::kY_U_V_440; + break; + case cc::YUVSubsampling::k444: + *config = SkYUVAInfo::PlanarConfig::kY_U_V_444; + break; + default: + return false; } + component_width_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY); + component_width_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU); + component_width_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV); // TODO(crbug/910276): Alpha plane is currently unsupported. - component_sizes[3] = SkISize::MakeEmpty(); component_width_bytes[3] = 0; - return true; } @@ -149,12 +163,13 @@ bool ImageFrameGenerator::DecodeAndScale( return true; } -bool ImageFrameGenerator::DecodeToYUV(SegmentReader* data, - size_t index, - SkColorType color_type, - const SkISize component_sizes[3], - void* planes[3], - const size_t row_bytes[3]) { +bool ImageFrameGenerator::DecodeToYUV( + SegmentReader* data, + size_t index, + SkColorType color_type, + const SkISize component_sizes[cc::kNumYUVPlanes], + void* planes[cc::kNumYUVPlanes], + const size_t row_bytes[cc::kNumYUVPlanes]) { MutexLocker lock(generator_mutex_); DCHECK_EQ(index, 0u); @@ -221,11 +236,11 @@ bool ImageFrameGenerator::HasAlpha(size_t index) { return true; } -bool ImageFrameGenerator::GetYUVComponentSizes(SegmentReader* data, - SkYUVASizeInfo* size_info, - SkYUVColorSpace* yuv_color_space, - uint8_t* bit_depth) { - TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width", +bool ImageFrameGenerator::GetYUVAInfo( + SegmentReader* data, + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* info) { + TRACE_EVENT2("blink", "ImageFrameGenerator::GetYUVAInfo", "width", full_size_.width(), "height", full_size_.height()); MutexLocker lock(generator_mutex_); @@ -238,11 +253,34 @@ bool ImageFrameGenerator::GetYUVComponentSizes(SegmentReader* data, DCHECK(decoder); DCHECK(decoder->CanDecodeToYUV()); - *yuv_color_space = decoder->GetYUVColorSpace(); - *bit_depth = decoder->GetYUVBitDepth(); + SkYUVAInfo::PlanarConfig config; + size_t width_bytes[SkYUVAInfo::kMaxPlanes]; + if (!UpdateYUVAInfoPlanarConfigAndWidthBytes(decoder.get(), &config, + width_bytes)) { + return false; + } + SkYUVAInfo yuva_info(full_size_, config, decoder->GetYUVColorSpace()); + SkYUVAPixmapInfo::DataType dataType; + if (decoder->GetYUVBitDepth() > 8) { + if (supported_data_types.supported(config, + SkYUVAPixmapInfo::DataType::kUnorm16)) { + dataType = SkYUVAPixmapInfo::DataType::kUnorm16; + } else if (supported_data_types.supported( + config, SkYUVAPixmapInfo::DataType::kFloat16)) { + dataType = SkYUVAPixmapInfo::DataType::kFloat16; + } else { + return false; + } + } else if (supported_data_types.supported( + config, SkYUVAPixmapInfo::DataType::kUnorm8)) { + dataType = SkYUVAPixmapInfo::DataType::kUnorm8; + } else { + return false; + } + *info = SkYUVAPixmapInfo(yuva_info, dataType, width_bytes); + DCHECK(info->isSupported(supported_data_types)); - return UpdateYUVComponentSizes(decoder.get(), size_info->fSizes, - size_info->fWidthBytes); + return true; } SkISize ImageFrameGenerator::GetSupportedDecodeSize( diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator.h b/third_party/blink/renderer/platform/graphics/image_frame_generator.h index bbbc6e489883a0..c3e5e18c8f8c7e 100644 --- a/third_party/blink/renderer/platform/graphics/image_frame_generator.h +++ b/third_party/blink/renderer/platform/graphics/image_frame_generator.h @@ -44,7 +44,8 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkSize.h" #include "third_party/skia/include/core/SkTypes.h" -#include "third_party/skia/include/core/SkYUVASizeInfo.h" +#include "third_party/skia/include/core/SkYUVAInfo.h" +#include "third_party/skia/include/core/SkYUVAPixmaps.h" namespace blink { @@ -90,16 +91,16 @@ class PLATFORM_EXPORT ImageFrameGenerator final cc::PaintImage::GeneratorClientId); // Decodes YUV components directly into the provided memory planes. Must not - // be called unless GetYUVComponentSizes has been called and returned true. + // be called unless GetYUVAInfo has been called and returned true. // TODO(crbug.com/943519): In order to support incremental YUV decoding, // ImageDecoder needs something analogous to its ImageFrame cache to hold // partial planes, and the GPU code needs to handle them. bool DecodeToYUV(SegmentReader*, size_t index, SkColorType color_type, - const SkISize component_sizes[3], - void* planes[3], - const size_t row_bytes[3]); + const SkISize component_sizes[cc::kNumYUVPlanes], + void* planes[cc::kNumYUVPlanes], + const size_t row_bytes[cc::kNumYUVPlanes]); const SkISize& GetFullSize() const { return full_size_; } @@ -114,10 +115,10 @@ class PLATFORM_EXPORT ImageFrameGenerator final bool HasAlpha(size_t index); // TODO(crbug.com/943519): Do not call unless the SkROBuffer has all the data. - bool GetYUVComponentSizes(SegmentReader*, - SkYUVASizeInfo*, - SkYUVColorSpace*, - uint8_t* bit_depth); + bool GetYUVAInfo( + SegmentReader*, + const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types, + SkYUVAPixmapInfo* info); private: class ClientMutexLocker { diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc index 20834693401c8d..53b2b620521072 100644 --- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc @@ -30,7 +30,6 @@ #include "third_party/libavif/src/include/avif/avif.h" #include "third_party/libyuv/include/libyuv.h" #include "third_party/skia/include/core/SkData.h" -#include "third_party/skia/include/core/SkYUVAIndex.h" #include "ui/gfx/color_space.h" #include "ui/gfx/color_transform.h" #include "ui/gfx/half_float.h" @@ -279,23 +278,32 @@ void AVIFImageDecoder::OnSetData(SegmentReader* data) { SetFailed(); } -IntSize AVIFImageDecoder::DecodedYUVSize(int component) const { - DCHECK_GE(component, 0); - // TODO(crbug.com/910276): Change after alpha support. - DCHECK_LE(component, 2); +cc::YUVSubsampling AVIFImageDecoder::GetYUVSubsampling() const { + switch (decoder_->image->yuvFormat) { + case AVIF_PIXEL_FORMAT_YUV420: + return cc::YUVSubsampling::k420; + case AVIF_PIXEL_FORMAT_YUV422: + return cc::YUVSubsampling::k422; + case AVIF_PIXEL_FORMAT_YUV444: + return cc::YUVSubsampling::k444; + case AVIF_PIXEL_FORMAT_YUV400: + return cc::YUVSubsampling::kUnknown; + case AVIF_PIXEL_FORMAT_NONE: + NOTREACHED(); + return cc::YUVSubsampling::kUnknown; + } +} + +IntSize AVIFImageDecoder::DecodedYUVSize(cc::YUVIndex index) const { DCHECK(IsDecodedSizeAvailable()); - if (component == SkYUVAIndex::kU_Index || - component == SkYUVAIndex::kV_Index) { + if (index == cc::YUVIndex::kU || index == cc::YUVIndex::kV) { return IntSize(UVSize(Size().Width(), chroma_shift_x_), UVSize(Size().Height(), chroma_shift_y_)); } return Size(); } -size_t AVIFImageDecoder::DecodedYUVWidthBytes(int component) const { - DCHECK_GE(component, 0); - // TODO(crbug.com/910276): Change after alpha support. - DCHECK_LE(component, 2); +size_t AVIFImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const { DCHECK(IsDecodedSizeAvailable()); // Try to return the same width bytes as used by the dav1d library. This will // allow DecodeToYUV() to copy each plane with a single memcpy() call. @@ -303,8 +311,7 @@ size_t AVIFImageDecoder::DecodedYUVWidthBytes(int component) const { // The comments for Dav1dPicAllocator in dav1d/picture.h require the pixel // width be padded to a multiple of 128 pixels. int aligned_width = base::bits::Align(Size().Width(), 128); - if (component == SkYUVAIndex::kU_Index || - component == SkYUVAIndex::kV_Index) { + if (index == cc::YUVIndex::kU || index == cc::YUVIndex::kV) { aligned_width >>= chroma_shift_x_; } // When the stride is a multiple of 1024, dav1d_default_picture_alloc() @@ -373,9 +380,9 @@ void AVIFImageDecoder::DecodeToYUV() { return; } DCHECK(!image->alphaPlane); - static_assert(SkYUVAIndex::kY_Index == static_cast(AVIF_CHAN_Y), ""); - static_assert(SkYUVAIndex::kU_Index == static_cast(AVIF_CHAN_U), ""); - static_assert(SkYUVAIndex::kV_Index == static_cast(AVIF_CHAN_V), ""); + static_assert(cc::YUVIndex::kY == static_cast(AVIF_CHAN_Y), ""); + static_assert(cc::YUVIndex::kU == static_cast(AVIF_CHAN_U), ""); + static_assert(cc::YUVIndex::kV == static_cast(AVIF_CHAN_V), ""); // Disable subnormal floats which can occur when converting to half float. std::unique_ptr disable_subnormals; @@ -393,21 +400,22 @@ void AVIFImageDecoder::DecodeToYUV() { // max_frame_height_minus_1 and frame_height_minus_1, respectively, as n-bit // unsigned integers for some n. DCHECK_GT(height, 0u); - for (int plane = 0; plane < 3; ++plane) { + for (size_t plane_index = 0; plane_index < cc::kNumYUVPlanes; ++plane_index) { + const cc::YUVIndex plane = static_cast(plane_index); const size_t src_row_bytes = - base::strict_cast(image->yuvRowBytes[plane]); + base::strict_cast(image->yuvRowBytes[plane_index]); const size_t dst_row_bytes = image_planes_->RowBytes(plane); if (bit_depth_ == 8) { DCHECK_EQ(image_planes_->color_type(), kGray_8_SkColorType); - const uint8_t* src = image->yuvPlanes[plane]; + const uint8_t* src = image->yuvPlanes[plane_index]; uint8_t* dst = static_cast(image_planes_->Plane(plane)); libyuv::CopyPlane(src, src_row_bytes, dst, dst_row_bytes, width, height); } else { DCHECK_GT(bit_depth_, 8u); DCHECK_LE(bit_depth_, 16u); const uint16_t* src = - reinterpret_cast(image->yuvPlanes[plane]); + reinterpret_cast(image->yuvPlanes[plane_index]); uint16_t* dst = static_cast(image_planes_->Plane(plane)); if (image_planes_->color_type() == kA16_unorm_SkColorType) { const size_t src_stride = src_row_bytes / 2; @@ -427,7 +435,7 @@ void AVIFImageDecoder::DecodeToYUV() { << static_cast(image_planes_->color_type()); } } - if (plane == 0) { + if (plane == cc::YUVIndex::kY) { // Having processed the luma plane, change |width| and |height| to the // width and height of the chroma planes. width = UVSize(width, chroma_shift_x_); @@ -569,22 +577,6 @@ bool AVIFImageDecoder::CanReusePreviousFrameBuffer(size_t index) const { return true; } -cc::YUVSubsampling AVIFImageDecoder::GetYUVSubsampling() const { - switch (decoder_->image->yuvFormat) { - case AVIF_PIXEL_FORMAT_YUV420: - return cc::YUVSubsampling::k420; - case AVIF_PIXEL_FORMAT_YUV422: - return cc::YUVSubsampling::k422; - case AVIF_PIXEL_FORMAT_YUV444: - return cc::YUVSubsampling::k444; - case AVIF_PIXEL_FORMAT_YUV400: - return cc::YUVSubsampling::kUnknown; - case AVIF_PIXEL_FORMAT_NONE: - NOTREACHED(); - return cc::YUVSubsampling::kUnknown; - } -} - bool AVIFImageDecoder::MaybeCreateDemuxer() { if (decoder_) return true; diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h index cbc7de23d6ac0d..b3de5b6c3a8a59 100644 --- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h @@ -35,8 +35,9 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { String FilenameExtension() const override { return "avif"; } bool ImageIsHighBitDepth() override; void OnSetData(SegmentReader* data) override; - IntSize DecodedYUVSize(int component) const override; - size_t DecodedYUVWidthBytes(int component) const override; + cc::YUVSubsampling GetYUVSubsampling() const override; + IntSize DecodedYUVSize(cc::YUVIndex) const override; + size_t DecodedYUVWidthBytes(cc::YUVIndex) const override; SkYUVColorSpace GetYUVColorSpace() const override; uint8_t GetYUVBitDepth() const override; void DecodeToYUV() override; @@ -57,7 +58,6 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { void InitializeNewFrame(size_t) override; void Decode(size_t) override; bool CanReusePreviousFrameBuffer(size_t) const override; - cc::YUVSubsampling GetYUVSubsampling() const override; // Creates |decoder_| and decodes the size and frame count. bool MaybeCreateDemuxer(); diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc index fc85dd91a5ea70..f2b7c4b0a07b49 100644 --- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder_test.cc @@ -516,9 +516,9 @@ void ReadYUV(const char* file_name, ASSERT_TRUE(decoder->CanDecodeToYUV()); IntSize size = decoder->DecodedSize(); - IntSize y_size = decoder->DecodedYUVSize(0); - IntSize u_size = decoder->DecodedYUVSize(1); - IntSize v_size = decoder->DecodedYUVSize(2); + IntSize y_size = decoder->DecodedYUVSize(cc::YUVIndex::kY); + IntSize u_size = decoder->DecodedYUVSize(cc::YUVIndex::kU); + IntSize v_size = decoder->DecodedYUVSize(cc::YUVIndex::kV); EXPECT_EQ(size, y_size); EXPECT_EQ(u_size, v_size); @@ -527,9 +527,9 @@ void ReadYUV(const char* file_name, EXPECT_EQ(expected_uv_size, u_size); size_t row_bytes[3]; - row_bytes[0] = decoder->DecodedYUVWidthBytes(0); - row_bytes[1] = decoder->DecodedYUVWidthBytes(1); - row_bytes[2] = decoder->DecodedYUVWidthBytes(2); + row_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY); + row_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU); + row_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV); size_t planes_data_size = row_bytes[0] * y_size.Height() + row_bytes[1] * u_size.Height() + diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc index 26868d53ab2b01..21742cc7b1f86f 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc @@ -726,32 +726,28 @@ size_t ImageDecoder::FindRequiredPreviousFrame(size_t frame_index, ImagePlanes::ImagePlanes() { color_type_ = kUnknown_SkColorType; - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < cc::kNumYUVPlanes; ++i) { planes_[i] = nullptr; row_bytes_[i] = 0; } } -ImagePlanes::ImagePlanes(void* planes[3], - const size_t row_bytes[3], +ImagePlanes::ImagePlanes(void* planes[cc::kNumYUVPlanes], + const size_t row_bytes[cc::kNumYUVPlanes], SkColorType color_type) : color_type_(color_type) { - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < cc::kNumYUVPlanes; ++i) { planes_[i] = planes[i]; row_bytes_[i] = row_bytes[i]; } } -void* ImagePlanes::Plane(int i) { - DCHECK_GE(i, 0); - DCHECK_LT(i, 3); - return planes_[i]; +void* ImagePlanes::Plane(cc::YUVIndex index) { + return planes_[static_cast(index)]; } -size_t ImagePlanes::RowBytes(int i) const { - DCHECK_GE(i, 0); - DCHECK_LT(i, 3); - return row_bytes_[i]; +size_t ImagePlanes::RowBytes(cc::YUVIndex index) const { + return row_bytes_[static_cast(index)]; } ColorProfile::ColorProfile(const skcms_ICCProfile& profile, diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.h b/third_party/blink/renderer/platform/image-decoders/image_decoder.h index 261a7c9b426245..65bf23538462d3 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.h @@ -72,17 +72,17 @@ class PLATFORM_EXPORT ImagePlanes final { // // TODO(crbug/910276): To support YUVA, ImagePlanes needs to support a // variable number of planes. - ImagePlanes(void* planes[3], - const size_t row_bytes[3], + ImagePlanes(void* planes[cc::kNumYUVPlanes], + const size_t row_bytes[cc::kNumYUVPlanes], SkColorType color_type); - void* Plane(int); - size_t RowBytes(int) const; + void* Plane(cc::YUVIndex); + size_t RowBytes(cc::YUVIndex) const; SkColorType color_type() const { return color_type_; } private: - void* planes_[3]; - size_t row_bytes_[3]; + void* planes_[cc::kNumYUVPlanes]; + size_t row_bytes_[cc::kNumYUVPlanes]; SkColorType color_type_; DISALLOW_COPY_AND_ASSIGN(ImagePlanes); @@ -266,16 +266,21 @@ class PLATFORM_EXPORT ImageDecoder { // return the actual decoded size. virtual IntSize DecodedSize() const { return Size(); } + // The YUV subsampling of the image. + virtual cc::YUVSubsampling GetYUVSubsampling() const { + return cc::YUVSubsampling::kUnknown; + } + // Image decoders that support YUV decoding must override this to // provide the size of each component. - virtual IntSize DecodedYUVSize(int component) const { + virtual IntSize DecodedYUVSize(cc::YUVIndex) const { NOTREACHED(); return IntSize(); } // Image decoders that support YUV decoding must override this to // return the width of each row of the memory allocation. - virtual size_t DecodedYUVWidthBytes(int component) const { + virtual size_t DecodedYUVWidthBytes(cc::YUVIndex) const { NOTREACHED(); return 0; } @@ -569,11 +574,6 @@ class PLATFORM_EXPORT ImageDecoder { std::unique_ptr image_planes_; private: - // The YUV subsampling of the image. - virtual cc::YUVSubsampling GetYUVSubsampling() const { - return cc::YUVSubsampling::kUnknown; - } - // Some code paths compute the size of the image as "width * height * 4 or 8" // and return it as a (signed) int. Avoid overflow. inline bool SizeCalculationMayOverflow(unsigned width, diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc index dd9ae96a457fa7..f408680aa9be76 100644 --- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc @@ -1038,24 +1038,27 @@ void JPEGImageDecoder::SetDecodedSize(unsigned width, unsigned height) { decoded_size_ = IntSize(width, height); } -IntSize JPEGImageDecoder::DecodedYUVSize(int component) const { - DCHECK_GE(component, 0); - DCHECK_LE(component, 2); +cc::YUVSubsampling JPEGImageDecoder::GetYUVSubsampling() const { + DCHECK(reader_->Info()); + // reader_->Info() should have gone through a jpeg_read_header() call. + DCHECK(IsDecodedSizeAvailable()); + return YuvSubsampling(*reader_->Info()); +} + +IntSize JPEGImageDecoder::DecodedYUVSize(cc::YUVIndex index) const { DCHECK(reader_); const jpeg_decompress_struct* info = reader_->Info(); DCHECK_EQ(info->out_color_space, JCS_YCbCr); - return ComputeYUVSize(info, component); + return ComputeYUVSize(info, static_cast(index)); } -size_t JPEGImageDecoder::DecodedYUVWidthBytes(int component) const { - DCHECK_GE(component, 0); - DCHECK_LE(component, 2); +size_t JPEGImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const { DCHECK(reader_); const jpeg_decompress_struct* info = reader_->Info(); DCHECK_EQ(info->out_color_space, JCS_YCbCr); - return ComputeYUVWidthBytes(info, component); + return ComputeYUVWidthBytes(info, static_cast(index)); } unsigned JPEGImageDecoder::DesiredScaleNumerator() const { @@ -1220,12 +1223,15 @@ static bool OutputRawData(JPEGImageReader* reader, ImagePlanes* image_planes) { int v = info->comp_info[0].v_samp_factor; IntSize uv_size = reader->UvSize(); int uv_height = uv_size.Height(); - JSAMPROW output_y = static_cast(image_planes->Plane(0)); - JSAMPROW output_u = static_cast(image_planes->Plane(1)); - JSAMPROW output_v = static_cast(image_planes->Plane(2)); - size_t row_bytes_y = image_planes->RowBytes(0); - size_t row_bytes_u = image_planes->RowBytes(1); - size_t row_bytes_v = image_planes->RowBytes(2); + JSAMPROW output_y = + static_cast(image_planes->Plane(cc::YUVIndex::kY)); + JSAMPROW output_u = + static_cast(image_planes->Plane(cc::YUVIndex::kU)); + JSAMPROW output_v = + static_cast(image_planes->Plane(cc::YUVIndex::kV)); + size_t row_bytes_y = image_planes->RowBytes(cc::YUVIndex::kY); + size_t row_bytes_u = image_planes->RowBytes(cc::YUVIndex::kU); + size_t row_bytes_v = image_planes->RowBytes(cc::YUVIndex::kV); // Request 8 or 16 scanlines: returns 0 or more scanlines. int y_scanlines_to_read = DCTSIZE * v; @@ -1345,13 +1351,6 @@ inline bool IsComplete(const JPEGImageDecoder* decoder, bool only_size) { return decoder->FrameIsDecodedAtIndex(0); } -cc::YUVSubsampling JPEGImageDecoder::GetYUVSubsampling() const { - DCHECK(reader_->Info()); - // reader_->Info() should have gone through a jpeg_read_header() call. - DCHECK(IsDecodedSizeAvailable()); - return YuvSubsampling(*reader_->Info()); -} - void JPEGImageDecoder::Decode(bool only_size) { if (Failed()) return; diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h index 0c38ff5ec5cfe2..97a8b171364f8a 100644 --- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h @@ -48,8 +48,9 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder { void OnSetData(SegmentReader* data) override; IntSize DecodedSize() const override { return decoded_size_; } bool SetSize(unsigned width, unsigned height) override; - IntSize DecodedYUVSize(int component) const override; - size_t DecodedYUVWidthBytes(int component) const override; + cc::YUVSubsampling GetYUVSubsampling() const override; + IntSize DecodedYUVSize(cc::YUVIndex) const override; + size_t DecodedYUVWidthBytes(cc::YUVIndex) const override; void DecodeToYUV() override; SkYUVColorSpace GetYUVColorSpace() const override; Vector GetSupportedDecodeSizes() const override; @@ -83,7 +84,6 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder { // ImageDecoder: void DecodeSize() override { Decode(true); } void Decode(size_t) override { Decode(false); } - cc::YUVSubsampling GetYUVSubsampling() const override; cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const override; // Attempts to calculate the coded size of the JPEG image. Returns a zero diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc index ce58c32a6e04e4..03e9114ce4f208 100644 --- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc @@ -94,9 +94,9 @@ void ReadYUV(size_t max_decoded_bytes, ASSERT_TRUE(decoder->CanDecodeToYUV()); IntSize size = decoder->DecodedSize(); - IntSize y_size = decoder->DecodedYUVSize(0); - IntSize u_size = decoder->DecodedYUVSize(1); - IntSize v_size = decoder->DecodedYUVSize(2); + IntSize y_size = decoder->DecodedYUVSize(cc::YUVIndex::kY); + IntSize u_size = decoder->DecodedYUVSize(cc::YUVIndex::kU); + IntSize v_size = decoder->DecodedYUVSize(cc::YUVIndex::kV); EXPECT_EQ(size, y_size); EXPECT_EQ(u_size, v_size); @@ -105,9 +105,9 @@ void ReadYUV(size_t max_decoded_bytes, EXPECT_EQ(expected_uv_size, u_size); size_t row_bytes[3]; - row_bytes[0] = decoder->DecodedYUVWidthBytes(0); - row_bytes[1] = decoder->DecodedYUVWidthBytes(1); - row_bytes[2] = decoder->DecodedYUVWidthBytes(2); + row_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY); + row_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU); + row_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV); size_t planes_data_size = row_bytes[0] * y_size.Height() + row_bytes[1] * u_size.Height() + diff --git a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc index 6bf654d24a0d88..931ca2d0c5ce9b 100644 --- a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc @@ -36,7 +36,6 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/wtf.h" #include "third_party/skia/include/core/SkData.h" -#include "third_party/skia/include/core/SkYUVAIndex.h" #if defined(ARCH_CPU_BIG_ENDIAN) #error Blink assumes a little-endian target. @@ -425,30 +424,25 @@ void WEBPImageDecoder::DecodeToYUV() { } } -IntSize WEBPImageDecoder::DecodedYUVSize(int component) const { - DCHECK_GE(component, 0); - // TODO(crbug.com/910276): Change after alpha support. - DCHECK_LE(component, 2); +IntSize WEBPImageDecoder::DecodedYUVSize(cc::YUVIndex index) const { DCHECK(IsDecodedSizeAvailable()); - switch (component) { - case SkYUVAIndex::kY_Index: + switch (index) { + case cc::YUVIndex::kY: return Size(); - case SkYUVAIndex::kU_Index: - case SkYUVAIndex::kV_Index: + case cc::YUVIndex::kU: + case cc::YUVIndex::kV: return IntSize((Size().Width() + 1) / 2, (Size().Height() + 1) / 2); } NOTREACHED(); return IntSize(0, 0); } -size_t WEBPImageDecoder::DecodedYUVWidthBytes(int component) const { - DCHECK_GE(component, 0); - DCHECK_LE(component, 2); - switch (component) { - case SkYUVAIndex::kY_Index: +size_t WEBPImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const { + switch (index) { + case cc::YUVIndex::kY: return base::checked_cast(Size().Width()); - case SkYUVAIndex::kU_Index: - case SkYUVAIndex::kV_Index: + case cc::YUVIndex::kU: + case cc::YUVIndex::kV: return base::checked_cast((Size().Width() + 1) / 2); } NOTREACHED(); @@ -692,29 +686,23 @@ bool WEBPImageDecoder::DecodeSingleFrameToYUV(const uint8_t* data_bytes, // Even if |decoder_| already exists, we must get most up-to-date pointers // because memory location might change e.g. upon tab resume. decoder_buffer_.u.YUVA.y = - static_cast(image_planes->Plane(SkYUVAIndex::kY_Index)); + static_cast(image_planes->Plane(cc::YUVIndex::kY)); decoder_buffer_.u.YUVA.u = - static_cast(image_planes->Plane(SkYUVAIndex::kU_Index)); + static_cast(image_planes->Plane(cc::YUVIndex::kU)); decoder_buffer_.u.YUVA.v = - static_cast(image_planes->Plane(SkYUVAIndex::kV_Index)); + static_cast(image_planes->Plane(cc::YUVIndex::kV)); if (!decoder_) { // libwebp only supports YUV 420 subsampling - decoder_buffer_.u.YUVA.y_stride = - image_planes->RowBytes(SkYUVAIndex::kY_Index); - decoder_buffer_.u.YUVA.y_size = - decoder_buffer_.u.YUVA.y_stride * - DecodedYUVSize(SkYUVAIndex::kY_Index).Height(); - decoder_buffer_.u.YUVA.u_stride = - image_planes->RowBytes(SkYUVAIndex::kU_Index); - decoder_buffer_.u.YUVA.u_size = - decoder_buffer_.u.YUVA.u_stride * - DecodedYUVSize(SkYUVAIndex::kU_Index).Height(); - decoder_buffer_.u.YUVA.v_stride = - image_planes->RowBytes(SkYUVAIndex::kV_Index); - decoder_buffer_.u.YUVA.v_size = - decoder_buffer_.u.YUVA.v_stride * - DecodedYUVSize(SkYUVAIndex::kV_Index).Height(); + decoder_buffer_.u.YUVA.y_stride = image_planes->RowBytes(cc::YUVIndex::kY); + decoder_buffer_.u.YUVA.y_size = decoder_buffer_.u.YUVA.y_stride * + DecodedYUVSize(cc::YUVIndex::kY).Height(); + decoder_buffer_.u.YUVA.u_stride = image_planes->RowBytes(cc::YUVIndex::kU); + decoder_buffer_.u.YUVA.u_size = decoder_buffer_.u.YUVA.u_stride * + DecodedYUVSize(cc::YUVIndex::kU).Height(); + decoder_buffer_.u.YUVA.v_stride = image_planes->RowBytes(cc::YUVIndex::kV); + decoder_buffer_.u.YUVA.v_size = decoder_buffer_.u.YUVA.v_stride * + DecodedYUVSize(cc::YUVIndex::kV).Height(); decoder_buffer_.is_external_memory = 1; decoder_ = WebPINewDecoder(&decoder_buffer_); diff --git a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h index 1c40d370d9e3d2..e529ec39e39593 100644 --- a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h @@ -49,6 +49,7 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder { // ImageDecoder: String FilenameExtension() const override { return "webp"; } void OnSetData(SegmentReader* data) override; + cc::YUVSubsampling GetYUVSubsampling() const override; int RepetitionCount() const override; bool FrameIsReceivedAtIndex(size_t) const override; base::TimeDelta FrameDurationAtIndex(size_t) const override; @@ -61,7 +62,6 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder { void Decode(size_t) override; void DecodeToYUV() override; SkYUVColorSpace GetYUVColorSpace() const override; - cc::YUVSubsampling GetYUVSubsampling() const override; cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const override; WEBP_CSP_MODE RGBOutputMode(); @@ -100,10 +100,10 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder { bool frame_background_has_alpha_; // Provides the size of each component. - IntSize DecodedYUVSize(int component) const override; + IntSize DecodedYUVSize(cc::YUVIndex) const override; // Returns the width of each row of the memory allocation. - size_t DecodedYUVWidthBytes(int component) const override; + size_t DecodedYUVWidthBytes(cc::YUVIndex) const override; void ReadColorProfile(); bool UpdateDemuxer();