picture.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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
3// found in the LICENSE file.
4
5#include "base/debug/trace_event.h"
6#include "cc/debug/rendering_stats.h"
7#include "cc/layers/content_layer_client.h"
8#include "cc/resources/picture.h"
9#include "skia/ext/analysis_canvas.h"
10#include "third_party/skia/include/core/SkCanvas.h"
11#include "third_party/skia/include/core/SkData.h"
12#include "third_party/skia/include/core/SkDrawFilter.h"
13#include "third_party/skia/include/core/SkPaint.h"
14#include "third_party/skia/include/utils/SkPictureUtils.h"
15#include "ui/gfx/rect_conversions.h"
16#include "ui/gfx/skia_util.h"
17
18namespace {
19// URI label for a lazily decoded SkPixelRef.
20const char kLabelLazyDecoded[] = "lazy";
21
22class DisableLCDTextFilter : public SkDrawFilter {
23 public:
24  // SkDrawFilter interface.
25  virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) {
26    if (type != SkDrawFilter::kText_Type)
27      return true;
28
29    paint->setLCDRenderText(false);
30    return true;
31  }
32};
33
34}
35
36namespace cc {
37
38scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) {
39  return make_scoped_refptr(new Picture(layer_rect));
40}
41
42Picture::Picture(gfx::Rect layer_rect)
43    : layer_rect_(layer_rect) {
44}
45
46Picture::Picture(const skia::RefPtr<SkPicture>& picture,
47                 gfx::Rect layer_rect,
48                 gfx::Rect opaque_rect) :
49    layer_rect_(layer_rect),
50    opaque_rect_(opaque_rect),
51    picture_(picture) {
52}
53
54Picture::~Picture() {
55}
56
57scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread(
58    unsigned thread_index) const {
59  // SkPicture is not thread-safe to rasterize with, this returns a clone
60  // to rasterize with on a specific thread.
61  CHECK_GT(clones_.size(), thread_index);
62  return clones_[thread_index];
63}
64
65void Picture::CloneForDrawing(int num_threads) {
66  TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads);
67
68  DCHECK(picture_);
69  scoped_array<SkPicture> clones(new SkPicture[num_threads]);
70  picture_->clone(&clones[0], num_threads);
71
72  clones_.clear();
73  for (int i = 0; i < num_threads; i++) {
74    scoped_refptr<Picture> clone = make_scoped_refptr(
75        new Picture(skia::AdoptRef(new SkPicture(clones[i])),
76                    layer_rect_,
77                    opaque_rect_));
78    clones_.push_back(clone);
79  }
80}
81
82void Picture::Record(ContentLayerClient* painter,
83                     RenderingStats* stats,
84                     const SkTileGridPicture::TileGridInfo& tile_grid_info) {
85  TRACE_EVENT2("cc", "Picture::Record",
86               "width", layer_rect_.width(), "height", layer_rect_.height());
87
88  // Record() should only be called once.
89  DCHECK(!picture_);
90  DCHECK(!tile_grid_info.fTileInterval.isEmpty());
91  picture_ = skia::AdoptRef(new SkTileGridPicture(
92      layer_rect_.width(), layer_rect_.height(), tile_grid_info));
93
94  SkCanvas* canvas = picture_->beginRecording(
95      layer_rect_.width(),
96      layer_rect_.height(),
97      SkPicture::kUsePathBoundsForClip_RecordingFlag |
98      SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
99
100  canvas->save();
101  canvas->translate(SkFloatToScalar(-layer_rect_.x()),
102                    SkFloatToScalar(-layer_rect_.y()));
103
104  SkPaint paint;
105  paint.setAntiAlias(false);
106  paint.setXfermodeMode(SkXfermode::kClear_Mode);
107  SkRect layer_skrect = SkRect::MakeXYWH(layer_rect_.x(),
108                                         layer_rect_.y(),
109                                         layer_rect_.width(),
110                                         layer_rect_.height());
111  canvas->clipRect(layer_skrect);
112  canvas->drawRect(layer_skrect, paint);
113
114  gfx::RectF opaque_layer_rect;
115  base::TimeTicks begin_paint_time;
116  if (stats)
117    begin_paint_time = base::TimeTicks::Now();
118  painter->PaintContents(canvas, layer_rect_, &opaque_layer_rect);
119  if (stats) {
120    stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time;
121    stats->total_pixels_painted +=
122        layer_rect_.width() * layer_rect_.height();
123  }
124
125  canvas->restore();
126  picture_->endRecording();
127
128  opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect);
129}
130
131void Picture::Raster(
132    SkCanvas* canvas,
133    gfx::Rect content_rect,
134    float contents_scale,
135    bool enable_lcd_text) {
136  TRACE_EVENT2("cc", "Picture::Raster",
137               "layer width", layer_rect_.width(),
138               "layer height", layer_rect_.height());
139  DCHECK(picture_);
140
141  DisableLCDTextFilter disable_lcd_text_filter;
142
143  canvas->save();
144  canvas->clipRect(gfx::RectToSkRect(content_rect));
145  canvas->scale(contents_scale, contents_scale);
146  canvas->translate(layer_rect_.x(), layer_rect_.y());
147  // Pictures by default have LCD text enabled.
148  if (!enable_lcd_text)
149    canvas->setDrawFilter(&disable_lcd_text_filter);
150  canvas->drawPicture(*picture_);
151  canvas->restore();
152}
153
154void Picture::GatherPixelRefs(const gfx::Rect& layer_rect,
155                              std::list<skia::LazyPixelRef*>& pixel_ref_list) {
156  DCHECK(picture_);
157  SkData* pixel_refs = SkPictureUtils::GatherPixelRefs(
158      picture_.get(), SkRect::MakeXYWH(layer_rect.x(),
159                                       layer_rect.y(),
160                                       layer_rect.width(),
161                                       layer_rect.height()));
162  if (!pixel_refs)
163    return;
164
165  void* data = const_cast<void*>(pixel_refs->data());
166  if (!data) {
167    pixel_refs->unref();
168    return;
169  }
170
171  SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data);
172  for (unsigned int i = 0; i < pixel_refs->size() / sizeof(SkPixelRef*); ++i) {
173    if (*refs && (*refs)->getURI() && !strncmp(
174        (*refs)->getURI(), kLabelLazyDecoded, 4)) {
175      pixel_ref_list.push_back(static_cast<skia::LazyPixelRef*>(*refs));
176    }
177    refs++;
178  }
179  pixel_refs->unref();
180}
181
182}  // namespace cc
183