// Copyright (c) 2012 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/ipc/cc_param_traits.h" #include #include #include "base/numerics/safe_conversions.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "base/unguessable_token.h" #include "cc/paint/filter_operations.h" #include "cc/paint/paint_filter.h" #include "cc/paint/paint_op_buffer.h" #include "cc/paint/paint_op_reader.h" #include "cc/paint/paint_op_writer.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/debug_border_draw_quad.h" #include "components/viz/common/quads/draw_quad.h" #include "components/viz/common/quads/largest_draw_quad.h" #include "components/viz/common/quads/render_pass_draw_quad.h" #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/surface_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" #include "components/viz/common/quads/yuv_video_draw_quad.h" #include "components/viz/common/surfaces/surface_id.h" #include "ui/gfx/ipc/geometry/gfx_param_traits.h" #include "ui/gfx/ipc/skia/gfx_skia_param_traits.h" namespace IPC { void ParamTraits::Write(base::Pickle* m, const param_type& p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::FilterOperation::Write"); WriteParam(m, p.type()); switch (p.type()) { case cc::FilterOperation::GRAYSCALE: case cc::FilterOperation::SEPIA: case cc::FilterOperation::SATURATE: case cc::FilterOperation::HUE_ROTATE: case cc::FilterOperation::INVERT: case cc::FilterOperation::BRIGHTNESS: case cc::FilterOperation::SATURATING_BRIGHTNESS: case cc::FilterOperation::CONTRAST: case cc::FilterOperation::OPACITY: WriteParam(m, p.amount()); break; case cc::FilterOperation::BLUR: WriteParam(m, p.amount()); WriteParam(m, p.blur_tile_mode()); break; case cc::FilterOperation::DROP_SHADOW: WriteParam(m, p.drop_shadow_offset()); WriteParam(m, p.amount()); WriteParam(m, p.drop_shadow_color()); break; case cc::FilterOperation::COLOR_MATRIX: for (int i = 0; i < 20; ++i) WriteParam(m, p.matrix()[i]); break; case cc::FilterOperation::ZOOM: WriteParam(m, p.amount()); WriteParam(m, p.zoom_inset()); break; case cc::FilterOperation::REFERENCE: WriteParam(m, p.image_filter()); break; case cc::FilterOperation::ALPHA_THRESHOLD: WriteParam(m, p.amount()); WriteParam(m, p.outer_threshold()); WriteParam(m, p.shape()); break; } } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* r) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::FilterOperation::Read"); cc::FilterOperation::FilterType type; float amount; float outer_threshold; gfx::Point drop_shadow_offset; SkColor drop_shadow_color; SkScalar matrix[20]; cc::FilterOperation::ShapeRects shape; int zoom_inset; SkBlurImageFilter::TileMode tile_mode; if (!ReadParam(m, iter, &type)) return false; r->set_type(type); bool success = false; switch (type) { case cc::FilterOperation::GRAYSCALE: case cc::FilterOperation::SEPIA: case cc::FilterOperation::SATURATE: case cc::FilterOperation::HUE_ROTATE: case cc::FilterOperation::INVERT: case cc::FilterOperation::BRIGHTNESS: case cc::FilterOperation::SATURATING_BRIGHTNESS: case cc::FilterOperation::CONTRAST: case cc::FilterOperation::OPACITY: if (ReadParam(m, iter, &amount)) { r->set_amount(amount); success = true; } break; case cc::FilterOperation::BLUR: if (ReadParam(m, iter, &amount) && ReadParam(m, iter, &tile_mode)) { r->set_amount(amount); r->set_blur_tile_mode(tile_mode); success = true; } break; case cc::FilterOperation::DROP_SHADOW: if (ReadParam(m, iter, &drop_shadow_offset) && ReadParam(m, iter, &amount) && ReadParam(m, iter, &drop_shadow_color)) { r->set_drop_shadow_offset(drop_shadow_offset); r->set_amount(amount); r->set_drop_shadow_color(drop_shadow_color); success = true; } break; case cc::FilterOperation::COLOR_MATRIX: { int i; for (i = 0; i < 20; ++i) { if (!ReadParam(m, iter, &matrix[i])) break; } if (i == 20) { r->set_matrix(matrix); success = true; } break; } case cc::FilterOperation::ZOOM: if (ReadParam(m, iter, &amount) && ReadParam(m, iter, &zoom_inset) && amount >= 0.f && zoom_inset >= 0) { r->set_amount(amount); r->set_zoom_inset(zoom_inset); success = true; } break; case cc::FilterOperation::REFERENCE: { sk_sp filter; if (!ReadParam(m, iter, &filter)) { success = false; break; } r->set_image_filter(std::move(filter)); success = true; break; } case cc::FilterOperation::ALPHA_THRESHOLD: if (ReadParam(m, iter, &amount) && ReadParam(m, iter, &outer_threshold) && ReadParam(m, iter, &shape) && amount >= 0.f && outer_threshold >= 0.f) { r->set_amount(amount); r->set_outer_threshold(amount); r->set_shape(shape); success = true; } break; } return success; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); LogParam(static_cast(p.type()), l); l->append(", "); switch (p.type()) { case cc::FilterOperation::GRAYSCALE: case cc::FilterOperation::SEPIA: case cc::FilterOperation::SATURATE: case cc::FilterOperation::HUE_ROTATE: case cc::FilterOperation::INVERT: case cc::FilterOperation::BRIGHTNESS: case cc::FilterOperation::SATURATING_BRIGHTNESS: case cc::FilterOperation::CONTRAST: case cc::FilterOperation::OPACITY: LogParam(p.amount(), l); break; case cc::FilterOperation::BLUR: LogParam(p.amount(), l); l->append(", "); LogParam(static_cast(p.blur_tile_mode()), l); break; case cc::FilterOperation::DROP_SHADOW: LogParam(p.drop_shadow_offset(), l); l->append(", "); LogParam(p.amount(), l); l->append(", "); LogParam(p.drop_shadow_color(), l); break; case cc::FilterOperation::COLOR_MATRIX: for (int i = 0; i < 20; ++i) { if (i) l->append(", "); LogParam(p.matrix()[i], l); } break; case cc::FilterOperation::ZOOM: LogParam(p.amount(), l); l->append(", "); LogParam(p.zoom_inset(), l); break; case cc::FilterOperation::REFERENCE: LogParam(p.image_filter(), l); break; case cc::FilterOperation::ALPHA_THRESHOLD: LogParam(p.amount(), l); l->append(", "); LogParam(p.outer_threshold(), l); l->append(", "); LogParam(p.shape(), l); break; } l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::FilterOperations::Write"); WriteParam(m, base::checked_cast(p.size())); for (std::size_t i = 0; i < p.size(); ++i) { WriteParam(m, p.at(i)); } } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* r) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::FilterOperations::Read"); uint32_t count; if (!ReadParam(m, iter, &count)) return false; for (std::size_t i = 0; i < count; ++i) { cc::FilterOperation op = cc::FilterOperation::CreateEmptyFilter(); if (!ReadParam(m, iter, &op)) return false; r->Append(op); } return true; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); for (std::size_t i = 0; i < p.size(); ++i) { if (i) l->append(", "); LogParam(p.at(i), l); } l->append(")"); } void ParamTraits>::Write(base::Pickle* m, const param_type& p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::PaintFilter::Write"); std::vector memory; memory.resize(cc::PaintOpWriter::HeaderBytes() + cc::PaintFilter::GetFilterSize(p.get())); cc::PaintOpWriter writer(memory.data(), memory.size(), nullptr, nullptr, true /* enable_security_constraints */); writer.Write(p.get()); if (writer.size() == 0u) m->WriteData(nullptr, 0); else m->WriteData(reinterpret_cast(memory.data()), writer.size()); } bool ParamTraits>::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* r) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::PaintFilter::Read"); const char* data = nullptr; int length = 0; if (!iter->ReadData(&data, &length)) return false; if (length <= 0) { r->reset(); return true; } cc::PaintOpReader reader(data, length, nullptr, true /* enable_security_constraints */); sk_sp filter; reader.Read(&filter); if (!filter) return false; *r = std::move(filter); return true; } void ParamTraits>::Log(const param_type& p, std::string* l) { l->append("("); auto type = p ? p->type() : cc::PaintFilter::Type::kNullFilter; LogParam(cc::PaintFilter::TypeToString(type), l); l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::RenderPass::Write"); WriteParam(m, p.id); WriteParam(m, p.output_rect); WriteParam(m, p.damage_rect); WriteParam(m, p.transform_to_root_target); WriteParam(m, p.filters); WriteParam(m, p.background_filters); WriteParam(m, p.color_space); WriteParam(m, p.has_transparent_background); WriteParam(m, p.cache_render_pass); WriteParam(m, p.has_damage_from_contributing_content); WriteParam(m, p.generate_mipmap); WriteParam(m, base::checked_cast(p.quad_list.size())); auto shared_quad_state_iter = p.shared_quad_state_list.cbegin(); auto last_shared_quad_state_iter = p.shared_quad_state_list.cend(); for (auto* quad : p.quad_list) { DCHECK(quad->rect.Contains(quad->visible_rect)) << quad->material << " rect: " << quad->rect.ToString() << " visible_rect: " << quad->visible_rect.ToString(); switch (quad->material) { case viz::DrawQuad::DEBUG_BORDER: WriteParam(m, *viz::DebugBorderDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::PICTURE_CONTENT: NOTREACHED(); break; case viz::DrawQuad::TEXTURE_CONTENT: WriteParam(m, *viz::TextureDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::RENDER_PASS: WriteParam(m, *viz::RenderPassDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::SOLID_COLOR: WriteParam(m, *viz::SolidColorDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::SURFACE_CONTENT: WriteParam(m, *viz::SurfaceDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::TILED_CONTENT: WriteParam(m, *viz::TileDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::STREAM_VIDEO_CONTENT: WriteParam(m, *viz::StreamVideoDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::YUV_VIDEO_CONTENT: WriteParam(m, *viz::YUVVideoDrawQuad::MaterialCast(quad)); break; case viz::DrawQuad::INVALID: break; } // Null shared quad states should not occur. DCHECK(quad->shared_quad_state); // SharedQuadStates should appear in the order they are used by DrawQuads. // Find the SharedQuadState for this DrawQuad. while (shared_quad_state_iter != p.shared_quad_state_list.end() && quad->shared_quad_state != *shared_quad_state_iter) { ++shared_quad_state_iter; } DCHECK(shared_quad_state_iter != p.shared_quad_state_list.end()); if (shared_quad_state_iter != last_shared_quad_state_iter) { WriteParam(m, true); WriteParam(m, **shared_quad_state_iter); last_shared_quad_state_iter = shared_quad_state_iter; } else { WriteParam(m, false); } } } static size_t ReserveSizeForRenderPassWrite(const viz::RenderPass& p) { size_t to_reserve = sizeof(viz::RenderPass); // Whether the quad points to a new shared quad state for each quad. to_reserve += p.quad_list.size() * sizeof(bool); // Shared quad state is only written when a quad contains a shared quad state // that has not been written. to_reserve += p.shared_quad_state_list.size() * sizeof(viz::SharedQuadState); // The largest quad type, verified by a unit test. to_reserve += p.quad_list.size() * viz::LargestDrawQuadSize(); to_reserve += sizeof(uint32_t) + p.filters.size() * sizeof(cc::FilterOperation); to_reserve += sizeof(uint32_t) + p.background_filters.size() * sizeof(cc::FilterOperation); return to_reserve; } template static viz::DrawQuad* ReadDrawQuad(const base::Pickle* m, base::PickleIterator* iter, viz::RenderPass* render_pass) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::ReadDrawQuad"); QuadType* quad = render_pass->CreateAndAppendDrawQuad(); if (!ReadParam(m, iter, quad)) return nullptr; return quad; } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::RenderPass::Read"); uint64_t id; gfx::Rect output_rect; gfx::Rect damage_rect; gfx::Transform transform_to_root_target; cc::FilterOperations filters; cc::FilterOperations background_filters; gfx::ColorSpace color_space; bool has_transparent_background; bool cache_render_pass; bool has_damage_from_contributing_content; bool generate_mipmap; uint32_t quad_list_size; if (!ReadParam(m, iter, &id) || !ReadParam(m, iter, &output_rect) || !ReadParam(m, iter, &damage_rect) || !ReadParam(m, iter, &transform_to_root_target) || !ReadParam(m, iter, &filters) || !ReadParam(m, iter, &background_filters) || !ReadParam(m, iter, &color_space) || !ReadParam(m, iter, &has_transparent_background) || !ReadParam(m, iter, &cache_render_pass) || !ReadParam(m, iter, &has_damage_from_contributing_content) || !ReadParam(m, iter, &generate_mipmap) || !ReadParam(m, iter, &quad_list_size)) return false; p->SetAll(id, output_rect, damage_rect, transform_to_root_target, filters, background_filters, color_space, has_transparent_background, cache_render_pass, has_damage_from_contributing_content, generate_mipmap); for (uint32_t i = 0; i < quad_list_size; ++i) { viz::DrawQuad::Material material; base::PickleIterator temp_iter = *iter; if (!ReadParam(m, &temp_iter, &material)) return false; viz::DrawQuad* draw_quad = nullptr; switch (material) { case viz::DrawQuad::DEBUG_BORDER: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::PICTURE_CONTENT: NOTREACHED(); return false; case viz::DrawQuad::SURFACE_CONTENT: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::TEXTURE_CONTENT: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::RENDER_PASS: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::SOLID_COLOR: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::TILED_CONTENT: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::STREAM_VIDEO_CONTENT: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::YUV_VIDEO_CONTENT: draw_quad = ReadDrawQuad(m, iter, p); break; case viz::DrawQuad::INVALID: break; } if (!draw_quad) return false; if (!draw_quad->rect.Contains(draw_quad->visible_rect)) { LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material << " rect: " << draw_quad->rect.ToString() << " visible_rect: " << draw_quad->visible_rect.ToString(); return false; } bool has_new_shared_quad_state; if (!ReadParam(m, iter, &has_new_shared_quad_state)) return false; // If the quad has a new shared quad state, read it in. if (has_new_shared_quad_state) { viz::SharedQuadState* state = p->CreateAndAppendSharedQuadState(); if (!ReadParam(m, iter, state)) return false; } draw_quad->shared_quad_state = p->shared_quad_state_list.back(); } return true; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("RenderPass(("); LogParam(p.id, l); l->append("), "); LogParam(p.output_rect, l); l->append(", "); LogParam(p.damage_rect, l); l->append(", "); LogParam(p.transform_to_root_target, l); l->append(", "); LogParam(p.filters, l); l->append(", "); LogParam(p.background_filters, l); l->append(", "); LogParam(p.color_space, l); l->append(", "); LogParam(p.has_transparent_background, l); l->append(", "); LogParam(p.cache_render_pass, l); l->append(", "); LogParam(p.has_damage_from_contributing_content, l); l->append(", "); l->append("["); for (auto* shared_quad_state : p.shared_quad_state_list) { if (shared_quad_state != p.shared_quad_state_list.front()) l->append(", "); LogParam(*shared_quad_state, l); } l->append("], ["); for (auto* quad : p.quad_list) { if (quad != p.quad_list.front()) l->append(", "); switch (quad->material) { case viz::DrawQuad::DEBUG_BORDER: LogParam(*viz::DebugBorderDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::PICTURE_CONTENT: NOTREACHED(); break; case viz::DrawQuad::TEXTURE_CONTENT: LogParam(*viz::TextureDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::RENDER_PASS: LogParam(*viz::RenderPassDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::SOLID_COLOR: LogParam(*viz::SolidColorDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::SURFACE_CONTENT: LogParam(*viz::SurfaceDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::TILED_CONTENT: LogParam(*viz::TileDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::STREAM_VIDEO_CONTENT: LogParam(*viz::StreamVideoDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::YUV_VIDEO_CONTENT: LogParam(*viz::YUVVideoDrawQuad::MaterialCast(quad), l); break; case viz::DrawQuad::INVALID: break; } } l->append("])"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.frame_start_time()); WriteParam(m, p.deadline_in_frames()); WriteParam(m, p.frame_interval()); WriteParam(m, p.use_default_lower_bound_deadline()); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { base::TimeTicks frame_start_time; if (!ReadParam(m, iter, &frame_start_time)) return false; uint32_t deadline_in_frames; if (!ReadParam(m, iter, &deadline_in_frames)) return false; base::TimeDelta frame_interval; if (!ReadParam(m, iter, &frame_interval)) return false; bool use_default_lower_bound_deadline; if (!ReadParam(m, iter, &use_default_lower_bound_deadline)) return false; *p = viz::FrameDeadline(frame_start_time, deadline_in_frames, frame_interval, use_default_lower_bound_deadline); return true; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("viz::FrameDeadline("); LogParam(p.frame_start_time(), l); l->append(", "); LogParam(p.deadline_in_frames(), l); l->append(", "); LogParam(p.frame_interval(), l); l->append(", "); LogParam(p.use_default_lower_bound_deadline(), l); l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { DCHECK(p.is_valid()); WriteParam(m, p.client_id()); WriteParam(m, p.sink_id()); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { uint32_t client_id; if (!ReadParam(m, iter, &client_id)) return false; uint32_t sink_id; if (!ReadParam(m, iter, &sink_id)) return false; *p = viz::FrameSinkId(client_id, sink_id); return p->is_valid(); } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("viz::FrameSinkId("); LogParam(p.client_id(), l); l->append(", "); LogParam(p.sink_id(), l); l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { DCHECK(p.is_valid()); WriteParam(m, p.parent_sequence_number()); WriteParam(m, p.child_sequence_number()); WriteParam(m, p.embed_token()); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { uint32_t parent_sequence_number; if (!ReadParam(m, iter, &parent_sequence_number)) return false; uint32_t child_sequence_number; if (!ReadParam(m, iter, &child_sequence_number)) return false; base::UnguessableToken embed_token; if (!ReadParam(m, iter, &embed_token)) return false; *p = viz::LocalSurfaceId(parent_sequence_number, child_sequence_number, embed_token); return p->is_valid(); } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("viz::LocalSurfaceId("); LogParam(p.parent_sequence_number(), l); l->append(", "); LogParam(p.child_sequence_number(), l); l->append(", "); LogParam(p.embed_token(), l); l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.frame_sink_id()); WriteParam(m, p.local_surface_id()); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { viz::FrameSinkId frame_sink_id; if (!ReadParam(m, iter, &frame_sink_id)) return false; viz::LocalSurfaceId local_surface_id; if (!ReadParam(m, iter, &local_surface_id)) return false; *p = viz::SurfaceId(frame_sink_id, local_surface_id); return true; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("viz::SurfaceId("); LogParam(p.frame_sink_id(), l); l->append(", "); LogParam(p.local_surface_id(), l); l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.id()); WriteParam(m, p.device_scale_factor()); WriteParam(m, p.size_in_pixels()); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { viz::SurfaceId surface_id; if (!ReadParam(m, iter, &surface_id)) return false; float device_scale_factor; if (!ReadParam(m, iter, &device_scale_factor)) return false; gfx::Size size_in_pixels; if (!ReadParam(m, iter, &size_in_pixels)) return false; *p = viz::SurfaceInfo(surface_id, device_scale_factor, size_in_pixels); return p->is_valid(); } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("viz::SurfaceInfo("); LogParam(p.id(), l); l->append(", "); LogParam(p.device_scale_factor(), l); l->append(", "); LogParam(p.size_in_pixels(), l); l->append(")"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::CompositorFrame::Write"); WriteParam(m, p.metadata); size_t to_reserve = 0u; to_reserve += p.resource_list.size() * sizeof(viz::TransferableResource); for (const auto& pass : p.render_pass_list) { to_reserve += sizeof(size_t) * 2; to_reserve += ReserveSizeForRenderPassWrite(*pass); } m->Reserve(to_reserve); WriteParam(m, p.resource_list); WriteParam(m, base::checked_cast(p.render_pass_list.size())); for (const auto& pass : p.render_pass_list) { WriteParam(m, base::checked_cast(pass->quad_list.size())); WriteParam( m, base::checked_cast(pass->shared_quad_state_list.size())); WriteParam(m, *pass); } } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::CompositorFrame::Read"); if (!ReadParam(m, iter, &p->metadata)) return false; const size_t kMaxRenderPasses = 10000; const size_t kMaxSharedQuadStateListSize = 100000; const size_t kMaxQuadListSize = 1000000; std::set pass_id_set; uint32_t num_render_passes; if (!ReadParam(m, iter, &p->resource_list) || !ReadParam(m, iter, &num_render_passes) || num_render_passes == 0 || num_render_passes > kMaxRenderPasses) return false; for (uint32_t i = 0; i < num_render_passes; ++i) { uint32_t quad_list_size; uint32_t shared_quad_state_list_size; if (!ReadParam(m, iter, &quad_list_size) || !ReadParam(m, iter, &shared_quad_state_list_size) || quad_list_size > kMaxQuadListSize || shared_quad_state_list_size > kMaxSharedQuadStateListSize) return false; std::unique_ptr render_pass = viz::RenderPass::Create( static_cast(shared_quad_state_list_size), static_cast(quad_list_size)); if (!ReadParam(m, iter, render_pass.get())) return false; // Validate that each viz::RenderPassDrawQuad points at a valid RenderPass // earlier in the frame. for (const auto* quad : render_pass->quad_list) { if (quad->material != viz::DrawQuad::RENDER_PASS) continue; const viz::RenderPassDrawQuad* rpdq = viz::RenderPassDrawQuad::MaterialCast(quad); if (!pass_id_set.count(rpdq->render_pass_id)) return false; } pass_id_set.insert(render_pass->id); p->render_pass_list.push_back(std::move(render_pass)); } if (p->render_pass_list.back()->output_rect.size().IsEmpty()) return false; return true; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("CompositorFrame("); LogParam(p.metadata, l); l->append(", "); LogParam(p.resource_list, l); l->append(", ["); for (size_t i = 0; i < p.render_pass_list.size(); ++i) { if (i) l->append(", "); LogParam(*p.render_pass_list[i], l); } l->append("])"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::DrawQuad::Resources::Write"); DCHECK_LE(p.count, viz::DrawQuad::Resources::kMaxResourceIdCount); WriteParam(m, p.count); for (size_t i = 0; i < p.count; ++i) WriteParam(m, p.ids[i]); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), "ParamTraits::DrawQuad::Resources::Read"); if (!ReadParam(m, iter, &p->count)) return false; if (p->count > viz::DrawQuad::Resources::kMaxResourceIdCount) return false; for (size_t i = 0; i < p->count; ++i) { if (!ReadParam(m, iter, &p->ids[i])) return false; } return true; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("DrawQuad::Resources("); LogParam(p.count, l); l->append(", ["); if (p.count > viz::DrawQuad::Resources::kMaxResourceIdCount) { l->append("])"); return; } for (size_t i = 0; i < p.count; ++i) { LogParam(p.ids[i], l); if (i < (p.count - 1)) l->append(", "); } l->append("])"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { ParamTraits::Write(m, p); WriteParam(m, p.ya_tex_coord_rect); WriteParam(m, p.uv_tex_coord_rect); WriteParam(m, p.ya_tex_size); WriteParam(m, p.uv_tex_size); WriteParam(m, p.video_color_space); WriteParam(m, p.resource_offset); WriteParam(m, p.resource_multiplier); WriteParam(m, p.bits_per_channel); } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { return ParamTraits::Read(m, iter, p) && ReadParam(m, iter, &p->ya_tex_coord_rect) && ReadParam(m, iter, &p->uv_tex_coord_rect) && ReadParam(m, iter, &p->ya_tex_size) && ReadParam(m, iter, &p->uv_tex_size) && ReadParam(m, iter, &p->video_color_space) && ReadParam(m, iter, &p->resource_offset) && ReadParam(m, iter, &p->resource_multiplier) && ReadParam(m, iter, &p->bits_per_channel) && p->bits_per_channel >= viz::YUVVideoDrawQuad::kMinBitsPerChannel && p->bits_per_channel <= viz::YUVVideoDrawQuad::kMaxBitsPerChannel; } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); ParamTraits::Log(p, l); l->append(", "); LogParam(p.ya_tex_coord_rect, l); l->append(", "); LogParam(p.uv_tex_coord_rect, l); l->append(", "); LogParam(p.ya_tex_size, l); l->append(", "); LogParam(p.uv_tex_size, l); l->append(", "); LogParam(p.video_color_space, l); l->append(", "); LogParam(p.resource_offset, l); l->append(", "); LogParam(p.resource_multiplier, l); l->append(", "); LogParam(p.bits_per_channel, l); l->append("])"); } void ParamTraits::Write(base::Pickle* m, const param_type& p) { m->WriteUInt64(p.sequence_number); m->WriteUInt64(p.source_id); // |has_damage| is implicit through IPC message name, so not transmitted. } bool ParamTraits::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { return iter->ReadUInt64(&p->sequence_number) && p->sequence_number >= viz::BeginFrameArgs::kStartingFrameNumber && iter->ReadUInt64(&p->source_id); } void ParamTraits::Log(const param_type& p, std::string* l) { l->append("("); LogParam(p.sequence_number, l); l->append(", "); LogParam(p.source_id, l); l->append(")"); } } // namespace IPC // Generate param traits write methods. #include "ipc/param_traits_write_macros.h" namespace IPC { #undef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ #include "cc/ipc/cc_param_traits_macros.h" } // namespace IPC // Generate param traits read methods. #include "ipc/param_traits_read_macros.h" namespace IPC { #undef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ #include "cc/ipc/cc_param_traits_macros.h" } // namespace IPC // Generate param traits log methods. #include "ipc/param_traits_log_macros.h" namespace IPC { #undef CC_IPC_CC_PARAM_TRAITS_MACROS_H_ #include "cc/ipc/cc_param_traits_macros.h" } // namespace IPC