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