| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |