| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/overdraw_metrics.h" | 5 #include "cc/overdraw_metrics.h" |
| 6 | 6 |
| 7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "cc/layer_tree_host.h" | 9 #include "cc/layer_tree_host.h" |
| 10 #include "cc/layer_tree_host_impl.h" | 10 #include "cc/layer_tree_host_impl.h" |
| 11 #include "cc/math_util.h" | 11 #include "cc/math_util.h" |
| 12 #include "ui/gfx/quad_f.h" | 12 #include "ui/gfx/quad_f.h" |
| 13 #include "ui/gfx/rect.h" | 13 #include "ui/gfx/rect.h" |
| 14 #include "ui/gfx/transform.h" | 14 #include "ui/gfx/transform.h" |
| 15 | 15 |
| 16 namespace cc { | 16 namespace cc { |
| 17 | 17 |
| 18 OverdrawMetrics::OverdrawMetrics(bool recordMetricsForFrame) | 18 OverdrawMetrics::OverdrawMetrics(bool record_metrics_for_frame) |
| 19 : m_recordMetricsForFrame(recordMetricsForFrame) | 19 : record_metrics_for_frame_(record_metrics_for_frame), |
| 20 , m_pixelsPainted(0) | 20 pixels_painted_(0), |
| 21 , m_pixelsUploadedOpaque(0) | 21 pixels_uploaded_opaque_(0), |
| 22 , m_pixelsUploadedTranslucent(0) | 22 pixels_uploaded_translucent_(0), |
| 23 , m_tilesCulledForUpload(0) | 23 tiles_culled_for_upload_(0), |
| 24 , m_contentsTextureUseBytes(0) | 24 contents_texture_use_bytes_(0), |
| 25 , m_renderSurfaceTextureUseBytes(0) | 25 render_surface_texture_use_bytes_(0), |
| 26 , m_pixelsDrawnOpaque(0) | 26 pixels_drawn_opaque_(0), |
| 27 , m_pixelsDrawnTranslucent(0) | 27 pixels_drawn_translucent_(0), |
| 28 , m_pixelsCulledForDrawing(0) | 28 pixels_culled_for_drawing_(0) {} |
| 29 { | 29 |
| 30 } | 30 static inline float WedgeProduct(gfx::PointF p1, gfx::PointF p2) { |
| 31 | 31 return p1.x() * p2.y() - p1.y() * p2.x(); |
| 32 static inline float wedgeProduct(const gfx::PointF& p1, const gfx::PointF& p2) | |
| 33 { | |
| 34 return p1.x() * p2.y() - p1.y() * p2.x(); | |
| 35 } | 32 } |
| 36 | 33 |
| 37 // Calculates area of an arbitrary convex polygon with up to 8 points. | 34 // Calculates area of an arbitrary convex polygon with up to 8 points. |
| 38 static inline float polygonArea(const gfx::PointF points[8], int numPoints) | 35 static inline float PolygonArea(gfx::PointF points[8], int num_points) { |
| 39 { | 36 if (num_points < 3) |
| 40 if (numPoints < 3) | 37 return 0; |
| 41 return 0; | 38 |
| 42 | 39 float area = 0; |
| 43 float area = 0; | 40 for (int i = 0; i < num_points; ++i) |
| 44 for (int i = 0; i < numPoints; ++i) | 41 area += WedgeProduct(points[i], points[(i+1)%num_points]); |
| 45 area += wedgeProduct(points[i], points[(i+1)%numPoints]); | 42 return fabs(0.5f * area); |
| 46 return fabs(0.5f * area); | 43 } |
| 47 } | 44 |
| 48 | 45 // Takes a given quad, maps it by the given transformation, and gives the area |
| 49 // Takes a given quad, maps it by the given transformation, and gives the area o
f the resulting polygon. | 46 // of the resulting polygon. |
| 50 static inline float areaOfMappedQuad(const gfx::Transform& transform, const gfx:
:QuadF& quad) | 47 static inline float AreaOfMappedQuad(const gfx::Transform& transform, |
| 51 { | 48 const gfx::QuadF& quad) { |
| 52 gfx::PointF clippedQuad[8]; | 49 gfx::PointF clippedQuad[8]; |
| 53 int numVerticesInClippedQuad = 0; | 50 int num_vertices_in_clipped_quad = 0; |
| 54 MathUtil::mapClippedQuad(transform, quad, clippedQuad, numVerticesInClippedQ
uad); | 51 MathUtil::mapClippedQuad(transform, |
| 55 return polygonArea(clippedQuad, numVerticesInClippedQuad); | 52 quad, |
| 56 } | 53 clippedQuad, |
| 57 | 54 num_vertices_in_clipped_quad); |
| 58 void OverdrawMetrics::didPaint(const gfx::Rect& paintedRect) | 55 return PolygonArea(clippedQuad, num_vertices_in_clipped_quad); |
| 59 { | 56 } |
| 60 if (!m_recordMetricsForFrame) | 57 |
| 61 return; | 58 void OverdrawMetrics::DidPaint(gfx::Rect painted_rect) { |
| 62 | 59 if (!record_metrics_for_frame_) |
| 63 m_pixelsPainted += static_cast<float>(paintedRect.width()) * paintedRect.hei
ght(); | 60 return; |
| 64 } | 61 |
| 65 | 62 pixels_painted_ += |
| 66 void OverdrawMetrics::didCullTilesForUpload(int count) | 63 static_cast<float>(painted_rect.width()) * painted_rect.height(); |
| 67 { | 64 } |
| 68 if (m_recordMetricsForFrame) | 65 |
| 69 m_tilesCulledForUpload += count; | 66 void OverdrawMetrics::DidCullTilesForUpload(int count) { |
| 70 } | 67 if (record_metrics_for_frame_) |
| 71 | 68 tiles_culled_for_upload_ += count; |
| 72 void OverdrawMetrics::didUpload(const gfx::Transform& transformToTarget, const g
fx::Rect& uploadRect, const gfx::Rect& opaqueRect) | 69 } |
| 73 { | 70 |
| 74 if (!m_recordMetricsForFrame) | 71 void OverdrawMetrics::DidUpload(const gfx::Transform& transform_to_target, |
| 75 return; | 72 gfx::Rect upload_rect, |
| 76 | 73 gfx::Rect opaque_rect) { |
| 77 float uploadArea = areaOfMappedQuad(transformToTarget, gfx::QuadF(uploadRect
)); | 74 if (!record_metrics_for_frame_) |
| 78 float uploadOpaqueArea = areaOfMappedQuad(transformToTarget, gfx::QuadF(gfx:
:IntersectRects(opaqueRect, uploadRect))); | 75 return; |
| 79 | 76 |
| 80 m_pixelsUploadedOpaque += uploadOpaqueArea; | 77 float upload_area = |
| 81 m_pixelsUploadedTranslucent += uploadArea - uploadOpaqueArea; | 78 AreaOfMappedQuad(transform_to_target, gfx::QuadF(upload_rect)); |
| 82 } | 79 float upload_opaque_area = |
| 83 | 80 AreaOfMappedQuad(transform_to_target, |
| 84 void OverdrawMetrics::didUseContentsTextureMemoryBytes(size_t contentsTextureUse
Bytes) | 81 gfx::QuadF(gfx::IntersectRects(opaque_rect, |
| 85 { | 82 upload_rect))); |
| 86 if (!m_recordMetricsForFrame) | 83 |
| 87 return; | 84 pixels_uploaded_opaque_ += upload_opaque_area; |
| 88 | 85 pixels_uploaded_translucent_ += upload_area - upload_opaque_area; |
| 89 m_contentsTextureUseBytes += contentsTextureUseBytes; | 86 } |
| 90 } | 87 |
| 91 | 88 void OverdrawMetrics::DidUseContentsTextureMemoryBytes( |
| 92 void OverdrawMetrics::didUseRenderSurfaceTextureMemoryBytes(size_t renderSurface
UseBytes) | 89 size_t contents_texture_use_bytes) { |
| 93 { | 90 if (!record_metrics_for_frame_) |
| 94 if (!m_recordMetricsForFrame) | 91 return; |
| 95 return; | 92 |
| 96 | 93 contents_texture_use_bytes_ += contents_texture_use_bytes; |
| 97 m_renderSurfaceTextureUseBytes += renderSurfaceUseBytes; | 94 } |
| 98 } | 95 |
| 99 | 96 void OverdrawMetrics::DidUseRenderSurfaceTextureMemoryBytes( |
| 100 void OverdrawMetrics::didCullForDrawing(const gfx::Transform& transformToTarget,
const gfx::Rect& beforeCullRect, const gfx::Rect& afterCullRect) | 97 size_t render_surface_use_bytes) { |
| 101 { | 98 if (!record_metrics_for_frame_) |
| 102 if (!m_recordMetricsForFrame) | 99 return; |
| 103 return; | 100 |
| 104 | 101 render_surface_texture_use_bytes_ += render_surface_use_bytes; |
| 105 float beforeCullArea = areaOfMappedQuad(transformToTarget, gfx::QuadF(before
CullRect)); | 102 } |
| 106 float afterCullArea = areaOfMappedQuad(transformToTarget, gfx::QuadF(afterCu
llRect)); | 103 |
| 107 | 104 void OverdrawMetrics::DidCullForDrawing( |
| 108 m_pixelsCulledForDrawing += beforeCullArea - afterCullArea; | 105 const gfx::Transform& transform_to_target, |
| 109 } | 106 gfx::Rect before_cull_rect, |
| 110 | 107 gfx::Rect after_cull_rect) { |
| 111 void OverdrawMetrics::didDraw(const gfx::Transform& transformToTarget, const gfx
::Rect& afterCullRect, const gfx::Rect& opaqueRect) | 108 if (!record_metrics_for_frame_) |
| 112 { | 109 return; |
| 113 if (!m_recordMetricsForFrame) | 110 |
| 114 return; | 111 float before_cull_area = |
| 115 | 112 AreaOfMappedQuad(transform_to_target, gfx::QuadF(before_cull_rect)); |
| 116 float afterCullArea = areaOfMappedQuad(transformToTarget, gfx::QuadF(afterCu
llRect)); | 113 float after_cull_area = |
| 117 float afterCullOpaqueArea = areaOfMappedQuad(transformToTarget, gfx::QuadF(g
fx::IntersectRects(opaqueRect, afterCullRect))); | 114 AreaOfMappedQuad(transform_to_target, gfx::QuadF(after_cull_rect)); |
| 118 | 115 |
| 119 m_pixelsDrawnOpaque += afterCullOpaqueArea; | 116 pixels_culled_for_drawing_ += before_cull_area - after_cull_area; |
| 120 m_pixelsDrawnTranslucent += afterCullArea - afterCullOpaqueArea; | 117 } |
| 121 } | 118 |
| 122 | 119 void OverdrawMetrics::DidDraw(const gfx::Transform& transform_to_target, |
| 123 void OverdrawMetrics::recordMetrics(const LayerTreeHost* layerTreeHost) const | 120 gfx::Rect after_cull_rect, |
| 124 { | 121 gfx::Rect opaque_rect) { |
| 125 if (m_recordMetricsForFrame) | 122 if (!record_metrics_for_frame_) |
| 126 recordMetricsInternal<LayerTreeHost>(UpdateAndCommit, layerTreeHost); | 123 return; |
| 127 } | 124 |
| 128 | 125 float after_cull_area = |
| 129 void OverdrawMetrics::recordMetrics(const LayerTreeHostImpl* layerTreeHost) cons
t | 126 AreaOfMappedQuad(transform_to_target, gfx::QuadF(after_cull_rect)); |
| 130 { | 127 float after_cull_opaque_area = |
| 131 if (m_recordMetricsForFrame) | 128 AreaOfMappedQuad(transform_to_target, |
| 132 recordMetricsInternal<LayerTreeHostImpl>(DrawingToScreen, layerTreeHost)
; | 129 gfx::QuadF(gfx::IntersectRects(opaque_rect, |
| 133 } | 130 after_cull_rect))); |
| 134 | 131 |
| 135 static gfx::Size DeviceViewportSize(const LayerTreeHost* host) { return host->de
viceViewportSize(); } | 132 pixels_drawn_opaque_ += after_cull_opaque_area; |
| 136 static gfx::Size DeviceViewportSize(const LayerTreeHostImpl* host_impl) { return
host_impl->DeviceViewportSize(); } | 133 pixels_drawn_translucent_ += after_cull_area - after_cull_opaque_area; |
| 137 | 134 } |
| 138 template<typename LayerTreeHostType> | 135 |
| 139 void OverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const Layer
TreeHostType* layerTreeHost) const | 136 void OverdrawMetrics::RecordMetrics( |
| 140 { | 137 const LayerTreeHost* layer_tree_host) const { |
| 141 // This gives approximately 10x the percentage of pixels to fill the viewpor
t once. | 138 if (record_metrics_for_frame_) |
| 142 float normalization = 1000.f / (DeviceViewportSize(layerTreeHost).width() *
DeviceViewportSize(layerTreeHost).height()); | 139 RecordMetricsInternal<LayerTreeHost>(UpdateAndCommit, layer_tree_host); |
| 143 // This gives approximately 100x the percentage of tiles to fill the viewpor
t once, if all tiles were 256x256. | 140 } |
| 144 float tileNormalization = 10000.f / (DeviceViewportSize(layerTreeHost).width
() / 256.f * DeviceViewportSize(layerTreeHost).height() / 256.f); | 141 |
| 145 // This gives approximately 10x the percentage of bytes to fill the viewport
once, assuming 4 bytes per pixel. | 142 void OverdrawMetrics::RecordMetrics( |
| 146 float byteNormalization = normalization / 4; | 143 const LayerTreeHostImpl* layer_tree_host_impl) const { |
| 147 | 144 if (record_metrics_for_frame_) { |
| 148 switch (metricsType) { | 145 RecordMetricsInternal<LayerTreeHostImpl>(DrawingToScreen, |
| 146 layer_tree_host_impl); |
| 147 } |
| 148 } |
| 149 |
| 150 static gfx::Size DeviceViewportSize(const LayerTreeHost* host) { |
| 151 return host->deviceViewportSize(); |
| 152 } |
| 153 static gfx::Size DeviceViewportSize(const LayerTreeHostImpl* host_impl) { |
| 154 return host_impl->DeviceViewportSize(); |
| 155 } |
| 156 |
| 157 template <typename LayerTreeHostType> |
| 158 void OverdrawMetrics::RecordMetricsInternal( |
| 159 MetricsType metrics_type, |
| 160 const LayerTreeHostType* layer_tree_host) const { |
| 161 // This gives approximately 10x the percentage of pixels to fill the viewport |
| 162 // once. |
| 163 float normalization = 1000.f / (DeviceViewportSize(layer_tree_host).width() * |
| 164 DeviceViewportSize(layer_tree_host).height()); |
| 165 // This gives approximately 100x the percentage of tiles to fill the viewport |
| 166 // once, if all tiles were 256x256. |
| 167 float tile_normalization = |
| 168 10000.f / (DeviceViewportSize(layer_tree_host).width() / 256.f * |
| 169 DeviceViewportSize(layer_tree_host).height() / 256.f); |
| 170 // This gives approximately 10x the percentage of bytes to fill the viewport |
| 171 // once, assuming 4 bytes per pixel. |
| 172 float byte_normalization = normalization / 4; |
| 173 |
| 174 switch (metrics_type) { |
| 149 case DrawingToScreen: { | 175 case DrawingToScreen: { |
| 150 UMA_HISTOGRAM_CUSTOM_COUNTS( | 176 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 151 "Renderer4.pixelCountOpaque_Draw", | 177 "Renderer4.pixelCountOpaque_Draw", |
| 152 static_cast<int>(normalization * m_pixelsDrawnOpaque), | 178 static_cast<int>(normalization * pixels_drawn_opaque_), |
| 153 100, 1000000, 50); | 179 100, 1000000, 50); |
| 154 UMA_HISTOGRAM_CUSTOM_COUNTS( | 180 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 155 "Renderer4.pixelCountTranslucent_Draw", | 181 "Renderer4.pixelCountTranslucent_Draw", |
| 156 static_cast<int>(normalization * m_pixelsDrawnTranslucent), | 182 static_cast<int>(normalization * pixels_drawn_translucent_), |
| 157 100, 1000000, 50); | 183 100, 1000000, 50); |
| 158 UMA_HISTOGRAM_CUSTOM_COUNTS( | 184 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 159 "Renderer4.pixelCountCulled_Draw", | 185 "Renderer4.pixelCountCulled_Draw", |
| 160 static_cast<int>(normalization * m_pixelsCulledForDrawing), | 186 static_cast<int>(normalization * pixels_culled_for_drawing_), |
| 161 100, 1000000, 50); | 187 100, 1000000, 50); |
| 162 | 188 |
| 163 TRACE_COUNTER_ID1("cc", "DrawPixelsCulled", layerTreeHost, m_pixelsCulle
dForDrawing); | 189 TRACE_COUNTER_ID1("cc", |
| 164 TRACE_EVENT2("cc", "OverdrawMetrics", "PixelsDrawnOpaque", m_pixelsDrawn
Opaque, "PixelsDrawnTranslucent", m_pixelsDrawnTranslucent); | 190 "DrawPixelsCulled", |
| 165 break; | 191 layer_tree_host, |
| 192 pixels_culled_for_drawing_); |
| 193 TRACE_EVENT2("cc", |
| 194 "OverdrawMetrics", |
| 195 "PixelsDrawnOpaque", |
| 196 pixels_drawn_opaque_, |
| 197 "PixelsDrawnTranslucent", |
| 198 pixels_drawn_translucent_); |
| 199 break; |
| 166 } | 200 } |
| 167 case UpdateAndCommit: { | 201 case UpdateAndCommit: { |
| 168 UMA_HISTOGRAM_CUSTOM_COUNTS( | 202 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 169 "Renderer4.pixelCountPainted", | 203 "Renderer4.pixelCountPainted", |
| 170 static_cast<int>(normalization * m_pixelsPainted), | 204 static_cast<int>(normalization * pixels_painted_), |
| 171 100, 1000000, 50); | 205 100, 1000000, 50); |
| 172 UMA_HISTOGRAM_CUSTOM_COUNTS( | 206 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 173 "Renderer4.pixelCountOpaque_Upload", | 207 "Renderer4.pixelCountOpaque_Upload", |
| 174 static_cast<int>(normalization * m_pixelsUploadedOpaque), | 208 static_cast<int>(normalization * pixels_uploaded_opaque_), |
| 175 100, 1000000, 50); | 209 100, 1000000, 50); |
| 176 UMA_HISTOGRAM_CUSTOM_COUNTS( | 210 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 177 "Renderer4.pixelCountTranslucent_Upload", | 211 "Renderer4.pixelCountTranslucent_Upload", |
| 178 static_cast<int>(normalization * m_pixelsUploadedTranslucent), | 212 static_cast<int>(normalization * pixels_uploaded_translucent_), |
| 179 100, 1000000, 50); | 213 100, 1000000, 50); |
| 180 UMA_HISTOGRAM_CUSTOM_COUNTS( | 214 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 181 "Renderer4.tileCountCulled_Upload", | 215 "Renderer4.tileCountCulled_Upload", |
| 182 static_cast<int>(tileNormalization * m_tilesCulledForUpload), | 216 static_cast<int>(tile_normalization * tiles_culled_for_upload_), |
| 183 100, 10000000, 50); | 217 100, 10000000, 50); |
| 184 UMA_HISTOGRAM_CUSTOM_COUNTS( | 218 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 185 "Renderer4.renderSurfaceTextureBytes_ViewportScaled", | 219 "Renderer4.renderSurfaceTextureBytes_ViewportScaled", |
| 186 static_cast<int>( | 220 static_cast<int>( |
| 187 byteNormalization * m_renderSurfaceTextureUseBytes), | 221 byte_normalization * render_surface_texture_use_bytes_), |
| 188 10, 1000000, 50); | 222 10, 1000000, 50); |
| 189 UMA_HISTOGRAM_CUSTOM_COUNTS( | 223 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 190 "Renderer4.renderSurfaceTextureBytes_Unscaled", | 224 "Renderer4.renderSurfaceTextureBytes_Unscaled", |
| 191 static_cast<int>(m_renderSurfaceTextureUseBytes / 1000), | 225 static_cast<int>(render_surface_texture_use_bytes_ / 1000), |
| 192 1000, 100000000, 50); | 226 1000, 100000000, 50); |
| 193 UMA_HISTOGRAM_CUSTOM_COUNTS( | 227 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 194 "Renderer4.contentsTextureBytes_ViewportScaled", | 228 "Renderer4.contentsTextureBytes_ViewportScaled", |
| 195 static_cast<int>(byteNormalization * m_contentsTextureUseBytes), | 229 static_cast<int>(byte_normalization * contents_texture_use_bytes_), |
| 196 10, 1000000, 50); | 230 10, 1000000, 50); |
| 197 UMA_HISTOGRAM_CUSTOM_COUNTS( | 231 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 198 "Renderer4.contentsTextureBytes_Unscaled", | 232 "Renderer4.contentsTextureBytes_Unscaled", |
| 199 static_cast<int>(m_contentsTextureUseBytes / 1000), | 233 static_cast<int>(contents_texture_use_bytes_ / 1000), |
| 200 1000, 100000000, 50); | 234 1000, 100000000, 50); { |
| 201 | 235 TRACE_COUNTER_ID1("cc", |
| 202 { | 236 "UploadTilesCulled", |
| 203 TRACE_COUNTER_ID1("cc", "UploadTilesCulled", layerTreeHost, m_tilesC
ulledForUpload); | 237 layer_tree_host, |
| 204 TRACE_EVENT2("cc", "OverdrawMetrics", "PixelsUploadedOpaque", m_pixe
lsUploadedOpaque, "PixelsUploadedTranslucent", m_pixelsUploadedTranslucent); | 238 tiles_culled_for_upload_); |
| 205 } | 239 TRACE_EVENT2("cc", |
| 206 { | 240 "OverdrawMetrics", |
| 207 // This must be in a different scope than the TRACE_EVENT2 above. | 241 "PixelsUploadedOpaque", |
| 208 TRACE_EVENT1("cc", "OverdrawPaintMetrics", "PixelsPainted", m_pixels
Painted); | 242 pixels_uploaded_opaque_, |
| 209 } | 243 "PixelsUploadedTranslucent", |
| 210 { | 244 pixels_uploaded_translucent_); |
| 211 // This must be in a different scope than the TRACE_EVENTs above. | 245 } |
| 212 TRACE_EVENT2("cc", "OverdrawPaintMetrics", "ContentsTextureBytes", m
_contentsTextureUseBytes, "RenderSurfaceTextureBytes", m_renderSurfaceTextureUse
Bytes); | 246 { |
| 213 } | 247 // This must be in a different scope than the TRACE_EVENT2 above. |
| 214 break; | 248 TRACE_EVENT1("cc", |
| 249 "OverdrawPaintMetrics", |
| 250 "PixelsPainted", |
| 251 pixels_painted_); |
| 252 } |
| 253 { |
| 254 // This must be in a different scope than the TRACE_EVENTs above. |
| 255 TRACE_EVENT2("cc", |
| 256 "OverdrawPaintMetrics", |
| 257 "ContentsTextureBytes", |
| 258 contents_texture_use_bytes_, |
| 259 "RenderSurfaceTextureBytes", |
| 260 render_surface_texture_use_bytes_); |
| 261 } |
| 262 break; |
| 215 } | 263 } |
| 216 } | 264 } |
| 217 } | 265 } |
| 218 | 266 |
| 219 } // namespace cc | 267 } // namespace cc |
| OLD | NEW |