1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/cc_messages.h"
7 #include "base/command_line.h"
8 #include "cc/output/compositor_frame.h"
9 #include "cc/output/filter_operations.h"
10 #include "content/public/common/common_param_traits.h"
11 #include "content/public/common/content_switches.h"
12 #include "third_party/skia/include/core/SkData.h"
13 #include "third_party/skia/include/core/SkFlattenableSerialization.h"
14 #include "ui/gfx/transform.h"
18 void ParamTraits<cc::FilterOperation>::Write(
19 Message* m, const param_type& p) {
20 WriteParam(m, p.type());
22 case cc::FilterOperation::GRAYSCALE:
23 case cc::FilterOperation::SEPIA:
24 case cc::FilterOperation::SATURATE:
25 case cc::FilterOperation::HUE_ROTATE:
26 case cc::FilterOperation::INVERT:
27 case cc::FilterOperation::BRIGHTNESS:
28 case cc::FilterOperation::SATURATING_BRIGHTNESS:
29 case cc::FilterOperation::CONTRAST:
30 case cc::FilterOperation::OPACITY:
31 case cc::FilterOperation::BLUR:
32 WriteParam(m, p.amount());
34 case cc::FilterOperation::DROP_SHADOW:
35 WriteParam(m, p.drop_shadow_offset());
36 WriteParam(m, p.amount());
37 WriteParam(m, p.drop_shadow_color());
39 case cc::FilterOperation::COLOR_MATRIX:
40 for (int i = 0; i < 20; ++i)
41 WriteParam(m, p.matrix()[i]);
43 case cc::FilterOperation::ZOOM:
44 WriteParam(m, p.amount());
45 WriteParam(m, p.zoom_inset());
47 case cc::FilterOperation::REFERENCE:
48 WriteParam(m, p.image_filter());
53 bool ParamTraits<cc::FilterOperation>::Read(
54 const Message* m, PickleIterator* iter, param_type* r) {
55 cc::FilterOperation::FilterType type;
57 gfx::Point drop_shadow_offset;
58 SkColor drop_shadow_color;
62 if (!ReadParam(m, iter, &type))
68 case cc::FilterOperation::GRAYSCALE:
69 case cc::FilterOperation::SEPIA:
70 case cc::FilterOperation::SATURATE:
71 case cc::FilterOperation::HUE_ROTATE:
72 case cc::FilterOperation::INVERT:
73 case cc::FilterOperation::BRIGHTNESS:
74 case cc::FilterOperation::SATURATING_BRIGHTNESS:
75 case cc::FilterOperation::CONTRAST:
76 case cc::FilterOperation::OPACITY:
77 case cc::FilterOperation::BLUR:
78 if (ReadParam(m, iter, &amount)) {
79 r->set_amount(amount);
83 case cc::FilterOperation::DROP_SHADOW:
84 if (ReadParam(m, iter, &drop_shadow_offset) &&
85 ReadParam(m, iter, &amount) &&
86 ReadParam(m, iter, &drop_shadow_color)) {
87 r->set_drop_shadow_offset(drop_shadow_offset);
88 r->set_amount(amount);
89 r->set_drop_shadow_color(drop_shadow_color);
93 case cc::FilterOperation::COLOR_MATRIX: {
95 for (i = 0; i < 20; ++i) {
96 if (!ReadParam(m, iter, &matrix[i]))
100 r->set_matrix(matrix);
105 case cc::FilterOperation::ZOOM:
106 if (ReadParam(m, iter, &amount) &&
107 ReadParam(m, iter, &zoom_inset) &&
110 r->set_amount(amount);
111 r->set_zoom_inset(zoom_inset);
115 case cc::FilterOperation::REFERENCE: {
116 skia::RefPtr<SkImageFilter> filter;
117 if (!ReadParam(m, iter, &filter)) {
121 r->set_image_filter(filter);
129 void ParamTraits<cc::FilterOperation>::Log(
130 const param_type& p, std::string* l) {
132 LogParam(static_cast<unsigned>(p.type()), l);
136 case cc::FilterOperation::GRAYSCALE:
137 case cc::FilterOperation::SEPIA:
138 case cc::FilterOperation::SATURATE:
139 case cc::FilterOperation::HUE_ROTATE:
140 case cc::FilterOperation::INVERT:
141 case cc::FilterOperation::BRIGHTNESS:
142 case cc::FilterOperation::SATURATING_BRIGHTNESS:
143 case cc::FilterOperation::CONTRAST:
144 case cc::FilterOperation::OPACITY:
145 case cc::FilterOperation::BLUR:
146 LogParam(p.amount(), l);
148 case cc::FilterOperation::DROP_SHADOW:
149 LogParam(p.drop_shadow_offset(), l);
151 LogParam(p.amount(), l);
153 LogParam(p.drop_shadow_color(), l);
155 case cc::FilterOperation::COLOR_MATRIX:
156 for (int i = 0; i < 20; ++i) {
159 LogParam(p.matrix()[i], l);
162 case cc::FilterOperation::ZOOM:
163 LogParam(p.amount(), l);
165 LogParam(p.zoom_inset(), l);
167 case cc::FilterOperation::REFERENCE:
168 LogParam(p.image_filter(), l);
174 void ParamTraits<cc::FilterOperations>::Write(
175 Message* m, const param_type& p) {
176 WriteParam(m, p.size());
177 for (std::size_t i = 0; i < p.size(); ++i) {
178 WriteParam(m, p.at(i));
182 bool ParamTraits<cc::FilterOperations>::Read(
183 const Message* m, PickleIterator* iter, param_type* r) {
185 if (!ReadParam(m, iter, &count))
188 for (std::size_t i = 0; i < count; ++i) {
189 cc::FilterOperation op = cc::FilterOperation::CreateEmptyFilter();
190 if (!ReadParam(m, iter, &op))
197 void ParamTraits<cc::FilterOperations>::Log(
198 const param_type& p, std::string* l) {
200 for (std::size_t i = 0; i < p.size(); ++i) {
203 LogParam(p.at(i), l);
208 void ParamTraits<skia::RefPtr<SkImageFilter> >::Write(
209 Message* m, const param_type& p) {
210 SkImageFilter* filter = p.get();
211 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
212 if (filter && command_line.HasSwitch(switches::kAllowFiltersOverIPC)) {
213 skia::RefPtr<SkData> data = skia::AdoptRef(SkSerializeFlattenable(filter));
214 m->WriteData(static_cast<const char*>(data->data()), data->size());
220 bool ParamTraits<skia::RefPtr<SkImageFilter> >::Read(
221 const Message* m, PickleIterator* iter, param_type* r) {
222 const char* data = 0;
224 if (!m->ReadData(iter, &data, &length))
226 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
227 if ((length > 0) && command_line.HasSwitch(switches::kAllowFiltersOverIPC)) {
228 SkFlattenable* flattenable = SkDeserializeFlattenable(data, length);
229 *r = skia::AdoptRef(static_cast<SkImageFilter*>(flattenable));
236 void ParamTraits<skia::RefPtr<SkImageFilter> >::Log(
237 const param_type& p, std::string* l) {
239 LogParam(p.get() ? p->countInputs() : 0, l);
243 void ParamTraits<gfx::Transform>::Write(
244 Message* m, const param_type& p) {
245 #ifdef SK_MSCALAR_IS_FLOAT
246 float column_major_data[16];
247 p.matrix().asColMajorf(column_major_data);
249 double column_major_data[16];
250 p.matrix().asColMajord(column_major_data);
252 m->WriteBytes(&column_major_data, sizeof(SkMScalar) * 16);
255 bool ParamTraits<gfx::Transform>::Read(
256 const Message* m, PickleIterator* iter, param_type* r) {
257 const char* column_major_data;
258 if (!m->ReadBytes(iter, &column_major_data, sizeof(SkMScalar) * 16))
260 r->matrix().setColMajor(
261 reinterpret_cast<const SkMScalar*>(column_major_data));
265 void ParamTraits<gfx::Transform>::Log(
266 const param_type& p, std::string* l) {
267 #ifdef SK_MSCALAR_IS_FLOAT
268 float row_major_data[16];
269 p.matrix().asRowMajorf(row_major_data);
271 double row_major_data[16];
272 p.matrix().asRowMajord(row_major_data);
275 for (int i = 0; i < 16; ++i) {
278 LogParam(row_major_data[i], l);
283 void ParamTraits<cc::RenderPass>::Write(
284 Message* m, const param_type& p) {
286 WriteParam(m, p.output_rect);
287 WriteParam(m, p.damage_rect);
288 WriteParam(m, p.transform_to_root_target);
289 WriteParam(m, p.has_transparent_background);
290 WriteParam(m, p.shared_quad_state_list.size());
291 WriteParam(m, p.quad_list.size());
293 for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i)
294 WriteParam(m, *p.shared_quad_state_list[i]);
296 size_t shared_quad_state_index = 0;
297 for (size_t i = 0; i < p.quad_list.size(); ++i) {
298 const cc::DrawQuad* quad = p.quad_list[i];
299 DCHECK(quad->rect.Contains(quad->visible_rect))
300 << quad->material << " rect: " << quad->rect.ToString()
301 << " visible_rect: " << quad->visible_rect.ToString();
302 DCHECK(quad->opaque_rect.IsEmpty() ||
303 quad->rect.Contains(quad->opaque_rect))
304 << quad->material << " rect: " << quad->rect.ToString()
305 << " opaque_rect: " << quad->opaque_rect.ToString();
307 switch (quad->material) {
308 case cc::DrawQuad::CHECKERBOARD:
309 WriteParam(m, *cc::CheckerboardDrawQuad::MaterialCast(quad));
311 case cc::DrawQuad::DEBUG_BORDER:
312 WriteParam(m, *cc::DebugBorderDrawQuad::MaterialCast(quad));
314 case cc::DrawQuad::IO_SURFACE_CONTENT:
315 WriteParam(m, *cc::IOSurfaceDrawQuad::MaterialCast(quad));
317 case cc::DrawQuad::PICTURE_CONTENT:
320 case cc::DrawQuad::TEXTURE_CONTENT:
321 WriteParam(m, *cc::TextureDrawQuad::MaterialCast(quad));
323 case cc::DrawQuad::RENDER_PASS:
324 WriteParam(m, *cc::RenderPassDrawQuad::MaterialCast(quad));
326 case cc::DrawQuad::SOLID_COLOR:
327 WriteParam(m, *cc::SolidColorDrawQuad::MaterialCast(quad));
329 case cc::DrawQuad::TILED_CONTENT:
330 WriteParam(m, *cc::TileDrawQuad::MaterialCast(quad));
332 case cc::DrawQuad::STREAM_VIDEO_CONTENT:
333 WriteParam(m, *cc::StreamVideoDrawQuad::MaterialCast(quad));
335 case cc::DrawQuad::YUV_VIDEO_CONTENT:
336 WriteParam(m, *cc::YUVVideoDrawQuad::MaterialCast(quad));
338 case cc::DrawQuad::INVALID:
342 const cc::ScopedPtrVector<cc::SharedQuadState>& sqs_list =
343 p.shared_quad_state_list;
345 // This is an invalid index.
346 size_t bad_index = sqs_list.size();
348 // Null shared quad states should not occur.
349 DCHECK(quad->shared_quad_state);
350 if (!quad->shared_quad_state) {
351 WriteParam(m, bad_index);
355 // SharedQuadStates should appear in the order they are used by DrawQuads.
356 // Find the SharedQuadState for this DrawQuad.
357 while (shared_quad_state_index < sqs_list.size() &&
358 quad->shared_quad_state != sqs_list[shared_quad_state_index])
359 ++shared_quad_state_index;
361 DCHECK_LT(shared_quad_state_index, sqs_list.size());
362 if (shared_quad_state_index >= sqs_list.size()) {
363 WriteParam(m, bad_index);
367 DCHECK_LT(shared_quad_state_index, p.shared_quad_state_list.size());
368 WriteParam(m, shared_quad_state_index);
372 static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
373 size_t to_reserve = sizeof(cc::RenderPass);
375 to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
377 // The shared_quad_state_index for each quad.
378 to_reserve += p.quad_list.size() * sizeof(size_t);
380 // The largest quad type, verified by a unit test.
381 to_reserve += p.quad_list.size() * sizeof(cc::RenderPassDrawQuad);
385 template<typename QuadType>
386 static scoped_ptr<cc::DrawQuad> ReadDrawQuad(const Message* m,
387 PickleIterator* iter) {
388 scoped_ptr<QuadType> quad = QuadType::Create();
389 if (!ReadParam(m, iter, quad.get()))
390 return scoped_ptr<QuadType>().template PassAs<cc::DrawQuad>();
391 return quad.template PassAs<cc::DrawQuad>();
394 bool ParamTraits<cc::RenderPass>::Read(
395 const Message* m, PickleIterator* iter, param_type* p) {
396 cc::RenderPass::Id id(-1, -1);
397 gfx::Rect output_rect;
398 gfx::RectF damage_rect;
399 gfx::Transform transform_to_root_target;
400 bool has_transparent_background;
401 size_t shared_quad_state_list_size;
402 size_t quad_list_size;
404 if (!ReadParam(m, iter, &id) ||
405 !ReadParam(m, iter, &output_rect) ||
406 !ReadParam(m, iter, &damage_rect) ||
407 !ReadParam(m, iter, &transform_to_root_target) ||
408 !ReadParam(m, iter, &has_transparent_background) ||
409 !ReadParam(m, iter, &shared_quad_state_list_size) ||
410 !ReadParam(m, iter, &quad_list_size))
416 transform_to_root_target,
417 has_transparent_background);
419 for (size_t i = 0; i < shared_quad_state_list_size; ++i) {
420 scoped_ptr<cc::SharedQuadState> state(cc::SharedQuadState::Create());
421 if (!ReadParam(m, iter, state.get()))
423 p->shared_quad_state_list.push_back(state.Pass());
426 size_t last_shared_quad_state_index = 0;
427 for (size_t i = 0; i < quad_list_size; ++i) {
428 cc::DrawQuad::Material material;
429 PickleIterator temp_iter = *iter;
430 if (!ReadParam(m, &temp_iter, &material))
433 scoped_ptr<cc::DrawQuad> draw_quad;
435 case cc::DrawQuad::CHECKERBOARD:
436 draw_quad = ReadDrawQuad<cc::CheckerboardDrawQuad>(m, iter);
438 case cc::DrawQuad::DEBUG_BORDER:
439 draw_quad = ReadDrawQuad<cc::DebugBorderDrawQuad>(m, iter);
441 case cc::DrawQuad::IO_SURFACE_CONTENT:
442 draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter);
444 case cc::DrawQuad::PICTURE_CONTENT:
447 case cc::DrawQuad::TEXTURE_CONTENT:
448 draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter);
450 case cc::DrawQuad::RENDER_PASS:
451 draw_quad = ReadDrawQuad<cc::RenderPassDrawQuad>(m, iter);
453 case cc::DrawQuad::SOLID_COLOR:
454 draw_quad = ReadDrawQuad<cc::SolidColorDrawQuad>(m, iter);
456 case cc::DrawQuad::TILED_CONTENT:
457 draw_quad = ReadDrawQuad<cc::TileDrawQuad>(m, iter);
459 case cc::DrawQuad::STREAM_VIDEO_CONTENT:
460 draw_quad = ReadDrawQuad<cc::StreamVideoDrawQuad>(m, iter);
462 case cc::DrawQuad::YUV_VIDEO_CONTENT:
463 draw_quad = ReadDrawQuad<cc::YUVVideoDrawQuad>(m, iter);
465 case cc::DrawQuad::INVALID:
470 if (!draw_quad->rect.Contains(draw_quad->visible_rect)) {
471 LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material
472 << " rect: " << draw_quad->rect.ToString()
473 << " visible_rect: " << draw_quad->visible_rect.ToString();
476 if (!draw_quad->opaque_rect.IsEmpty() &&
477 !draw_quad->rect.Contains(draw_quad->opaque_rect)) {
478 LOG(ERROR) << "Quad with invalid opaque rect " << draw_quad->material
479 << " rect: " << draw_quad->rect.ToString()
480 << " opaque_rect: " << draw_quad->opaque_rect.ToString();
484 size_t shared_quad_state_index;
485 if (!ReadParam(m, iter, &shared_quad_state_index) ||
486 shared_quad_state_index >= p->shared_quad_state_list.size())
488 // SharedQuadState indexes should be in ascending order.
489 if (shared_quad_state_index < last_shared_quad_state_index)
491 last_shared_quad_state_index = shared_quad_state_index;
493 draw_quad->shared_quad_state =
494 p->shared_quad_state_list[shared_quad_state_index];
496 p->quad_list.push_back(draw_quad.Pass());
502 void ParamTraits<cc::RenderPass>::Log(
503 const param_type& p, std::string* l) {
504 l->append("RenderPass((");
507 LogParam(p.output_rect, l);
509 LogParam(p.damage_rect, l);
511 LogParam(p.transform_to_root_target, l);
513 LogParam(p.has_transparent_background, l);
517 for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i) {
520 LogParam(*p.shared_quad_state_list[i], l);
523 for (size_t i = 0; i < p.quad_list.size(); ++i) {
526 const cc::DrawQuad* quad = p.quad_list[i];
527 switch (quad->material) {
528 case cc::DrawQuad::CHECKERBOARD:
529 LogParam(*cc::CheckerboardDrawQuad::MaterialCast(quad), l);
531 case cc::DrawQuad::DEBUG_BORDER:
532 LogParam(*cc::DebugBorderDrawQuad::MaterialCast(quad), l);
534 case cc::DrawQuad::IO_SURFACE_CONTENT:
535 LogParam(*cc::IOSurfaceDrawQuad::MaterialCast(quad), l);
537 case cc::DrawQuad::PICTURE_CONTENT:
540 case cc::DrawQuad::TEXTURE_CONTENT:
541 LogParam(*cc::TextureDrawQuad::MaterialCast(quad), l);
543 case cc::DrawQuad::RENDER_PASS:
544 LogParam(*cc::RenderPassDrawQuad::MaterialCast(quad), l);
546 case cc::DrawQuad::SOLID_COLOR:
547 LogParam(*cc::SolidColorDrawQuad::MaterialCast(quad), l);
549 case cc::DrawQuad::TILED_CONTENT:
550 LogParam(*cc::TileDrawQuad::MaterialCast(quad), l);
552 case cc::DrawQuad::STREAM_VIDEO_CONTENT:
553 LogParam(*cc::StreamVideoDrawQuad::MaterialCast(quad), l);
555 case cc::DrawQuad::YUV_VIDEO_CONTENT:
556 LogParam(*cc::YUVVideoDrawQuad::MaterialCast(quad), l);
558 case cc::DrawQuad::INVALID:
566 enum CompositorFrameType {
574 void ParamTraits<cc::CompositorFrame>::Write(Message* m,
575 const param_type& p) {
576 WriteParam(m, p.metadata);
577 if (p.delegated_frame_data) {
578 DCHECK(!p.gl_frame_data);
579 DCHECK(!p.software_frame_data);
580 WriteParam(m, static_cast<int>(DELEGATED_FRAME));
581 WriteParam(m, *p.delegated_frame_data);
582 } else if (p.gl_frame_data) {
583 DCHECK(!p.software_frame_data);
584 WriteParam(m, static_cast<int>(GL_FRAME));
585 WriteParam(m, *p.gl_frame_data);
586 } else if (p.software_frame_data) {
587 WriteParam(m, static_cast<int>(SOFTWARE_FRAME));
588 WriteParam(m, *p.software_frame_data);
590 WriteParam(m, static_cast<int>(NO_FRAME));
594 bool ParamTraits<cc::CompositorFrame>::Read(const Message* m,
595 PickleIterator* iter,
597 if (!ReadParam(m, iter, &p->metadata))
600 int compositor_frame_type;
601 if (!ReadParam(m, iter, &compositor_frame_type))
604 switch (compositor_frame_type) {
605 case DELEGATED_FRAME:
606 p->delegated_frame_data.reset(new cc::DelegatedFrameData());
607 if (!ReadParam(m, iter, p->delegated_frame_data.get()))
611 p->gl_frame_data.reset(new cc::GLFrameData());
612 if (!ReadParam(m, iter, p->gl_frame_data.get()))
616 p->software_frame_data.reset(new cc::SoftwareFrameData());
617 if (!ReadParam(m, iter, p->software_frame_data.get()))
628 void ParamTraits<cc::CompositorFrame>::Log(const param_type& p,
630 l->append("CompositorFrame(");
631 LogParam(p.metadata, l);
633 if (p.delegated_frame_data)
634 LogParam(*p.delegated_frame_data, l);
635 else if (p.gl_frame_data)
636 LogParam(*p.gl_frame_data, l);
637 else if (p.software_frame_data)
638 LogParam(*p.software_frame_data, l);
642 void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
643 const param_type& p) {
644 WriteParam(m, p.resources);
645 WriteParam(m, p.last_software_frame_id);
646 if (p.gl_frame_data) {
647 WriteParam(m, static_cast<int>(GL_FRAME));
648 WriteParam(m, *p.gl_frame_data);
650 WriteParam(m, static_cast<int>(NO_FRAME));
654 bool ParamTraits<cc::CompositorFrameAck>::Read(const Message* m,
655 PickleIterator* iter,
657 if (!ReadParam(m, iter, &p->resources))
660 if (!ReadParam(m, iter, &p->last_software_frame_id))
663 int compositor_frame_type;
664 if (!ReadParam(m, iter, &compositor_frame_type))
667 switch (compositor_frame_type) {
671 p->gl_frame_data.reset(new cc::GLFrameData());
672 if (!ReadParam(m, iter, p->gl_frame_data.get()))
681 void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
683 l->append("CompositorFrameAck(");
684 LogParam(p.resources, l);
686 LogParam(p.last_software_frame_id, l);
689 LogParam(*p.gl_frame_data, l);
693 void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
694 const param_type& p) {
695 DCHECK_NE(0u, p.render_pass_list.size());
697 size_t to_reserve = p.resource_list.size() * sizeof(cc::TransferableResource);
698 for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
699 const cc::RenderPass* pass = p.render_pass_list[i];
700 to_reserve += ReserveSizeForRenderPassWrite(*pass);
702 m->Reserve(to_reserve);
704 WriteParam(m, p.resource_list);
705 WriteParam(m, p.render_pass_list.size());
706 for (size_t i = 0; i < p.render_pass_list.size(); ++i)
707 WriteParam(m, *p.render_pass_list[i]);
710 bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
711 PickleIterator* iter,
713 const static size_t kMaxRenderPasses = 10000;
715 size_t num_render_passes;
716 if (!ReadParam(m, iter, &p->resource_list) ||
717 !ReadParam(m, iter, &num_render_passes) ||
718 num_render_passes > kMaxRenderPasses || num_render_passes == 0)
720 for (size_t i = 0; i < num_render_passes; ++i) {
721 scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
722 if (!ReadParam(m, iter, render_pass.get()))
724 p->render_pass_list.push_back(render_pass.Pass());
729 void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p,
731 l->append("DelegatedFrameData(");
732 LogParam(p.resource_list, l);
734 for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
737 LogParam(*p.render_pass_list[i], l);