Commit aeed0e1d authored by Thiabaud Engelbrecht's avatar Thiabaud Engelbrecht Committed by Chromium LUCI CQ

[parkable_image] Minimal changes to add ParkableImage into the codebase.

See related bug for details. This CL lays the groundwork for further
ParkableImage work by encapsulating the RWBuffer in DeferredImageDecoder
inside a ParkableImage.

This CL does not introduce any changes to functionality.

Bug: 1142834
Change-Id: Ic5497b89346f8b2437a41d70381220b72ffed9de
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519728
Commit-Queue: Thiabaud Engelbrecht <thiabaud@google.com>
Reviewed-by: default avatarBenoit L <lizeb@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844684}
parent 3ce71938
...@@ -1095,6 +1095,8 @@ component("platform") { ...@@ -1095,6 +1095,8 @@ component("platform") {
"graphics/paint_worklet_paint_dispatcher.cc", "graphics/paint_worklet_paint_dispatcher.cc",
"graphics/paint_worklet_paint_dispatcher.h", "graphics/paint_worklet_paint_dispatcher.h",
"graphics/paint_worklet_painter.h", "graphics/paint_worklet_painter.h",
"graphics/parkable_image.cc",
"graphics/parkable_image.h",
"graphics/parkable_image_manager.cc", "graphics/parkable_image_manager.cc",
"graphics/parkable_image_manager.h", "graphics/parkable_image_manager.h",
"graphics/path.cc", "graphics/path.cc",
...@@ -2028,6 +2030,7 @@ source_set("blink_platform_unittests_sources") { ...@@ -2028,6 +2030,7 @@ source_set("blink_platform_unittests_sources") {
"graphics/paint/raster_invalidator_test.cc", "graphics/paint/raster_invalidator_test.cc",
"graphics/paint/scrollbar_display_item_test.cc", "graphics/paint/scrollbar_display_item_test.cc",
"graphics/paint_invalidation_reason_test.cc", "graphics/paint_invalidation_reason_test.cc",
"graphics/parkable_image_test.cc",
"graphics/path_test.cc", "graphics/path_test.cc",
"graphics/placeholder_image_test.cc", "graphics/placeholder_image_test.cc",
"graphics/raster_dark_mode_filter_impl_test.cc", "graphics/raster_dark_mode_filter_impl_test.cc",
......
...@@ -171,11 +171,9 @@ DeferredImageDecoder::DeferredImageDecoder( ...@@ -171,11 +171,9 @@ DeferredImageDecoder::DeferredImageDecoder(
has_hot_spot_(false), has_hot_spot_(false),
image_is_high_bit_depth_(false), image_is_high_bit_depth_(false),
complete_frame_content_id_(PaintImage::GetNextContentId()) { complete_frame_content_id_(PaintImage::GetNextContentId()) {
ParkableImageManager::Instance().Add(this);
} }
DeferredImageDecoder::~DeferredImageDecoder() { DeferredImageDecoder::~DeferredImageDecoder() {
ParkableImageManager::Instance().Remove(this);
} }
String DeferredImageDecoder::FilenameExtension() const { String DeferredImageDecoder::FilenameExtension() const {
...@@ -195,9 +193,8 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator() { ...@@ -195,9 +193,8 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator() {
DCHECK_GT(decoded_size.width(), 0); DCHECK_GT(decoded_size.width(), 0);
DCHECK_GT(decoded_size.height(), 0); DCHECK_GT(decoded_size.height(), 0);
scoped_refptr<ROBuffer> ro_buffer(rw_buffer_->MakeROBufferSnapshot());
scoped_refptr<SegmentReader> segment_reader = scoped_refptr<SegmentReader> segment_reader =
SegmentReader::CreateFromROBuffer(std::move(ro_buffer)); parkable_image_->MakeROSnapshot();
SkImageInfo info = SkImageInfo info =
SkImageInfo::MakeN32(decoded_size.width(), decoded_size.height(), SkImageInfo::MakeN32(decoded_size.width(), decoded_size.height(),
...@@ -254,15 +251,7 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator() { ...@@ -254,15 +251,7 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator() {
} }
scoped_refptr<SharedBuffer> DeferredImageDecoder::Data() { scoped_refptr<SharedBuffer> DeferredImageDecoder::Data() {
if (!rw_buffer_) return parkable_image_ ? parkable_image_->Data() : nullptr;
return nullptr;
scoped_refptr<ROBuffer> ro_buffer(rw_buffer_->MakeROBufferSnapshot());
scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create();
ROBuffer::Iter it(ro_buffer.get());
do {
shared_buffer->Append(static_cast<const char*>(it.data()), it.size());
} while (it.Next());
return shared_buffer;
} }
void DeferredImageDecoder::SetData(scoped_refptr<SharedBuffer> data, void DeferredImageDecoder::SetData(scoped_refptr<SharedBuffer> data,
...@@ -283,16 +272,14 @@ void DeferredImageDecoder::SetDataInternal(scoped_refptr<SharedBuffer> data, ...@@ -283,16 +272,14 @@ void DeferredImageDecoder::SetDataInternal(scoped_refptr<SharedBuffer> data,
} }
if (frame_generator_) { if (frame_generator_) {
if (!rw_buffer_) if (!parkable_image_)
rw_buffer_ = std::make_unique<RWBuffer>(data->size()); parkable_image_ = ParkableImage::Create(data->size());
for (auto it = data->GetIteratorAt(rw_buffer_->size()); it != data->cend(); parkable_image_->Append(data.get(), parkable_image_->size());
++it) {
DCHECK_GE(data->size(), rw_buffer_->size() + it->size());
const size_t remaining = data->size() - rw_buffer_->size() - it->size();
rw_buffer_->Append(it->data(), it->size(), remaining);
}
} }
if (all_data_received && parkable_image_)
parkable_image_->Freeze();
} }
bool DeferredImageDecoder::IsSizeAvailable() { bool DeferredImageDecoder::IsSizeAvailable() {
...@@ -383,7 +370,7 @@ IntSize DeferredImageDecoder::DensityCorrectedSizeAtIndex(size_t index) const { ...@@ -383,7 +370,7 @@ IntSize DeferredImageDecoder::DensityCorrectedSizeAtIndex(size_t index) const {
size_t DeferredImageDecoder::ByteSize() const { size_t DeferredImageDecoder::ByteSize() const {
return rw_buffer_ ? rw_buffer_->size() : 0u; return parkable_image_ ? parkable_image_->size() : 0u;
} }
void DeferredImageDecoder::ActivateLazyDecoding() { void DeferredImageDecoder::ActivateLazyDecoding() {
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/graphics/parkable_image.h"
#include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkRefCnt.h"
...@@ -104,7 +105,7 @@ class PLATFORM_EXPORT DeferredImageDecoder final { ...@@ -104,7 +105,7 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
// Copy of the data that is passed in, used by deferred decoding. // Copy of the data that is passed in, used by deferred decoding.
// Allows creating readonly snapshots that may be read in another thread. // Allows creating readonly snapshots that may be read in another thread.
std::unique_ptr<RWBuffer> rw_buffer_; std::unique_ptr<ParkableImage> parkable_image_;
std::unique_ptr<ImageDecoder> metadata_decoder_; std::unique_ptr<ImageDecoder> metadata_decoder_;
String filename_extension_; String filename_extension_;
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/parkable_image.h"
#include "base/debug/stack_trace.h"
#include "base/memory/ref_counted.h"
#include "third_party/blink/renderer/platform/graphics/parkable_image_manager.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
void ParkableImage::Append(WTF::SharedBuffer* buffer, size_t offset) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!frozen_);
for (auto it = buffer->GetIteratorAt(offset); it != buffer->cend(); ++it) {
DCHECK_GE(buffer->size(), rw_buffer_.size() + it->size());
const size_t remaining = buffer->size() - rw_buffer_.size() - it->size();
rw_buffer_.Append(it->data(), it->size(), remaining);
}
size_ = rw_buffer_.size();
}
scoped_refptr<SharedBuffer> ParkableImage::Data() const {
scoped_refptr<ROBuffer> ro_buffer(rw_buffer_.MakeROBufferSnapshot());
scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create();
ROBuffer::Iter it(ro_buffer.get());
do {
shared_buffer->Append(static_cast<const char*>(it.data()), it.size());
} while (it.Next());
return shared_buffer;
}
scoped_refptr<SegmentReader> ParkableImage::GetSegmentReader() const {
scoped_refptr<ROBuffer> ro_buffer(rw_buffer_.MakeROBufferSnapshot());
scoped_refptr<SegmentReader> segment_reader =
SegmentReader::CreateFromROBuffer(std::move(ro_buffer));
return segment_reader;
}
ParkableImage::ParkableImage(size_t initial_capacity)
: rw_buffer_(initial_capacity) {
size_ = rw_buffer_.size();
ParkableImageManager::Instance().Add(this);
}
ParkableImage::~ParkableImage() {
ParkableImageManager::Instance().Remove(this);
}
// static
std::unique_ptr<ParkableImage> ParkableImage::Create(size_t initial_capacity) {
return std::make_unique<ParkableImage>(initial_capacity);
}
scoped_refptr<SegmentReader> ParkableImage::MakeROSnapshot() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return GetSegmentReader();
}
void ParkableImage::Freeze() {
DCHECK(!frozen_);
frozen_ = true;
}
size_t ParkableImage::size() const {
return size_;
}
} // namespace blink
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_H_
#include <memory>
#include "base/debug/stack_trace.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/renderer/platform/graphics/rw_buffer.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
namespace blink {
class SegmentReader;
class ParkableImageManager;
// Wraps a RWBuffer containing encoded image data. In the future, this will be
// written/read from disk when no needed, to improve memory usage.
class PLATFORM_EXPORT ParkableImage final {
public:
// |initial_capacity| reserves space in the internal buffer, if you know how
// much data you'll be appending in advance.
explicit ParkableImage(size_t initial_capacity = 0);
~ParkableImage();
ParkableImage& operator=(const ParkableImage&) = delete;
ParkableImage(const ParkableImage&) = delete;
// Factory method to construct a ParkableImage.
static std::unique_ptr<ParkableImage> Create(size_t initial_capacity = 0);
// Freezes the ParkableImage. This changes the following:
// We are no longer allowed to mutate the internal buffer (e.g. via
// Append)
void Freeze();
// Adds data to the internal buffer of ParkableImage. Cannot be called after
// the ParkableImage has been frozen (see Freeze()). |offset| is the offset
// from the start of |buffer| that we want to start copying the data from.
void Append(WTF::SharedBuffer* buffer, size_t offset = 0);
// Make a Read-Only snapshot of the data within ParkableImage. This may be a
// view into the internal buffer of ParkableImage, or a copy of the data. It
// is guaranteed to be safe to read this data from another thread at any time.
scoped_refptr<SegmentReader> MakeROSnapshot();
// Returns the data in the internal buffer. It should not be modified after
// the ParkableImage has been frozen.
scoped_refptr<SharedBuffer> Data() const;
// Returns the size of the internal buffer. Can be called even when
// ParkableImage has been parked.
size_t size() const;
private:
friend class ParkableImageManager;
scoped_refptr<SegmentReader> GetSegmentReader() const;
RWBuffer rw_buffer_;
size_t size_ = 0;
bool frozen_ = false;
THREAD_CHECKER(thread_checker_);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PARKABLE_IMAGE_H_
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/process_memory_dump.h"
#include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.h" #include "third_party/blink/renderer/platform/graphics/parkable_image.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h" #include "third_party/blink/renderer/platform/wtf/wtf.h"
...@@ -41,14 +41,14 @@ ParkableImageManager::Statistics ParkableImageManager::ComputeStatistics() ...@@ -41,14 +41,14 @@ ParkableImageManager::Statistics ParkableImageManager::ComputeStatistics()
const { const {
Statistics stats; Statistics stats;
for (auto* image : image_decoders_) { for (auto* image : images_) {
stats.total_size += image->ByteSize(); stats.total_size += image->size();
} }
return stats; return stats;
} }
void ParkableImageManager::Add(DeferredImageDecoder* image) { void ParkableImageManager::Add(ParkableImage* image) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
if (!has_posted_accounting_task_) { if (!has_posted_accounting_task_) {
...@@ -64,13 +64,13 @@ void ParkableImageManager::Add(DeferredImageDecoder* image) { ...@@ -64,13 +64,13 @@ void ParkableImageManager::Add(DeferredImageDecoder* image) {
has_posted_accounting_task_ = true; has_posted_accounting_task_ = true;
} }
image_decoders_.insert(image); images_.insert(image);
} }
void ParkableImageManager::Remove(DeferredImageDecoder* image) { void ParkableImageManager::Remove(ParkableImage* image) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
image_decoders_.erase(image); images_.erase(image);
} }
void ParkableImageManager::RecordStatisticsAfter5Minutes() const { void ParkableImageManager::RecordStatisticsAfter5Minutes() const {
......
...@@ -8,11 +8,10 @@ ...@@ -8,11 +8,10 @@
#include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink { namespace blink {
class DeferredImageDecoder; class ParkableImage;
// Manages parkable images, which are used in blink::BitmapImage. Currently, // Manages parkable images, which are used in blink::BitmapImage. Currently,
// only records metrics for this. In the future we will park eligible images // only records metrics for this. In the future we will park eligible images
...@@ -30,13 +29,13 @@ class PLATFORM_EXPORT ParkableImageManager ...@@ -30,13 +29,13 @@ class PLATFORM_EXPORT ParkableImageManager
private: private:
struct Statistics; struct Statistics;
friend class DeferredImageDecoder; friend class ParkableImage;
friend class base::NoDestructor<ParkableImageManager>; friend class base::NoDestructor<ParkableImageManager>;
ParkableImageManager() = default; ParkableImageManager() = default;
void Add(DeferredImageDecoder* image); void Add(ParkableImage* image);
void Remove(DeferredImageDecoder* image); void Remove(ParkableImage* image);
Statistics ComputeStatistics() const; Statistics ComputeStatistics() const;
...@@ -44,7 +43,7 @@ class PLATFORM_EXPORT ParkableImageManager ...@@ -44,7 +43,7 @@ class PLATFORM_EXPORT ParkableImageManager
constexpr static const char* kAllocatorDumpName = "parkable_images"; constexpr static const char* kAllocatorDumpName = "parkable_images";
WTF::HashSet<DeferredImageDecoder*> image_decoders_; WTF::HashSet<ParkableImage*> images_;
bool has_posted_accounting_task_ = false; bool has_posted_accounting_task_ = false;
}; };
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/parkable_image.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
namespace blink {
namespace {
const char gABC[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char g123[] = "1234567890";
} // namespace
TEST(ParkableImageTest, Size) {
base::test::SingleThreadTaskEnvironment task_environment;
auto pi = ParkableImage::Create();
EXPECT_EQ(pi->size(), 0u);
// This has capacity 10, not size 10; size should still be 0.
pi = ParkableImage::Create(10);
EXPECT_EQ(pi->size(), 0u);
}
TEST(ParkableImageTest, Append) {
base::test::SingleThreadTaskEnvironment task_environment;
auto pi = ParkableImage::Create();
ASSERT_EQ(pi->size(), 0u); // Should be empty when created.
pi->Append(WTF::SharedBuffer::Create(gABC, sizeof(gABC)).get(), 0);
EXPECT_EQ(pi->size(), sizeof(gABC));
}
TEST(ParkableImageTest, AppendMultiple) {
base::test::SingleThreadTaskEnvironment task_environment;
auto pi = ParkableImage::Create();
ASSERT_EQ(pi->size(), 0u); // Should be empty when created.
auto sb = WTF::SharedBuffer::Create(gABC, sizeof(gABC));
ASSERT_EQ(sb->size(), sizeof(gABC));
pi->Append(sb.get(), 0);
EXPECT_EQ(pi->size(), sizeof(gABC));
sb->Append(g123, sizeof(g123));
ASSERT_EQ(sb->size(), sizeof(g123) + sizeof(gABC));
pi->Append(sb.get(), pi->size());
EXPECT_EQ(pi->size(), sizeof(gABC) + sizeof(g123));
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment