render_surface_impl.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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. #include "cc/layers/render_surface_impl.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include "base/check_op.h"
  8. #include "cc/base/math_util.h"
  9. #include "cc/debug/debug_colors.h"
  10. #include "cc/layers/append_quads_data.h"
  11. #include "cc/paint/element_id.h"
  12. #include "cc/paint/filter_operations.h"
  13. #include "cc/trees/damage_tracker.h"
  14. #include "cc/trees/effect_node.h"
  15. #include "cc/trees/layer_tree_impl.h"
  16. #include "cc/trees/occlusion.h"
  17. #include "cc/trees/transform_node.h"
  18. #include "components/viz/common/display/de_jelly.h"
  19. #include "components/viz/common/quads/compositor_render_pass.h"
  20. #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
  21. #include "components/viz/common/quads/content_draw_quad_base.h"
  22. #include "components/viz/common/quads/debug_border_draw_quad.h"
  23. #include "components/viz/common/quads/shared_quad_state.h"
  24. #include "components/viz/common/quads/solid_color_draw_quad.h"
  25. #include "components/viz/common/quads/tile_draw_quad.h"
  26. #include "third_party/skia/include/core/SkImageFilter.h"
  27. #include "ui/gfx/geometry/rect_conversions.h"
  28. #include "ui/gfx/geometry/transform.h"
  29. namespace cc {
  30. RenderSurfaceImpl::RenderSurfaceImpl(LayerTreeImpl* layer_tree_impl,
  31. uint64_t stable_id)
  32. : layer_tree_impl_(layer_tree_impl),
  33. stable_id_(stable_id),
  34. effect_tree_index_(kInvalidPropertyNodeId),
  35. num_contributors_(0),
  36. has_contributing_layer_that_escapes_clip_(false),
  37. surface_property_changed_(false),
  38. ancestor_property_changed_(false),
  39. contributes_to_drawn_surface_(false),
  40. is_render_surface_list_member_(false),
  41. intersects_damage_under_(true),
  42. nearest_occlusion_immune_ancestor_(nullptr) {
  43. damage_tracker_ = DamageTracker::Create();
  44. }
  45. RenderSurfaceImpl::~RenderSurfaceImpl() = default;
  46. RenderSurfaceImpl* RenderSurfaceImpl::render_target() {
  47. EffectTree& effect_tree =
  48. layer_tree_impl_->property_trees()->effect_tree_mutable();
  49. EffectNode* node = effect_tree.Node(EffectTreeIndex());
  50. if (node->target_id != kRootPropertyNodeId)
  51. return effect_tree.GetRenderSurface(node->target_id);
  52. else
  53. return this;
  54. }
  55. const RenderSurfaceImpl* RenderSurfaceImpl::render_target() const {
  56. const EffectTree& effect_tree =
  57. layer_tree_impl_->property_trees()->effect_tree();
  58. const EffectNode* node = effect_tree.Node(EffectTreeIndex());
  59. if (node->target_id != kRootPropertyNodeId)
  60. return effect_tree.GetRenderSurface(node->target_id);
  61. else
  62. return this;
  63. }
  64. RenderSurfaceImpl::DrawProperties::DrawProperties() {
  65. draw_opacity = 1.f;
  66. is_clipped = false;
  67. }
  68. RenderSurfaceImpl::DrawProperties::~DrawProperties() = default;
  69. gfx::RectF RenderSurfaceImpl::DrawableContentRect() const {
  70. if (content_rect().IsEmpty())
  71. return gfx::RectF();
  72. gfx::Rect surface_content_rect = content_rect();
  73. const FilterOperations& filters = Filters();
  74. if (!filters.IsEmpty()) {
  75. surface_content_rect =
  76. filters.MapRect(surface_content_rect, SurfaceScale().matrix().asM33());
  77. }
  78. gfx::RectF drawable_content_rect = MathUtil::MapClippedRect(
  79. draw_transform(), gfx::RectF(surface_content_rect));
  80. if (!filters.IsEmpty() && is_clipped()) {
  81. // Filter could move pixels around, but still need to be clipped.
  82. drawable_content_rect.Intersect(gfx::RectF(clip_rect()));
  83. }
  84. // If the rect has a NaN coordinate, we return empty rect to avoid crashes in
  85. // functions (for example, gfx::ToEnclosedRect) that are called on this rect.
  86. if (std::isnan(drawable_content_rect.x()) ||
  87. std::isnan(drawable_content_rect.y()) ||
  88. std::isnan(drawable_content_rect.right()) ||
  89. std::isnan(drawable_content_rect.bottom()))
  90. return gfx::RectF();
  91. return drawable_content_rect;
  92. }
  93. SkBlendMode RenderSurfaceImpl::BlendMode() const {
  94. return OwningEffectNode()->blend_mode;
  95. }
  96. SkColor4f RenderSurfaceImpl::GetDebugBorderColor() const {
  97. return DebugColors::SurfaceBorderColor();
  98. }
  99. float RenderSurfaceImpl::GetDebugBorderWidth() const {
  100. return DebugColors::SurfaceBorderWidth(
  101. layer_tree_impl_ ? layer_tree_impl_->device_scale_factor() : 1);
  102. }
  103. LayerImpl* RenderSurfaceImpl::BackdropMaskLayer() const {
  104. ElementId mask_element_id = OwningEffectNode()->backdrop_mask_element_id;
  105. if (!mask_element_id)
  106. return nullptr;
  107. return layer_tree_impl_->LayerByElementId(mask_element_id);
  108. }
  109. bool RenderSurfaceImpl::HasMaskingContributingSurface() const {
  110. return OwningEffectNode()->has_masking_child;
  111. }
  112. const FilterOperations& RenderSurfaceImpl::Filters() const {
  113. return OwningEffectNode()->filters;
  114. }
  115. gfx::Transform RenderSurfaceImpl::SurfaceScale() const {
  116. gfx::Transform surface_scale;
  117. surface_scale.Scale(OwningEffectNode()->surface_contents_scale.x(),
  118. OwningEffectNode()->surface_contents_scale.y());
  119. return surface_scale;
  120. }
  121. const FilterOperations& RenderSurfaceImpl::BackdropFilters() const {
  122. return OwningEffectNode()->backdrop_filters;
  123. }
  124. absl::optional<gfx::RRectF> RenderSurfaceImpl::BackdropFilterBounds() const {
  125. return OwningEffectNode()->backdrop_filter_bounds;
  126. }
  127. bool RenderSurfaceImpl::TrilinearFiltering() const {
  128. return OwningEffectNode()->trilinear_filtering;
  129. }
  130. bool RenderSurfaceImpl::HasCopyRequest() const {
  131. return OwningEffectNode()->has_copy_request;
  132. }
  133. viz::SubtreeCaptureId RenderSurfaceImpl::SubtreeCaptureId() const {
  134. return OwningEffectNode()->subtree_capture_id;
  135. }
  136. gfx::Size RenderSurfaceImpl::SubtreeSize() const {
  137. return OwningEffectNode()->subtree_size;
  138. }
  139. bool RenderSurfaceImpl::ShouldCacheRenderSurface() const {
  140. return OwningEffectNode()->cache_render_surface;
  141. }
  142. bool RenderSurfaceImpl::CopyOfOutputRequired() const {
  143. return HasCopyRequest() || ShouldCacheRenderSurface() ||
  144. SubtreeCaptureId().is_valid() ||
  145. OwningEffectNode()->shared_element_resource_id.IsValid();
  146. }
  147. int RenderSurfaceImpl::TransformTreeIndex() const {
  148. return OwningEffectNode()->transform_id;
  149. }
  150. int RenderSurfaceImpl::ClipTreeIndex() const {
  151. return OwningEffectNode()->clip_id;
  152. }
  153. int RenderSurfaceImpl::EffectTreeIndex() const {
  154. return effect_tree_index_;
  155. }
  156. const EffectNode* RenderSurfaceImpl::OwningEffectNode() const {
  157. return layer_tree_impl_->property_trees()->effect_tree().Node(
  158. EffectTreeIndex());
  159. }
  160. const DocumentTransitionSharedElementId&
  161. RenderSurfaceImpl::GetDocumentTransitionSharedElementId() const {
  162. return OwningEffectNode()->document_transition_shared_element_id;
  163. }
  164. void RenderSurfaceImpl::SetClipRect(const gfx::Rect& clip_rect) {
  165. if (clip_rect == draw_properties_.clip_rect)
  166. return;
  167. surface_property_changed_ = true;
  168. draw_properties_.clip_rect = clip_rect;
  169. }
  170. void RenderSurfaceImpl::SetContentRect(const gfx::Rect& content_rect) {
  171. if (content_rect == draw_properties_.content_rect)
  172. return;
  173. surface_property_changed_ = true;
  174. draw_properties_.content_rect = content_rect;
  175. }
  176. void RenderSurfaceImpl::SetContentRectForTesting(const gfx::Rect& rect) {
  177. SetContentRect(rect);
  178. }
  179. gfx::Rect RenderSurfaceImpl::CalculateExpandedClipForFilters(
  180. const gfx::Transform& target_to_surface) {
  181. gfx::Rect clip_in_surface_space =
  182. MathUtil::ProjectEnclosingClippedRect(target_to_surface, clip_rect());
  183. gfx::Rect expanded_clip_in_surface_space =
  184. Filters().MapRect(clip_in_surface_space, SurfaceScale().matrix().asM33());
  185. gfx::Rect expanded_clip_in_target_space = MathUtil::MapEnclosingClippedRect(
  186. draw_transform(), expanded_clip_in_surface_space);
  187. return expanded_clip_in_target_space;
  188. }
  189. gfx::Rect RenderSurfaceImpl::CalculateClippedAccumulatedContentRect() {
  190. if (CopyOfOutputRequired() || !is_clipped())
  191. return accumulated_content_rect();
  192. if (accumulated_content_rect().IsEmpty())
  193. return gfx::Rect();
  194. // Calculate projection from the target surface rect to local
  195. // space. Non-invertible draw transforms means no able to bring clipped rect
  196. // in target space back to local space, early out without clip.
  197. gfx::Transform target_to_surface(gfx::Transform::kSkipInitialization);
  198. if (!draw_transform().GetInverse(&target_to_surface))
  199. return accumulated_content_rect();
  200. // Clip rect is in target space. Bring accumulated content rect to
  201. // target space in preparation for clipping.
  202. gfx::Rect accumulated_rect_in_target_space =
  203. MathUtil::MapEnclosingClippedRect(draw_transform(),
  204. accumulated_content_rect());
  205. // If accumulated content rect is contained within clip rect, early out
  206. // without clipping.
  207. if (clip_rect().Contains(accumulated_rect_in_target_space))
  208. return accumulated_content_rect();
  209. gfx::Rect clipped_accumulated_rect_in_target_space;
  210. if (Filters().HasFilterThatMovesPixels()) {
  211. clipped_accumulated_rect_in_target_space =
  212. CalculateExpandedClipForFilters(target_to_surface);
  213. } else {
  214. clipped_accumulated_rect_in_target_space = clip_rect();
  215. }
  216. if (layer_tree_impl_->settings().allow_de_jelly_effect) {
  217. clipped_accumulated_rect_in_target_space.Inset(
  218. gfx::Insets::VH(-viz::MaxDeJellyHeight(), 0));
  219. }
  220. clipped_accumulated_rect_in_target_space.Intersect(
  221. accumulated_rect_in_target_space);
  222. if (clipped_accumulated_rect_in_target_space.IsEmpty())
  223. return gfx::Rect();
  224. gfx::Rect clipped_accumulated_rect_in_local_space =
  225. MathUtil::ProjectEnclosingClippedRect(
  226. target_to_surface, clipped_accumulated_rect_in_target_space);
  227. // Bringing clipped accumulated rect back to local space may result
  228. // in inflation due to axis-alignment.
  229. clipped_accumulated_rect_in_local_space.Intersect(accumulated_content_rect());
  230. return clipped_accumulated_rect_in_local_space;
  231. }
  232. void RenderSurfaceImpl::CalculateContentRectFromAccumulatedContentRect(
  233. int max_texture_size) {
  234. // Root render surface use viewport, and does not calculate content rect.
  235. DCHECK_NE(render_target(), this);
  236. // Surface's content rect is the clipped accumulated content rect. By default
  237. // use accumulated content rect, and then try to clip it.
  238. gfx::Rect surface_content_rect = CalculateClippedAccumulatedContentRect();
  239. // The RenderSurfaceImpl backing texture cannot exceed the maximum supported
  240. // texture size.
  241. surface_content_rect.set_width(
  242. std::min(surface_content_rect.width(), max_texture_size));
  243. surface_content_rect.set_height(
  244. std::min(surface_content_rect.height(), max_texture_size));
  245. SetContentRect(surface_content_rect);
  246. }
  247. void RenderSurfaceImpl::SetContentRectToViewport() {
  248. // Only root render surface use viewport as content rect.
  249. DCHECK_EQ(render_target(), this);
  250. gfx::Rect viewport = gfx::ToEnclosingRect(
  251. layer_tree_impl_->property_trees()->clip_tree().ViewportClip());
  252. SetContentRect(viewport);
  253. }
  254. void RenderSurfaceImpl::ClearAccumulatedContentRect() {
  255. accumulated_content_rect_ = gfx::Rect();
  256. }
  257. void RenderSurfaceImpl::AccumulateContentRectFromContributingLayer(
  258. LayerImpl* layer) {
  259. DCHECK(layer->draws_content());
  260. DCHECK_EQ(this, layer->render_target());
  261. // Root render surface doesn't accumulate content rect, it always uses
  262. // viewport for content rect.
  263. if (render_target() == this)
  264. return;
  265. accumulated_content_rect_.Union(layer->visible_drawable_content_rect());
  266. }
  267. void RenderSurfaceImpl::AccumulateContentRectFromContributingRenderSurface(
  268. RenderSurfaceImpl* contributing_surface) {
  269. DCHECK_NE(this, contributing_surface);
  270. DCHECK_EQ(this, contributing_surface->render_target());
  271. // Root render surface doesn't accumulate content rect, it always uses
  272. // viewport for content rect.
  273. if (render_target() == this)
  274. return;
  275. // If this surface is a shared element id then it is being used to generate an
  276. // independent snapshot and won't contribute to its target surface.
  277. if (contributing_surface->OwningEffectNode()
  278. ->shared_element_resource_id.IsValid())
  279. return;
  280. // The content rect of contributing surface is in its own space. Instead, we
  281. // will use contributing surface's DrawableContentRect which is in target
  282. // space (local space for this render surface) as required.
  283. accumulated_content_rect_.Union(
  284. gfx::ToEnclosedRect(contributing_surface->DrawableContentRect()));
  285. }
  286. bool RenderSurfaceImpl::SurfacePropertyChanged() const {
  287. // Surface property changes are tracked as follows:
  288. //
  289. // - surface_property_changed_ is flagged when the clip_rect or content_rect
  290. // change. As of now, these are the only two properties that can be affected
  291. // by descendant layers.
  292. //
  293. // - all other property changes come from the surface's property tree nodes
  294. // (or some ancestor node that propagates its change to one of these nodes).
  295. //
  296. return surface_property_changed_ || AncestorPropertyChanged();
  297. }
  298. bool RenderSurfaceImpl::SurfacePropertyChangedOnlyFromDescendant() const {
  299. return surface_property_changed_ && !AncestorPropertyChanged();
  300. }
  301. bool RenderSurfaceImpl::AncestorPropertyChanged() const {
  302. const PropertyTrees* property_trees = layer_tree_impl_->property_trees();
  303. return ancestor_property_changed_ || property_trees->full_tree_damaged() ||
  304. property_trees->transform_tree()
  305. .Node(TransformTreeIndex())
  306. ->transform_changed ||
  307. property_trees->effect_tree().Node(EffectTreeIndex())->effect_changed;
  308. }
  309. void RenderSurfaceImpl::NoteAncestorPropertyChanged() {
  310. ancestor_property_changed_ = true;
  311. }
  312. bool RenderSurfaceImpl::HasDamageFromeContributingContent() const {
  313. return damage_tracker_->has_damage_from_contributing_content();
  314. }
  315. gfx::Rect RenderSurfaceImpl::GetDamageRect() const {
  316. gfx::Rect damage_rect;
  317. bool is_valid_rect = damage_tracker_->GetDamageRectIfValid(&damage_rect);
  318. if (!is_valid_rect)
  319. return content_rect();
  320. return damage_rect;
  321. }
  322. RenderSurfacePropertyChangedFlags RenderSurfaceImpl::GetPropertyChangeFlags()
  323. const {
  324. return {surface_property_changed_, ancestor_property_changed_};
  325. }
  326. void RenderSurfaceImpl::ApplyPropertyChangeFlags(
  327. const RenderSurfacePropertyChangedFlags& flags) {
  328. surface_property_changed_ = flags.self_changed();
  329. ancestor_property_changed_ = flags.ancestor_changed();
  330. }
  331. void RenderSurfaceImpl::ResetPropertyChangedFlags() {
  332. surface_property_changed_ = false;
  333. ancestor_property_changed_ = false;
  334. }
  335. std::unique_ptr<viz::CompositorRenderPass>
  336. RenderSurfaceImpl::CreateRenderPass() {
  337. std::unique_ptr<viz::CompositorRenderPass> pass =
  338. viz::CompositorRenderPass::Create(num_contributors_);
  339. gfx::Rect damage_rect = GetDamageRect();
  340. damage_rect.Intersect(content_rect());
  341. pass->SetNew(render_pass_id(), content_rect(), damage_rect,
  342. draw_properties_.screen_space_transform);
  343. pass->filters = Filters();
  344. pass->backdrop_filters = BackdropFilters();
  345. pass->backdrop_filter_bounds = BackdropFilterBounds();
  346. pass->generate_mipmap = TrilinearFiltering();
  347. pass->subtree_capture_id = SubtreeCaptureId();
  348. // The subtree size may be slightly larger than our content rect during
  349. // some animations, so we clamp it here.
  350. pass->subtree_size = SubtreeSize();
  351. pass->subtree_size.SetToMin(content_rect().size());
  352. pass->cache_render_pass = ShouldCacheRenderSurface();
  353. pass->has_damage_from_contributing_content =
  354. HasDamageFromeContributingContent();
  355. pass->shared_element_resource_id =
  356. OwningEffectNode()->shared_element_resource_id;
  357. return pass;
  358. }
  359. void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode,
  360. viz::CompositorRenderPass* render_pass,
  361. AppendQuadsData* append_quads_data) {
  362. gfx::Rect unoccluded_content_rect =
  363. occlusion_in_content_space().GetUnoccludedContentRect(content_rect());
  364. if (unoccluded_content_rect.IsEmpty())
  365. return;
  366. // If this render surface has a valid |shared_element_resource_id| then its
  367. // being used to produce live content. Its content will be drawn to its
  368. // actual position in the Viz process.
  369. if (OwningEffectNode()->shared_element_resource_id.IsValid())
  370. return;
  371. const PropertyTrees* property_trees = layer_tree_impl_->property_trees();
  372. int sorting_context_id = property_trees->transform_tree()
  373. .Node(TransformTreeIndex())
  374. ->sorting_context_id;
  375. bool contents_opaque = false;
  376. viz::SharedQuadState* shared_quad_state =
  377. render_pass->CreateAndAppendSharedQuadState();
  378. absl::optional<gfx::Rect> clip_rect;
  379. if (draw_properties_.is_clipped) {
  380. clip_rect = draw_properties_.clip_rect;
  381. }
  382. shared_quad_state->SetAll(draw_transform(), content_rect(), content_rect(),
  383. mask_filter_info(), clip_rect, contents_opaque,
  384. draw_properties_.draw_opacity, BlendMode(),
  385. sorting_context_id);
  386. if (layer_tree_impl_->debug_state().show_debug_borders.test(
  387. DebugBorderType::RENDERPASS)) {
  388. auto* debug_border_quad =
  389. render_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
  390. debug_border_quad->SetNew(shared_quad_state, content_rect(),
  391. unoccluded_content_rect, GetDebugBorderColor(),
  392. GetDebugBorderWidth());
  393. }
  394. LayerImpl* mask_layer = BackdropMaskLayer();
  395. viz::ResourceId mask_resource_id = viz::kInvalidResourceId;
  396. gfx::Size mask_texture_size;
  397. gfx::RectF mask_uv_rect;
  398. gfx::Vector2dF surface_contents_scale =
  399. OwningEffectNode()->surface_contents_scale;
  400. // Resourceless mode does not support masks.
  401. if (draw_mode != DRAW_MODE_RESOURCELESS_SOFTWARE && mask_layer &&
  402. mask_layer->draws_content() && !mask_layer->bounds().IsEmpty()) {
  403. // The software renderer applies mask layer and blending in the wrong
  404. // order but kDstIn doesn't commute with masking. It is okay to not
  405. // support this configuration because kDstIn was introduced to replace
  406. // mask layers.
  407. DCHECK(BlendMode() != SkBlendMode::kDstIn)
  408. << "kDstIn blend mode with mask layer is unsupported.";
  409. TRACE_EVENT1("cc", "RenderSurfaceImpl::AppendQuads",
  410. "mask_layer_gpu_memory_usage",
  411. mask_layer->GPUMemoryUsageInBytes());
  412. gfx::SizeF mask_uv_size;
  413. mask_layer->GetContentsResourceId(&mask_resource_id, &mask_texture_size,
  414. &mask_uv_size);
  415. gfx::SizeF unclipped_mask_target_size =
  416. gfx::ScaleSize(gfx::SizeF(mask_layer->bounds()),
  417. surface_contents_scale.x(), surface_contents_scale.y());
  418. gfx::Vector2dF mask_offset = gfx::ScaleVector2d(
  419. mask_layer->offset_to_transform_parent(), surface_contents_scale.x(),
  420. surface_contents_scale.y());
  421. // Convert content_rect from target space to normalized mask UV space.
  422. // Where |unclipped_mask_target_size| maps to |mask_uv_size|.
  423. mask_uv_rect = gfx::ScaleRect(
  424. // Translate content_rect into mask resource's space.
  425. gfx::RectF(content_rect()) - mask_offset,
  426. mask_uv_size.width() / unclipped_mask_target_size.width(),
  427. mask_uv_size.height() / unclipped_mask_target_size.height());
  428. }
  429. gfx::RectF tex_coord_rect(gfx::Rect(content_rect().size()));
  430. auto* quad =
  431. render_pass->CreateAndAppendDrawQuad<viz::CompositorRenderPassDrawQuad>();
  432. quad->SetAll(
  433. shared_quad_state, content_rect(), unoccluded_content_rect,
  434. /*needs_blending=*/true, render_pass_id(), mask_resource_id, mask_uv_rect,
  435. mask_texture_size, surface_contents_scale, gfx::PointF(), tex_coord_rect,
  436. !layer_tree_impl_->settings().enable_edge_anti_aliasing,
  437. OwningEffectNode()->backdrop_filter_quality, intersects_damage_under_);
  438. }
  439. } // namespace cc