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/strings/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 26 namespace cc { 27 28 RenderSurfaceImpl::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 contributes_to_drawn_surface_(false), 37 nearest_ancestor_that_moves_pixels_(NULL), 38 target_render_surface_layer_index_history_(0), 39 current_layer_index_history_(0) { 40 damage_tracker_ = DamageTracker::Create(); 41 } 42 43 RenderSurfaceImpl::~RenderSurfaceImpl() {} 44 45 gfx::RectF RenderSurfaceImpl::DrawableContentRect() const { 46 gfx::RectF drawable_content_rect = 47 MathUtil::MapClippedRect(draw_transform_, content_rect_); 48 if (owning_layer_->has_replica()) { 49 drawable_content_rect.Union( 50 MathUtil::MapClippedRect(replica_draw_transform_, content_rect_)); 51 } 52 53 return drawable_content_rect; 54 } 55 56 std::string RenderSurfaceImpl::Name() const { 57 return base::StringPrintf("RenderSurfaceImpl(id=%i,owner=%s)", 58 owning_layer_->id(), 59 owning_layer_->debug_name().data()); 60 } 61 62 int RenderSurfaceImpl::OwningLayerId() const { 63 return owning_layer_ ? owning_layer_->id() : 0; 64 } 65 66 67 void RenderSurfaceImpl::SetClipRect(gfx::Rect clip_rect) { 68 if (clip_rect_ == clip_rect) 69 return; 70 71 surface_property_changed_ = true; 72 clip_rect_ = clip_rect; 73 } 74 75 bool RenderSurfaceImpl::ContentsChanged() const { 76 return !damage_tracker_->current_damage_rect().IsEmpty(); 77 } 78 79 void RenderSurfaceImpl::SetContentRect(gfx::Rect content_rect) { 80 if (content_rect_ == content_rect) 81 return; 82 83 surface_property_changed_ = true; 84 content_rect_ = content_rect; 85 } 86 87 bool RenderSurfaceImpl::SurfacePropertyChanged() const { 88 // Surface property changes are tracked as follows: 89 // 90 // - surface_property_changed_ is flagged when the clip_rect or content_rect 91 // change. As of now, these are the only two properties that can be affected 92 // by descendant layers. 93 // 94 // - all other property changes come from the owning layer (or some ancestor 95 // layer that propagates its change to the owning layer). 96 // 97 DCHECK(owning_layer_); 98 return surface_property_changed_ || owning_layer_->LayerPropertyChanged(); 99 } 100 101 bool RenderSurfaceImpl::SurfacePropertyChangedOnlyFromDescendant() const { 102 return surface_property_changed_ && !owning_layer_->LayerPropertyChanged(); 103 } 104 105 void RenderSurfaceImpl::AddContributingDelegatedRenderPassLayer( 106 LayerImpl* layer) { 107 DCHECK(std::find(layer_list_.begin(), layer_list_.end(), layer) != 108 layer_list_.end()); 109 DelegatedRendererLayerImpl* delegated_renderer_layer = 110 static_cast<DelegatedRendererLayerImpl*>(layer); 111 contributing_delegated_render_pass_layer_list_.push_back( 112 delegated_renderer_layer); 113 } 114 115 void RenderSurfaceImpl::ClearLayerLists() { 116 layer_list_.clear(); 117 contributing_delegated_render_pass_layer_list_.clear(); 118 } 119 120 RenderPass::Id RenderSurfaceImpl::RenderPassId() { 121 int layer_id = owning_layer_->id(); 122 int sub_id = 0; 123 DCHECK_GT(layer_id, 0); 124 return RenderPass::Id(layer_id, sub_id); 125 } 126 127 void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) { 128 for (size_t i = 0; 129 i < contributing_delegated_render_pass_layer_list_.size(); 130 ++i) { 131 DelegatedRendererLayerImpl* delegated_renderer_layer = 132 contributing_delegated_render_pass_layer_list_[i]; 133 delegated_renderer_layer->AppendContributingRenderPasses(pass_sink); 134 } 135 136 scoped_ptr<RenderPass> pass = RenderPass::Create(); 137 pass->SetNew(RenderPassId(), 138 content_rect_, 139 damage_tracker_->current_damage_rect(), 140 screen_space_transform_); 141 pass_sink->AppendRenderPass(pass.Pass()); 142 } 143 144 void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink, 145 AppendQuadsData* append_quads_data, 146 bool for_replica, 147 RenderPass::Id render_pass_id) { 148 DCHECK(!for_replica || owning_layer_->has_replica()); 149 150 const gfx::Transform& draw_transform = 151 for_replica ? replica_draw_transform_ : draw_transform_; 152 SharedQuadState* shared_quad_state = 153 quad_sink->UseSharedQuadState(SharedQuadState::Create()); 154 shared_quad_state->SetAll(draw_transform, 155 content_rect_.size(), 156 content_rect_, 157 clip_rect_, 158 is_clipped_, 159 draw_opacity_); 160 161 if (owning_layer_->ShowDebugBorders()) { 162 SkColor color = for_replica ? 163 DebugColors::SurfaceReplicaBorderColor() : 164 DebugColors::SurfaceBorderColor(); 165 float width = for_replica ? 166 DebugColors::SurfaceReplicaBorderWidth( 167 owning_layer_->layer_tree_impl()) : 168 DebugColors::SurfaceBorderWidth( 169 owning_layer_->layer_tree_impl()); 170 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = 171 DebugBorderDrawQuad::Create(); 172 debug_border_quad->SetNew(shared_quad_state, content_rect_, color, width); 173 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data); 174 } 175 176 // TODO(shawnsingh): By using the same RenderSurfaceImpl for both the content 177 // and its reflection, it's currently not possible to apply a separate mask to 178 // the reflection layer or correctly handle opacity in reflections (opacity 179 // must be applied after drawing both the layer and its reflection). The 180 // solution is to introduce yet another RenderSurfaceImpl to draw the layer 181 // and its reflection in. For now we only apply a separate reflection mask if 182 // the contents don't have a mask of their own. 183 LayerImpl* mask_layer = owning_layer_->mask_layer(); 184 if (mask_layer && 185 (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty())) 186 mask_layer = NULL; 187 188 if (!mask_layer && for_replica) { 189 mask_layer = owning_layer_->replica_layer()->mask_layer(); 190 if (mask_layer && 191 (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty())) 192 mask_layer = NULL; 193 } 194 195 gfx::RectF mask_uv_rect(0.f, 0.f, 1.f, 1.f); 196 if (mask_layer) { 197 gfx::Vector2dF owning_layer_draw_scale = 198 MathUtil::ComputeTransform2dScaleComponents( 199 owning_layer_->draw_transform(), 1.f); 200 gfx::SizeF unclipped_mask_target_size = gfx::ScaleSize( 201 owning_layer_->content_bounds(), 202 owning_layer_draw_scale.x(), 203 owning_layer_draw_scale.y()); 204 205 float uv_scale_x = 206 content_rect_.width() / unclipped_mask_target_size.width(); 207 float uv_scale_y = 208 content_rect_.height() / unclipped_mask_target_size.height(); 209 210 mask_uv_rect = gfx::RectF( 211 uv_scale_x * content_rect_.x() / content_rect_.width(), 212 uv_scale_y * content_rect_.y() / content_rect_.height(), 213 uv_scale_x, 214 uv_scale_y); 215 } 216 217 ResourceProvider::ResourceId mask_resource_id = 218 mask_layer ? mask_layer->ContentsResourceId() : 0; 219 gfx::Rect contents_changed_since_last_frame = 220 ContentsChanged() ? content_rect_ : gfx::Rect(); 221 222 scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create(); 223 quad->SetNew(shared_quad_state, 224 content_rect_, 225 render_pass_id, 226 for_replica, 227 mask_resource_id, 228 contents_changed_since_last_frame, 229 mask_uv_rect, 230 owning_layer_->filters(), 231 owning_layer_->filter(), 232 owning_layer_->background_filters()); 233 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); 234 } 235 236 } // namespace cc 237