render_surface_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/layers/render_surface_impl.h"
6
7#include <algorithm>
8
9#include "base/logging.h"
10#include "base/stringprintf.h"
11#include "cc/base/math_util.h"
12#include "cc/debug/debug_colors.h"
13#include "cc/layers/delegated_renderer_layer_impl.h"
14#include "cc/layers/layer_impl.h"
15#include "cc/layers/quad_sink.h"
16#include "cc/layers/render_pass_sink.h"
17#include "cc/quads/debug_border_draw_quad.h"
18#include "cc/quads/render_pass.h"
19#include "cc/quads/render_pass_draw_quad.h"
20#include "cc/quads/shared_quad_state.h"
21#include "cc/trees/damage_tracker.h"
22#include "third_party/skia/include/core/SkImageFilter.h"
23#include "ui/gfx/rect_conversions.h"
24#include "ui/gfx/transform.h"
25
26namespace cc {
27
28RenderSurfaceImpl::RenderSurfaceImpl(LayerImpl* owning_layer)
29    : owning_layer_(owning_layer),
30      surface_property_changed_(false),
31      draw_opacity_(1),
32      draw_opacity_is_animating_(false),
33      target_surface_transforms_are_animating_(false),
34      screen_space_transforms_are_animating_(false),
35      is_clipped_(false),
36      nearest_ancestor_that_moves_pixels_(NULL),
37      target_render_surface_layer_index_history_(0),
38      current_layer_index_history_(0) {
39  damage_tracker_ = DamageTracker::Create();
40}
41
42RenderSurfaceImpl::~RenderSurfaceImpl() {}
43
44gfx::RectF RenderSurfaceImpl::DrawableContentRect() const {
45  gfx::RectF drawable_content_rect =
46      MathUtil::MapClippedRect(draw_transform_, content_rect_);
47  if (owning_layer_->has_replica()) {
48    drawable_content_rect.Union(
49        MathUtil::MapClippedRect(replica_draw_transform_, content_rect_));
50  }
51
52  return drawable_content_rect;
53}
54
55std::string RenderSurfaceImpl::Name() const {
56  return base::StringPrintf("RenderSurfaceImpl(id=%i,owner=%s)",
57                            owning_layer_->id(),
58                            owning_layer_->debug_name().data());
59}
60
61static std::string IndentString(int indent) {
62  std::string str;
63  for (int i = 0; i != indent; ++i)
64    str.append("  ");
65  return str;
66}
67
68void RenderSurfaceImpl::DumpSurface(std::string* str, int indent) const {
69  std::string indent_str = IndentString(indent);
70  str->append(indent_str);
71  base::StringAppendF(str, "%s\n", Name().data());
72
73  indent_str.append("  ");
74  str->append(indent_str);
75  base::StringAppendF(str,
76                      "content_rect: (%d, %d, %d, %d)\n",
77                      content_rect_.x(),
78                      content_rect_.y(),
79                      content_rect_.width(),
80                      content_rect_.height());
81
82  str->append(indent_str);
83  base::StringAppendF(str,
84                      "draw_transform: "
85                      "%f, %f, %f, %f, "
86                      "%f, %f, %f, %f, "
87                      "%f, %f, %f, %f, "
88                      "%f, %f, %f, %f\n",
89                      draw_transform_.matrix().getDouble(0, 0),
90                      draw_transform_.matrix().getDouble(0, 1),
91                      draw_transform_.matrix().getDouble(0, 2),
92                      draw_transform_.matrix().getDouble(0, 3),
93                      draw_transform_.matrix().getDouble(1, 0),
94                      draw_transform_.matrix().getDouble(1, 1),
95                      draw_transform_.matrix().getDouble(1, 2),
96                      draw_transform_.matrix().getDouble(1, 3),
97                      draw_transform_.matrix().getDouble(2, 0),
98                      draw_transform_.matrix().getDouble(2, 1),
99                      draw_transform_.matrix().getDouble(2, 2),
100                      draw_transform_.matrix().getDouble(2, 3),
101                      draw_transform_.matrix().getDouble(3, 0),
102                      draw_transform_.matrix().getDouble(3, 1),
103                      draw_transform_.matrix().getDouble(3, 2),
104                      draw_transform_.matrix().getDouble(3, 3));
105
106  str->append(indent_str);
107  base::StringAppendF(str,
108                      "current_damage_rect is pos(%f, %f), size(%f, %f)\n",
109                      damage_tracker_->current_damage_rect().x(),
110                      damage_tracker_->current_damage_rect().y(),
111                      damage_tracker_->current_damage_rect().width(),
112                      damage_tracker_->current_damage_rect().height());
113}
114
115int RenderSurfaceImpl::OwningLayerId() const {
116  return owning_layer_ ? owning_layer_->id() : 0;
117}
118
119
120void RenderSurfaceImpl::SetClipRect(gfx::Rect clip_rect) {
121  if (clip_rect_ == clip_rect)
122    return;
123
124  surface_property_changed_ = true;
125  clip_rect_ = clip_rect;
126}
127
128bool RenderSurfaceImpl::ContentsChanged() const {
129  return !damage_tracker_->current_damage_rect().IsEmpty();
130}
131
132void RenderSurfaceImpl::SetContentRect(gfx::Rect content_rect) {
133  if (content_rect_ == content_rect)
134    return;
135
136  surface_property_changed_ = true;
137  content_rect_ = content_rect;
138}
139
140bool RenderSurfaceImpl::SurfacePropertyChanged() const {
141  // Surface property changes are tracked as follows:
142  //
143  // - surface_property_changed_ is flagged when the clip_rect or content_rect
144  //   change. As of now, these are the only two properties that can be affected
145  //   by descendant layers.
146  //
147  // - all other property changes come from the owning layer (or some ancestor
148  //   layer that propagates its change to the owning layer).
149  //
150  DCHECK(owning_layer_);
151  return surface_property_changed_ || owning_layer_->LayerPropertyChanged();
152}
153
154bool RenderSurfaceImpl::SurfacePropertyChangedOnlyFromDescendant() const {
155  return surface_property_changed_ && !owning_layer_->LayerPropertyChanged();
156}
157
158void RenderSurfaceImpl::AddContributingDelegatedRenderPassLayer(
159    LayerImpl* layer) {
160  DCHECK(std::find(layer_list_.begin(), layer_list_.end(), layer) !=
161         layer_list_.end());
162  DelegatedRendererLayerImpl* delegated_renderer_layer =
163      static_cast<DelegatedRendererLayerImpl*>(layer);
164  contributing_delegated_render_pass_layer_list_.push_back(
165      delegated_renderer_layer);
166}
167
168void RenderSurfaceImpl::ClearLayerLists() {
169  layer_list_.clear();
170  contributing_delegated_render_pass_layer_list_.clear();
171}
172
173RenderPass::Id RenderSurfaceImpl::RenderPassId() {
174  int layer_id = owning_layer_->id();
175  int sub_id = 0;
176  DCHECK_GT(layer_id, 0);
177  return RenderPass::Id(layer_id, sub_id);
178}
179
180void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) {
181  for (size_t i = 0;
182       i < contributing_delegated_render_pass_layer_list_.size();
183       ++i) {
184    DelegatedRendererLayerImpl* delegated_renderer_layer =
185        contributing_delegated_render_pass_layer_list_[i];
186    delegated_renderer_layer->AppendContributingRenderPasses(pass_sink);
187  }
188
189  scoped_ptr<RenderPass> pass = RenderPass::Create();
190  pass->SetNew(RenderPassId(),
191               content_rect_,
192               damage_tracker_->current_damage_rect(),
193               screen_space_transform_);
194  pass_sink->AppendRenderPass(pass.Pass());
195}
196
197void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink,
198                                    AppendQuadsData* append_quads_data,
199                                    bool for_replica,
200                                    RenderPass::Id render_pass_id) {
201  DCHECK(!for_replica || owning_layer_->has_replica());
202
203  const gfx::Transform& draw_transform =
204      for_replica ? replica_draw_transform_ : draw_transform_;
205  SharedQuadState* shared_quad_state =
206      quad_sink->UseSharedQuadState(SharedQuadState::Create());
207  shared_quad_state->SetAll(draw_transform,
208                            content_rect_.size(),
209                            content_rect_,
210                            clip_rect_,
211                            is_clipped_,
212                            draw_opacity_);
213
214  if (owning_layer_->ShowDebugBorders()) {
215    SkColor color = for_replica ?
216                    DebugColors::SurfaceReplicaBorderColor() :
217                    DebugColors::SurfaceBorderColor();
218    float width = for_replica ?
219                  DebugColors::SurfaceReplicaBorderWidth(
220                      owning_layer_->layer_tree_impl()) :
221                  DebugColors::SurfaceBorderWidth(
222                      owning_layer_->layer_tree_impl());
223    scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
224        DebugBorderDrawQuad::Create();
225    debug_border_quad->SetNew(shared_quad_state, content_rect_, color, width);
226    quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
227  }
228
229  // FIXME: By using the same RenderSurfaceImpl for both the content and its
230  // reflection, it's currently not possible to apply a separate mask to the
231  // reflection layer or correctly handle opacity in reflections (opacity must
232  // be applied after drawing both the layer and its reflection). The solution
233  // is to introduce yet another RenderSurfaceImpl to draw the layer and its
234  // reflection in. For now we only apply a separate reflection mask if the
235  // contents don't have a mask of their own.
236  LayerImpl* mask_layer = owning_layer_->mask_layer();
237  if (mask_layer &&
238      (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty()))
239    mask_layer = NULL;
240
241  if (!mask_layer && for_replica) {
242    mask_layer = owning_layer_->replica_layer()->mask_layer();
243    if (mask_layer &&
244        (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty()))
245      mask_layer = NULL;
246  }
247
248  gfx::RectF mask_uv_rect(0.f, 0.f, 1.f, 1.f);
249  if (mask_layer) {
250    gfx::Vector2dF owning_layer_draw_scale =
251        MathUtil::ComputeTransform2dScaleComponents(
252            owning_layer_->draw_transform(), 1.f);
253    gfx::SizeF unclipped_surface_size = gfx::ScaleSize(
254        owning_layer_->content_bounds(),
255        owning_layer_draw_scale.x(),
256        owning_layer_draw_scale.y());
257    // This assumes that the owning layer clips its subtree when a mask is
258    // present.
259    DCHECK(gfx::RectF(unclipped_surface_size).Contains(content_rect_));
260
261    float uv_scale_x = content_rect_.width() / unclipped_surface_size.width();
262    float uv_scale_y = content_rect_.height() / unclipped_surface_size.height();
263
264    mask_uv_rect = gfx::RectF(
265        uv_scale_x * content_rect_.x() / content_rect_.width(),
266        uv_scale_y * content_rect_.y() / content_rect_.height(),
267        uv_scale_x,
268        uv_scale_y);
269  }
270
271  ResourceProvider::ResourceId mask_resource_id =
272      mask_layer ? mask_layer->ContentsResourceId() : 0;
273  gfx::Rect contents_changed_since_last_frame =
274      ContentsChanged() ? content_rect_ : gfx::Rect();
275
276  scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create();
277  quad->SetNew(shared_quad_state,
278               content_rect_,
279               render_pass_id,
280               for_replica,
281               mask_resource_id,
282               contents_changed_since_last_frame,
283               mask_uv_rect,
284               owning_layer_->filters(),
285               owning_layer_->filter(),
286               owning_layer_->background_filters());
287  quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
288}
289
290}  // namespace cc
291