1 // Copyright 2011 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 "cc/resources/content_layer_updater.h" 6 7 #include "base/debug/trace_event.h" 8 #include "base/time/time.h" 9 #include "cc/debug/rendering_stats_instrumentation.h" 10 #include "cc/resources/layer_painter.h" 11 #include "third_party/skia/include/core/SkCanvas.h" 12 #include "third_party/skia/include/core/SkPaint.h" 13 #include "third_party/skia/include/core/SkRect.h" 14 #include "third_party/skia/include/core/SkScalar.h" 15 #include "ui/gfx/rect_conversions.h" 16 #include "ui/gfx/rect_f.h" 17 #include "ui/gfx/skia_util.h" 18 19 namespace cc { 20 21 ContentLayerUpdater::ContentLayerUpdater( 22 scoped_ptr<LayerPainter> painter, 23 RenderingStatsInstrumentation* stats_instrumentation, 24 int layer_id) 25 : rendering_stats_instrumentation_(stats_instrumentation), 26 layer_id_(layer_id), 27 layer_is_opaque_(false), 28 layer_fills_bounds_completely_(false), 29 painter_(painter.Pass()), 30 background_color_(SK_ColorTRANSPARENT) { 31 } 32 33 ContentLayerUpdater::~ContentLayerUpdater() {} 34 35 void ContentLayerUpdater::set_rendering_stats_instrumentation( 36 RenderingStatsInstrumentation* rsi) { 37 rendering_stats_instrumentation_ = rsi; 38 } 39 40 void ContentLayerUpdater::PaintContents(SkCanvas* canvas, 41 const gfx::Size& layer_content_size, 42 const gfx::Rect& paint_rect, 43 float contents_width_scale, 44 float contents_height_scale) { 45 TRACE_EVENT0("cc", "ContentLayerUpdater::PaintContents"); 46 if (!canvas) 47 return; 48 canvas->save(); 49 canvas->translate(SkIntToScalar(-paint_rect.x()), 50 SkIntToScalar(-paint_rect.y())); 51 52 // The |canvas| backing should be sized to hold the |paint_rect|. 53 DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width()); 54 DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height()); 55 56 const bool is_scaled = 57 contents_width_scale != 1.f || contents_height_scale != 1.f; 58 59 if (is_scaled && (layer_is_opaque_ || layer_fills_bounds_completely_)) { 60 // Even if completely covered, for rasterizations that touch the edge of the 61 // layer, we also need to raster the background color underneath the last 62 // texel (since the paint won't cover it). 63 // 64 // The final texel of content may only be partially covered by a 65 // rasterization; this rect represents the content rect that is fully 66 // covered by content. 67 const gfx::Rect layer_content_rect = gfx::Rect(layer_content_size); 68 gfx::Rect deflated_layer_content_rect = layer_content_rect; 69 deflated_layer_content_rect.Inset(0, 0, 1, 1); 70 71 if (!layer_content_rect.Contains(deflated_layer_content_rect)) { 72 // Drawing at most 1 x 1 x (canvas width + canvas height) texels is 2-3X 73 // faster than clearing, so special case this. 74 DCHECK_LE(paint_rect.right(), layer_content_rect.right()); 75 DCHECK_LE(paint_rect.bottom(), layer_content_rect.bottom()); 76 canvas->save(); 77 canvas->clipRect(gfx::RectToSkRect(layer_content_rect), 78 SkRegion::kReplace_Op); 79 canvas->clipRect(gfx::RectToSkRect(deflated_layer_content_rect), 80 SkRegion::kDifference_Op); 81 canvas->drawColor(background_color_, SkXfermode::kSrc_Mode); 82 canvas->restore(); 83 } 84 } 85 86 gfx::Rect layer_rect; 87 if (is_scaled) { 88 canvas->scale(SkFloatToScalar(contents_width_scale), 89 SkFloatToScalar(contents_height_scale)); 90 91 // NOTE: this may go beyond the bounds of the layer, but that shouldn't 92 // cause problems (anything beyond the layer is clipped out). 93 layer_rect = gfx::ScaleToEnclosingRect( 94 paint_rect, 1.f / contents_width_scale, 1.f / contents_height_scale); 95 } else { 96 layer_rect = paint_rect; 97 } 98 99 SkRect layer_sk_rect = SkRect::MakeXYWH( 100 layer_rect.x(), layer_rect.y(), layer_rect.width(), layer_rect.height()); 101 102 canvas->clipRect(layer_sk_rect); 103 104 // If the layer has opaque contents or will fill the bounds completely there 105 // is no need to clear the canvas before painting. 106 if (!layer_is_opaque_ && !layer_fills_bounds_completely_) { 107 TRACE_EVENT0("cc", "Clear"); 108 canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode); 109 } 110 111 painter_->Paint(canvas, layer_rect); 112 canvas->restore(); 113 114 paint_rect_ = paint_rect; 115 } 116 117 void ContentLayerUpdater::SetOpaque(bool opaque) { 118 layer_is_opaque_ = opaque; 119 } 120 121 void ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds) { 122 layer_fills_bounds_completely_ = fills_bounds; 123 } 124 125 void ContentLayerUpdater::SetBackgroundColor(SkColor background_color) { 126 background_color_ = background_color; 127 } 128 129 } // namespace cc 130