Commit c96940cb authored by Khushal's avatar Khushal Committed by Commit Bot

cc: Avoid extra allocation and copy for SkTextBlob serialization.

When serializing a SkTextBlob, skia flattens it into allocated memory
which is then copied into PaintOpWriter's memory. Change this to
directly serialize into the writer's memory.

R=enne@chromium.org, reed@google.com
BUG:821584

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;luci.chromium.try:android_optional_gpu_tests_rel
Change-Id: I644a02aba1b8f5b204596eaf2b04d8763a9cce37
Reviewed-on: https://chromium-review.googlesource.com/961274Reviewed-by: default avatarenne <enne@chromium.org>
Commit-Queue: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548599}
parent f400ffb7
...@@ -1955,7 +1955,7 @@ TEST_P(PaintOpSerializationTest, UsesOverridenFlags) { ...@@ -1955,7 +1955,7 @@ TEST_P(PaintOpSerializationTest, UsesOverridenFlags) {
PaintOp* written = PaintOp::Deserialize( PaintOp* written = PaintOp::Deserialize(
output_.get(), bytes_written, deserialized.get(), deserialized_size, output_.get(), bytes_written, deserialized.get(), deserialized_size,
&bytes_read, options_provider.deserialize_options()); &bytes_read, options_provider.deserialize_options());
ASSERT_TRUE(written); ASSERT_TRUE(written) << PaintOpTypeToString(GetParamType());
EXPECT_EQ(*op, *written); EXPECT_EQ(*op, *written);
written->DestroyThis(); written->DestroyThis();
written = nullptr; written = nullptr;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "cc/paint/transfer_cache_deserialize_helper.h" #include "cc/paint/transfer_cache_deserialize_helper.h"
#include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkSerialProcs.h"
#include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkTextBlob.h"
namespace cc { namespace cc {
...@@ -33,8 +34,15 @@ struct TypefacesCatalog { ...@@ -33,8 +34,15 @@ struct TypefacesCatalog {
bool had_null = false; bool had_null = false;
}; };
sk_sp<SkTypeface> ResolveTypeface(uint32_t id, void* ctx) { sk_sp<SkTypeface> ResolveTypeface(const void* data, size_t length, void* ctx) {
TypefacesCatalog* catalog = static_cast<TypefacesCatalog*>(ctx); TypefacesCatalog* catalog = static_cast<TypefacesCatalog*>(ctx);
if (length != 4) {
catalog->had_null = true;
return nullptr;
}
uint32_t id;
memcpy(&id, data, length);
auto* entry = catalog->transfer_cache auto* entry = catalog->transfer_cache
->GetEntryAs<ServicePaintTypefaceTransferCacheEntry>(id); ->GetEntryAs<ServicePaintTypefaceTransferCacheEntry>(id);
// TODO(vmpstr): The !entry->typeface() check is here because not all // TODO(vmpstr): The !entry->typeface() check is here because not all
...@@ -386,24 +394,19 @@ void PaintOpReader::Read(sk_sp<SkColorSpace>* color_space) { ...@@ -386,24 +394,19 @@ void PaintOpReader::Read(sk_sp<SkColorSpace>* color_space) {
void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) { void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) {
size_t data_bytes = 0u; size_t data_bytes = 0u;
ReadSimple(&data_bytes); ReadSimple(&data_bytes);
// Skia expects aligned data size, make sure we don't pass it incorrect data. if (remaining_bytes_ < data_bytes || data_bytes == 0u)
if (remaining_bytes_ < data_bytes || data_bytes == 0u ||
!SkIsAlign4(data_bytes)) {
SetInvalid(); SetInvalid();
}
if (!valid_) if (!valid_)
return; return;
sk_sp<SkData> data =
SkData::MakeWithoutCopy(const_cast<const char*>(memory_), data_bytes);
memory_ += data_bytes;
remaining_bytes_ -= data_bytes;
TypefacesCatalog catalog; TypefacesCatalog catalog;
catalog.transfer_cache = transfer_cache_; catalog.transfer_cache = transfer_cache_;
sk_sp<SkTextBlob> blob = SkTextBlob::Deserialize(data->data(), data->size(),
&ResolveTypeface, &catalog); SkDeserialProcs procs;
procs.fTypefaceProc = &ResolveTypeface;
procs.fTypefaceCtx = &catalog;
sk_sp<SkTextBlob> blob = SkTextBlob::Deserialize(
const_cast<const char*>(memory_), data_bytes, procs);
// TODO(vmpstr): If we couldn't serialize |blob|, we should make |paint_blob| // TODO(vmpstr): If we couldn't serialize |blob|, we should make |paint_blob|
// nullptr. However, this causes GL errors right now, because not all // nullptr. However, this causes GL errors right now, because not all
// typefaces are serialized. Fix this once we serialize everything. For now // typefaces are serialized. Fix this once we serialize everything. For now
...@@ -414,6 +417,8 @@ void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) { ...@@ -414,6 +417,8 @@ void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) {
blob = nullptr; blob = nullptr;
*paint_blob = base::MakeRefCounted<PaintTextBlob>( *paint_blob = base::MakeRefCounted<PaintTextBlob>(
std::move(blob), std::vector<PaintTypeface>()); std::move(blob), std::vector<PaintTypeface>());
memory_ += data_bytes;
remaining_bytes_ -= data_bytes;
} }
void PaintOpReader::Read(sk_sp<PaintShader>* shader) { void PaintOpReader::Read(sk_sp<PaintShader>* shader) {
......
...@@ -12,16 +12,27 @@ ...@@ -12,16 +12,27 @@
#include "cc/paint/paint_shader.h" #include "cc/paint/paint_shader.h"
#include "cc/paint/paint_typeface_transfer_cache_entry.h" #include "cc/paint/paint_typeface_transfer_cache_entry.h"
#include "cc/paint/transfer_cache_serialize_helper.h" #include "cc/paint/transfer_cache_serialize_helper.h"
#include "third_party/skia/include/core/SkSerialProcs.h"
#include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkTextBlob.h"
#include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
namespace cc { namespace cc {
namespace { namespace {
void TypefaceCataloger(SkTypeface* typeface, void* ctx) { const size_t kSkiaAlignment = 4u;
sk_sp<SkData> TypefaceCataloger(SkTypeface* typeface, void* ctx) {
static_cast<TransferCacheSerializeHelper*>(ctx)->AssertLocked( static_cast<TransferCacheSerializeHelper*>(ctx)->AssertLocked(
TransferCacheEntryType::kPaintTypeface, typeface->uniqueID()); TransferCacheEntryType::kPaintTypeface, typeface->uniqueID());
uint32_t id = typeface->uniqueID();
return SkData::MakeWithCopy(&id, sizeof(uint32_t));
}
size_t RoundDownToAlignment(size_t bytes, size_t alignment) {
return bytes - (bytes & (alignment - 1));
} }
} // namespace } // namespace
// static // static
...@@ -97,16 +108,28 @@ void PaintOpWriter::WriteSimple(const T& val) { ...@@ -97,16 +108,28 @@ void PaintOpWriter::WriteSimple(const T& val) {
void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) { void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) {
DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_))) DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)))
<< "Flattenable must start writing at 4 byte alignment."; << "Flattenable must start writing at 4 byte alignment.";
if (!val) { if (!val) {
WriteSize(static_cast<size_t>(0u)); WriteSize(static_cast<size_t>(0u));
return; return;
} }
sk_sp<SkData> data = val->serialize(); size_t size_offset = sizeof(size_t);
WriteSize(data->size()); EnsureBytes(size_offset);
if (!data->isEmpty()) if (!valid_)
WriteData(data->size(), data->data()); return;
char* size_memory = memory_;
memory_ += size_offset;
remaining_bytes_ -= size_offset;
size_t bytes_written = val->serialize(
memory_, RoundDownToAlignment(remaining_bytes_, kSkiaAlignment));
if (bytes_written == 0u) {
valid_ = false;
return;
}
reinterpret_cast<size_t*>(size_memory)[0] = bytes_written;
memory_ += bytes_written;
remaining_bytes_ -= bytes_written;
} }
void PaintOpWriter::WriteSize(size_t size) { void PaintOpWriter::WriteSize(size_t size) {
...@@ -250,13 +273,28 @@ void PaintOpWriter::Write(const SkColorSpace* color_space) { ...@@ -250,13 +273,28 @@ void PaintOpWriter::Write(const SkColorSpace* color_space) {
} }
void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) {
// TODO(khushalsagar): Change skia API to serialize directly into shared mem. DCHECK(blob);
auto data = blob->serialize(&TypefaceCataloger, transfer_cache_);
DCHECK(data); size_t size_offset = sizeof(size_t);
DCHECK_GT(data->size(), 0u); EnsureBytes(size_offset);
if (!valid_)
return;
WriteSize(data->size()); char* size_memory = memory_;
WriteData(data->size(), data->data()); memory_ += size_offset;
remaining_bytes_ -= size_offset;
SkSerialProcs procs;
procs.fTypefaceProc = &TypefaceCataloger;
procs.fTypefaceCtx = transfer_cache_;
size_t bytes_written = blob->serialize(
procs, memory_, RoundDownToAlignment(remaining_bytes_, kSkiaAlignment));
if (bytes_written == 0u) {
valid_ = false;
return;
}
reinterpret_cast<size_t*>(size_memory)[0] = bytes_written;
memory_ += bytes_written;
remaining_bytes_ -= bytes_written;
} }
void PaintOpWriter::Write(const scoped_refptr<PaintTextBlob>& blob) { void PaintOpWriter::Write(const scoped_refptr<PaintTextBlob>& blob) {
......
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