Skip to content

Commit

Permalink
[blimp] Add SkPicture caching support.
Browse files Browse the repository at this point in the history
This CL adds support for de-duplication of SkPicture blobs across
consecutive frames.

Previously all DrawingDisplayItems and their respective SkPictures were
transferred from the engine to the client whenever the frames that
contained them was sent to the client. This lead to the same SkPictures
being sent over and over.

This CL changes this behavior so the engine can assume that the client
always keeps around the contents of the interest rect since last commit
and only sends down the new SkPictures that occur in the interest rect.

Both the engine and the client agrees on what is currently part of the
interest rect, and as such they can separately control their own caches
accordingly.

This has the benefit of sending less data from the engine to the client
whenever two consecutive frames have a lot of the same content.

This CL also creates //cc/blimp which is to be used for blimp-related
code living in //cc.

BUG=597811
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review-Url: https://codereview.chromium.org/1982893002
Cr-Commit-Position: refs/heads/master@{#402006}
  • Loading branch information
tommynyquist authored and Commit bot committed Jun 24, 2016
1 parent 4debe2a commit fbaee11
Show file tree
Hide file tree
Showing 78 changed files with 1,978 additions and 276 deletions.
4 changes: 4 additions & 0 deletions blimp/client/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ source_set("test_support") {

source_set("compositor") {
sources = [
"feature/compositor/blimp_client_picture_cache.cc",
"feature/compositor/blimp_client_picture_cache.h",
"feature/compositor/blimp_compositor.cc",
"feature/compositor/blimp_compositor.h",
"feature/compositor/blimp_compositor_manager.cc",
Expand Down Expand Up @@ -245,6 +247,7 @@ source_set("feature_unit_tests") {
testonly = true

sources = [
"feature/compositor/blimp_client_picture_cache_unittest.cc",
"feature/compositor/blimp_compositor_manager_unittest.cc",
"feature/navigation_feature_unittest.cc",
"feature/render_widget_feature_unittest.cc",
Expand All @@ -261,6 +264,7 @@ source_set("feature_unit_tests") {
"//blimp/common/proto",
"//blimp/net",
"//blimp/net:test_support",
"//blimp/test:support",
"//cc/proto",
"//net",
"//net:test_support",
Expand Down
98 changes: 98 additions & 0 deletions blimp/client/feature/compositor/blimp_client_picture_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2016 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 "blimp/client/feature/compositor/blimp_client_picture_cache.h"

#include <utility>
#include <vector>

#include "third_party/skia/include/core/SkStream.h"

namespace blimp {
namespace client {
namespace {

// Helper function to deserialize the content of |picture_data| into an
// SkPicture.
sk_sp<const SkPicture> DeserializePicture(
SkPicture::InstallPixelRefProc pixel_deserializer,
const cc::PictureData& picture_data) {
SkMemoryStream stream(picture_data.data);
return SkPicture::MakeFromStream(&stream, pixel_deserializer);
}

} // namespace

BlimpClientPictureCache::BlimpClientPictureCache(
SkPicture::InstallPixelRefProc pixel_deserializer)
: pixel_deserializer_(pixel_deserializer) {}

BlimpClientPictureCache::~BlimpClientPictureCache() = default;

sk_sp<const SkPicture> BlimpClientPictureCache::GetPicture(
uint32_t engine_picture_id) {
return GetPictureFromCache(engine_picture_id);
}

void BlimpClientPictureCache::ApplyCacheUpdate(
const std::vector<cc::PictureData>& cache_update) {
// Add new pictures from the |cache_update| to |pictures_|.
for (const cc::PictureData& picture_data : cache_update) {
DCHECK(pictures_.find(picture_data.unique_id) == pictures_.end());
sk_sp<const SkPicture> deserialized_picture =
DeserializePicture(pixel_deserializer_, picture_data);

pictures_[picture_data.unique_id] = std::move(deserialized_picture);

#if DCHECK_IS_ON()
last_added_.insert(picture_data.unique_id);
#endif // DCHECK_IS_ON()
}
}

void BlimpClientPictureCache::Flush() {
// Calculate which pictures can now be removed. |added| is only used for
// verifying that what we calculated matches the new items that have been
// inserted into the cache.
std::vector<uint32_t> added;
std::vector<uint32_t> removed;
reference_tracker_.CommitRefCounts(&added, &removed);

VerifyCacheUpdateMatchesReferenceTrackerData(added);

RemoveUnusedPicturesFromCache(removed);
reference_tracker_.ClearRefCounts();
}

void BlimpClientPictureCache::MarkUsed(uint32_t engine_picture_id) {
reference_tracker_.IncrementRefCount(engine_picture_id);
}

void BlimpClientPictureCache::RemoveUnusedPicturesFromCache(
const std::vector<uint32_t>& removed) {
for (const auto& engine_picture_id : removed) {
auto entry = pictures_.find(engine_picture_id);
DCHECK(entry != pictures_.end());
pictures_.erase(entry);
}
}

sk_sp<const SkPicture> BlimpClientPictureCache::GetPictureFromCache(
uint32_t engine_picture_id) {
DCHECK(pictures_.find(engine_picture_id) != pictures_.end());
return pictures_[engine_picture_id];
}

void BlimpClientPictureCache::VerifyCacheUpdateMatchesReferenceTrackerData(
const std::vector<uint32_t>& new_tracked_items) {
#if DCHECK_IS_ON()
DCHECK_EQ(new_tracked_items.size(), last_added_.size());
DCHECK(std::unordered_set<uint32_t>(new_tracked_items.begin(),
new_tracked_items.end()) == last_added_);
last_added_.clear();
#endif // DCHECK_IS_ON()
}

} // namespace client
} // namespace blimp
84 changes: 84 additions & 0 deletions blimp/client/feature/compositor/blimp_client_picture_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2016 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 BLIMP_CLIENT_FEATURE_COMPOSITOR_BLIMP_CLIENT_PICTURE_CACHE_H_
#define BLIMP_CLIENT_FEATURE_COMPOSITOR_BLIMP_CLIENT_PICTURE_CACHE_H_

#include <stdint.h>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "base/logging.h"
#include "base/macros.h"
#include "blimp/common/compositor/reference_tracker.h"
#include "cc/blimp/client_picture_cache.h"
#include "cc/blimp/engine_picture_cache.h"
#include "cc/blimp/picture_data.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRefCnt.h"

namespace blimp {
namespace client {

// BlimpClientPictureCache provides functionality for caching SkPictures once
// they are received from the engine, and cleaning up once the pictures are no
// longer in use. It is required to update this cache when an SkPicture starts
// being used and when it is not longer in use by calling
// MarkPictureForRegistration and MarkPictureForUnregistration respectively.
class BlimpClientPictureCache : public cc::ClientPictureCache {
public:
explicit BlimpClientPictureCache(
SkPicture::InstallPixelRefProc pixel_deserializer);
~BlimpClientPictureCache() override;

// cc::ClientPictureCache implementation.
sk_sp<const SkPicture> GetPicture(uint32_t engine_picture_id) override;
void ApplyCacheUpdate(
const std::vector<cc::PictureData>& cache_update) override;
void Flush() override;
void MarkUsed(uint32_t engine_picture_id) override;

private:
// Removes all pictures specified in |picture_ids| from |pictures_|. The
// picture IDs passed to this function must refer to the pictures that are no
// longer in use.
void RemoveUnusedPicturesFromCache(const std::vector<uint32_t>& picture_ids);

// Retrieves the SkPicture with the given |picture_id| from the cache. The
// given |picture_id| is the unique ID that the engine used to identify the
// picture in the cc::PictureCacheUpdate that contained the image.
sk_sp<const SkPicture> GetPictureFromCache(uint32_t picture_id);

// Verify that the incoming cache update matches the new items that were added
// to the |reference_tracker_|.
void VerifyCacheUpdateMatchesReferenceTrackerData(
const std::vector<uint32_t>& new_tracked_items);

#if DCHECK_IS_ON()
// A set of the items that were added when the last cache update was applied.
// Used for verifying that the calculation from the registry matches the
// expectations.
std::unordered_set<uint32_t> last_added_;
#endif // DCHECK_IS_ON()

// A function pointer valid to use for deserializing images when
// using SkPicture::CreateFromStream to create an SkPicture from a stream.
SkPicture::InstallPixelRefProc pixel_deserializer_;

// The current cache of SkPictures. The key is the unique ID used by the
// engine, and the value is the SkPicture itself.
std::unordered_map<uint32_t, sk_sp<const SkPicture>> pictures_;

// The reference tracker maintains the reference count of used SkPictures.
ReferenceTracker reference_tracker_;

DISALLOW_COPY_AND_ASSIGN(BlimpClientPictureCache);
};

} // namespace client
} // namespace blimp

#endif // BLIMP_CLIENT_FEATURE_COMPOSITOR_BLIMP_CLIENT_PICTURE_CACHE_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2016 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 "blimp/client/feature/compositor/blimp_client_picture_cache.h"

#include <stdint.h>
#include <memory>
#include <vector>

#include "blimp/test/support/compositor/picture_cache_test_support.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRefCnt.h"

namespace blimp {
namespace client {
namespace {

bool FakeImageDecoder(const void* input, size_t input_size, SkBitmap* bitmap) {
return true;
}

class BlimpClientPictureCacheTest : public testing::Test {
public:
BlimpClientPictureCacheTest() : cache_(&FakeImageDecoder) {}
~BlimpClientPictureCacheTest() override = default;

protected:
BlimpClientPictureCache cache_;

private:
DISALLOW_COPY_AND_ASSIGN(BlimpClientPictureCacheTest);
};

TEST_F(BlimpClientPictureCacheTest, TwoSkPicturesInCache) {
sk_sp<const SkPicture> picture1 = CreateSkPicture(SK_ColorBLUE);
sk_sp<const SkPicture> picture2 = CreateSkPicture(SK_ColorRED);
cc::PictureData picture1_data = CreatePictureData(picture1);
cc::PictureData picture2_data = CreatePictureData(picture2);

std::vector<cc::PictureData> cache_update;
cache_update.push_back(picture1_data);
cache_update.push_back(picture2_data);

cache_.ApplyCacheUpdate(cache_update);

cache_.MarkUsed(picture1->uniqueID());
cache_.MarkUsed(picture2->uniqueID());

sk_sp<const SkPicture> cached_picture1 =
cache_.GetPicture(picture1->uniqueID());
EXPECT_NE(nullptr, cached_picture1);
EXPECT_EQ(GetBlobId(picture1), GetBlobId(cached_picture1));
sk_sp<const SkPicture> cached_picture2 =
cache_.GetPicture(picture2->uniqueID());
EXPECT_NE(nullptr, cached_picture2);
EXPECT_EQ(GetBlobId(picture2), GetBlobId(cached_picture2));

cache_.Flush();
}

} // namespace
} // namespace client
} // namespace blimp
2 changes: 1 addition & 1 deletion blimp/client/feature/compositor/blimp_image_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
namespace blimp {
namespace client {

bool BlimpImageDecoder(const void* input, size_t input_size, SkBitmap* bitmap) {
bool DecodeBlimpImage(const void* input, size_t input_size, SkBitmap* bitmap) {
DCHECK(bitmap);

// Initialize an empty WebPDecoderConfig.
Expand Down
4 changes: 2 additions & 2 deletions blimp/client/feature/compositor/blimp_image_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ class SkBitmap;
namespace blimp {
namespace client {

// BlimpImageDecoder is an implementation of SkPicture::InstallPixelRefProc
// DecodeBlimpImage is an implementation of SkPicture::InstallPixelRefProc
// which is used by the client to decode WebP images that are part of an
// SkPicture.
bool BlimpImageDecoder(const void* input, size_t input_size, SkBitmap* bitmap);
bool DecodeBlimpImage(const void* input, size_t input_size, SkBitmap* bitmap);

} // namespace client
} // namespace blimp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#include <vector>

#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "blimp/client/feature/compositor/blimp_client_picture_cache.h"
#include "blimp/client/feature/compositor/blimp_image_decoder.h"
#include "blimp/common/blob_cache/blob_cache.h"
#include "blimp/common/blob_cache/id_util.h"
Expand Down Expand Up @@ -77,18 +79,20 @@ bool BlobImageSerializationProcessor::GetAndDecodeBlob(const void* input,
DVLOG(1) << "GetAndDecodeBlob(" << BlobIdToString(parsed_metadata.id())
<< ")";

return BlimpImageDecoder(reinterpret_cast<const void*>(&blob->data[0]),
blob->data.size(), bitmap);
return DecodeBlimpImage(reinterpret_cast<const void*>(&blob->data[0]),
blob->data.size(), bitmap);
}

SkPixelSerializer* BlobImageSerializationProcessor::GetPixelSerializer() {
std::unique_ptr<cc::EnginePictureCache>
BlobImageSerializationProcessor::CreateEnginePictureCache() {
NOTREACHED();
return nullptr;
}

SkPicture::InstallPixelRefProc
BlobImageSerializationProcessor::GetPixelDeserializer() {
return &BlobImageSerializationProcessor::InstallPixelRefProc;
std::unique_ptr<cc::ClientPictureCache>
BlobImageSerializationProcessor::CreateClientPictureCache() {
return base::WrapUnique(new BlimpClientPictureCache(
&BlobImageSerializationProcessor::InstallPixelRefProc));
}

} // namespace client
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include "base/macros.h"
#include "base/memory/singleton.h"
#include "cc/proto/image_serialization_processor.h"
#include "cc/blimp/image_serialization_processor.h"
#include "third_party/skia/include/core/SkPicture.h"

class SkPixelSerializer;
Expand All @@ -20,7 +20,8 @@ class BlobChannelReceiver;

namespace client {

// Adds BlobChannel image retrieval support to the Skia image decoding process.
// Adds BlobChannel image retrieval support to the Skia image decoding process,
// in addition to providing a cache for Skia images.
class BlobImageSerializationProcessor : public cc::ImageSerializationProcessor {
public:
class ErrorDelegate {
Expand All @@ -33,7 +34,7 @@ class BlobImageSerializationProcessor : public cc::ImageSerializationProcessor {
static BlobImageSerializationProcessor* current();

BlobImageSerializationProcessor();
virtual ~BlobImageSerializationProcessor();
~BlobImageSerializationProcessor() override;

// Sets the |blob_receiver| to use for reading images.
// |blob_receiver| must outlive |this|.
Expand Down Expand Up @@ -62,8 +63,8 @@ class BlobImageSerializationProcessor : public cc::ImageSerializationProcessor {
SkBitmap* bitmap);

// cc:ImageSerializationProcessor implementation.
SkPixelSerializer* GetPixelSerializer() override;
SkPicture::InstallPixelRefProc GetPixelDeserializer() override;
std::unique_ptr<cc::EnginePictureCache> CreateEnginePictureCache() override;
std::unique_ptr<cc::ClientPictureCache> CreateClientPictureCache() override;

// Interface for accessing stored images received over the Blob Channel.
BlobChannelReceiver* blob_receiver_ = nullptr;
Expand Down
3 changes: 3 additions & 0 deletions blimp/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ component("common") {
"blob_cache/in_memory_blob_cache.h",
"compositor/blimp_task_graph_runner.cc",
"compositor/blimp_task_graph_runner.h",
"compositor/reference_tracker.cc",
"compositor/reference_tracker.h",
"create_blimp_message.cc",
"create_blimp_message.h",
"get_client_token.cc",
Expand Down Expand Up @@ -64,6 +66,7 @@ source_set("unit_tests") {
sources = [
"blob_cache/id_util_unittest.cc",
"blob_cache/in_memory_blob_cache_unittest.cc",
"compositor/reference_tracker_unittest.cc",
"create_blimp_message_unittest.cc",
"logging_unittest.cc",
]
Expand Down
Loading

0 comments on commit fbaee11

Please sign in to comment.