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