blob: 82be5625783376f3afd79ccc33cabea48335b59e [file] [log] [blame]
// Copyright (c) 2017 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 "cc/paint/image_transfer_cache_entry.h"
#include "base/logging.h"
#include "base/numerics/checked_math.h"
#include "cc/paint/paint_op_reader.h"
#include "cc/paint/paint_op_writer.h"
#include "third_party/skia/include/gpu/GrContext.h"
namespace cc {
ClientImageTransferCacheEntry::ClientImageTransferCacheEntry(
const SkPixmap* pixmap,
const SkColorSpace* target_color_space)
: id_(s_next_id_.GetNext()), pixmap_(pixmap) {
// Compute and cache the size of the data.
// We write the following:
// - Image color type (uint32_t)
// - Image width (uint32_t)
// - Image height (uint32_t)
// - Pixels size (uint32_t)
// - Pixels (variable)
base::CheckedNumeric<size_t> safe_size;
safe_size += sizeof(uint32_t); // color type
safe_size += sizeof(uint32_t); // width
safe_size += sizeof(uint32_t); // height
safe_size += sizeof(size_t); // pixels size
safe_size += pixmap_->computeByteSize();
safe_size += PaintOpWriter::HeaderBytes();
size_ = safe_size.ValueOrDie();
// TODO(ericrk): Handle colorspace.
}
ClientImageTransferCacheEntry::~ClientImageTransferCacheEntry() = default;
// static
base::AtomicSequenceNumber ClientImageTransferCacheEntry::s_next_id_;
size_t ClientImageTransferCacheEntry::SerializedSize() const {
return size_;
}
uint32_t ClientImageTransferCacheEntry::Id() const {
return id_;
}
bool ClientImageTransferCacheEntry::Serialize(base::span<uint8_t> data) const {
DCHECK_GE(data.size(), SerializedSize());
PaintOpWriter writer(data.data(), data.size(), nullptr, nullptr);
writer.Write(pixmap_->colorType());
writer.Write(pixmap_->width());
writer.Write(pixmap_->height());
size_t pixmap_size = pixmap_->computeByteSize();
writer.WriteSize(pixmap_size);
writer.WriteData(pixmap_size, pixmap_->addr());
// TODO(ericrk): Handle colorspace.
if (writer.size() != data.size())
return false;
return true;
}
ServiceImageTransferCacheEntry::ServiceImageTransferCacheEntry() = default;
ServiceImageTransferCacheEntry::~ServiceImageTransferCacheEntry() = default;
ServiceImageTransferCacheEntry::ServiceImageTransferCacheEntry(
ServiceImageTransferCacheEntry&& other) = default;
ServiceImageTransferCacheEntry& ServiceImageTransferCacheEntry::operator=(
ServiceImageTransferCacheEntry&& other) = default;
size_t ServiceImageTransferCacheEntry::CachedSize() const {
return size_;
}
bool ServiceImageTransferCacheEntry::Deserialize(GrContext* context,
base::span<uint8_t> data) {
PaintOpReader reader(data.data(), data.size(), nullptr);
SkColorType color_type;
reader.Read(&color_type);
uint32_t width;
reader.Read(&width);
uint32_t height;
reader.Read(&height);
size_t pixel_size;
reader.ReadSize(&pixel_size);
size_ = data.size();
if (!reader.valid())
return false;
// TODO(ericrk): Handle colorspace.
SkImageInfo image_info =
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
const volatile void* pixel_data = reader.ExtractReadableMemory(pixel_size);
if (!reader.valid())
return false;
// Const-cast away the "volatile" on |pixel_data|. We specifically understand
// that a malicious caller may change our pixels under us, and are OK with
// this as the worst case scenario is visual corruption.
SkPixmap pixmap(image_info, const_cast<const void*>(pixel_data),
image_info.minRowBytes());
// Depending on whether the pixmap will fit in a GPU texture, either create
// a software or GPU SkImage.
uint32_t max_size = context->caps()->maxTextureSize();
bool fits_on_gpu = width <= max_size && height <= max_size;
if (fits_on_gpu) {
sk_sp<SkImage> image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
DCHECK(image);
image_ = image->makeTextureImage(context, nullptr);
} else {
image_ = SkImage::MakeRasterCopy(pixmap);
}
return image_;
}
} // namespace cc