cc_messages.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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.
4
5#include "content/common/cc_messages.h"
6
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"
15
16namespace IPC {
17
18void ParamTraits<cc::FilterOperation>::Write(
19    Message* m, const param_type& p) {
20  WriteParam(m, p.type());
21  switch (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());
33      break;
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());
38      break;
39    case cc::FilterOperation::COLOR_MATRIX:
40      for (int i = 0; i < 20; ++i)
41        WriteParam(m, p.matrix()[i]);
42      break;
43    case cc::FilterOperation::ZOOM:
44      WriteParam(m, p.amount());
45      WriteParam(m, p.zoom_inset());
46      break;
47    case cc::FilterOperation::REFERENCE:
48      WriteParam(m, p.image_filter());
49      break;
50  }
51}
52
53bool ParamTraits<cc::FilterOperation>::Read(
54    const Message* m, PickleIterator* iter, param_type* r) {
55  cc::FilterOperation::FilterType type;
56  float amount;
57  gfx::Point drop_shadow_offset;
58  SkColor drop_shadow_color;
59  SkScalar matrix[20];
60  int zoom_inset;
61
62  if (!ReadParam(m, iter, &type))
63    return false;
64  r->set_type(type);
65
66  bool success = false;
67  switch (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);
80        success = true;
81      }
82      break;
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);
90        success = true;
91      }
92      break;
93    case cc::FilterOperation::COLOR_MATRIX: {
94      int i;
95      for (i = 0; i < 20; ++i) {
96        if (!ReadParam(m, iter, &matrix[i]))
97          break;
98      }
99      if (i == 20) {
100        r->set_matrix(matrix);
101        success = true;
102      }
103      break;
104    }
105    case cc::FilterOperation::ZOOM:
106      if (ReadParam(m, iter, &amount) &&
107          ReadParam(m, iter, &zoom_inset) &&
108          amount >= 0.f &&
109          zoom_inset >= 0) {
110        r->set_amount(amount);
111        r->set_zoom_inset(zoom_inset);
112        success = true;
113      }
114      break;
115    case cc::FilterOperation::REFERENCE: {
116      skia::RefPtr<SkImageFilter> filter;
117      if (!ReadParam(m, iter, &filter)) {
118        success = false;
119        break;
120      }
121      r->set_image_filter(filter);
122      success = true;
123      break;
124    }
125  }
126  return success;
127}
128
129void ParamTraits<cc::FilterOperation>::Log(
130    const param_type& p, std::string* l) {
131  l->append("(");
132  LogParam(static_cast<unsigned>(p.type()), l);
133  l->append(", ");
134
135  switch (p.type()) {
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);
147      break;
148    case cc::FilterOperation::DROP_SHADOW:
149      LogParam(p.drop_shadow_offset(), l);
150      l->append(", ");
151      LogParam(p.amount(), l);
152      l->append(", ");
153      LogParam(p.drop_shadow_color(), l);
154      break;
155    case cc::FilterOperation::COLOR_MATRIX:
156      for (int i = 0; i < 20; ++i) {
157        if (i)
158          l->append(", ");
159        LogParam(p.matrix()[i], l);
160      }
161      break;
162    case cc::FilterOperation::ZOOM:
163      LogParam(p.amount(), l);
164      l->append(", ");
165      LogParam(p.zoom_inset(), l);
166      break;
167    case cc::FilterOperation::REFERENCE:
168      LogParam(p.image_filter(), l);
169      break;
170  }
171  l->append(")");
172}
173
174void 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));
179  }
180}
181
182bool ParamTraits<cc::FilterOperations>::Read(
183    const Message* m, PickleIterator* iter, param_type* r) {
184  size_t count;
185  if (!ReadParam(m, iter, &count))
186    return false;
187
188  for (std::size_t i = 0; i < count; ++i) {
189    cc::FilterOperation op = cc::FilterOperation::CreateEmptyFilter();
190    if (!ReadParam(m, iter, &op))
191      return false;
192    r->Append(op);
193  }
194  return true;
195}
196
197void ParamTraits<cc::FilterOperations>::Log(
198    const param_type& p, std::string* l) {
199  l->append("(");
200  for (std::size_t i = 0; i < p.size(); ++i) {
201    if (i)
202      l->append(", ");
203    LogParam(p.at(i), l);
204  }
205  l->append(")");
206}
207
208void 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::kDisableFiltersOverIPC)) {
213    skia::RefPtr<SkData> data =
214        skia::AdoptRef(SkValidatingSerializeFlattenable(filter));
215    m->WriteData(static_cast<const char*>(data->data()), data->size());
216  } else {
217    m->WriteData(0, 0);
218  }
219}
220
221bool ParamTraits<skia::RefPtr<SkImageFilter> >::Read(
222    const Message* m, PickleIterator* iter, param_type* r) {
223  const char* data = 0;
224  int length = 0;
225  if (!m->ReadData(iter, &data, &length))
226    return false;
227  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
228  if ((length > 0) &&
229      !command_line.HasSwitch(switches::kDisableFiltersOverIPC)) {
230    SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(
231        data, length, SkImageFilter::GetFlattenableType());
232    *r = skia::AdoptRef(static_cast<SkImageFilter*>(flattenable));
233  } else {
234    r->clear();
235  }
236  return true;
237}
238
239void ParamTraits<skia::RefPtr<SkImageFilter> >::Log(
240    const param_type& p, std::string* l) {
241  l->append("(");
242  LogParam(p.get() ? p->countInputs() : 0, l);
243  l->append(")");
244}
245
246void ParamTraits<gfx::Transform>::Write(
247    Message* m, const param_type& p) {
248#ifdef SK_MSCALAR_IS_FLOAT
249  float column_major_data[16];
250  p.matrix().asColMajorf(column_major_data);
251#else
252  double column_major_data[16];
253  p.matrix().asColMajord(column_major_data);
254#endif
255  m->WriteBytes(&column_major_data, sizeof(SkMScalar) * 16);
256}
257
258bool ParamTraits<gfx::Transform>::Read(
259    const Message* m, PickleIterator* iter, param_type* r) {
260  const char* column_major_data;
261  if (!m->ReadBytes(iter, &column_major_data, sizeof(SkMScalar) * 16))
262    return false;
263  r->matrix().setColMajor(
264      reinterpret_cast<const SkMScalar*>(column_major_data));
265  return true;
266}
267
268void ParamTraits<gfx::Transform>::Log(
269    const param_type& p, std::string* l) {
270#ifdef SK_MSCALAR_IS_FLOAT
271  float row_major_data[16];
272  p.matrix().asRowMajorf(row_major_data);
273#else
274  double row_major_data[16];
275  p.matrix().asRowMajord(row_major_data);
276#endif
277  l->append("(");
278  for (int i = 0; i < 16; ++i) {
279    if (i > 0)
280      l->append(", ");
281    LogParam(row_major_data[i], l);
282  }
283  l->append(") ");
284}
285
286void ParamTraits<cc::RenderPass>::Write(
287    Message* m, const param_type& p) {
288  WriteParam(m, p.id);
289  WriteParam(m, p.output_rect);
290  WriteParam(m, p.damage_rect);
291  WriteParam(m, p.transform_to_root_target);
292  WriteParam(m, p.has_transparent_background);
293  WriteParam(m, p.shared_quad_state_list.size());
294  WriteParam(m, p.quad_list.size());
295
296  size_t shared_quad_state_index = 0;
297  size_t last_shared_quad_state_index = kuint32max;
298  for (size_t i = 0; i < p.quad_list.size(); ++i) {
299    const cc::DrawQuad* quad = p.quad_list[i];
300    DCHECK(quad->rect.Contains(quad->visible_rect))
301        << quad->material << " rect: " << quad->rect.ToString()
302        << " visible_rect: " << quad->visible_rect.ToString();
303    DCHECK(quad->opaque_rect.IsEmpty() ||
304           quad->rect.Contains(quad->opaque_rect))
305        << quad->material << " rect: " << quad->rect.ToString()
306        << " opaque_rect: " << quad->opaque_rect.ToString();
307
308    switch (quad->material) {
309      case cc::DrawQuad::CHECKERBOARD:
310        WriteParam(m, *cc::CheckerboardDrawQuad::MaterialCast(quad));
311        break;
312      case cc::DrawQuad::DEBUG_BORDER:
313        WriteParam(m, *cc::DebugBorderDrawQuad::MaterialCast(quad));
314        break;
315      case cc::DrawQuad::IO_SURFACE_CONTENT:
316        WriteParam(m, *cc::IOSurfaceDrawQuad::MaterialCast(quad));
317        break;
318      case cc::DrawQuad::PICTURE_CONTENT:
319        NOTREACHED();
320        break;
321      case cc::DrawQuad::TEXTURE_CONTENT:
322        WriteParam(m, *cc::TextureDrawQuad::MaterialCast(quad));
323        break;
324      case cc::DrawQuad::RENDER_PASS:
325        WriteParam(m, *cc::RenderPassDrawQuad::MaterialCast(quad));
326        break;
327      case cc::DrawQuad::SOLID_COLOR:
328        WriteParam(m, *cc::SolidColorDrawQuad::MaterialCast(quad));
329        break;
330      case cc::DrawQuad::SURFACE_CONTENT:
331        WriteParam(m, *cc::SurfaceDrawQuad::MaterialCast(quad));
332        break;
333      case cc::DrawQuad::TILED_CONTENT:
334        WriteParam(m, *cc::TileDrawQuad::MaterialCast(quad));
335        break;
336      case cc::DrawQuad::STREAM_VIDEO_CONTENT:
337        WriteParam(m, *cc::StreamVideoDrawQuad::MaterialCast(quad));
338        break;
339      case cc::DrawQuad::YUV_VIDEO_CONTENT:
340        WriteParam(m, *cc::YUVVideoDrawQuad::MaterialCast(quad));
341        break;
342      case cc::DrawQuad::INVALID:
343        break;
344    }
345
346    const cc::ScopedPtrVector<cc::SharedQuadState>& sqs_list =
347        p.shared_quad_state_list;
348
349    // This is an invalid index.
350    size_t bad_index = sqs_list.size();
351
352    // Null shared quad states should not occur.
353    DCHECK(quad->shared_quad_state);
354    if (!quad->shared_quad_state) {
355      WriteParam(m, bad_index);
356      continue;
357    }
358
359    // SharedQuadStates should appear in the order they are used by DrawQuads.
360    // Find the SharedQuadState for this DrawQuad.
361    while (shared_quad_state_index < sqs_list.size() &&
362           quad->shared_quad_state != sqs_list[shared_quad_state_index])
363      ++shared_quad_state_index;
364
365    DCHECK_LT(shared_quad_state_index, sqs_list.size());
366    if (shared_quad_state_index >= sqs_list.size()) {
367      WriteParam(m, bad_index);
368      continue;
369    }
370
371    WriteParam(m, shared_quad_state_index);
372    if (shared_quad_state_index != last_shared_quad_state_index) {
373      WriteParam(m, *sqs_list[shared_quad_state_index]);
374      last_shared_quad_state_index = shared_quad_state_index;
375    }
376  }
377}
378
379static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
380  size_t to_reserve = sizeof(cc::RenderPass);
381
382  to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
383
384  // The shared_quad_state_index for each quad.
385  to_reserve += p.quad_list.size() * sizeof(size_t);
386
387  // The largest quad type, verified by a unit test.
388  to_reserve += p.quad_list.size() * sizeof(cc::RenderPassDrawQuad);
389  return to_reserve;
390}
391
392template<typename QuadType>
393static scoped_ptr<cc::DrawQuad> ReadDrawQuad(const Message* m,
394                                             PickleIterator* iter) {
395  scoped_ptr<QuadType> quad = QuadType::Create();
396  if (!ReadParam(m, iter, quad.get()))
397    return scoped_ptr<QuadType>().template PassAs<cc::DrawQuad>();
398  return quad.template PassAs<cc::DrawQuad>();
399}
400
401bool ParamTraits<cc::RenderPass>::Read(
402    const Message* m, PickleIterator* iter, param_type* p) {
403  cc::RenderPass::Id id(-1, -1);
404  gfx::Rect output_rect;
405  gfx::Rect damage_rect;
406  gfx::Transform transform_to_root_target;
407  bool has_transparent_background;
408  size_t shared_quad_state_list_size;
409  size_t quad_list_size;
410
411  if (!ReadParam(m, iter, &id) ||
412      !ReadParam(m, iter, &output_rect) ||
413      !ReadParam(m, iter, &damage_rect) ||
414      !ReadParam(m, iter, &transform_to_root_target) ||
415      !ReadParam(m, iter, &has_transparent_background) ||
416      !ReadParam(m, iter, &shared_quad_state_list_size) ||
417      !ReadParam(m, iter, &quad_list_size))
418    return false;
419
420  p->SetAll(id,
421            output_rect,
422            damage_rect,
423            transform_to_root_target,
424            has_transparent_background);
425
426  size_t last_shared_quad_state_index = kuint32max;
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))
431      return false;
432
433    scoped_ptr<cc::DrawQuad> draw_quad;
434    switch (material) {
435      case cc::DrawQuad::CHECKERBOARD:
436        draw_quad = ReadDrawQuad<cc::CheckerboardDrawQuad>(m, iter);
437        break;
438      case cc::DrawQuad::DEBUG_BORDER:
439        draw_quad = ReadDrawQuad<cc::DebugBorderDrawQuad>(m, iter);
440        break;
441      case cc::DrawQuad::IO_SURFACE_CONTENT:
442        draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter);
443        break;
444      case cc::DrawQuad::PICTURE_CONTENT:
445        NOTREACHED();
446        return false;
447      case cc::DrawQuad::SURFACE_CONTENT:
448        draw_quad = ReadDrawQuad<cc::SurfaceDrawQuad>(m, iter);
449        break;
450      case cc::DrawQuad::TEXTURE_CONTENT:
451        draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter);
452        break;
453      case cc::DrawQuad::RENDER_PASS:
454        draw_quad = ReadDrawQuad<cc::RenderPassDrawQuad>(m, iter);
455        break;
456      case cc::DrawQuad::SOLID_COLOR:
457        draw_quad = ReadDrawQuad<cc::SolidColorDrawQuad>(m, iter);
458        break;
459      case cc::DrawQuad::TILED_CONTENT:
460        draw_quad = ReadDrawQuad<cc::TileDrawQuad>(m, iter);
461        break;
462      case cc::DrawQuad::STREAM_VIDEO_CONTENT:
463        draw_quad = ReadDrawQuad<cc::StreamVideoDrawQuad>(m, iter);
464        break;
465      case cc::DrawQuad::YUV_VIDEO_CONTENT:
466        draw_quad = ReadDrawQuad<cc::YUVVideoDrawQuad>(m, iter);
467        break;
468      case cc::DrawQuad::INVALID:
469        break;
470    }
471    if (!draw_quad)
472      return false;
473    if (!draw_quad->rect.Contains(draw_quad->visible_rect)) {
474      LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material
475                 << " rect: " << draw_quad->rect.ToString()
476                 << " visible_rect: " << draw_quad->visible_rect.ToString();
477      return false;
478    }
479    if (!draw_quad->opaque_rect.IsEmpty() &&
480        !draw_quad->rect.Contains(draw_quad->opaque_rect)) {
481      LOG(ERROR) << "Quad with invalid opaque rect " << draw_quad->material
482                 << " rect: " << draw_quad->rect.ToString()
483                 << " opaque_rect: " << draw_quad->opaque_rect.ToString();
484      return false;
485    }
486
487    size_t shared_quad_state_index;
488    if (!ReadParam(m, iter, &shared_quad_state_index))
489      return false;
490    if (shared_quad_state_index >= shared_quad_state_list_size)
491      return false;
492    // SharedQuadState indexes should be in ascending order.
493    if (last_shared_quad_state_index != kuint32max &&
494        shared_quad_state_index < last_shared_quad_state_index)
495      return false;
496
497    // If the quad has a new shared quad state, read it in.
498    if (last_shared_quad_state_index != shared_quad_state_index) {
499      scoped_ptr<cc::SharedQuadState> state(cc::SharedQuadState::Create());
500      if (!ReadParam(m, iter, state.get()))
501        return false;
502      p->shared_quad_state_list.push_back(state.Pass());
503      last_shared_quad_state_index = shared_quad_state_index;
504    }
505
506    draw_quad->shared_quad_state = p->shared_quad_state_list.back();
507    p->quad_list.push_back(draw_quad.Pass());
508  }
509
510  return true;
511}
512
513void ParamTraits<cc::RenderPass>::Log(
514    const param_type& p, std::string* l) {
515  l->append("RenderPass((");
516  LogParam(p.id, l);
517  l->append("), ");
518  LogParam(p.output_rect, l);
519  l->append(", ");
520  LogParam(p.damage_rect, l);
521  l->append(", ");
522  LogParam(p.transform_to_root_target, l);
523  l->append(", ");
524  LogParam(p.has_transparent_background, l);
525  l->append(", ");
526
527  l->append("[");
528  for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i) {
529    if (i)
530      l->append(", ");
531    LogParam(*p.shared_quad_state_list[i], l);
532  }
533  l->append("], [");
534  for (size_t i = 0; i < p.quad_list.size(); ++i) {
535    if (i)
536      l->append(", ");
537    const cc::DrawQuad* quad = p.quad_list[i];
538    switch (quad->material) {
539      case cc::DrawQuad::CHECKERBOARD:
540        LogParam(*cc::CheckerboardDrawQuad::MaterialCast(quad), l);
541        break;
542      case cc::DrawQuad::DEBUG_BORDER:
543        LogParam(*cc::DebugBorderDrawQuad::MaterialCast(quad), l);
544        break;
545      case cc::DrawQuad::IO_SURFACE_CONTENT:
546        LogParam(*cc::IOSurfaceDrawQuad::MaterialCast(quad), l);
547        break;
548      case cc::DrawQuad::PICTURE_CONTENT:
549        NOTREACHED();
550        break;
551      case cc::DrawQuad::TEXTURE_CONTENT:
552        LogParam(*cc::TextureDrawQuad::MaterialCast(quad), l);
553        break;
554      case cc::DrawQuad::RENDER_PASS:
555        LogParam(*cc::RenderPassDrawQuad::MaterialCast(quad), l);
556        break;
557      case cc::DrawQuad::SOLID_COLOR:
558        LogParam(*cc::SolidColorDrawQuad::MaterialCast(quad), l);
559        break;
560      case cc::DrawQuad::SURFACE_CONTENT:
561        LogParam(*cc::SurfaceDrawQuad::MaterialCast(quad), l);
562        break;
563      case cc::DrawQuad::TILED_CONTENT:
564        LogParam(*cc::TileDrawQuad::MaterialCast(quad), l);
565        break;
566      case cc::DrawQuad::STREAM_VIDEO_CONTENT:
567        LogParam(*cc::StreamVideoDrawQuad::MaterialCast(quad), l);
568        break;
569      case cc::DrawQuad::YUV_VIDEO_CONTENT:
570        LogParam(*cc::YUVVideoDrawQuad::MaterialCast(quad), l);
571        break;
572      case cc::DrawQuad::INVALID:
573        break;
574    }
575  }
576  l->append("])");
577}
578
579namespace {
580  enum CompositorFrameType {
581    NO_FRAME,
582    DELEGATED_FRAME,
583    GL_FRAME,
584    SOFTWARE_FRAME,
585  };
586}
587
588void ParamTraits<cc::CompositorFrame>::Write(Message* m,
589                                             const param_type& p) {
590  WriteParam(m, p.metadata);
591  if (p.delegated_frame_data) {
592    DCHECK(!p.gl_frame_data);
593    DCHECK(!p.software_frame_data);
594    WriteParam(m, static_cast<int>(DELEGATED_FRAME));
595    WriteParam(m, *p.delegated_frame_data);
596  } else if (p.gl_frame_data) {
597    DCHECK(!p.software_frame_data);
598    WriteParam(m, static_cast<int>(GL_FRAME));
599    WriteParam(m, *p.gl_frame_data);
600  } else if (p.software_frame_data) {
601    WriteParam(m, static_cast<int>(SOFTWARE_FRAME));
602    WriteParam(m, *p.software_frame_data);
603  } else {
604    WriteParam(m, static_cast<int>(NO_FRAME));
605  }
606}
607
608bool ParamTraits<cc::CompositorFrame>::Read(const Message* m,
609                                            PickleIterator* iter,
610                                            param_type* p) {
611  if (!ReadParam(m, iter, &p->metadata))
612    return false;
613
614  int compositor_frame_type;
615  if (!ReadParam(m, iter, &compositor_frame_type))
616    return false;
617
618  switch (compositor_frame_type) {
619    case DELEGATED_FRAME:
620      p->delegated_frame_data.reset(new cc::DelegatedFrameData());
621      if (!ReadParam(m, iter, p->delegated_frame_data.get()))
622        return false;
623      break;
624    case GL_FRAME:
625      p->gl_frame_data.reset(new cc::GLFrameData());
626      if (!ReadParam(m, iter, p->gl_frame_data.get()))
627        return false;
628      break;
629    case SOFTWARE_FRAME:
630      p->software_frame_data.reset(new cc::SoftwareFrameData());
631      if (!ReadParam(m, iter, p->software_frame_data.get()))
632        return false;
633      break;
634    case NO_FRAME:
635      break;
636    default:
637      return false;
638  }
639  return true;
640}
641
642void ParamTraits<cc::CompositorFrame>::Log(const param_type& p,
643                                           std::string* l) {
644  l->append("CompositorFrame(");
645  LogParam(p.metadata, l);
646  l->append(", ");
647  if (p.delegated_frame_data)
648    LogParam(*p.delegated_frame_data, l);
649  else if (p.gl_frame_data)
650    LogParam(*p.gl_frame_data, l);
651  else if (p.software_frame_data)
652    LogParam(*p.software_frame_data, l);
653  l->append(")");
654}
655
656void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
657                                                const param_type& p) {
658  WriteParam(m, p.resources);
659  WriteParam(m, p.last_software_frame_id);
660  if (p.gl_frame_data) {
661    WriteParam(m, static_cast<int>(GL_FRAME));
662    WriteParam(m, *p.gl_frame_data);
663  } else {
664    WriteParam(m, static_cast<int>(NO_FRAME));
665  }
666}
667
668bool ParamTraits<cc::CompositorFrameAck>::Read(const Message* m,
669                                               PickleIterator* iter,
670                                               param_type* p) {
671  if (!ReadParam(m, iter, &p->resources))
672    return false;
673
674  if (!ReadParam(m, iter, &p->last_software_frame_id))
675    return false;
676
677  int compositor_frame_type;
678  if (!ReadParam(m, iter, &compositor_frame_type))
679    return false;
680
681  switch (compositor_frame_type) {
682    case NO_FRAME:
683      break;
684    case GL_FRAME:
685      p->gl_frame_data.reset(new cc::GLFrameData());
686      if (!ReadParam(m, iter, p->gl_frame_data.get()))
687        return false;
688      break;
689    default:
690      return false;
691  }
692  return true;
693}
694
695void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
696                                              std::string* l) {
697  l->append("CompositorFrameAck(");
698  LogParam(p.resources, l);
699  l->append(", ");
700  LogParam(p.last_software_frame_id, l);
701  l->append(", ");
702  if (p.gl_frame_data)
703    LogParam(*p.gl_frame_data, l);
704  l->append(")");
705}
706
707void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
708                                                const param_type& p) {
709  DCHECK_NE(0u, p.render_pass_list.size());
710
711  size_t to_reserve = p.resource_list.size() * sizeof(cc::TransferableResource);
712  for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
713    const cc::RenderPass* pass = p.render_pass_list[i];
714    to_reserve += ReserveSizeForRenderPassWrite(*pass);
715  }
716  m->Reserve(to_reserve);
717
718  WriteParam(m, p.resource_list);
719  WriteParam(m, p.render_pass_list.size());
720  for (size_t i = 0; i < p.render_pass_list.size(); ++i)
721    WriteParam(m, *p.render_pass_list[i]);
722}
723
724bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
725                                               PickleIterator* iter,
726                                               param_type* p) {
727  const static size_t kMaxRenderPasses = 10000;
728
729  size_t num_render_passes;
730  if (!ReadParam(m, iter, &p->resource_list) ||
731      !ReadParam(m, iter, &num_render_passes) ||
732      num_render_passes > kMaxRenderPasses || num_render_passes == 0)
733    return false;
734  for (size_t i = 0; i < num_render_passes; ++i) {
735    scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
736    if (!ReadParam(m, iter, render_pass.get()))
737      return false;
738    p->render_pass_list.push_back(render_pass.Pass());
739  }
740  return true;
741}
742
743void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p,
744                                              std::string* l) {
745  l->append("DelegatedFrameData(");
746  LogParam(p.resource_list, l);
747  l->append(", [");
748  for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
749    if (i)
750      l->append(", ");
751    LogParam(*p.render_pass_list[i], l);
752  }
753  l->append("])");
754}
755
756void ParamTraits<cc::SoftwareFrameData>::Write(Message* m,
757                                               const param_type& p) {
758  DCHECK(cc::SharedBitmap::VerifySizeInBytes(p.size));
759
760  m->Reserve(sizeof(cc::SoftwareFrameData));
761  WriteParam(m, p.id);
762  WriteParam(m, p.size);
763  WriteParam(m, p.damage_rect);
764  WriteParam(m, p.bitmap_id);
765}
766
767bool ParamTraits<cc::SoftwareFrameData>::Read(const Message* m,
768                                              PickleIterator* iter,
769                                              param_type* p) {
770  if (!ReadParam(m, iter, &p->id))
771    return false;
772  if (!ReadParam(m, iter, &p->size) ||
773      !cc::SharedBitmap::VerifySizeInBytes(p->size))
774    return false;
775  if (!ReadParam(m, iter, &p->damage_rect))
776    return false;
777  if (!ReadParam(m, iter, &p->bitmap_id))
778    return false;
779  return true;
780}
781
782void ParamTraits<cc::SoftwareFrameData>::Log(const param_type& p,
783                                             std::string* l) {
784  l->append("SoftwareFrameData(");
785  LogParam(p.id, l);
786  l->append(", ");
787  LogParam(p.size, l);
788  l->append(", ");
789  LogParam(p.damage_rect, l);
790  l->append(", ");
791  LogParam(p.bitmap_id, l);
792  l->append(")");
793}
794
795}  // namespace IPC
796