1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/paint/paint_op_reader.h"
11 #include <type_traits>
15 #include "base/bits.h"
16 #include "base/compiler_specific.h"
17 #include "base/debug/dump_without_crashing.h"
18 #include "base/memory/raw_ptr.h"
19 #include "base/metrics/histogram_functions.h"
20 #include "base/notreached.h"
21 #include "base/rand_util.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/types/optional_util.h"
24 #include "cc/paint/image_transfer_cache_entry.h"
25 #include "cc/paint/paint_cache.h"
26 #include "cc/paint/paint_flags.h"
27 #include "cc/paint/paint_image_builder.h"
28 #include "cc/paint/paint_op_buffer.h"
29 #include "cc/paint/paint_shader.h"
30 #include "cc/paint/shader_transfer_cache_entry.h"
31 #include "cc/paint/skottie_transfer_cache_entry.h"
32 #include "cc/paint/skottie_wrapper.h"
33 #include "cc/paint/transfer_cache_deserialize_helper.h"
34 #include "components/crash/core/common/crash_key.h"
35 #include "third_party/skia/include/core/SkColorSpace.h"
36 #include "third_party/skia/include/core/SkPath.h"
37 #include "third_party/skia/include/core/SkRRect.h"
38 #include "third_party/skia/include/core/SkSerialProcs.h"
39 #include "third_party/skia/include/private/chromium/GrSlug.h"
40 #include "third_party/skia/include/private/chromium/SkChromeRemoteGlyphCache.h"
45 bool IsValidPaintShaderType(PaintShader::Type type) {
46 return static_cast<uint8_t>(type) <
47 static_cast<uint8_t>(PaintShader::Type::kShaderCount);
50 bool IsValidPaintShaderScalingBehavior(PaintShader::ScalingBehavior behavior) {
51 return behavior == PaintShader::ScalingBehavior::kRasterAtScale ||
52 behavior == PaintShader::ScalingBehavior::kFixedScale;
58 void PaintOpReader::FixupMatrixPostSerialization(SkMatrix* matrix) {
59 // Can't trust malicious clients to provide the correct derived matrix type.
60 // However, if a matrix thinks that it's identity, then make it so.
61 if (matrix->isIdentity())
62 matrix->setIdentity();
64 matrix->dirtyMatrixTypeCache();
68 bool PaintOpReader::ReadAndValidateOpHeader(const volatile void* input,
74 uint32_t first_word = reinterpret_cast<const volatile uint32_t*>(input)[0];
75 *type = static_cast<uint8_t>(first_word & 0xFF);
76 *skip = first_word >> 8;
78 if (input_size < *skip)
80 if (*skip % PaintOpBuffer::PaintOpAlign != 0)
82 if (*type > static_cast<uint8_t>(PaintOpType::LastPaintOpType))
88 void PaintOpReader::ReadSimple(T* val) {
89 static_assert(std::is_trivially_copyable_v<T>);
91 DCHECK_EQ(memory_, base::bits::AlignUp(memory_, PaintOpWriter::Alignment()));
92 // Align everything to 4 bytes, as the writer does.
93 static constexpr size_t size =
94 base::bits::AlignUp(sizeof(T), PaintOpWriter::Alignment());
96 if (remaining_bytes_ < size)
97 SetInvalid(DeserializationError::kInsufficientRemainingBytes_ReadSimple);
102 // Most of the time this is used for primitives, but this function is also
103 // used for SkRect/SkIRect/SkMatrix whose implicit operator= can't use a
104 // volatile. TOCTOU violations don't matter for these simple types so
106 *val = *reinterpret_cast<const T*>(const_cast<const char*>(memory_));
109 remaining_bytes_ -= size;
112 uint8_t* PaintOpReader::CopyScratchSpace(size_t bytes) {
113 DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)));
115 if (options_.scratch_buffer->size() < bytes)
116 options_.scratch_buffer->resize(bytes);
117 memcpy(options_.scratch_buffer->data(), const_cast<const char*>(memory_),
119 return options_.scratch_buffer->data();
122 template <typename T>
123 void PaintOpReader::ReadFlattenable(
126 DeserializationError error_on_factory_failure) {
129 if (remaining_bytes_ < bytes) {
131 DeserializationError::kInsufficientRemainingBytes_ReadFlattenable);
138 auto* scratch = CopyScratchSpace(bytes);
139 val->reset(factory(scratch, bytes, nullptr).release());
141 SetInvalid(error_on_factory_failure);
148 void PaintOpReader::ReadData(size_t bytes, void* data) {
149 DCHECK_EQ(memory_, base::bits::AlignUp(memory_, PaintOpWriter::Alignment()));
153 if (remaining_bytes_ < bytes) {
154 SetInvalid(DeserializationError::kInsufficientRemainingBytes_ReadData);
158 memcpy(data, const_cast<const char*>(memory_), bytes);
162 void PaintOpReader::ReadSize(size_t* size) {
171 void PaintOpReader::Read(SkScalar* data) {
176 PaintOpReader::Read(uint8_t* data) {
180 void PaintOpReader::Read(uint32_t* data) {
184 void PaintOpReader::Read(uint64_t* data) {
188 void PaintOpReader::Read(int32_t* data) {
192 void PaintOpReader::Read(SkRect* rect) {
196 void PaintOpReader::Read(SkIRect* rect) {
200 void PaintOpReader::Read(SkRRect* rect) {
204 void PaintOpReader::Read(SkColor4f* color) {
208 void PaintOpReader::Read(SkPath* path) {
210 ReadSimple(&path_id);
214 uint32_t entry_state_int = 0u;
215 ReadSimple(&entry_state_int);
216 if (entry_state_int > static_cast<uint32_t>(PaintCacheEntryState::kLast)) {
221 auto entry_state = static_cast<PaintCacheEntryState>(entry_state_int);
222 switch (entry_state) {
223 case PaintCacheEntryState::kEmpty:
225 case PaintCacheEntryState::kCached:
226 if (!options_.paint_cache->GetPath(path_id, path))
227 SetInvalid(DeserializationError::kMissingPaintCachePathEntry);
229 case PaintCacheEntryState::kInlined:
230 case PaintCacheEntryState::kInlinedDoNotCache: {
231 size_t path_bytes = 0u;
232 ReadSize(&path_bytes);
233 if (path_bytes > remaining_bytes_)
235 DeserializationError::kInsufficientRemainingBytes_Read_SkPath);
236 if (path_bytes == 0u)
237 SetInvalid(DeserializationError::kZeroSkPathBytes);
241 auto* scratch = CopyScratchSpace(path_bytes);
242 size_t bytes_read = path->readFromMemory(scratch, path_bytes);
243 if (bytes_read == 0u) {
244 SetInvalid(DeserializationError::kSkPathReadFromMemoryFailure);
247 if (entry_state == PaintCacheEntryState::kInlined) {
248 options_.paint_cache->PutPath(path_id, *path);
250 // If we know that this path will only be drawn once, which is
251 // implied by kInlinedDoNotCache, we signal to skia that it should not
252 // do any caching either.
253 path->setIsVolatile(true);
261 void PaintOpReader::Read(PaintFlags* flags) {
262 ReadSimple(&flags->color_);
263 Read(&flags->width_);
264 Read(&flags->miter_limit_);
266 Read(&flags->blend_mode_);
268 ReadSimple(&flags->bitfields_uint_);
270 ReadFlattenable(&flags->path_effect_, SkPathEffect::Deserialize,
271 DeserializationError::kSkPathEffectUnflattenFailure);
272 ReadFlattenable(&flags->mask_filter_, SkMaskFilter::Deserialize,
273 DeserializationError::kSkMaskFilterUnflattenFailure);
274 ReadFlattenable(&flags->color_filter_, SkColorFilter::Deserialize,
275 DeserializationError::kSkColorFilterUnflattenFailure);
277 if (enable_security_constraints_) {
281 SetInvalid(DeserializationError::kDrawLooperForbidden);
285 ReadFlattenable(&flags->draw_looper_, SkDrawLooper::Deserialize,
286 DeserializationError::kSkDrawLooperUnflattenFailure);
289 Read(&flags->image_filter_);
290 Read(&flags->shader_);
293 void PaintOpReader::Read(PaintImage* image) {
294 uint8_t serialized_type_int = 0u;
295 Read(&serialized_type_int);
296 if (serialized_type_int >
297 static_cast<uint8_t>(PaintOp::SerializedImageType::kLastType)) {
298 SetInvalid(DeserializationError::kInvalidSerializedImageType);
302 auto serialized_type =
303 static_cast<PaintOp::SerializedImageType>(serialized_type_int);
304 if (serialized_type == PaintOp::SerializedImageType::kNoImage)
307 if (enable_security_constraints_) {
308 switch (serialized_type) {
309 case PaintOp::SerializedImageType::kNoImage:
312 case PaintOp::SerializedImageType::kImageData: {
313 SkColorType color_type;
320 ReadSize(&pixel_size);
324 SkImageInfo image_info =
325 SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
326 if (pixel_size < image_info.computeMinByteSize()) {
327 SetInvalid(DeserializationError::kInsufficientPixelData);
330 const volatile void* pixel_data = ExtractReadableMemory(pixel_size);
334 SkPixmap pixmap(image_info, const_cast<const void*>(pixel_data),
335 image_info.minRowBytes());
337 *image = PaintImageBuilder::WithDefault()
338 .set_id(PaintImage::GetNextId())
339 .set_texture_image(SkImage::MakeRasterCopy(pixmap),
340 PaintImage::kNonLazyStableId)
344 case PaintOp::SerializedImageType::kTransferCacheEntry:
345 case PaintOp::SerializedImageType::kMailbox:
346 SetInvalid(DeserializationError::kForbiddenSerializedImageType);
354 if (serialized_type == PaintOp::SerializedImageType::kMailbox) {
355 if (!options_.shared_image_provider) {
356 SetInvalid(DeserializationError::kMissingSharedImageProvider);
360 gpu::Mailbox mailbox;
362 if (mailbox.IsZero()) {
363 SetInvalid(DeserializationError::kZeroMailbox);
367 SharedImageProvider::Error error;
368 sk_sp<SkImage> sk_image =
369 options_.shared_image_provider->OpenSharedImageForRead(mailbox, error);
370 if (error != SharedImageProvider::Error::kNoError) {
372 case SharedImageProvider::Error::kNoAccess:
373 SetInvalid(DeserializationError::kSharedImageProviderNoAccess);
375 case SharedImageProvider::Error::kSkImageCreationFailed:
377 DeserializationError::kSharedImageProviderSkImageCreationFailed);
379 case SharedImageProvider::Error::kUnknownMailbox:
380 SetInvalid(DeserializationError::kSharedImageProviderUnknownMailbox);
386 SetInvalid(DeserializationError::kSharedImageOpenFailure);
391 *image = PaintImageBuilder::WithDefault()
392 .set_id(PaintImage::GetNextId())
393 .set_texture_image(std::move(sk_image),
394 PaintImage::kNonLazyStableId)
399 if (serialized_type != PaintOp::SerializedImageType::kTransferCacheEntry) {
400 SetInvalid(DeserializationError::kUnexpectedSerializedImageType);
404 uint32_t transfer_cache_entry_id;
405 ReadSimple(&transfer_cache_entry_id);
410 ReadSimple(&needs_mips);
414 // If we encountered a decode failure, we may write an invalid id for the
415 // image. In these cases, just return, leaving the image as nullptr.
416 if (transfer_cache_entry_id == kInvalidImageTransferCacheEntryId)
419 // The transfer cache entry for an image may not exist if the upload fails.
421 options_.transfer_cache->GetEntryAs<ServiceImageTransferCacheEntry>(
422 transfer_cache_entry_id)) {
426 PaintImageBuilder::WithDefault()
427 .set_id(PaintImage::GetNextId())
428 .set_texture_image(entry->image(), PaintImage::kNonLazyStableId)
433 void PaintOpReader::Read(sk_sp<SkData>* data) {
436 if (remaining_bytes_ < bytes)
437 SetInvalid(DeserializationError::kInsufficientRemainingBytes_Read_SkData);
441 // Separate out empty vs not valid cases.
443 bool has_data = false;
446 *data = SkData::MakeEmpty();
450 // This is safe to cast away the volatile as it is just a memcpy internally.
451 *data = SkData::MakeWithCopy(const_cast<const char*>(memory_), bytes);
455 void PaintOpReader::Read(sk_sp<SkColorSpace>* color_space) {
458 if (remaining_bytes_ < size)
460 if (!valid_ || size == 0)
463 auto* scratch = CopyScratchSpace(size);
464 *color_space = SkColorSpace::Deserialize(scratch, size);
465 // If this had non-zero bytes, it should be a valid color space.
467 SetInvalid(DeserializationError::kSkColorSpaceDeserializeFailure);
472 void PaintOpReader::Read(sk_sp<GrSlug>* slug) {
473 AssertAlignment(PaintOpWriter::Alignment());
475 size_t data_bytes = 0u;
476 ReadSize(&data_bytes);
477 if (data_bytes == 0) {
482 if (remaining_bytes_ < data_bytes) {
483 SetInvalid(DeserializationError::kInsufficientRemainingBytes_Read_GrSlug);
487 *slug = GrSlug::Deserialize(const_cast<const char*>(memory_), data_bytes,
488 options_.strike_client);
492 SetInvalid(DeserializationError::kGrSlugDeserializeFailure);
497 void PaintOpReader::Read(sk_sp<PaintShader>* shader) {
498 bool has_shader = false;
499 ReadSimple(&has_shader);
504 PaintShader::Type shader_type;
505 ReadSimple(&shader_type);
506 // Avoid creating a shader if something is invalid.
507 if (!valid_ || !IsValidPaintShaderType(shader_type)) {
508 SetInvalid(DeserializationError::kInvalidPaintShaderType);
512 *shader = sk_sp<PaintShader>(new PaintShader(shader_type));
513 PaintShader& ref = **shader;
514 ReadSimple(&ref.flags_);
515 ReadSimple(&ref.end_radius_);
516 ReadSimple(&ref.start_radius_);
519 ReadSimple(&ref.fallback_color_);
520 ReadSimple(&ref.scaling_behavior_);
521 if (!IsValidPaintShaderScalingBehavior(ref.scaling_behavior_))
522 SetInvalid(DeserializationError::kInvalidPaintShaderScalingBehavior);
523 bool has_local_matrix = false;
524 ReadSimple(&has_local_matrix);
525 if (has_local_matrix) {
526 ref.local_matrix_.emplace();
527 Read(&*ref.local_matrix_);
529 ReadSimple(&ref.center_);
530 ReadSimple(&ref.tile_);
531 ReadSimple(&ref.start_point_);
532 ReadSimple(&ref.end_point_);
533 ReadSimple(&ref.start_degrees_);
534 ReadSimple(&ref.end_degrees_);
536 bool has_record = false;
537 ReadSimple(&has_record);
538 uint32_t shader_id = PaintShader::kInvalidRecordShaderId;
539 size_t shader_size = 0;
541 if (shader_type != PaintShader::Type::kPaintRecord) {
542 SetInvalid(DeserializationError::kUnexpectedPaintShaderType);
546 if (shader_id == PaintShader::kInvalidRecordShaderId) {
547 SetInvalid(DeserializationError::kInvalidRecordShaderId);
551 // Track dependent transfer cache entries to make cached shader size
553 size_t pre_size = options_.transfer_cache->GetTotalEntrySizes();
554 size_t record_size = Read(&ref.record_);
555 size_t post_size = options_.transfer_cache->GetTotalEntrySizes();
556 shader_size = post_size - pre_size + record_size;
560 decltype(ref.colors_)::size_type colors_size = 0;
561 ReadSize(&colors_size);
563 // If there are too many colors, abort.
564 if (colors_size > remaining_bytes_) {
565 SetInvalid(DeserializationError::
566 kInsufficientRemainingBytes_Read_PaintShader_ColorSize);
569 size_t colors_bytes =
570 colors_size * (colors_size > 0 ? sizeof(ref.colors_[0]) : 0u);
571 if (colors_bytes > remaining_bytes_) {
572 SetInvalid(DeserializationError::
573 kInsufficientRemainingBytes_Read_PaintShader_ColorBytes);
576 ref.colors_.resize(colors_size);
577 ReadData(colors_bytes, ref.colors_.data());
579 decltype(ref.positions_)::size_type positions_size = 0;
580 ReadSize(&positions_size);
581 // Positions are optional. If they exist, they have the same count as colors.
582 if (positions_size > 0 && positions_size != colors_size) {
583 SetInvalid(DeserializationError::kInvalidPaintShaderPositionsSize);
586 size_t positions_bytes = positions_size * sizeof(SkScalar);
587 if (positions_bytes > remaining_bytes_) {
588 SetInvalid(DeserializationError::
589 kInsufficientRemainingBytes_Read_PaintShader_Positions);
592 ref.positions_.resize(positions_size);
593 ReadData(positions_size * sizeof(SkScalar), ref.positions_.data());
595 // We don't write the cached shader, so don't attempt to read it either.
597 if (!(*shader)->IsValid()) {
598 SetInvalid(DeserializationError::kInvalidPaintShader);
602 // All shader types but records are done.
603 if (shader_type != PaintShader::Type::kPaintRecord) {
604 (*shader)->ResolveSkObjects();
608 // Record shaders have shader ids. Attempt to use cached versions of
609 // these so that Skia can cache based on SkPictureShader::fUniqueId.
610 // These shaders are always serialized (and assumed to not be large
611 // records). Handling this edge case in this roundabout way prevents
612 // transfer cache entries from needing to depend on other transfer cache
615 options_.transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(
617 // Only consider entries that use the same scale. This limits the service
618 // side transfer cache to only having one entry per shader but this will hit
619 // the common case of enabling Skia reuse.
620 if (entry && entry->shader()->tile_ == ref.tile_) {
621 DCHECK(!ref.sk_cached_picture_);
622 ref.sk_cached_picture_ = entry->shader()->sk_cached_picture_;
624 ref.ResolveSkObjects();
625 DCHECK(ref.sk_cached_picture_);
626 options_.transfer_cache->CreateLocalEntry(
627 shader_id, std::make_unique<ServiceShaderTransferCacheEntry>(
628 *shader, shader_size));
632 void PaintOpReader::Read(SkMatrix* matrix) {
634 FixupMatrixPostSerialization(matrix);
637 void PaintOpReader::Read(SkM44* matrix) {
641 void PaintOpReader::Read(SkSamplingOptions* sampling) {
645 SkCubicResampler cubic;
648 *sampling = SkSamplingOptions(cubic);
654 *sampling = SkSamplingOptions(filter, mipmap);
658 void PaintOpReader::Read(SkYUVColorSpace* yuv_color_space) {
659 uint32_t raw_yuv_color_space = kIdentity_SkYUVColorSpace;
660 ReadSimple(&raw_yuv_color_space);
662 if (raw_yuv_color_space > kLastEnum_SkYUVColorSpace) {
663 SetInvalid(DeserializationError::kInvalidSkYUVColorSpace);
667 *yuv_color_space = static_cast<SkYUVColorSpace>(raw_yuv_color_space);
670 void PaintOpReader::Read(SkYUVAInfo::PlaneConfig* plane_config) {
671 uint32_t raw_plane_config =
672 static_cast<uint32_t>(SkYUVAInfo::PlaneConfig::kUnknown);
673 ReadSimple(&raw_plane_config);
675 if (raw_plane_config >
676 static_cast<uint32_t>(SkYUVAInfo::PlaneConfig::kLast)) {
677 SetInvalid(DeserializationError::kInvalidPlaneConfig);
681 *plane_config = static_cast<SkYUVAInfo::PlaneConfig>(raw_plane_config);
684 void PaintOpReader::Read(SkYUVAInfo::Subsampling* subsampling) {
685 uint32_t raw_subsampling =
686 static_cast<uint32_t>(SkYUVAInfo::Subsampling::kUnknown);
687 ReadSimple(&raw_subsampling);
689 if (raw_subsampling > static_cast<uint32_t>(SkYUVAInfo::Subsampling::kLast)) {
690 SetInvalid(DeserializationError::kInvalidSubsampling);
694 *subsampling = static_cast<SkYUVAInfo::Subsampling>(raw_subsampling);
697 void PaintOpReader::Read(gpu::Mailbox* mailbox) {
698 ReadData(sizeof(gpu::Mailbox::Name), (*mailbox).name);
701 void PaintOpReader::Read(scoped_refptr<SkottieWrapper>* skottie) {
702 if (!options_.is_privileged) {
707 uint32_t transfer_cache_entry_id;
708 ReadSimple(&transfer_cache_entry_id);
712 options_.transfer_cache->GetEntryAs<ServiceSkottieTransferCacheEntry>(
713 transfer_cache_entry_id);
715 *skottie = entry->skottie();
720 size_t bytes_to_skip = 0u;
721 ReadSize(&bytes_to_skip);
724 if (bytes_to_skip > remaining_bytes_) {
728 DidRead(bytes_to_skip);
731 void PaintOpReader::AlignMemory(size_t alignment) {
732 size_t padding = base::bits::AlignUp(memory_, alignment) - memory_;
733 if (padding > remaining_bytes_)
734 SetInvalid(DeserializationError::kInsufficientRemainingBytes_AlignMemory);
737 remaining_bytes_ -= padding;
740 // Don't inline this function so that crash reports can show the caller.
741 NOINLINE void PaintOpReader::SetInvalid(DeserializationError error) {
742 static crash_reporter::CrashKeyString<4> deserialization_error_crash_key(
743 "PaintOpReader deserialization error");
744 base::UmaHistogramEnumeration("GPU.PaintOpReader.DeserializationError",
746 if (valid_ && options_.crash_dump_on_failure && base::RandInt(1, 10) == 1) {
747 crash_reporter::ScopedCrashKeyString crash_key_scope(
748 &deserialization_error_crash_key,
749 base::NumberToString(static_cast<int>(error)));
750 base::debug::DumpWithoutCrashing();
755 const volatile void* PaintOpReader::ExtractReadableMemory(size_t bytes) {
756 if (remaining_bytes_ < bytes)
757 SetInvalid(DeserializationError::
758 kInsufficientRemainingBytes_ExtractReadableMemory);
764 const volatile void* extracted_memory = memory_;
766 return extracted_memory;
769 void PaintOpReader::Read(sk_sp<PaintFilter>* filter) {
770 PaintFilter::Type type;
775 if (type == PaintFilter::Type::kNullFilter) {
780 uint32_t has_crop_rect = 0;
781 absl::optional<PaintFilter::CropRect> crop_rect;
782 ReadSimple(&has_crop_rect);
784 SkRect rect = SkRect::MakeEmpty();
786 crop_rect.emplace(rect);
789 AssertAlignment(PaintOpWriter::Alignment());
791 case PaintFilter::Type::kNullFilter:
794 case PaintFilter::Type::kColorFilter:
795 ReadColorFilterPaintFilter(filter, crop_rect);
797 case PaintFilter::Type::kBlur:
798 ReadBlurPaintFilter(filter, crop_rect);
800 case PaintFilter::Type::kDropShadow:
801 ReadDropShadowPaintFilter(filter, crop_rect);
803 case PaintFilter::Type::kMagnifier:
804 ReadMagnifierPaintFilter(filter, crop_rect);
806 case PaintFilter::Type::kCompose:
807 ReadComposePaintFilter(filter, crop_rect);
809 case PaintFilter::Type::kAlphaThreshold:
810 ReadAlphaThresholdPaintFilter(filter, crop_rect);
812 case PaintFilter::Type::kXfermode:
813 ReadXfermodePaintFilter(filter, crop_rect);
815 case PaintFilter::Type::kArithmetic:
816 ReadArithmeticPaintFilter(filter, crop_rect);
818 case PaintFilter::Type::kMatrixConvolution:
819 ReadMatrixConvolutionPaintFilter(filter, crop_rect);
821 case PaintFilter::Type::kDisplacementMapEffect:
822 ReadDisplacementMapEffectPaintFilter(filter, crop_rect);
824 case PaintFilter::Type::kImage:
825 ReadImagePaintFilter(filter, crop_rect);
827 case PaintFilter::Type::kPaintRecord:
828 ReadRecordPaintFilter(filter, crop_rect);
830 case PaintFilter::Type::kMerge:
831 ReadMergePaintFilter(filter, crop_rect);
833 case PaintFilter::Type::kMorphology:
834 ReadMorphologyPaintFilter(filter, crop_rect);
836 case PaintFilter::Type::kOffset:
837 ReadOffsetPaintFilter(filter, crop_rect);
839 case PaintFilter::Type::kTile:
840 ReadTilePaintFilter(filter, crop_rect);
842 case PaintFilter::Type::kTurbulence:
843 ReadTurbulencePaintFilter(filter, crop_rect);
845 case PaintFilter::Type::kShader:
846 ReadShaderPaintFilter(filter, crop_rect);
848 case PaintFilter::Type::kMatrix:
849 ReadMatrixPaintFilter(filter, crop_rect);
851 case PaintFilter::Type::kLightingDistant:
852 ReadLightingDistantPaintFilter(filter, crop_rect);
854 case PaintFilter::Type::kLightingPoint:
855 ReadLightingPointPaintFilter(filter, crop_rect);
857 case PaintFilter::Type::kLightingSpot:
858 ReadLightingSpotPaintFilter(filter, crop_rect);
860 case PaintFilter::Type::kStretch:
861 ReadStretchPaintFilter(filter, crop_rect);
866 void PaintOpReader::ReadColorFilterPaintFilter(
867 sk_sp<PaintFilter>* filter,
868 const absl::optional<PaintFilter::CropRect>& crop_rect) {
869 sk_sp<SkColorFilter> color_filter;
870 sk_sp<PaintFilter> input;
872 ReadFlattenable(&color_filter, SkColorFilter::Deserialize,
873 DeserializationError::kSkColorFilterUnflattenFailure);
876 SetInvalid(DeserializationError::kZeroSkColorFilterBytes);
879 filter->reset(new ColorFilterPaintFilter(std::move(color_filter),
881 base::OptionalToPtr(crop_rect)));
884 void PaintOpReader::ReadBlurPaintFilter(
885 sk_sp<PaintFilter>* filter,
886 const absl::optional<PaintFilter::CropRect>& crop_rect) {
887 SkScalar sigma_x = 0.f;
888 SkScalar sigma_y = 0.f;
889 SkTileMode tile_mode;
890 sk_sp<PaintFilter> input;
898 filter->reset(new BlurPaintFilter(sigma_x, sigma_y, tile_mode,
900 base::OptionalToPtr(crop_rect)));
903 void PaintOpReader::ReadDropShadowPaintFilter(
904 sk_sp<PaintFilter>* filter,
905 const absl::optional<PaintFilter::CropRect>& crop_rect) {
908 SkScalar sigma_x = 0.f;
909 SkScalar sigma_y = 0.f;
910 SkColor color = SK_ColorBLACK;
911 DropShadowPaintFilter::ShadowMode shadow_mode;
912 sk_sp<PaintFilter> input;
919 ReadEnum(&shadow_mode);
923 // TODO(crbug/1308932): Remove FromColor and make all SkColor4f.
924 filter->reset(new DropShadowPaintFilter(
925 dx, dy, sigma_x, sigma_y, SkColor4f::FromColor(color), shadow_mode,
926 std::move(input), base::OptionalToPtr(crop_rect)));
929 void PaintOpReader::ReadMagnifierPaintFilter(
930 sk_sp<PaintFilter>* filter,
931 const absl::optional<PaintFilter::CropRect>& crop_rect) {
932 SkRect src_rect = SkRect::MakeEmpty();
933 SkScalar inset = 0.f;
934 sk_sp<PaintFilter> input;
941 filter->reset(new MagnifierPaintFilter(src_rect, inset, std::move(input),
942 base::OptionalToPtr(crop_rect)));
945 void PaintOpReader::ReadComposePaintFilter(
946 sk_sp<PaintFilter>* filter,
947 const absl::optional<PaintFilter::CropRect>& crop_rect) {
948 sk_sp<PaintFilter> outer;
949 sk_sp<PaintFilter> inner;
955 filter->reset(new ComposePaintFilter(std::move(outer), std::move(inner)));
958 void PaintOpReader::ReadAlphaThresholdPaintFilter(
959 sk_sp<PaintFilter>* filter,
960 const absl::optional<PaintFilter::CropRect>& crop_rect) {
962 SkScalar inner_min = 0.f;
963 SkScalar outer_max = 0.f;
964 sk_sp<PaintFilter> input;
967 ReadSimple(&inner_min);
968 ReadSimple(&outer_max);
972 filter->reset(new AlphaThresholdPaintFilter(region, inner_min, outer_max,
974 base::OptionalToPtr(crop_rect)));
977 void PaintOpReader::ReadXfermodePaintFilter(
978 sk_sp<PaintFilter>* filter,
979 const absl::optional<PaintFilter::CropRect>& crop_rect) {
980 SkBlendMode blend_mode;
981 sk_sp<PaintFilter> background;
982 sk_sp<PaintFilter> foreground;
990 filter->reset(new XfermodePaintFilter(blend_mode, std::move(background),
991 std::move(foreground),
992 base::OptionalToPtr(crop_rect)));
995 void PaintOpReader::ReadArithmeticPaintFilter(
996 sk_sp<PaintFilter>* filter,
997 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1002 bool enforce_pm_color = false;
1003 sk_sp<PaintFilter> background;
1004 sk_sp<PaintFilter> foreground;
1009 Read(&enforce_pm_color);
1014 filter->reset(new ArithmeticPaintFilter(
1015 k1, k2, k3, k4, enforce_pm_color, std::move(background),
1016 std::move(foreground), base::OptionalToPtr(crop_rect)));
1019 void PaintOpReader::ReadMatrixConvolutionPaintFilter(
1020 sk_sp<PaintFilter>* filter,
1021 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1022 SkISize kernel_size = SkISize::MakeEmpty();
1023 SkScalar gain = 0.f;
1024 SkScalar bias = 0.f;
1025 SkIPoint kernel_offset = SkIPoint::Make(0, 0);
1026 SkTileMode tile_mode;
1027 bool convolve_alpha = false;
1028 sk_sp<PaintFilter> input;
1030 ReadSimple(&kernel_size);
1034 static_cast<size_t>(sk_64_mul(kernel_size.width(), kernel_size.height()));
1035 if (size > remaining_bytes_) {
1037 DeserializationError::
1038 kInsufficientRemainingBytes_ReadMatrixConvolutionPaintFilter);
1041 std::vector<SkScalar> kernel(size);
1042 for (size_t i = 0; i < size; ++i)
1046 ReadSimple(&kernel_offset);
1048 Read(&convolve_alpha);
1052 filter->reset(new MatrixConvolutionPaintFilter(
1053 kernel_size, kernel.data(), gain, bias, kernel_offset, tile_mode,
1054 convolve_alpha, std::move(input), base::OptionalToPtr(crop_rect)));
1057 void PaintOpReader::ReadDisplacementMapEffectPaintFilter(
1058 sk_sp<PaintFilter>* filter,
1059 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1060 SkColorChannel channel_x;
1061 SkColorChannel channel_y;
1062 SkScalar scale = 0.f;
1063 sk_sp<PaintFilter> displacement;
1064 sk_sp<PaintFilter> color;
1066 ReadEnum<SkColorChannel, SkColorChannel::kA>(&channel_x);
1067 ReadEnum<SkColorChannel, SkColorChannel::kA>(&channel_y);
1069 Read(&displacement);
1074 filter->reset(new DisplacementMapEffectPaintFilter(
1075 channel_x, channel_y, scale, std::move(displacement), std::move(color),
1076 base::OptionalToPtr(crop_rect)));
1079 void PaintOpReader::ReadImagePaintFilter(
1080 sk_sp<PaintFilter>* filter,
1081 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1085 SetInvalid(DeserializationError::kReadImageFailure);
1093 PaintFlags::FilterQuality quality;
1099 new ImagePaintFilter(std::move(image), src_rect, dst_rect, quality));
1102 void PaintOpReader::ReadRecordPaintFilter(
1103 sk_sp<PaintFilter>* filter,
1104 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1105 bool has_filter = false;
1106 ReadSimple(&has_filter);
1112 SkRect record_bounds = SkRect::MakeEmpty();
1113 gfx::SizeF raster_scale = {0.f, 0.f};
1114 PaintShader::ScalingBehavior scaling_behavior =
1115 PaintShader::ScalingBehavior::kRasterAtScale;
1116 sk_sp<PaintRecord> record;
1118 ReadSimple(&record_bounds);
1119 ReadSimple(&raster_scale);
1120 if (raster_scale.width() <= 0.f || raster_scale.height() <= 0.f) {
1121 SetInvalid(DeserializationError::kInvalidRasterScale);
1125 ReadSimple(&scaling_behavior);
1126 if (!IsValidPaintShaderScalingBehavior(scaling_behavior)) {
1127 SetInvalid(DeserializationError::kInvalidPaintShaderScalingBehavior);
1131 // RecordPaintFilter also requires kRasterAtScale to have {1.f, 1.f} as the
1132 // raster_scale, since that is intended for kFixedScale
1133 if (scaling_behavior == PaintShader::ScalingBehavior::kRasterAtScale &&
1134 (raster_scale.width() != 1.f || raster_scale.height() != 1.f)) {
1135 SetInvalid(DeserializationError::kInvalidRasterScale);
1142 filter->reset(new RecordPaintFilter(std::move(record), record_bounds,
1143 raster_scale, scaling_behavior));
1146 void PaintOpReader::ReadMergePaintFilter(
1147 sk_sp<PaintFilter>* filter,
1148 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1149 size_t input_count = 0;
1150 ReadSize(&input_count);
1152 // The minimum size for a serialized filter is 4 bytes (a zero uint32_t to
1153 // indicate a null filter). Make sure the |input_count| doesn't exceed the
1154 // maximum number of filters possible for the remaining data.
1155 const size_t max_filters = remaining_bytes_ / 4u;
1156 if (input_count > max_filters)
1157 SetInvalid(DeserializationError::kPaintFilterHasTooManyInputs);
1160 std::vector<sk_sp<PaintFilter>> inputs(input_count);
1161 for (auto& input : inputs)
1165 filter->reset(new MergePaintFilter(inputs.data(),
1166 static_cast<int>(input_count),
1167 base::OptionalToPtr(crop_rect)));
1170 void PaintOpReader::ReadMorphologyPaintFilter(
1171 sk_sp<PaintFilter>* filter,
1172 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1173 MorphologyPaintFilter::MorphType morph_type;
1176 sk_sp<PaintFilter> input;
1177 ReadEnum(&morph_type);
1183 filter->reset(new MorphologyPaintFilter(morph_type, radius_x, radius_y,
1185 base::OptionalToPtr(crop_rect)));
1188 void PaintOpReader::ReadOffsetPaintFilter(
1189 sk_sp<PaintFilter>* filter,
1190 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1193 sk_sp<PaintFilter> input;
1200 filter->reset(new OffsetPaintFilter(dx, dy, std::move(input),
1201 base::OptionalToPtr(crop_rect)));
1204 void PaintOpReader::ReadTilePaintFilter(
1205 sk_sp<PaintFilter>* filter,
1206 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1207 SkRect src = SkRect::MakeEmpty();
1208 SkRect dst = SkRect::MakeEmpty();
1209 sk_sp<PaintFilter> input;
1216 filter->reset(new TilePaintFilter(src, dst, std::move(input)));
1219 void PaintOpReader::ReadTurbulencePaintFilter(
1220 sk_sp<PaintFilter>* filter,
1221 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1222 TurbulencePaintFilter::TurbulenceType turbulence_type;
1223 SkScalar base_frequency_x = 0.f;
1224 SkScalar base_frequency_y = 0.f;
1225 int num_octaves = 0;
1226 SkScalar seed = 0.f;
1227 SkISize tile_size = SkISize::MakeEmpty();
1229 ReadEnum(&turbulence_type);
1230 Read(&base_frequency_x);
1231 Read(&base_frequency_y);
1234 ReadSimple(&tile_size);
1237 filter->reset(new TurbulencePaintFilter(
1238 turbulence_type, base_frequency_x, base_frequency_y, num_octaves, seed,
1239 &tile_size, base::OptionalToPtr(crop_rect)));
1242 void PaintOpReader::ReadShaderPaintFilter(
1243 sk_sp<PaintFilter>* filter,
1244 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1245 using Dither = SkImageFilters::Dither;
1247 sk_sp<PaintShader> shader;
1248 uint8_t alpha = 255;
1249 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
1250 Dither dither = Dither::kNo;
1255 ReadEnum<Dither, Dither::kYes>(&dither);
1257 if (!shader || !valid_)
1260 filter->reset(new ShaderPaintFilter(std::move(shader), alpha, quality, dither,
1261 base::OptionalToPtr(crop_rect)));
1264 void PaintOpReader::ReadMatrixPaintFilter(
1265 sk_sp<PaintFilter>* filter,
1266 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1267 SkMatrix matrix = SkMatrix::I();
1268 PaintFlags::FilterQuality filter_quality = PaintFlags::FilterQuality::kNone;
1269 sk_sp<PaintFilter> input;
1272 Read(&filter_quality);
1277 new MatrixPaintFilter(matrix, filter_quality, std::move(input)));
1280 void PaintOpReader::ReadLightingDistantPaintFilter(
1281 sk_sp<PaintFilter>* filter,
1282 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1283 PaintFilter::LightingType lighting_type;
1284 SkPoint3 direction = SkPoint3::Make(0.f, 0.f, 0.f);
1285 SkColor light_color = SK_ColorBLACK;
1286 SkScalar surface_scale = 0.f;
1287 SkScalar kconstant = 0.f;
1288 SkScalar shininess = 0.f;
1289 sk_sp<PaintFilter> input;
1291 ReadEnum(&lighting_type);
1292 ReadSimple(&direction);
1294 Read(&surface_scale);
1300 // TODO(crbug/1308932): Remove FromColor and make all SkColor4f.
1301 filter->reset(new LightingDistantPaintFilter(
1302 lighting_type, direction, SkColor4f::FromColor(light_color),
1303 surface_scale, kconstant, shininess, std::move(input),
1304 base::OptionalToPtr(crop_rect)));
1307 void PaintOpReader::ReadLightingPointPaintFilter(
1308 sk_sp<PaintFilter>* filter,
1309 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1310 PaintFilter::LightingType lighting_type;
1311 SkPoint3 location = SkPoint3::Make(0.f, 0.f, 0.f);
1312 SkColor light_color = SK_ColorBLACK;
1313 SkScalar surface_scale = 0.f;
1314 SkScalar kconstant = 0.f;
1315 SkScalar shininess = 0.f;
1316 sk_sp<PaintFilter> input;
1318 ReadEnum(&lighting_type);
1319 ReadSimple(&location);
1321 Read(&surface_scale);
1327 // TODO(crbug/1308932): Remove FromColor and make all SkColor4f.
1328 filter->reset(new LightingPointPaintFilter(
1329 lighting_type, location, SkColor4f::FromColor(light_color), surface_scale,
1330 kconstant, shininess, std::move(input), base::OptionalToPtr(crop_rect)));
1333 void PaintOpReader::ReadLightingSpotPaintFilter(
1334 sk_sp<PaintFilter>* filter,
1335 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1336 PaintFilter::LightingType lighting_type;
1337 SkPoint3 location = SkPoint3::Make(0.f, 0.f, 0.f);
1338 SkPoint3 target = SkPoint3::Make(0.f, 0.f, 0.f);
1339 SkScalar specular_exponent = 0.f;
1340 SkScalar cutoff_angle = 0.f;
1341 SkColor light_color = SK_ColorBLACK;
1342 SkScalar surface_scale = 0.f;
1343 SkScalar kconstant = 0.f;
1344 SkScalar shininess = 0.f;
1345 sk_sp<PaintFilter> input;
1347 ReadEnum(&lighting_type);
1348 ReadSimple(&location);
1349 ReadSimple(&target);
1350 Read(&specular_exponent);
1351 Read(&cutoff_angle);
1353 Read(&surface_scale);
1360 // TODO(crbug/1308932): Remove FromColor and make all SkColor4f.
1361 filter->reset(new LightingSpotPaintFilter(
1362 lighting_type, location, target, specular_exponent, cutoff_angle,
1363 SkColor4f::FromColor(light_color), surface_scale, kconstant, shininess,
1364 std::move(input), base::OptionalToPtr(crop_rect)));
1367 void PaintOpReader::ReadStretchPaintFilter(
1368 sk_sp<PaintFilter>* filter,
1369 const absl::optional<PaintFilter::CropRect>& crop_rect) {
1370 SkScalar stretch_x = 0.f;
1371 SkScalar stretch_y = 0.f;
1372 SkScalar width = 0.f;
1373 SkScalar height = 0.f;
1374 sk_sp<PaintFilter> input;
1384 filter->reset(new StretchPaintFilter(stretch_x, stretch_y, width, height,
1386 base::OptionalToPtr(crop_rect)));
1389 size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) {
1390 size_t size_bytes = 0;
1391 ReadSize(&size_bytes);
1392 AlignMemory(PaintOpBuffer::PaintOpAlign);
1393 if (enable_security_constraints_) {
1394 // Validate that the record was not serialized if security constraints are
1396 if (size_bytes != 0) {
1397 SetInvalid(DeserializationError::kPaintRecordForbidden);
1400 *record = sk_make_sp<PaintOpBuffer>();
1404 if (size_bytes > remaining_bytes_)
1406 DeserializationError::kInsufficientRemainingBytes_Read_PaintRecord);
1410 *record = PaintOpBuffer::MakeFromMemory(memory_, size_bytes, options_);
1412 SetInvalid(DeserializationError::kPaintOpBufferMakeFromMemoryFailure);
1415 DidRead(size_bytes);
1419 void PaintOpReader::Read(SkRegion* region) {
1420 size_t region_bytes = 0;
1421 ReadSize(®ion_bytes);
1422 if (region_bytes == 0)
1423 SetInvalid(DeserializationError::kZeroRegionBytes);
1424 if (region_bytes > remaining_bytes_)
1425 SetInvalid(DeserializationError::kInsufficientRemainingBytes_Read_SkRegion);
1428 std::unique_ptr<char[]> data(new char[region_bytes]);
1429 ReadData(region_bytes, data.get());
1432 size_t result = region->readFromMemory(data.get(), region_bytes);
1434 SetInvalid(DeserializationError::kSkRegionReadFromMemoryFailure);
1437 inline void PaintOpReader::DidRead(size_t bytes_read) {
1438 // All data are aligned with PaintOpWriter::Alignment() at least.
1439 size_t aligned_bytes =
1440 base::bits::AlignUp(bytes_read, PaintOpWriter::Alignment());
1441 memory_ += aligned_bytes;
1442 DCHECK_LE(aligned_bytes, remaining_bytes_);
1443 remaining_bytes_ -= aligned_bytes;