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 "cc/output/compositor_frame.h"
8#include "cc/output/filter_operations.h"
9#include "cc/quads/largest_draw_quad.h"
10#include "content/public/common/common_param_traits.h"
11#include "third_party/skia/include/core/SkData.h"
12#include "third_party/skia/include/core/SkFlattenableSerialization.h"
13#include "ui/gfx/transform.h"
14
15namespace IPC {
16
17void ParamTraits<cc::FilterOperation>::Write(
18    Message* m, const param_type& p) {
19  WriteParam(m, p.type());
20  switch (p.type()) {
21    case cc::FilterOperation::GRAYSCALE:
22    case cc::FilterOperation::SEPIA:
23    case cc::FilterOperation::SATURATE:
24    case cc::FilterOperation::HUE_ROTATE:
25    case cc::FilterOperation::INVERT:
26    case cc::FilterOperation::BRIGHTNESS:
27    case cc::FilterOperation::SATURATING_BRIGHTNESS:
28    case cc::FilterOperation::CONTRAST:
29    case cc::FilterOperation::OPACITY:
30    case cc::FilterOperation::BLUR:
31      WriteParam(m, p.amount());
32      break;
33    case cc::FilterOperation::DROP_SHADOW:
34      WriteParam(m, p.drop_shadow_offset());
35      WriteParam(m, p.amount());
36      WriteParam(m, p.drop_shadow_color());
37      break;
38    case cc::FilterOperation::COLOR_MATRIX:
39      for (int i = 0; i < 20; ++i)
40        WriteParam(m, p.matrix()[i]);
41      break;
42    case cc::FilterOperation::ZOOM:
43      WriteParam(m, p.amount());
44      WriteParam(m, p.zoom_inset());
45      break;
46    case cc::FilterOperation::REFERENCE:
47      WriteParam(m, p.image_filter());
48      break;
49    case cc::FilterOperation::ALPHA_THRESHOLD:
50      NOTREACHED();
51      break;
52  }
53}
54
55bool ParamTraits<cc::FilterOperation>::Read(
56    const Message* m, PickleIterator* iter, param_type* r) {
57  cc::FilterOperation::FilterType type;
58  float amount;
59  gfx::Point drop_shadow_offset;
60  SkColor drop_shadow_color;
61  SkScalar matrix[20];
62  int zoom_inset;
63
64  if (!ReadParam(m, iter, &type))
65    return false;
66  r->set_type(type);
67
68  bool success = false;
69  switch (type) {
70    case cc::FilterOperation::GRAYSCALE:
71    case cc::FilterOperation::SEPIA:
72    case cc::FilterOperation::SATURATE:
73    case cc::FilterOperation::HUE_ROTATE:
74    case cc::FilterOperation::INVERT:
75    case cc::FilterOperation::BRIGHTNESS:
76    case cc::FilterOperation::SATURATING_BRIGHTNESS:
77    case cc::FilterOperation::CONTRAST:
78    case cc::FilterOperation::OPACITY:
79    case cc::FilterOperation::BLUR:
80      if (ReadParam(m, iter, &amount)) {
81        r->set_amount(amount);
82        success = true;
83      }
84      break;
85    case cc::FilterOperation::DROP_SHADOW:
86      if (ReadParam(m, iter, &drop_shadow_offset) &&
87          ReadParam(m, iter, &amount) &&
88          ReadParam(m, iter, &drop_shadow_color)) {
89        r->set_drop_shadow_offset(drop_shadow_offset);
90        r->set_amount(amount);
91        r->set_drop_shadow_color(drop_shadow_color);
92        success = true;
93      }
94      break;
95    case cc::FilterOperation::COLOR_MATRIX: {
96      int i;
97      for (i = 0; i < 20; ++i) {
98        if (!ReadParam(m, iter, &matrix[i]))
99          break;
100      }
101      if (i == 20) {
102        r->set_matrix(matrix);
103        success = true;
104      }
105      break;
106    }
107    case cc::FilterOperation::ZOOM:
108      if (ReadParam(m, iter, &amount) &&
109          ReadParam(m, iter, &zoom_inset) &&
110          amount >= 0.f &&
111          zoom_inset >= 0) {
112        r->set_amount(amount);
113        r->set_zoom_inset(zoom_inset);
114        success = true;
115      }
116      break;
117    case cc::FilterOperation::REFERENCE: {
118      skia::RefPtr<SkImageFilter> filter;
119      if (!ReadParam(m, iter, &filter)) {
120        success = false;
121        break;
122      }
123      r->set_image_filter(filter);
124      success = true;
125      break;
126    }
127    case cc::FilterOperation::ALPHA_THRESHOLD:
128      break;
129  }
130  return success;
131}
132
133void ParamTraits<cc::FilterOperation>::Log(
134    const param_type& p, std::string* l) {
135  l->append("(");
136  LogParam(static_cast<unsigned>(p.type()), l);
137  l->append(", ");
138
139  switch (p.type()) {
140    case cc::FilterOperation::GRAYSCALE:
141    case cc::FilterOperation::SEPIA:
142    case cc::FilterOperation::SATURATE:
143    case cc::FilterOperation::HUE_ROTATE:
144    case cc::FilterOperation::INVERT:
145    case cc::FilterOperation::BRIGHTNESS:
146    case cc::FilterOperation::SATURATING_BRIGHTNESS:
147    case cc::FilterOperation::CONTRAST:
148    case cc::FilterOperation::OPACITY:
149    case cc::FilterOperation::BLUR:
150      LogParam(p.amount(), l);
151      break;
152    case cc::FilterOperation::DROP_SHADOW:
153      LogParam(p.drop_shadow_offset(), l);
154      l->append(", ");
155      LogParam(p.amount(), l);
156      l->append(", ");
157      LogParam(p.drop_shadow_color(), l);
158      break;
159    case cc::FilterOperation::COLOR_MATRIX:
160      for (int i = 0; i < 20; ++i) {
161        if (i)
162          l->append(", ");
163        LogParam(p.matrix()[i], l);
164      }
165      break;
166    case cc::FilterOperation::ZOOM:
167      LogParam(p.amount(), l);
168      l->append(", ");
169      LogParam(p.zoom_inset(), l);
170      break;
171    case cc::FilterOperation::REFERENCE:
172      LogParam(p.image_filter(), l);
173      break;
174    case cc::FilterOperation::ALPHA_THRESHOLD:
175      NOTREACHED();
176      break;
177  }
178  l->append(")");
179}
180
181void ParamTraits<cc::FilterOperations>::Write(
182    Message* m, const param_type& p) {
183  WriteParam(m, p.size());
184  for (std::size_t i = 0; i < p.size(); ++i) {
185    WriteParam(m, p.at(i));
186  }
187}
188
189bool ParamTraits<cc::FilterOperations>::Read(
190    const Message* m, PickleIterator* iter, param_type* r) {
191  size_t count;
192  if (!ReadParam(m, iter, &count))
193    return false;
194
195  for (std::size_t i = 0; i < count; ++i) {
196    cc::FilterOperation op = cc::FilterOperation::CreateEmptyFilter();
197    if (!ReadParam(m, iter, &op))
198      return false;
199    r->Append(op);
200  }
201  return true;
202}
203
204void ParamTraits<cc::FilterOperations>::Log(
205    const param_type& p, std::string* l) {
206  l->append("(");
207  for (std::size_t i = 0; i < p.size(); ++i) {
208    if (i)
209      l->append(", ");
210    LogParam(p.at(i), l);
211  }
212  l->append(")");
213}
214
215void ParamTraits<skia::RefPtr<SkImageFilter> >::Write(
216    Message* m, const param_type& p) {
217  SkImageFilter* filter = p.get();
218  if (filter) {
219    skia::RefPtr<SkData> data =
220        skia::AdoptRef(SkValidatingSerializeFlattenable(filter));
221    m->WriteData(static_cast<const char*>(data->data()), data->size());
222  } else {
223    m->WriteData(0, 0);
224  }
225}
226
227bool ParamTraits<skia::RefPtr<SkImageFilter> >::Read(
228    const Message* m, PickleIterator* iter, param_type* r) {
229  const char* data = 0;
230  int length = 0;
231  if (!m->ReadData(iter, &data, &length))
232    return false;
233  if (length > 0) {
234    SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(
235        data, length, SkImageFilter::GetFlattenableType());
236    *r = skia::AdoptRef(static_cast<SkImageFilter*>(flattenable));
237  } else {
238    r->clear();
239  }
240  return true;
241}
242
243void ParamTraits<skia::RefPtr<SkImageFilter> >::Log(
244    const param_type& p, std::string* l) {
245  l->append("(");
246  LogParam(p.get() ? p->countInputs() : 0, l);
247  l->append(")");
248}
249
250void ParamTraits<gfx::Transform>::Write(
251    Message* m, const param_type& p) {
252#ifdef SK_MSCALAR_IS_FLOAT
253  float column_major_data[16];
254  p.matrix().asColMajorf(column_major_data);
255#else
256  double column_major_data[16];
257  p.matrix().asColMajord(column_major_data);
258#endif
259  m->WriteBytes(&column_major_data, sizeof(SkMScalar) * 16);
260}
261
262bool ParamTraits<gfx::Transform>::Read(
263    const Message* m, PickleIterator* iter, param_type* r) {
264  const char* column_major_data;
265  if (!m->ReadBytes(iter, &column_major_data, sizeof(SkMScalar) * 16))
266    return false;
267  r->matrix().setColMajor(
268      reinterpret_cast<const SkMScalar*>(column_major_data));
269  return true;
270}
271
272void ParamTraits<gfx::Transform>::Log(
273    const param_type& p, std::string* l) {
274#ifdef SK_MSCALAR_IS_FLOAT
275  float row_major_data[16];
276  p.matrix().asRowMajorf(row_major_data);
277#else
278  double row_major_data[16];
279  p.matrix().asRowMajord(row_major_data);
280#endif
281  l->append("(");
282  for (int i = 0; i < 16; ++i) {
283    if (i > 0)
284      l->append(", ");
285    LogParam(row_major_data[i], l);
286  }
287  l->append(") ");
288}
289
290void ParamTraits<cc::RenderPass>::Write(
291    Message* m, const param_type& p) {
292  WriteParam(m, p.id);
293  WriteParam(m, p.output_rect);
294  WriteParam(m, p.damage_rect);
295  WriteParam(m, p.transform_to_root_target);
296  WriteParam(m, p.has_transparent_background);
297  WriteParam(m, p.shared_quad_state_list.size());
298  WriteParam(m, p.quad_list.size());
299
300  size_t shared_quad_state_index = 0;
301  size_t last_shared_quad_state_index = kuint32max;
302  for (cc::QuadList::ConstIterator iter = p.quad_list.begin();
303       iter != p.quad_list.end();
304       ++iter) {
305    const cc::DrawQuad* quad = &*iter;
306    DCHECK(quad->rect.Contains(quad->visible_rect))
307        << quad->material << " rect: " << quad->rect.ToString()
308        << " visible_rect: " << quad->visible_rect.ToString();
309    DCHECK(quad->opaque_rect.IsEmpty() ||
310           quad->rect.Contains(quad->opaque_rect))
311        << quad->material << " rect: " << quad->rect.ToString()
312        << " opaque_rect: " << quad->opaque_rect.ToString();
313
314    switch (quad->material) {
315      case cc::DrawQuad::CHECKERBOARD:
316        WriteParam(m, *cc::CheckerboardDrawQuad::MaterialCast(quad));
317        break;
318      case cc::DrawQuad::DEBUG_BORDER:
319        WriteParam(m, *cc::DebugBorderDrawQuad::MaterialCast(quad));
320        break;
321      case cc::DrawQuad::IO_SURFACE_CONTENT:
322        WriteParam(m, *cc::IOSurfaceDrawQuad::MaterialCast(quad));
323        break;
324      case cc::DrawQuad::PICTURE_CONTENT:
325        NOTREACHED();
326        break;
327      case cc::DrawQuad::TEXTURE_CONTENT:
328        WriteParam(m, *cc::TextureDrawQuad::MaterialCast(quad));
329        break;
330      case cc::DrawQuad::RENDER_PASS:
331        WriteParam(m, *cc::RenderPassDrawQuad::MaterialCast(quad));
332        break;
333      case cc::DrawQuad::SOLID_COLOR:
334        WriteParam(m, *cc::SolidColorDrawQuad::MaterialCast(quad));
335        break;
336      case cc::DrawQuad::SURFACE_CONTENT:
337        WriteParam(m, *cc::SurfaceDrawQuad::MaterialCast(quad));
338        break;
339      case cc::DrawQuad::TILED_CONTENT:
340        WriteParam(m, *cc::TileDrawQuad::MaterialCast(quad));
341        break;
342      case cc::DrawQuad::STREAM_VIDEO_CONTENT:
343        WriteParam(m, *cc::StreamVideoDrawQuad::MaterialCast(quad));
344        break;
345      case cc::DrawQuad::YUV_VIDEO_CONTENT:
346        WriteParam(m, *cc::YUVVideoDrawQuad::MaterialCast(quad));
347        break;
348      case cc::DrawQuad::INVALID:
349        break;
350    }
351
352    const cc::ScopedPtrVector<cc::SharedQuadState>& sqs_list =
353        p.shared_quad_state_list;
354
355    // This is an invalid index.
356    size_t bad_index = sqs_list.size();
357
358    // Null shared quad states should not occur.
359    DCHECK(quad->shared_quad_state);
360    if (!quad->shared_quad_state) {
361      WriteParam(m, bad_index);
362      continue;
363    }
364
365    // SharedQuadStates should appear in the order they are used by DrawQuads.
366    // Find the SharedQuadState for this DrawQuad.
367    while (shared_quad_state_index < sqs_list.size() &&
368           quad->shared_quad_state != sqs_list[shared_quad_state_index])
369      ++shared_quad_state_index;
370
371    DCHECK_LT(shared_quad_state_index, sqs_list.size());
372    if (shared_quad_state_index >= sqs_list.size()) {
373      WriteParam(m, bad_index);
374      continue;
375    }
376
377    WriteParam(m, shared_quad_state_index);
378    if (shared_quad_state_index != last_shared_quad_state_index) {
379      WriteParam(m, *sqs_list[shared_quad_state_index]);
380      last_shared_quad_state_index = shared_quad_state_index;
381    }
382  }
383}
384
385static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
386  size_t to_reserve = sizeof(cc::RenderPass);
387
388  to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
389
390  // The shared_quad_state_index for each quad.
391  to_reserve += p.quad_list.size() * sizeof(size_t);
392
393  // The largest quad type, verified by a unit test.
394  to_reserve += p.quad_list.size() * sizeof(cc::kLargestDrawQuad);
395  return to_reserve;
396}
397
398template <typename QuadType>
399static cc::DrawQuad* ReadDrawQuad(const Message* m,
400                                  PickleIterator* iter,
401                                  cc::RenderPass* render_pass) {
402  QuadType* quad = render_pass->CreateAndAppendDrawQuad<QuadType>();
403  if (!ReadParam(m, iter, quad))
404    return NULL;
405  return quad;
406}
407
408bool ParamTraits<cc::RenderPass>::Read(
409    const Message* m, PickleIterator* iter, param_type* p) {
410  cc::RenderPassId id(-1, -1);
411  gfx::Rect output_rect;
412  gfx::Rect damage_rect;
413  gfx::Transform transform_to_root_target;
414  bool has_transparent_background;
415  size_t shared_quad_state_list_size;
416  size_t quad_list_size;
417
418  if (!ReadParam(m, iter, &id) ||
419      !ReadParam(m, iter, &output_rect) ||
420      !ReadParam(m, iter, &damage_rect) ||
421      !ReadParam(m, iter, &transform_to_root_target) ||
422      !ReadParam(m, iter, &has_transparent_background) ||
423      !ReadParam(m, iter, &shared_quad_state_list_size) ||
424      !ReadParam(m, iter, &quad_list_size))
425    return false;
426
427  p->SetAll(id,
428            output_rect,
429            damage_rect,
430            transform_to_root_target,
431            has_transparent_background);
432
433  size_t last_shared_quad_state_index = kuint32max;
434  for (size_t i = 0; i < quad_list_size; ++i) {
435    cc::DrawQuad::Material material;
436    PickleIterator temp_iter = *iter;
437    if (!ReadParam(m, &temp_iter, &material))
438      return false;
439
440    cc::DrawQuad* draw_quad = NULL;
441    switch (material) {
442      case cc::DrawQuad::CHECKERBOARD:
443        draw_quad = ReadDrawQuad<cc::CheckerboardDrawQuad>(m, iter, p);
444        break;
445      case cc::DrawQuad::DEBUG_BORDER:
446        draw_quad = ReadDrawQuad<cc::DebugBorderDrawQuad>(m, iter, p);
447        break;
448      case cc::DrawQuad::IO_SURFACE_CONTENT:
449        draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter, p);
450        break;
451      case cc::DrawQuad::PICTURE_CONTENT:
452        NOTREACHED();
453        return false;
454      case cc::DrawQuad::SURFACE_CONTENT:
455        draw_quad = ReadDrawQuad<cc::SurfaceDrawQuad>(m, iter, p);
456        break;
457      case cc::DrawQuad::TEXTURE_CONTENT:
458        draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter, p);
459        break;
460      case cc::DrawQuad::RENDER_PASS:
461        draw_quad = ReadDrawQuad<cc::RenderPassDrawQuad>(m, iter, p);
462        break;
463      case cc::DrawQuad::SOLID_COLOR:
464        draw_quad = ReadDrawQuad<cc::SolidColorDrawQuad>(m, iter, p);
465        break;
466      case cc::DrawQuad::TILED_CONTENT:
467        draw_quad = ReadDrawQuad<cc::TileDrawQuad>(m, iter, p);
468        break;
469      case cc::DrawQuad::STREAM_VIDEO_CONTENT:
470        draw_quad = ReadDrawQuad<cc::StreamVideoDrawQuad>(m, iter, p);
471        break;
472      case cc::DrawQuad::YUV_VIDEO_CONTENT:
473        draw_quad = ReadDrawQuad<cc::YUVVideoDrawQuad>(m, iter, p);
474        break;
475      case cc::DrawQuad::INVALID:
476        break;
477    }
478    if (!draw_quad)
479      return false;
480    if (!draw_quad->rect.Contains(draw_quad->visible_rect)) {
481      LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material
482                 << " rect: " << draw_quad->rect.ToString()
483                 << " visible_rect: " << draw_quad->visible_rect.ToString();
484      return false;
485    }
486    if (!draw_quad->opaque_rect.IsEmpty() &&
487        !draw_quad->rect.Contains(draw_quad->opaque_rect)) {
488      LOG(ERROR) << "Quad with invalid opaque rect " << draw_quad->material
489                 << " rect: " << draw_quad->rect.ToString()
490                 << " opaque_rect: " << draw_quad->opaque_rect.ToString();
491      return false;
492    }
493
494    size_t shared_quad_state_index;
495    if (!ReadParam(m, iter, &shared_quad_state_index))
496      return false;
497    if (shared_quad_state_index >= shared_quad_state_list_size)
498      return false;
499    // SharedQuadState indexes should be in ascending order.
500    if (last_shared_quad_state_index != kuint32max &&
501        shared_quad_state_index < last_shared_quad_state_index)
502      return false;
503
504    // If the quad has a new shared quad state, read it in.
505    if (last_shared_quad_state_index != shared_quad_state_index) {
506      cc::SharedQuadState* state = p->CreateAndAppendSharedQuadState();
507      if (!ReadParam(m, iter, state))
508        return false;
509      last_shared_quad_state_index = shared_quad_state_index;
510    }
511
512    draw_quad->shared_quad_state = p->shared_quad_state_list.back();
513  }
514
515  return true;
516}
517
518void ParamTraits<cc::RenderPass>::Log(
519    const param_type& p, std::string* l) {
520  l->append("RenderPass((");
521  LogParam(p.id, l);
522  l->append("), ");
523  LogParam(p.output_rect, l);
524  l->append(", ");
525  LogParam(p.damage_rect, l);
526  l->append(", ");
527  LogParam(p.transform_to_root_target, l);
528  l->append(", ");
529  LogParam(p.has_transparent_background, l);
530  l->append(", ");
531
532  l->append("[");
533  for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i) {
534    if (i)
535      l->append(", ");
536    LogParam(*p.shared_quad_state_list[i], l);
537  }
538  l->append("], [");
539  for (cc::QuadList::ConstIterator iter = p.quad_list.begin();
540       iter != p.quad_list.end();
541       ++iter) {
542    if (iter != p.quad_list.begin())
543      l->append(", ");
544    const cc::DrawQuad* quad = &*iter;
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 = sizeof(p.device_scale_factor);
719  to_reserve += p.resource_list.size() * sizeof(cc::TransferableResource);
720  for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
721    const cc::RenderPass* pass = p.render_pass_list[i];
722    to_reserve += ReserveSizeForRenderPassWrite(*pass);
723  }
724  m->Reserve(to_reserve);
725
726  WriteParam(m, p.device_scale_factor);
727  WriteParam(m, p.resource_list);
728  WriteParam(m, p.render_pass_list.size());
729  for (size_t i = 0; i < p.render_pass_list.size(); ++i)
730    WriteParam(m, *p.render_pass_list[i]);
731}
732
733bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
734                                               PickleIterator* iter,
735                                               param_type* p) {
736  if (!ReadParam(m, iter, &p->device_scale_factor))
737    return false;
738
739  const static size_t kMaxRenderPasses = 10000;
740
741  size_t num_render_passes;
742  if (!ReadParam(m, iter, &p->resource_list) ||
743      !ReadParam(m, iter, &num_render_passes) ||
744      num_render_passes > kMaxRenderPasses || num_render_passes == 0)
745    return false;
746  for (size_t i = 0; i < num_render_passes; ++i) {
747    scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
748    if (!ReadParam(m, iter, render_pass.get()))
749      return false;
750    p->render_pass_list.push_back(render_pass.Pass());
751  }
752  return true;
753}
754
755void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p,
756                                              std::string* l) {
757  l->append("DelegatedFrameData(");
758  LogParam(p.device_scale_factor, l);
759  LogParam(p.resource_list, l);
760  l->append(", [");
761  for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
762    if (i)
763      l->append(", ");
764    LogParam(*p.render_pass_list[i], l);
765  }
766  l->append("])");
767}
768
769void ParamTraits<cc::SoftwareFrameData>::Write(Message* m,
770                                               const param_type& p) {
771  DCHECK(cc::SharedBitmap::VerifySizeInBytes(p.size));
772
773  m->Reserve(sizeof(cc::SoftwareFrameData));
774  WriteParam(m, p.id);
775  WriteParam(m, p.size);
776  WriteParam(m, p.damage_rect);
777  WriteParam(m, p.bitmap_id);
778}
779
780bool ParamTraits<cc::SoftwareFrameData>::Read(const Message* m,
781                                              PickleIterator* iter,
782                                              param_type* p) {
783  if (!ReadParam(m, iter, &p->id))
784    return false;
785  if (!ReadParam(m, iter, &p->size) ||
786      !cc::SharedBitmap::VerifySizeInBytes(p->size))
787    return false;
788  if (!ReadParam(m, iter, &p->damage_rect))
789    return false;
790  if (!ReadParam(m, iter, &p->bitmap_id))
791    return false;
792  return true;
793}
794
795void ParamTraits<cc::SoftwareFrameData>::Log(const param_type& p,
796                                             std::string* l) {
797  l->append("SoftwareFrameData(");
798  LogParam(p.id, l);
799  l->append(", ");
800  LogParam(p.size, l);
801  l->append(", ");
802  LogParam(p.damage_rect, l);
803  l->append(", ");
804  LogParam(p.bitmap_id, l);
805  l->append(")");
806}
807
808}  // namespace IPC
809