Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: content/common/gpu/image_transport_surface_overlay_mac.mm

Issue 1647523002: Mac overlays: Move CALayerPartialDamageTree to its own file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/image_transport_surface_overlay_mac.h ('k') | content/content_common.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/image_transport_surface_overlay_mac.h" 5 #include "content/common/gpu/image_transport_surface_overlay_mac.h"
6 6
7 #include <CoreGraphics/CoreGraphics.h> 7 #include <CoreGraphics/CoreGraphics.h>
8 #include <IOSurface/IOSurface.h> 8 #include <IOSurface/IOSurface.h>
9 #include <OpenGL/CGLRenderers.h> 9 #include <OpenGL/CGLRenderers.h>
10 #include <OpenGL/CGLTypes.h> 10 #include <OpenGL/CGLTypes.h>
11 #include <OpenGL/gl.h> 11 #include <OpenGL/gl.h>
12 #include <stddef.h> 12 #include <stddef.h>
13 13
14 #include <algorithm> 14 #include <algorithm>
15 15
16 // This type consistently causes problem on Mac, and needs to be dealt with 16 // This type consistently causes problem on Mac, and needs to be dealt with
17 // in a systemic way. 17 // in a systemic way.
18 // http://crbug.com/517208 18 // http://crbug.com/517208
19 #ifndef GL_OES_EGL_image 19 #ifndef GL_OES_EGL_image
20 typedef void* GLeglImageOES; 20 typedef void* GLeglImageOES;
21 #endif 21 #endif
22 22
23 #include "base/command_line.h"
24 #include "base/mac/scoped_cftyperef.h" 23 #include "base/mac/scoped_cftyperef.h"
25 #include "base/mac/sdk_forward_declarations.h" 24 #include "content/common/gpu/ca_layer_partial_damage_tree_mac.h"
26 #include "content/common/gpu/ca_layer_tree_mac.h" 25 #include "content/common/gpu/ca_layer_tree_mac.h"
27 #include "content/common/gpu/gpu_messages.h" 26 #include "content/common/gpu/gpu_messages.h"
28 #include "ui/accelerated_widget_mac/io_surface_context.h" 27 #include "ui/accelerated_widget_mac/io_surface_context.h"
29 #include "ui/base/cocoa/animation_utils.h" 28 #include "ui/base/cocoa/animation_utils.h"
30 #include "ui/base/cocoa/remote_layer_api.h" 29 #include "ui/base/cocoa/remote_layer_api.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/gfx/geometry/rect_conversions.h" 30 #include "ui/gfx/geometry/rect_conversions.h"
33 #include "ui/gfx/transform.h" 31 #include "ui/gfx/transform.h"
34 #include "ui/gl/gl_context.h" 32 #include "ui/gl/gl_context.h"
35 #include "ui/gl/gl_fence.h" 33 #include "ui/gl/gl_fence.h"
36 #include "ui/gl/gl_image_io_surface.h" 34 #include "ui/gl/gl_image_io_surface.h"
37 #include "ui/gl/gpu_switching_manager.h" 35 #include "ui/gl/gpu_switching_manager.h"
38 #include "ui/gl/scoped_api.h" 36 #include "ui/gl/scoped_api.h"
39 #include "ui/gl/scoped_cgl.h" 37 #include "ui/gl/scoped_cgl.h"
40 38
41 namespace { 39 namespace {
(...skipping 10 matching lines...) Expand all
52 // the next frame. 50 // the next frame.
53 const double kVSyncIntervalFractionForDisplayCallback = 0.5; 51 const double kVSyncIntervalFractionForDisplayCallback = 0.5;
54 52
55 // If swaps arrive regularly and nearly at the vsync rate, then attempt to 53 // If swaps arrive regularly and nearly at the vsync rate, then attempt to
56 // make animation smooth (each frame is shown for one vsync interval) by sending 54 // make animation smooth (each frame is shown for one vsync interval) by sending
57 // them to the window server only when their GL work completes. If frames are 55 // them to the window server only when their GL work completes. If frames are
58 // not coming in with each vsync, then just throw them at the window server as 56 // not coming in with each vsync, then just throw them at the window server as
59 // they come. 57 // they come.
60 const double kMaximumVSyncsBetweenSwapsForSmoothAnimation = 1.5; 58 const double kMaximumVSyncsBetweenSwapsForSmoothAnimation = 1.5;
61 59
62 // When selecting a CALayer to re-use for partial damage, this is the maximum
63 // fraction of the merged layer's pixels that may be not-updated by the swap
64 // before we consider the CALayer to not be a good enough match, and create a
65 // new one.
66 const float kMaximumPartialDamageWasteFraction = 1.2f;
67
68 // The maximum number of partial damage layers that may be created before we
69 // give up and remove them all (doing full damage in the process).
70 const size_t kMaximumPartialDamageLayers = 8;
71
72 void CheckGLErrors(const char* msg) { 60 void CheckGLErrors(const char* msg) {
73 GLenum gl_error; 61 GLenum gl_error;
74 while ((gl_error = glGetError()) != GL_NO_ERROR) { 62 while ((gl_error = glGetError()) != GL_NO_ERROR) {
75 LOG(ERROR) << "OpenGL error hit " << msg << ": " << gl_error; 63 LOG(ERROR) << "OpenGL error hit " << msg << ": " << gl_error;
76 } 64 }
77 } 65 }
78 66
79 void IOSurfaceContextNoOp(scoped_refptr<ui::IOSurfaceContext>) { 67 void IOSurfaceContextNoOp(scoped_refptr<ui::IOSurfaceContext>) {
80 } 68 }
81 69
82 } // namespace 70 } // namespace
83 71
84 @interface CALayer(Private) 72 @interface CALayer(Private)
85 -(void)setContentsChanged; 73 -(void)setContentsChanged;
86 @end 74 @end
87 75
88 namespace content { 76 namespace content {
89 77
90 scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( 78 scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
91 GpuChannelManager* manager, 79 GpuChannelManager* manager,
92 GpuCommandBufferStub* stub, 80 GpuCommandBufferStub* stub,
93 gfx::PluginWindowHandle handle) { 81 gfx::PluginWindowHandle handle) {
94 return new ImageTransportSurfaceOverlayMac(manager, stub, handle); 82 return new ImageTransportSurfaceOverlayMac(manager, stub, handle);
95 } 83 }
96 84
97 class CALayerPartialDamageTree {
98 public:
99 CALayerPartialDamageTree(bool allow_partial_swap,
100 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
101 const gfx::Rect& pixel_frame_rect);
102 ~CALayerPartialDamageTree();
103
104 base::ScopedCFTypeRef<IOSurfaceRef> RootLayerIOSurface();
105 void CommitCALayers(CALayer* superlayer,
106 scoped_ptr<CALayerPartialDamageTree> old_tree,
107 float scale_factor,
108 const gfx::Rect& pixel_damage_rect);
109
110 private:
111 class OverlayPlane;
112
113 void UpdateRootAndPartialDamagePlanes(CALayerPartialDamageTree* old_tree,
114 const gfx::RectF& pixel_damage_rect);
115 void UpdateRootAndPartialDamageCALayers(CALayer* superlayer,
116 float scale_factor);
117
118 const bool allow_partial_swap_;
119 linked_ptr<OverlayPlane> root_plane_;
120 std::list<linked_ptr<OverlayPlane>> partial_damage_planes_;
121 };
122
123 class CALayerPartialDamageTree::OverlayPlane {
124 public:
125 static linked_ptr<OverlayPlane> CreateWithFrameRect(
126 int z_order,
127 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
128 const gfx::RectF& pixel_frame_rect,
129 const gfx::RectF& contents_rect) {
130 gfx::Transform transform;
131 transform.Translate(pixel_frame_rect.x(), pixel_frame_rect.y());
132 return linked_ptr<OverlayPlane>(
133 new OverlayPlane(z_order, io_surface, contents_rect, pixel_frame_rect));
134 }
135
136 ~OverlayPlane() {
137 [ca_layer setContents:nil];
138 [ca_layer removeFromSuperlayer];
139 ca_layer.reset();
140 }
141
142 const int z_order;
143 const base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
144 const gfx::RectF contents_rect;
145 const gfx::RectF pixel_frame_rect;
146 bool layer_needs_update;
147 base::scoped_nsobject<CALayer> ca_layer;
148
149 void TakeCALayerFrom(OverlayPlane* other_plane) {
150 ca_layer.swap(other_plane->ca_layer);
151 }
152
153 void UpdateProperties(float scale_factor) {
154 if (layer_needs_update) {
155 [ca_layer setOpaque:YES];
156
157 id new_contents = static_cast<id>(io_surface.get());
158 if ([ca_layer contents] == new_contents && z_order == 0)
159 [ca_layer setContentsChanged];
160 else
161 [ca_layer setContents:new_contents];
162 [ca_layer setContentsRect:contents_rect.ToCGRect()];
163
164 [ca_layer setAnchorPoint:CGPointZero];
165
166 if ([ca_layer respondsToSelector:(@selector(setContentsScale:))])
167 [ca_layer setContentsScale:scale_factor];
168 gfx::RectF dip_frame_rect = gfx::RectF(pixel_frame_rect);
169 dip_frame_rect.Scale(1 / scale_factor);
170 [ca_layer setBounds:CGRectMake(0, 0, dip_frame_rect.width(),
171 dip_frame_rect.height())];
172 [ca_layer
173 setPosition:CGPointMake(dip_frame_rect.x(), dip_frame_rect.y())];
174 }
175 static bool show_borders =
176 base::CommandLine::ForCurrentProcess()->HasSwitch(
177 switches::kShowMacOverlayBorders);
178 if (show_borders) {
179 base::ScopedCFTypeRef<CGColorRef> color;
180 if (!layer_needs_update) {
181 // Green represents contents that are unchanged across frames.
182 color.reset(CGColorCreateGenericRGB(0, 1, 0, 1));
183 } else {
184 // Red represents damaged contents.
185 color.reset(CGColorCreateGenericRGB(1, 0, 0, 1));
186 }
187 [ca_layer setBorderWidth:1];
188 [ca_layer setBorderColor:color];
189 }
190 layer_needs_update = false;
191 }
192
193 private:
194 OverlayPlane(int z_order,
195 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
196 const gfx::RectF& contents_rect,
197 const gfx::RectF& pixel_frame_rect)
198 : z_order(z_order),
199 io_surface(io_surface),
200 contents_rect(contents_rect),
201 pixel_frame_rect(pixel_frame_rect),
202 layer_needs_update(true) {}
203 };
204
205 class ImageTransportSurfaceOverlayMac::PendingSwap { 85 class ImageTransportSurfaceOverlayMac::PendingSwap {
206 public: 86 public:
207 PendingSwap() {} 87 PendingSwap() {}
208 ~PendingSwap() { DCHECK(!gl_fence); } 88 ~PendingSwap() { DCHECK(!gl_fence); }
209 89
210 gfx::Size pixel_size; 90 gfx::Size pixel_size;
211 float scale_factor; 91 float scale_factor;
212 gfx::Rect pixel_damage_rect; 92 gfx::Rect pixel_damage_rect;
213 93
214 scoped_ptr<CALayerPartialDamageTree> partial_damage_tree; 94 scoped_ptr<CALayerPartialDamageTree> partial_damage_tree;
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 } 314 }
435 params.size = swap->pixel_size; 315 params.size = swap->pixel_size;
436 params.scale_factor = swap->scale_factor; 316 params.scale_factor = swap->scale_factor;
437 params.latency_info.swap(swap->latency_info); 317 params.latency_info.swap(swap->latency_info);
438 helper_->SendAcceleratedSurfaceBuffersSwapped(params); 318 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
439 319
440 // Remove this from the queue, and reset any callback timers. 320 // Remove this from the queue, and reset any callback timers.
441 pending_swaps_.pop_front(); 321 pending_swaps_.pop_front();
442 } 322 }
443 323
444 void CALayerPartialDamageTree::UpdateRootAndPartialDamagePlanes(
445 CALayerPartialDamageTree* old_tree,
446 const gfx::RectF& pixel_damage_rect) {
447 // This is the plane that will be updated this frame. It may be the root plane
448 // or a child plane.
449 linked_ptr<OverlayPlane> plane_for_swap;
450
451 // If the frame's size changed, if we haven't updated the root layer, if
452 // we have full damage, or if we don't support remote layers, then use the
453 // root layer directly.
454 if (!allow_partial_swap_ || !old_tree ||
455 old_tree->root_plane_->pixel_frame_rect !=
456 root_plane_->pixel_frame_rect ||
457 pixel_damage_rect == root_plane_->pixel_frame_rect) {
458 plane_for_swap = root_plane_;
459 }
460
461 // Walk though the old tree's partial damage layers and see if there is one
462 // that is appropriate to re-use.
463 if (!plane_for_swap.get() && !pixel_damage_rect.IsEmpty()) {
464 gfx::RectF plane_to_reuse_dip_enlarged_rect;
465
466 // Find the last partial damage plane to re-use the CALayer from. Grow the
467 // new rect for this layer to include this damage, and all nearby partial
468 // damage layers.
469 linked_ptr<OverlayPlane> plane_to_reuse;
470 for (auto& old_plane : old_tree->partial_damage_planes_) {
471 gfx::RectF dip_enlarged_rect = old_plane->pixel_frame_rect;
472 dip_enlarged_rect.Union(pixel_damage_rect);
473
474 // Compute the fraction of the pixels that would not be updated by this
475 // swap. If it is too big, try another layer.
476 float waste_fraction = dip_enlarged_rect.size().GetArea() * 1.f /
477 pixel_damage_rect.size().GetArea();
478 if (waste_fraction > kMaximumPartialDamageWasteFraction)
479 continue;
480
481 plane_to_reuse = old_plane;
482 plane_to_reuse_dip_enlarged_rect.Union(dip_enlarged_rect);
483 }
484
485 if (plane_to_reuse.get()) {
486 gfx::RectF enlarged_contents_rect = plane_to_reuse_dip_enlarged_rect;
487 enlarged_contents_rect.Scale(1. / root_plane_->pixel_frame_rect.width(),
488 1. / root_plane_->pixel_frame_rect.height());
489
490 plane_for_swap = OverlayPlane::CreateWithFrameRect(
491 0, root_plane_->io_surface, plane_to_reuse_dip_enlarged_rect,
492 enlarged_contents_rect);
493
494 plane_for_swap->TakeCALayerFrom(plane_to_reuse.get());
495 if (plane_to_reuse != old_tree->partial_damage_planes_.back())
496 [plane_for_swap->ca_layer removeFromSuperlayer];
497 }
498 }
499
500 // If we haven't found an appropriate layer to re-use, create a new one, if
501 // we haven't already created too many.
502 if (!plane_for_swap.get() && !pixel_damage_rect.IsEmpty() &&
503 old_tree->partial_damage_planes_.size() < kMaximumPartialDamageLayers) {
504 gfx::RectF contents_rect = gfx::RectF(pixel_damage_rect);
505 contents_rect.Scale(1. / root_plane_->pixel_frame_rect.width(),
506 1. / root_plane_->pixel_frame_rect.height());
507 plane_for_swap = OverlayPlane::CreateWithFrameRect(
508 0, root_plane_->io_surface, pixel_damage_rect, contents_rect);
509 }
510
511 // And if we still don't have a layer, use the root layer.
512 if (!plane_for_swap.get() && !pixel_damage_rect.IsEmpty())
513 plane_for_swap = root_plane_;
514
515 // Walk all old partial damage planes. Remove anything that is now completely
516 // covered, and move everything else into the new |partial_damage_planes_|.
517 if (old_tree) {
518 for (auto& old_plane : old_tree->partial_damage_planes_) {
519 // Intersect the planes' frames with the new root plane to ensure that
520 // they don't get kept alive inappropriately.
521 gfx::RectF old_plane_frame_rect = old_plane->pixel_frame_rect;
522 old_plane_frame_rect.Intersect(root_plane_->pixel_frame_rect);
523
524 bool old_plane_covered_by_swap = false;
525 if (plane_for_swap.get() &&
526 plane_for_swap->pixel_frame_rect.Contains(old_plane_frame_rect)) {
527 old_plane_covered_by_swap = true;
528 }
529 if (!old_plane_covered_by_swap) {
530 DCHECK(old_plane->ca_layer);
531 partial_damage_planes_.push_back(old_plane);
532 }
533 }
534 if (plane_for_swap != root_plane_)
535 root_plane_ = old_tree->root_plane_;
536 }
537
538 // Finally, add the new swap's plane at the back of the list, if it exists.
539 if (plane_for_swap.get() && plane_for_swap != root_plane_) {
540 partial_damage_planes_.push_back(plane_for_swap);
541 }
542 }
543
544 void CALayerPartialDamageTree::UpdateRootAndPartialDamageCALayers(
545 CALayer* superlayer,
546 float scale_factor) {
547 if (!allow_partial_swap_) {
548 DCHECK(partial_damage_planes_.empty());
549 return;
550 }
551
552 // Allocate and update CALayers for the backbuffer and partial damage layers.
553 if (!root_plane_->ca_layer) {
554 root_plane_->ca_layer.reset([[CALayer alloc] init]);
555 [superlayer setSublayers:nil];
556 [superlayer addSublayer:root_plane_->ca_layer];
557 }
558 for (auto& plane : partial_damage_planes_) {
559 if (!plane->ca_layer) {
560 DCHECK(plane == partial_damage_planes_.back());
561 plane->ca_layer.reset([[CALayer alloc] init]);
562 }
563 if (![plane->ca_layer superlayer]) {
564 DCHECK(plane == partial_damage_planes_.back());
565 [superlayer addSublayer:plane->ca_layer];
566 }
567 }
568 root_plane_->UpdateProperties(scale_factor);
569 for (auto& plane : partial_damage_planes_)
570 plane->UpdateProperties(scale_factor);
571 }
572
573 void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() { 324 void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() {
574 TRACE_EVENT0("gpu", 325 TRACE_EVENT0("gpu",
575 "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps"); 326 "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps");
576 while (!pending_swaps_.empty()) 327 while (!pending_swaps_.empty())
577 DisplayFirstPendingSwapImmediately(); 328 DisplayFirstPendingSwapImmediately();
578 } 329 }
579 330
580 void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() { 331 void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() {
581 TRACE_EVENT0("gpu", 332 TRACE_EVENT0("gpu",
582 "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback"); 333 "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback");
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 509
759 // Compute the previous vsync time. 510 // Compute the previous vsync time.
760 base::TimeTicks previous_vsync = 511 base::TimeTicks previous_vsync =
761 vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) + 512 vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) +
762 vsync_timebase_; 513 vsync_timebase_;
763 514
764 // Return |interval_fraction| through the next vsync. 515 // Return |interval_fraction| through the next vsync.
765 return previous_vsync + (1 + interval_fraction) * vsync_interval_; 516 return previous_vsync + (1 + interval_fraction) * vsync_interval_;
766 } 517 }
767 518
768 CALayerPartialDamageTree::CALayerPartialDamageTree(
769 bool allow_partial_swap,
770 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
771 const gfx::Rect& pixel_frame_rect)
772 : allow_partial_swap_(allow_partial_swap) {
773 root_plane_ = OverlayPlane::CreateWithFrameRect(
774 0, io_surface, gfx::RectF(pixel_frame_rect), gfx::RectF(0, 0, 1, 1));
775 }
776
777 CALayerPartialDamageTree::~CALayerPartialDamageTree() {}
778
779 base::ScopedCFTypeRef<IOSurfaceRef>
780 CALayerPartialDamageTree::RootLayerIOSurface() {
781 return root_plane_->io_surface;
782 }
783
784 void CALayerPartialDamageTree::CommitCALayers(
785 CALayer* superlayer,
786 scoped_ptr<CALayerPartialDamageTree> old_tree,
787 float scale_factor,
788 const gfx::Rect& pixel_damage_rect) {
789 UpdateRootAndPartialDamagePlanes(old_tree.get(),
790 gfx::RectF(pixel_damage_rect));
791 UpdateRootAndPartialDamageCALayers(superlayer, scale_factor);
792 }
793
794 } // namespace content 519 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/image_transport_surface_overlay_mac.h ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698