12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2011 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/content_layer_updater.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h"
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/debug/rendering_stats_instrumentation.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/layer_painter.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkPaint.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkRect.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkScalar.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_f.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/gfx/skia_util.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ContentLayerUpdater::ContentLayerUpdater(
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<LayerPainter> painter,
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RenderingStatsInstrumentation* stats_instrumentation,
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int layer_id)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : rendering_stats_instrumentation_(stats_instrumentation),
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      layer_id_(layer_id),
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      layer_is_opaque_(false),
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      layer_fills_bounds_completely_(false),
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      painter_(painter.Pass()),
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      background_color_(SK_ColorTRANSPARENT) {
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ContentLayerUpdater::~ContentLayerUpdater() {}
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ContentLayerUpdater::set_rendering_stats_instrumentation(
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RenderingStatsInstrumentation* rsi) {
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rendering_stats_instrumentation_ = rsi;
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ContentLayerUpdater::PaintContents(SkCanvas* canvas,
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        const gfx::Size& layer_content_size,
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        const gfx::Rect& paint_rect,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        float contents_width_scale,
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        float contents_height_scale) {
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TRACE_EVENT0("cc", "ContentLayerUpdater::PaintContents");
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!canvas)
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->save();
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  canvas->translate(SkIntToScalar(-paint_rect.x()),
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    SkIntToScalar(-paint_rect.y()));
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The |canvas| backing should be sized to hold the |paint_rect|.
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width());
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height());
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const bool is_scaled =
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      contents_width_scale != 1.f || contents_height_scale != 1.f;
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (is_scaled && (layer_is_opaque_ || layer_fills_bounds_completely_)) {
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Even if completely covered, for rasterizations that touch the edge of the
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // layer, we also need to raster the background color underneath the last
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // texel (since the paint won't cover it).
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // The final texel of content may only be partially covered by a
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // rasterization; this rect represents the content rect that is fully
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // covered by content.
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const gfx::Rect layer_content_rect = gfx::Rect(layer_content_size);
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Rect deflated_layer_content_rect = layer_content_rect;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    deflated_layer_content_rect.Inset(0, 0, 1, 1);
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!layer_content_rect.Contains(deflated_layer_content_rect)) {
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Drawing at most 1 x 1 x (canvas width + canvas height) texels is 2-3X
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // faster than clearing, so special case this.
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DCHECK_LE(paint_rect.right(), layer_content_rect.right());
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DCHECK_LE(paint_rect.bottom(), layer_content_rect.bottom());
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      canvas->save();
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      canvas->clipRect(gfx::RectToSkRect(layer_content_rect),
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       SkRegion::kReplace_Op);
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      canvas->clipRect(gfx::RectToSkRect(deflated_layer_content_rect),
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       SkRegion::kDifference_Op);
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      canvas->drawColor(background_color_, SkXfermode::kSrc_Mode);
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      canvas->restore();
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect layer_rect;
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (is_scaled) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->scale(SkFloatToScalar(contents_width_scale),
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  SkFloatToScalar(contents_height_scale));
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // NOTE: this may go beyond the bounds of the layer, but that shouldn't
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // cause problems (anything beyond the layer is clipped out).
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    layer_rect = gfx::ScaleToEnclosingRect(
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        paint_rect, 1.f / contents_width_scale, 1.f / contents_height_scale);
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    layer_rect = paint_rect;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect layer_sk_rect = SkRect::MakeXYWH(
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      layer_rect.x(), layer_rect.y(), layer_rect.width(), layer_rect.height());
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  canvas->clipRect(layer_sk_rect);
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // If the layer has opaque contents or will fill the bounds completely there
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // is no need to clear the canvas before painting.
106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!layer_is_opaque_ && !layer_fills_bounds_completely_) {
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TRACE_EVENT0("cc", "Clear");
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode);
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  painter_->Paint(canvas, layer_rect);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->restore();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  paint_rect_ = paint_rect;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void ContentLayerUpdater::SetOpaque(bool opaque) {
118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  layer_is_opaque_ = opaque;
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds) {
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  layer_fills_bounds_completely_ = fills_bounds;
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ContentLayerUpdater::SetBackgroundColor(SkColor background_color) {
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  background_color_ = background_color;
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
130