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

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

Issue 1661453003: Mac overlays: Clean up partial swap code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2623
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 ImageTransportSurfaceOverlayMac::OverlayPlane {
98 public:
99 static linked_ptr<OverlayPlane> CreateWithFrameRect(
100 int z_order,
101 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
102 const gfx::RectF& pixel_frame_rect,
103 const gfx::RectF& contents_rect) {
104 gfx::Transform transform;
105 transform.Translate(pixel_frame_rect.x(), pixel_frame_rect.y());
106 return linked_ptr<OverlayPlane>(
107 new OverlayPlane(z_order, io_surface, contents_rect, pixel_frame_rect));
108 }
109
110 ~OverlayPlane() {
111 [ca_layer setContents:nil];
112 [ca_layer removeFromSuperlayer];
113 ca_layer.reset();
114 }
115
116 const int z_order;
117 const base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
118 const gfx::RectF contents_rect;
119 const gfx::RectF pixel_frame_rect;
120 bool layer_needs_update;
121 base::scoped_nsobject<CALayer> ca_layer;
122
123 void TakeCALayerFrom(OverlayPlane* other_plane) {
124 ca_layer.swap(other_plane->ca_layer);
125 }
126
127 void UpdateProperties(float scale_factor) {
128 if (layer_needs_update) {
129 [ca_layer setOpaque:YES];
130
131 id new_contents = static_cast<id>(io_surface.get());
132 if ([ca_layer contents] == new_contents && z_order == 0)
133 [ca_layer setContentsChanged];
134 else
135 [ca_layer setContents:new_contents];
136 [ca_layer setContentsRect:contents_rect.ToCGRect()];
137
138 [ca_layer setAnchorPoint:CGPointZero];
139
140 if ([ca_layer respondsToSelector:(@selector(setContentsScale:))])
141 [ca_layer setContentsScale:scale_factor];
142 gfx::RectF dip_frame_rect = gfx::RectF(pixel_frame_rect);
143 dip_frame_rect.Scale(1 / scale_factor);
144 [ca_layer setBounds:CGRectMake(0, 0, dip_frame_rect.width(),
145 dip_frame_rect.height())];
146 [ca_layer
147 setPosition:CGPointMake(dip_frame_rect.x(), dip_frame_rect.y())];
148 }
149 static bool show_borders =
150 base::CommandLine::ForCurrentProcess()->HasSwitch(
151 switches::kShowMacOverlayBorders);
152 if (show_borders) {
153 base::ScopedCFTypeRef<CGColorRef> color;
154 if (!layer_needs_update) {
155 // Green represents contents that are unchanged across frames.
156 color.reset(CGColorCreateGenericRGB(0, 1, 0, 1));
157 } else {
158 // Red represents damaged contents.
159 color.reset(CGColorCreateGenericRGB(1, 0, 0, 1));
160 }
161 [ca_layer setBorderWidth:1];
162 [ca_layer setBorderColor:color];
163 }
164 layer_needs_update = false;
165 }
166
167 private:
168 OverlayPlane(int z_order,
169 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
170 const gfx::RectF& contents_rect,
171 const gfx::RectF& pixel_frame_rect)
172 : z_order(z_order),
173 io_surface(io_surface),
174 contents_rect(contents_rect),
175 pixel_frame_rect(pixel_frame_rect),
176 layer_needs_update(true) {}
177 };
178
179 class ImageTransportSurfaceOverlayMac::PendingSwap { 85 class ImageTransportSurfaceOverlayMac::PendingSwap {
180 public: 86 public:
181 PendingSwap() {} 87 PendingSwap() {}
182 ~PendingSwap() { DCHECK(!gl_fence); } 88 ~PendingSwap() { DCHECK(!gl_fence); }
183 89
184 gfx::Size pixel_size; 90 gfx::Size pixel_size;
185 float scale_factor; 91 float scale_factor;
186 gfx::Rect pixel_damage_rect; 92 gfx::Rect pixel_damage_rect;
187 93
188 linked_ptr<OverlayPlane> root_plane; 94 scoped_ptr<CALayerPartialDamageTree> partial_damage_tree;
189 scoped_ptr<CALayerTree> ca_layer_tree; 95 scoped_ptr<CALayerTree> ca_layer_tree;
190 std::vector<ui::LatencyInfo> latency_info; 96 std::vector<ui::LatencyInfo> latency_info;
191 97
192 // A fence object, and the CGL context it was issued in. 98 // A fence object, and the CGL context it was issued in.
193 base::ScopedTypeRef<CGLContextObj> cgl_context; 99 base::ScopedTypeRef<CGLContextObj> cgl_context;
194 scoped_ptr<gfx::GLFence> gl_fence; 100 scoped_ptr<gfx::GLFence> gl_fence;
195 101
196 // The earliest time that this frame may be drawn. A frame is not allowed 102 // The earliest time that this frame may be drawn. A frame is not allowed
197 // to draw until a fraction of the way through the vsync interval after its 103 // to draw until a fraction of the way through the vsync interval after its
198 // This extra latency is to allow wiggle-room for smoothness. 104 // This extra latency is to allow wiggle-room for smoothness.
199 base::TimeTicks earliest_display_time_allowed; 105 base::TimeTicks earliest_display_time_allowed;
200 106
201 // The time that this will wake up and draw, if a following swap does not 107 // The time that this will wake up and draw, if a following swap does not
202 // cause it to draw earlier. 108 // cause it to draw earlier.
203 base::TimeTicks target_display_time; 109 base::TimeTicks target_display_time;
204 }; 110 };
205 111
206 ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac( 112 ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac(
207 GpuChannelManager* manager, 113 GpuChannelManager* manager,
208 GpuCommandBufferStub* stub, 114 GpuCommandBufferStub* stub,
209 gfx::PluginWindowHandle handle) 115 gfx::PluginWindowHandle handle)
210 : use_remote_layer_api_(ui::RemoteLayerAPISupported()), 116 : use_remote_layer_api_(ui::RemoteLayerAPISupported()),
211 scale_factor_(1), 117 scale_factor_(1),
212 gl_renderer_id_(0), 118 gl_renderer_id_(0),
213 vsync_parameters_valid_(false), 119 vsync_parameters_valid_(false),
214 next_ca_layer_z_order_(1),
215 display_pending_swap_timer_(true, false), 120 display_pending_swap_timer_(true, false),
216 weak_factory_(this) { 121 weak_factory_(this) {
217 helper_.reset(new ImageTransportHelper(this, manager, stub, handle)); 122 helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
218 ui::GpuSwitchingManager::GetInstance()->AddObserver(this); 123 ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
219 } 124 }
220 125
221 ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() { 126 ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() {
222 ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this); 127 ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
223 Destroy(); 128 Destroy();
224 } 129 }
(...skipping 11 matching lines...) Expand all
236 ca_root_layer_.reset([[CALayer alloc] init]); 141 ca_root_layer_.reset([[CALayer alloc] init]);
237 [ca_root_layer_ setGeometryFlipped:YES]; 142 [ca_root_layer_ setGeometryFlipped:YES];
238 [ca_root_layer_ setOpaque:YES]; 143 [ca_root_layer_ setOpaque:YES];
239 [ca_context_ setLayer:ca_root_layer_]; 144 [ca_context_ setLayer:ca_root_layer_];
240 } 145 }
241 return true; 146 return true;
242 } 147 }
243 148
244 void ImageTransportSurfaceOverlayMac::Destroy() { 149 void ImageTransportSurfaceOverlayMac::Destroy() {
245 DisplayAndClearAllPendingSwaps(); 150 DisplayAndClearAllPendingSwaps();
246 current_partial_damage_planes_.clear(); 151
247 current_root_plane_.reset(); 152 current_partial_damage_tree_.reset();
153 current_ca_layer_tree_.reset();
248 } 154 }
249 155
250 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { 156 bool ImageTransportSurfaceOverlayMac::IsOffscreen() {
251 return false; 157 return false;
252 } 158 }
253 159
254 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal( 160 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal(
255 const gfx::Rect& pixel_damage_rect) { 161 const gfx::Rect& pixel_damage_rect) {
256 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); 162 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal");
257 next_ca_layer_z_order_ = 1;
258 163
259 // Use the same concept of 'now' for the entire function. The duration of 164 // Use the same concept of 'now' for the entire function. The duration of
260 // this function only affect the result if this function lasts across a vsync 165 // this function only affect the result if this function lasts across a vsync
261 // boundary, in which case smooth animation is out the window anyway. 166 // boundary, in which case smooth animation is out the window anyway.
262 const base::TimeTicks now = base::TimeTicks::Now(); 167 const base::TimeTicks now = base::TimeTicks::Now();
263 168
264 // Decide if the frame should be drawn immediately, or if we should wait until 169 // Decide if the frame should be drawn immediately, or if we should wait until
265 // its work finishes before drawing immediately. 170 // its work finishes before drawing immediately.
266 bool display_immediately = false; 171 bool display_immediately = false;
267 if (vsync_parameters_valid_ && 172 if (vsync_parameters_valid_ &&
(...skipping 10 matching lines...) Expand all
278 if (IsFirstPendingSwapReadyToDisplay(now)) 183 if (IsFirstPendingSwapReadyToDisplay(now))
279 DisplayFirstPendingSwapImmediately(); 184 DisplayFirstPendingSwapImmediately();
280 } 185 }
281 186
282 // The remainder of the function will populate the PendingSwap structure and 187 // The remainder of the function will populate the PendingSwap structure and
283 // then enqueue it. 188 // then enqueue it.
284 linked_ptr<PendingSwap> new_swap(new PendingSwap); 189 linked_ptr<PendingSwap> new_swap(new PendingSwap);
285 new_swap->pixel_size = pixel_size_; 190 new_swap->pixel_size = pixel_size_;
286 new_swap->scale_factor = scale_factor_; 191 new_swap->scale_factor = scale_factor_;
287 new_swap->pixel_damage_rect = pixel_damage_rect; 192 new_swap->pixel_damage_rect = pixel_damage_rect;
288 new_swap->root_plane = pending_root_plane_; 193 new_swap->partial_damage_tree.swap(pending_partial_damage_tree_);
289 pending_root_plane_ = linked_ptr<OverlayPlane>();
290 new_swap->ca_layer_tree.swap(pending_ca_layer_tree_); 194 new_swap->ca_layer_tree.swap(pending_ca_layer_tree_);
291 new_swap->latency_info.swap(latency_info_); 195 new_swap->latency_info.swap(latency_info_);
292 196
293 // A flush is required to ensure that all content appears in the layer. 197 // A flush is required to ensure that all content appears in the layer.
294 { 198 {
295 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; 199 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
296 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFlush"); 200 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFlush");
297 CheckGLErrors("before flushing frame"); 201 CheckGLErrors("before flushing frame");
298 new_swap->cgl_context.reset(CGLGetCurrentContext(), 202 new_swap->cgl_context.reset(CGLGetCurrentContext(),
299 base::scoped_policy::RETAIN); 203 base::scoped_policy::RETAIN);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 // If there is a fence for this object, delete it. 263 // If there is a fence for this object, delete it.
360 if (swap->gl_fence) { 264 if (swap->gl_fence) {
361 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; 265 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
362 gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); 266 gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context);
363 267
364 CheckGLErrors("before deleting active fence"); 268 CheckGLErrors("before deleting active fence");
365 swap->gl_fence.reset(); 269 swap->gl_fence.reset();
366 CheckGLErrors("while deleting active fence"); 270 CheckGLErrors("while deleting active fence");
367 } 271 }
368 272
369 // Update the plane lists. 273 // Update the CALayer hierarchy.
370 { 274 {
371 // Sort the input planes by z-index, and remove any overlays from the
372 // damage rect.
373 gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect); 275 gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect);
374 ScopedCAActionDisabler disabler; 276 ScopedCAActionDisabler disabler;
375 UpdateRootAndPartialDamagePlanes(swap->root_plane, pixel_damage_rect); 277 if (swap->ca_layer_tree) {
376 UpdateRootAndPartialDamageCALayers(swap->scale_factor); 278 swap->ca_layer_tree->CommitScheduledCALayers(
377 UpdateCALayerTree(std::move(swap->ca_layer_tree), swap->scale_factor); 279 ca_root_layer_.get(), std::move(current_ca_layer_tree_),
280 swap->scale_factor);
281 current_ca_layer_tree_.swap(swap->ca_layer_tree);
282 current_partial_damage_tree_.reset();
283 } else if (swap->partial_damage_tree) {
284 swap->partial_damage_tree->CommitCALayers(
285 ca_root_layer_.get(), std::move(current_partial_damage_tree_),
286 swap->scale_factor, swap->pixel_damage_rect);
287 current_partial_damage_tree_.swap(swap->partial_damage_tree);
288 current_ca_layer_tree_.reset();
289 } else {
290 [ca_root_layer_ setSublayers:nil];
291 }
292 swap->ca_layer_tree.reset();
293 swap->partial_damage_tree.reset();
378 } 294 }
379 295
380 // Update the latency info to reflect the swap time. 296 // Update the latency info to reflect the swap time.
381 base::TimeTicks swap_time = base::TimeTicks::Now(); 297 base::TimeTicks swap_time = base::TimeTicks::Now();
382 for (auto latency_info : swap->latency_info) { 298 for (auto latency_info : swap->latency_info) {
383 latency_info.AddLatencyNumberWithTimestamp( 299 latency_info.AddLatencyNumberWithTimestamp(
384 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1); 300 ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
385 latency_info.AddLatencyNumberWithTimestamp( 301 latency_info.AddLatencyNumberWithTimestamp(
386 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0, 302 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
387 swap_time, 1); 303 swap_time, 1);
388 } 304 }
389 305
390 // Send acknowledgement to the browser. 306 // Send acknowledgement to the browser.
391 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; 307 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
392 if (use_remote_layer_api_) { 308 if (use_remote_layer_api_) {
393 params.ca_context_id = [ca_context_ contextId]; 309 params.ca_context_id = [ca_context_ contextId];
394 } else if (current_root_plane_.get()) { 310 } else if (current_partial_damage_tree_) {
395 params.io_surface.reset( 311 params.io_surface.reset(IOSurfaceCreateMachPort(
396 IOSurfaceCreateMachPort(current_root_plane_->io_surface)); 312 current_partial_damage_tree_->RootLayerIOSurface()));
397 } 313 }
398 params.size = swap->pixel_size; 314 params.size = swap->pixel_size;
399 params.scale_factor = swap->scale_factor; 315 params.scale_factor = swap->scale_factor;
400 params.latency_info.swap(swap->latency_info); 316 params.latency_info.swap(swap->latency_info);
401 helper_->SendAcceleratedSurfaceBuffersSwapped(params); 317 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
402 318
403 // Remove this from the queue, and reset any callback timers. 319 // Remove this from the queue, and reset any callback timers.
404 pending_swaps_.pop_front(); 320 pending_swaps_.pop_front();
405 } 321 }
406 322
407 void ImageTransportSurfaceOverlayMac::UpdateRootAndPartialDamagePlanes(
408 const linked_ptr<OverlayPlane>& new_root_plane,
409 const gfx::RectF& pixel_damage_rect) {
410 std::list<linked_ptr<OverlayPlane>> old_partial_damage_planes;
411 old_partial_damage_planes.swap(current_partial_damage_planes_);
412 linked_ptr<OverlayPlane> plane_for_swap;
413
414 // If there is no new root plane, remove everything.
415 if (!new_root_plane.get()) {
416 old_partial_damage_planes.clear();
417 current_root_plane_.reset();
418 return;
419 }
420
421 // If the frame's size changed, if we haven't updated the root layer, if
422 // we have full damage, or if we don't support remote layers, then use the
423 // root layer directly.
424 if (!use_remote_layer_api_ || !current_root_plane_.get() ||
425 current_root_plane_->pixel_frame_rect !=
426 new_root_plane->pixel_frame_rect ||
427 pixel_damage_rect == new_root_plane->pixel_frame_rect) {
428 plane_for_swap = new_root_plane;
429 }
430
431 // Walk though the existing partial damage layers and see if there is one that
432 // is appropriate to re-use.
433 if (!plane_for_swap.get() && !pixel_damage_rect.IsEmpty()) {
434 gfx::RectF plane_to_reuse_dip_enlarged_rect;
435
436 // Find the last partial damage plane to re-use the CALayer from. Grow the
437 // new rect for this layer to include this damage, and all nearby partial
438 // damage layers.
439 linked_ptr<OverlayPlane> plane_to_reuse;
440 for (auto& old_plane : old_partial_damage_planes) {
441 gfx::RectF dip_enlarged_rect = old_plane->pixel_frame_rect;
442 dip_enlarged_rect.Union(pixel_damage_rect);
443
444 // Compute the fraction of the pixels that would not be updated by this
445 // swap. If it is too big, try another layer.
446 float waste_fraction = dip_enlarged_rect.size().GetArea() * 1.f /
447 pixel_damage_rect.size().GetArea();
448 if (waste_fraction > kMaximumPartialDamageWasteFraction)
449 continue;
450
451 plane_to_reuse = old_plane;
452 plane_to_reuse_dip_enlarged_rect.Union(dip_enlarged_rect);
453 }
454
455 if (plane_to_reuse.get()) {
456 gfx::RectF enlarged_contents_rect = plane_to_reuse_dip_enlarged_rect;
457 enlarged_contents_rect.Scale(
458 1. / new_root_plane->pixel_frame_rect.width(),
459 1. / new_root_plane->pixel_frame_rect.height());
460
461 plane_for_swap = OverlayPlane::CreateWithFrameRect(
462 0, new_root_plane->io_surface, plane_to_reuse_dip_enlarged_rect,
463 enlarged_contents_rect);
464
465 plane_for_swap->TakeCALayerFrom(plane_to_reuse.get());
466 if (plane_to_reuse != old_partial_damage_planes.back())
467 [plane_for_swap->ca_layer removeFromSuperlayer];
468 }
469 }
470
471 // If we haven't found an appropriate layer to re-use, create a new one, if
472 // we haven't already created too many.
473 if (!plane_for_swap.get() && !pixel_damage_rect.IsEmpty() &&
474 old_partial_damage_planes.size() < kMaximumPartialDamageLayers) {
475 gfx::RectF contents_rect = gfx::RectF(pixel_damage_rect);
476 contents_rect.Scale(1. / new_root_plane->pixel_frame_rect.width(),
477 1. / new_root_plane->pixel_frame_rect.height());
478 plane_for_swap = OverlayPlane::CreateWithFrameRect(
479 0, new_root_plane->io_surface, pixel_damage_rect, contents_rect);
480 }
481
482 // And if we still don't have a layer, use the root layer.
483 if (!plane_for_swap.get() && !pixel_damage_rect.IsEmpty())
484 plane_for_swap = new_root_plane;
485
486 // Walk all old partial damage planes. Remove anything that is now completely
487 // covered, and move everything else into the new
488 // |current_partial_damage_planes_|.
489 for (auto& old_plane : old_partial_damage_planes) {
490 // Intersect the planes' frames with the new root plane to ensure that
491 // they don't get kept alive inappropriately.
492 gfx::RectF old_plane_frame_rect = old_plane->pixel_frame_rect;
493 old_plane_frame_rect.Intersect(new_root_plane->pixel_frame_rect);
494
495 bool old_plane_covered_by_swap = false;
496 if (plane_for_swap.get() &&
497 plane_for_swap->pixel_frame_rect.Contains(old_plane_frame_rect)) {
498 old_plane_covered_by_swap = true;
499 }
500 if (!old_plane_covered_by_swap) {
501 DCHECK(old_plane->ca_layer);
502 current_partial_damage_planes_.push_back(old_plane);
503 }
504 }
505
506 // Finally, add the new swap's plane at the back of the list, if it exists.
507 if (plane_for_swap == new_root_plane) {
508 current_root_plane_ = new_root_plane;
509 } else if (plane_for_swap.get()) {
510 current_partial_damage_planes_.push_back(plane_for_swap);
511 }
512 }
513
514 void ImageTransportSurfaceOverlayMac::UpdateRootAndPartialDamageCALayers(
515 float scale_factor) {
516 if (!use_remote_layer_api_) {
517 DCHECK(current_partial_damage_planes_.empty());
518 return;
519 }
520
521 // Allocate and update CALayers for the backbuffer and partial damage layers.
522 if (current_root_plane_.get()) {
523 if (!current_root_plane_->ca_layer) {
524 current_root_plane_->ca_layer.reset([[CALayer alloc] init]);
525 [ca_root_layer_ setSublayers:nil];
526 [ca_root_layer_ addSublayer:current_root_plane_->ca_layer];
527 }
528 }
529 for (auto& plane : current_partial_damage_planes_) {
530 if (!plane->ca_layer) {
531 DCHECK(plane == current_partial_damage_planes_.back());
532 plane->ca_layer.reset([[CALayer alloc] init]);
533 }
534 if (![plane->ca_layer superlayer]) {
535 DCHECK(plane == current_partial_damage_planes_.back());
536 [ca_root_layer_ addSublayer:plane->ca_layer];
537 }
538 }
539 if (current_root_plane_.get())
540 current_root_plane_->UpdateProperties(scale_factor);
541 for (auto& plane : current_partial_damage_planes_)
542 plane->UpdateProperties(scale_factor);
543 }
544
545 void ImageTransportSurfaceOverlayMac::UpdateCALayerTree(
546 scoped_ptr<CALayerTree> ca_layer_tree,
547 float scale_factor) {
548 if (ca_layer_tree) {
549 ca_layer_tree->CommitScheduledCALayers(
550 ca_root_layer_.get(), std::move(current_ca_layer_tree_), scale_factor);
551 current_ca_layer_tree_.swap(ca_layer_tree);
552 ca_layer_tree.reset();
553 } else {
554 current_ca_layer_tree_.reset();
555 }
556 }
557
558 void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() { 323 void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() {
559 TRACE_EVENT0("gpu", 324 TRACE_EVENT0("gpu",
560 "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps"); 325 "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps");
561 while (!pending_swaps_.empty()) 326 while (!pending_swaps_.empty())
562 DisplayFirstPendingSwapImmediately(); 327 DisplayFirstPendingSwapImmediately();
563 } 328 }
564 329
565 void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() { 330 void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() {
566 TRACE_EVENT0("gpu", 331 TRACE_EVENT0("gpu",
567 "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback"); 332 "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback");
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 const gfx::Rect& pixel_frame_rect, 403 const gfx::Rect& pixel_frame_rect,
639 const gfx::RectF& crop_rect) { 404 const gfx::RectF& crop_rect) {
640 if (transform != gfx::OVERLAY_TRANSFORM_NONE) { 405 if (transform != gfx::OVERLAY_TRANSFORM_NONE) {
641 DLOG(ERROR) << "Invalid overlay plane transform."; 406 DLOG(ERROR) << "Invalid overlay plane transform.";
642 return false; 407 return false;
643 } 408 }
644 if (z_order) { 409 if (z_order) {
645 DLOG(ERROR) << "Invalid non-zero Z order."; 410 DLOG(ERROR) << "Invalid non-zero Z order.";
646 return false; 411 return false;
647 } 412 }
648 413 if (pending_partial_damage_tree_) {
649 pending_root_plane_ = OverlayPlane::CreateWithFrameRect( 414 DLOG(ERROR) << "Only one overlay per swap is allowed.";
650 z_order, static_cast<gl::GLImageIOSurface*>(image)->io_surface(), 415 return false;
651 gfx::RectF(pixel_frame_rect), crop_rect); 416 }
417 pending_partial_damage_tree_.reset(new CALayerPartialDamageTree(
418 use_remote_layer_api_,
419 static_cast<gl::GLImageIOSurface*>(image)->io_surface(),
420 pixel_frame_rect));
652 return true; 421 return true;
653 } 422 }
654 423
655 bool ImageTransportSurfaceOverlayMac::ScheduleCALayer( 424 bool ImageTransportSurfaceOverlayMac::ScheduleCALayer(
656 gl::GLImage* contents_image, 425 gl::GLImage* contents_image,
657 const gfx::RectF& contents_rect, 426 const gfx::RectF& contents_rect,
658 float opacity, 427 float opacity,
659 unsigned background_color, 428 unsigned background_color,
660 unsigned edge_aa_mask, 429 unsigned edge_aa_mask,
661 const gfx::RectF& rect, 430 const gfx::RectF& rect,
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 // Compute the previous vsync time. 509 // Compute the previous vsync time.
741 base::TimeTicks previous_vsync = 510 base::TimeTicks previous_vsync =
742 vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) + 511 vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) +
743 vsync_timebase_; 512 vsync_timebase_;
744 513
745 // Return |interval_fraction| through the next vsync. 514 // Return |interval_fraction| through the next vsync.
746 return previous_vsync + (1 + interval_fraction) * vsync_interval_; 515 return previous_vsync + (1 + interval_fraction) * vsync_interval_;
747 } 516 }
748 517
749 } // namespace content 518 } // 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