Home | History | Annotate | Download | only in common
      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 
     16 namespace IPC {
     17 
     18 void 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 
     53 bool 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 
    129 void 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 
    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));
    179   }
    180 }
    181 
    182 bool 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 
    197 void 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 
    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::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 
    221 bool 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 
    239 void 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 
    246 void 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 
    258 bool 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 
    268 void 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 
    286 void 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::TILED_CONTENT:
    331         WriteParam(m, *cc::TileDrawQuad::MaterialCast(quad));
    332         break;
    333       case cc::DrawQuad::STREAM_VIDEO_CONTENT:
    334         WriteParam(m, *cc::StreamVideoDrawQuad::MaterialCast(quad));
    335         break;
    336       case cc::DrawQuad::YUV_VIDEO_CONTENT:
    337         WriteParam(m, *cc::YUVVideoDrawQuad::MaterialCast(quad));
    338         break;
    339       case cc::DrawQuad::INVALID:
    340         break;
    341     }
    342 
    343     const cc::ScopedPtrVector<cc::SharedQuadState>& sqs_list =
    344         p.shared_quad_state_list;
    345 
    346     // This is an invalid index.
    347     size_t bad_index = sqs_list.size();
    348 
    349     // Null shared quad states should not occur.
    350     DCHECK(quad->shared_quad_state);
    351     if (!quad->shared_quad_state) {
    352       WriteParam(m, bad_index);
    353       continue;
    354     }
    355 
    356     // SharedQuadStates should appear in the order they are used by DrawQuads.
    357     // Find the SharedQuadState for this DrawQuad.
    358     while (shared_quad_state_index < sqs_list.size() &&
    359            quad->shared_quad_state != sqs_list[shared_quad_state_index])
    360       ++shared_quad_state_index;
    361 
    362     DCHECK_LT(shared_quad_state_index, sqs_list.size());
    363     if (shared_quad_state_index >= sqs_list.size()) {
    364       WriteParam(m, bad_index);
    365       continue;
    366     }
    367 
    368     WriteParam(m, shared_quad_state_index);
    369     if (shared_quad_state_index != last_shared_quad_state_index) {
    370       WriteParam(m, *sqs_list[shared_quad_state_index]);
    371       last_shared_quad_state_index = shared_quad_state_index;
    372     }
    373   }
    374 }
    375 
    376 static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
    377   size_t to_reserve = sizeof(cc::RenderPass);
    378 
    379   to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
    380 
    381   // The shared_quad_state_index for each quad.
    382   to_reserve += p.quad_list.size() * sizeof(size_t);
    383 
    384   // The largest quad type, verified by a unit test.
    385   to_reserve += p.quad_list.size() * sizeof(cc::RenderPassDrawQuad);
    386   return to_reserve;
    387 }
    388 
    389 template<typename QuadType>
    390 static scoped_ptr<cc::DrawQuad> ReadDrawQuad(const Message* m,
    391                                              PickleIterator* iter) {
    392   scoped_ptr<QuadType> quad = QuadType::Create();
    393   if (!ReadParam(m, iter, quad.get()))
    394     return scoped_ptr<QuadType>().template PassAs<cc::DrawQuad>();
    395   return quad.template PassAs<cc::DrawQuad>();
    396 }
    397 
    398 bool ParamTraits<cc::RenderPass>::Read(
    399     const Message* m, PickleIterator* iter, param_type* p) {
    400   cc::RenderPass::Id id(-1, -1);
    401   gfx::Rect output_rect;
    402   gfx::RectF damage_rect;
    403   gfx::Transform transform_to_root_target;
    404   bool has_transparent_background;
    405   size_t shared_quad_state_list_size;
    406   size_t quad_list_size;
    407 
    408   if (!ReadParam(m, iter, &id) ||
    409       !ReadParam(m, iter, &output_rect) ||
    410       !ReadParam(m, iter, &damage_rect) ||
    411       !ReadParam(m, iter, &transform_to_root_target) ||
    412       !ReadParam(m, iter, &has_transparent_background) ||
    413       !ReadParam(m, iter, &shared_quad_state_list_size) ||
    414       !ReadParam(m, iter, &quad_list_size))
    415     return false;
    416 
    417   p->SetAll(id,
    418             output_rect,
    419             damage_rect,
    420             transform_to_root_target,
    421             has_transparent_background);
    422 
    423   size_t last_shared_quad_state_index = kuint32max;
    424   for (size_t i = 0; i < quad_list_size; ++i) {
    425     cc::DrawQuad::Material material;
    426     PickleIterator temp_iter = *iter;
    427     if (!ReadParam(m, &temp_iter, &material))
    428       return false;
    429 
    430     scoped_ptr<cc::DrawQuad> draw_quad;
    431     switch (material) {
    432       case cc::DrawQuad::CHECKERBOARD:
    433         draw_quad = ReadDrawQuad<cc::CheckerboardDrawQuad>(m, iter);
    434         break;
    435       case cc::DrawQuad::DEBUG_BORDER:
    436         draw_quad = ReadDrawQuad<cc::DebugBorderDrawQuad>(m, iter);
    437         break;
    438       case cc::DrawQuad::IO_SURFACE_CONTENT:
    439         draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter);
    440         break;
    441       case cc::DrawQuad::PICTURE_CONTENT:
    442         NOTREACHED();
    443         return false;
    444       case cc::DrawQuad::TEXTURE_CONTENT:
    445         draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter);
    446         break;
    447       case cc::DrawQuad::RENDER_PASS:
    448         draw_quad = ReadDrawQuad<cc::RenderPassDrawQuad>(m, iter);
    449         break;
    450       case cc::DrawQuad::SOLID_COLOR:
    451         draw_quad = ReadDrawQuad<cc::SolidColorDrawQuad>(m, iter);
    452         break;
    453       case cc::DrawQuad::TILED_CONTENT:
    454         draw_quad = ReadDrawQuad<cc::TileDrawQuad>(m, iter);
    455         break;
    456       case cc::DrawQuad::STREAM_VIDEO_CONTENT:
    457         draw_quad = ReadDrawQuad<cc::StreamVideoDrawQuad>(m, iter);
    458         break;
    459       case cc::DrawQuad::YUV_VIDEO_CONTENT:
    460         draw_quad = ReadDrawQuad<cc::YUVVideoDrawQuad>(m, iter);
    461         break;
    462       case cc::DrawQuad::INVALID:
    463         break;
    464     }
    465     if (!draw_quad)
    466       return false;
    467     if (!draw_quad->rect.Contains(draw_quad->visible_rect)) {
    468       LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material
    469                  << " rect: " << draw_quad->rect.ToString()
    470                  << " visible_rect: " << draw_quad->visible_rect.ToString();
    471       return false;
    472     }
    473     if (!draw_quad->opaque_rect.IsEmpty() &&
    474         !draw_quad->rect.Contains(draw_quad->opaque_rect)) {
    475       LOG(ERROR) << "Quad with invalid opaque rect " << draw_quad->material
    476                  << " rect: " << draw_quad->rect.ToString()
    477                  << " opaque_rect: " << draw_quad->opaque_rect.ToString();
    478       return false;
    479     }
    480 
    481     size_t shared_quad_state_index;
    482     if (!ReadParam(m, iter, &shared_quad_state_index))
    483       return false;
    484     if (shared_quad_state_index >= shared_quad_state_list_size)
    485       return false;
    486     // SharedQuadState indexes should be in ascending order.
    487     if (last_shared_quad_state_index != kuint32max &&
    488         shared_quad_state_index < last_shared_quad_state_index)
    489       return false;
    490 
    491     // If the quad has a new shared quad state, read it in.
    492     if (last_shared_quad_state_index != shared_quad_state_index) {
    493       scoped_ptr<cc::SharedQuadState> state(cc::SharedQuadState::Create());
    494       if (!ReadParam(m, iter, state.get()))
    495         return false;
    496       p->shared_quad_state_list.push_back(state.Pass());
    497       last_shared_quad_state_index = shared_quad_state_index;
    498     }
    499 
    500     draw_quad->shared_quad_state = p->shared_quad_state_list.back();
    501     p->quad_list.push_back(draw_quad.Pass());
    502   }
    503 
    504   return true;
    505 }
    506 
    507 void ParamTraits<cc::RenderPass>::Log(
    508     const param_type& p, std::string* l) {
    509   l->append("RenderPass((");
    510   LogParam(p.id, l);
    511   l->append("), ");
    512   LogParam(p.output_rect, l);
    513   l->append(", ");
    514   LogParam(p.damage_rect, l);
    515   l->append(", ");
    516   LogParam(p.transform_to_root_target, l);
    517   l->append(", ");
    518   LogParam(p.has_transparent_background, l);
    519   l->append(", ");
    520 
    521   l->append("[");
    522   for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i) {
    523     if (i)
    524       l->append(", ");
    525     LogParam(*p.shared_quad_state_list[i], l);
    526   }
    527   l->append("], [");
    528   for (size_t i = 0; i < p.quad_list.size(); ++i) {
    529     if (i)
    530       l->append(", ");
    531     const cc::DrawQuad* quad = p.quad_list[i];
    532     switch (quad->material) {
    533       case cc::DrawQuad::CHECKERBOARD:
    534         LogParam(*cc::CheckerboardDrawQuad::MaterialCast(quad), l);
    535         break;
    536       case cc::DrawQuad::DEBUG_BORDER:
    537         LogParam(*cc::DebugBorderDrawQuad::MaterialCast(quad), l);
    538         break;
    539       case cc::DrawQuad::IO_SURFACE_CONTENT:
    540         LogParam(*cc::IOSurfaceDrawQuad::MaterialCast(quad), l);
    541         break;
    542       case cc::DrawQuad::PICTURE_CONTENT:
    543         NOTREACHED();
    544         break;
    545       case cc::DrawQuad::TEXTURE_CONTENT:
    546         LogParam(*cc::TextureDrawQuad::MaterialCast(quad), l);
    547         break;
    548       case cc::DrawQuad::RENDER_PASS:
    549         LogParam(*cc::RenderPassDrawQuad::MaterialCast(quad), l);
    550         break;
    551       case cc::DrawQuad::SOLID_COLOR:
    552         LogParam(*cc::SolidColorDrawQuad::MaterialCast(quad), l);
    553         break;
    554       case cc::DrawQuad::TILED_CONTENT:
    555         LogParam(*cc::TileDrawQuad::MaterialCast(quad), l);
    556         break;
    557       case cc::DrawQuad::STREAM_VIDEO_CONTENT:
    558         LogParam(*cc::StreamVideoDrawQuad::MaterialCast(quad), l);
    559         break;
    560       case cc::DrawQuad::YUV_VIDEO_CONTENT:
    561         LogParam(*cc::YUVVideoDrawQuad::MaterialCast(quad), l);
    562         break;
    563       case cc::DrawQuad::INVALID:
    564         break;
    565     }
    566   }
    567   l->append("])");
    568 }
    569 
    570 namespace {
    571   enum CompositorFrameType {
    572     NO_FRAME,
    573     DELEGATED_FRAME,
    574     GL_FRAME,
    575     SOFTWARE_FRAME,
    576   };
    577 }
    578 
    579 void ParamTraits<cc::CompositorFrame>::Write(Message* m,
    580                                              const param_type& p) {
    581   WriteParam(m, p.metadata);
    582   if (p.delegated_frame_data) {
    583     DCHECK(!p.gl_frame_data);
    584     DCHECK(!p.software_frame_data);
    585     WriteParam(m, static_cast<int>(DELEGATED_FRAME));
    586     WriteParam(m, *p.delegated_frame_data);
    587   } else if (p.gl_frame_data) {
    588     DCHECK(!p.software_frame_data);
    589     WriteParam(m, static_cast<int>(GL_FRAME));
    590     WriteParam(m, *p.gl_frame_data);
    591   } else if (p.software_frame_data) {
    592     WriteParam(m, static_cast<int>(SOFTWARE_FRAME));
    593     WriteParam(m, *p.software_frame_data);
    594   } else {
    595     WriteParam(m, static_cast<int>(NO_FRAME));
    596   }
    597 }
    598 
    599 bool ParamTraits<cc::CompositorFrame>::Read(const Message* m,
    600                                             PickleIterator* iter,
    601                                             param_type* p) {
    602   if (!ReadParam(m, iter, &p->metadata))
    603     return false;
    604 
    605   int compositor_frame_type;
    606   if (!ReadParam(m, iter, &compositor_frame_type))
    607     return false;
    608 
    609   switch (compositor_frame_type) {
    610     case DELEGATED_FRAME:
    611       p->delegated_frame_data.reset(new cc::DelegatedFrameData());
    612       if (!ReadParam(m, iter, p->delegated_frame_data.get()))
    613         return false;
    614       break;
    615     case GL_FRAME:
    616       p->gl_frame_data.reset(new cc::GLFrameData());
    617       if (!ReadParam(m, iter, p->gl_frame_data.get()))
    618         return false;
    619       break;
    620     case SOFTWARE_FRAME:
    621       p->software_frame_data.reset(new cc::SoftwareFrameData());
    622       if (!ReadParam(m, iter, p->software_frame_data.get()))
    623         return false;
    624       break;
    625     case NO_FRAME:
    626       break;
    627     default:
    628       return false;
    629   }
    630   return true;
    631 }
    632 
    633 void ParamTraits<cc::CompositorFrame>::Log(const param_type& p,
    634                                            std::string* l) {
    635   l->append("CompositorFrame(");
    636   LogParam(p.metadata, l);
    637   l->append(", ");
    638   if (p.delegated_frame_data)
    639     LogParam(*p.delegated_frame_data, l);
    640   else if (p.gl_frame_data)
    641     LogParam(*p.gl_frame_data, l);
    642   else if (p.software_frame_data)
    643     LogParam(*p.software_frame_data, l);
    644   l->append(")");
    645 }
    646 
    647 void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
    648                                                 const param_type& p) {
    649   WriteParam(m, p.resources);
    650   WriteParam(m, p.last_software_frame_id);
    651   if (p.gl_frame_data) {
    652     WriteParam(m, static_cast<int>(GL_FRAME));
    653     WriteParam(m, *p.gl_frame_data);
    654   } else {
    655     WriteParam(m, static_cast<int>(NO_FRAME));
    656   }
    657 }
    658 
    659 bool ParamTraits<cc::CompositorFrameAck>::Read(const Message* m,
    660                                                PickleIterator* iter,
    661                                                param_type* p) {
    662   if (!ReadParam(m, iter, &p->resources))
    663     return false;
    664 
    665   if (!ReadParam(m, iter, &p->last_software_frame_id))
    666     return false;
    667 
    668   int compositor_frame_type;
    669   if (!ReadParam(m, iter, &compositor_frame_type))
    670     return false;
    671 
    672   switch (compositor_frame_type) {
    673     case NO_FRAME:
    674       break;
    675     case GL_FRAME:
    676       p->gl_frame_data.reset(new cc::GLFrameData());
    677       if (!ReadParam(m, iter, p->gl_frame_data.get()))
    678         return false;
    679       break;
    680     default:
    681       return false;
    682   }
    683   return true;
    684 }
    685 
    686 void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
    687                                               std::string* l) {
    688   l->append("CompositorFrameAck(");
    689   LogParam(p.resources, l);
    690   l->append(", ");
    691   LogParam(p.last_software_frame_id, l);
    692   l->append(", ");
    693   if (p.gl_frame_data)
    694     LogParam(*p.gl_frame_data, l);
    695   l->append(")");
    696 }
    697 
    698 void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
    699                                                 const param_type& p) {
    700   DCHECK_NE(0u, p.render_pass_list.size());
    701 
    702   size_t to_reserve = p.resource_list.size() * sizeof(cc::TransferableResource);
    703   for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
    704     const cc::RenderPass* pass = p.render_pass_list[i];
    705     to_reserve += ReserveSizeForRenderPassWrite(*pass);
    706   }
    707   m->Reserve(to_reserve);
    708 
    709   WriteParam(m, p.resource_list);
    710   WriteParam(m, p.render_pass_list.size());
    711   for (size_t i = 0; i < p.render_pass_list.size(); ++i)
    712     WriteParam(m, *p.render_pass_list[i]);
    713 }
    714 
    715 bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
    716                                                PickleIterator* iter,
    717                                                param_type* p) {
    718   const static size_t kMaxRenderPasses = 10000;
    719 
    720   size_t num_render_passes;
    721   if (!ReadParam(m, iter, &p->resource_list) ||
    722       !ReadParam(m, iter, &num_render_passes) ||
    723       num_render_passes > kMaxRenderPasses || num_render_passes == 0)
    724     return false;
    725   for (size_t i = 0; i < num_render_passes; ++i) {
    726     scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
    727     if (!ReadParam(m, iter, render_pass.get()))
    728       return false;
    729     p->render_pass_list.push_back(render_pass.Pass());
    730   }
    731   return true;
    732 }
    733 
    734 void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p,
    735                                               std::string* l) {
    736   l->append("DelegatedFrameData(");
    737   LogParam(p.resource_list, l);
    738   l->append(", [");
    739   for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
    740     if (i)
    741       l->append(", ");
    742     LogParam(*p.render_pass_list[i], l);
    743   }
    744   l->append("])");
    745 }
    746 
    747 }  // namespace IPC
    748