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