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