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