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