| 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 <IOSurface/IOSurface.h> | 7 #include <IOSurface/IOSurface.h> |
| 8 #include <OpenGL/GL.h> | 8 #include <OpenGL/GL.h> |
| 9 | 9 |
| 10 // This type consistently causes problem on Mac, and needs to be dealt with | 10 // This type consistently causes problem on Mac, and needs to be dealt with |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 | 57 |
| 58 class ImageTransportSurfaceOverlayMac::PendingSwap { | 58 class ImageTransportSurfaceOverlayMac::PendingSwap { |
| 59 public: | 59 public: |
| 60 PendingSwap() : scale_factor(1) {} | 60 PendingSwap() : scale_factor(1) {} |
| 61 ~PendingSwap() { DCHECK(!gl_fence); } | 61 ~PendingSwap() { DCHECK(!gl_fence); } |
| 62 | 62 |
| 63 gfx::Size pixel_size; | 63 gfx::Size pixel_size; |
| 64 float scale_factor; | 64 float scale_factor; |
| 65 std::vector<ui::LatencyInfo> latency_info; | 65 std::vector<ui::LatencyInfo> latency_info; |
| 66 | 66 |
| 67 // If true, the partial damage rect for the frame. |
| 68 bool use_partial_damage; |
| 69 gfx::Rect pixel_partial_damage_rect; |
| 70 |
| 67 // The IOSurface with new content for this swap. | 71 // The IOSurface with new content for this swap. |
| 68 base::ScopedCFTypeRef<IOSurfaceRef> io_surface; | 72 base::ScopedCFTypeRef<IOSurfaceRef> io_surface; |
| 69 | 73 |
| 70 // A fence object, and the CGL context it was issued in. | 74 // A fence object, and the CGL context it was issued in. |
| 71 base::ScopedTypeRef<CGLContextObj> cgl_context; | 75 base::ScopedTypeRef<CGLContextObj> cgl_context; |
| 72 scoped_ptr<gfx::GLFence> gl_fence; | 76 scoped_ptr<gfx::GLFence> gl_fence; |
| 73 | 77 |
| 74 // The earliest time that this frame may be drawn. A frame is not allowed | 78 // The earliest time that this frame may be drawn. A frame is not allowed |
| 75 // to draw until a fraction of the way through the vsync interval after its | 79 // to draw until a fraction of the way through the vsync interval after its |
| 76 // This extra latency is to allow wiggle-room for smoothness. | 80 // This extra latency is to allow wiggle-room for smoothness. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 98 | 102 |
| 99 // Create the CAContext to send this to the GPU process, and the layer for | 103 // Create the CAContext to send this to the GPU process, and the layer for |
| 100 // the context. | 104 // the context. |
| 101 CGSConnectionID connection_id = CGSMainConnectionID(); | 105 CGSConnectionID connection_id = CGSMainConnectionID(); |
| 102 ca_context_.reset( | 106 ca_context_.reset( |
| 103 [[CAContext contextWithCGSConnection:connection_id options:@{}] retain]); | 107 [[CAContext contextWithCGSConnection:connection_id options:@{}] retain]); |
| 104 layer_.reset([[CALayer alloc] init]); | 108 layer_.reset([[CALayer alloc] init]); |
| 105 [layer_ setGeometryFlipped:YES]; | 109 [layer_ setGeometryFlipped:YES]; |
| 106 [layer_ setOpaque:YES]; | 110 [layer_ setOpaque:YES]; |
| 107 [ca_context_ setLayer:layer_]; | 111 [ca_context_ setLayer:layer_]; |
| 112 |
| 113 partial_damage_layer_.reset([[CALayer alloc] init]); |
| 114 [partial_damage_layer_ setOpaque:YES]; |
| 108 return true; | 115 return true; |
| 109 } | 116 } |
| 110 | 117 |
| 111 void ImageTransportSurfaceOverlayMac::Destroy() { | 118 void ImageTransportSurfaceOverlayMac::Destroy() { |
| 112 FinishAllPendingSwaps(); | 119 FinishAllPendingSwaps(); |
| 113 } | 120 } |
| 114 | 121 |
| 115 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { | 122 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { |
| 116 return false; | 123 return false; |
| 117 } | 124 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 new_swap->latest_allowed_draw_time = now + | 180 new_swap->latest_allowed_draw_time = now + |
| 174 base::TimeDelta::FromSecondsD(kMaximumDelayWaitingForFenceInSeconds); | 181 base::TimeDelta::FromSecondsD(kMaximumDelayWaitingForFenceInSeconds); |
| 175 } else { | 182 } else { |
| 176 // If we have no display link (because vsync is disabled or because we have | 183 // If we have no display link (because vsync is disabled or because we have |
| 177 // not received display parameters yet), immediately attempt to display the | 184 // not received display parameters yet), immediately attempt to display the |
| 178 // surface. | 185 // surface. |
| 179 new_swap->earliest_allowed_draw_time = now; | 186 new_swap->earliest_allowed_draw_time = now; |
| 180 new_swap->latest_allowed_draw_time = now; | 187 new_swap->latest_allowed_draw_time = now; |
| 181 } | 188 } |
| 182 | 189 |
| 190 // Determine if this will be a full or partial damage, and compute the rects |
| 191 // for the damage. |
| 192 { |
| 193 // Grow the partial damage rect to include the new damage. |
| 194 accumulated_partial_damage_pixel_rect_.Union(pixel_damage_rect); |
| 195 // Compute the fraction of the full layer that has been damaged. If this |
| 196 // fraction is very large (>85%), just damage the full layer, and don't |
| 197 // bother with the partial layer. |
| 198 const double kMaximumFractionOfFullDamage = 0.85; |
| 199 double fraction_of_full_damage = |
| 200 accumulated_partial_damage_pixel_rect_.size().GetArea() / |
| 201 static_cast<double>(pixel_size_.GetArea()); |
| 202 // Compute the fraction of the accumulated partial damage rect that has been |
| 203 // damaged. If this gets too small (<75%), just re-damage the full window, |
| 204 // so we can re-create a smaller partial damage layer next frame. |
| 205 const double kMinimumFractionOfPartialDamage = 0.75; |
| 206 double fraction_of_partial_damage = |
| 207 pixel_damage_rect.size().GetArea() / static_cast<double>( |
| 208 accumulated_partial_damage_pixel_rect_.size().GetArea()); |
| 209 if (fraction_of_full_damage < kMaximumFractionOfFullDamage && |
| 210 fraction_of_partial_damage > kMinimumFractionOfPartialDamage) { |
| 211 new_swap->use_partial_damage = true; |
| 212 new_swap->pixel_partial_damage_rect = |
| 213 accumulated_partial_damage_pixel_rect_; |
| 214 } else { |
| 215 new_swap->use_partial_damage = false; |
| 216 accumulated_partial_damage_pixel_rect_ = gfx::Rect(); |
| 217 } |
| 218 } |
| 219 |
| 183 pending_swaps_.push_back(new_swap); | 220 pending_swaps_.push_back(new_swap); |
| 184 PostCheckPendingSwapsCallbackIfNeeded(now); | 221 PostCheckPendingSwapsCallbackIfNeeded(now); |
| 185 return gfx::SwapResult::SWAP_ACK; | 222 return gfx::SwapResult::SWAP_ACK; |
| 186 } | 223 } |
| 187 | 224 |
| 188 bool ImageTransportSurfaceOverlayMac::IsFirstPendingSwapReadyToDisplay( | 225 bool ImageTransportSurfaceOverlayMac::IsFirstPendingSwapReadyToDisplay( |
| 189 const base::TimeTicks& now) { | 226 const base::TimeTicks& now) { |
| 190 DCHECK(!pending_swaps_.empty()); | 227 DCHECK(!pending_swaps_.empty()); |
| 191 linked_ptr<PendingSwap> swap = pending_swaps_.front(); | 228 linked_ptr<PendingSwap> swap = pending_swaps_.front(); |
| 192 | 229 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 CheckGLErrors("while deleting active fence"); | 276 CheckGLErrors("while deleting active fence"); |
| 240 } | 277 } |
| 241 | 278 |
| 242 // Update the CALayer hierarchy. | 279 // Update the CALayer hierarchy. |
| 243 { | 280 { |
| 244 TRACE_EVENT1("gpu", "ImageTransportSurfaceOverlayMac::setContents", | 281 TRACE_EVENT1("gpu", "ImageTransportSurfaceOverlayMac::setContents", |
| 245 "surface", swap->io_surface.get()); | 282 "surface", swap->io_surface.get()); |
| 246 ScopedCAActionDisabler disabler; | 283 ScopedCAActionDisabler disabler; |
| 247 | 284 |
| 248 id new_contents = static_cast<id>(swap->io_surface.get()); | 285 id new_contents = static_cast<id>(swap->io_surface.get()); |
| 249 [layer_ setContents:new_contents]; | 286 if (swap->use_partial_damage) { |
| 287 if (![partial_damage_layer_ superlayer]) |
| 288 [layer_ addSublayer:partial_damage_layer_]; |
| 289 [partial_damage_layer_ setContents:new_contents]; |
| 250 | 290 |
| 251 CGRect new_frame = gfx::ConvertRectToDIP( | 291 CGRect new_frame = gfx::ConvertRectToDIP( |
| 252 swap->scale_factor, gfx::Rect(swap->pixel_size)).ToCGRect(); | 292 swap->scale_factor, swap->pixel_partial_damage_rect).ToCGRect(); |
| 253 if (!CGRectEqualToRect([layer_ frame], new_frame)) | 293 if (!CGRectEqualToRect([partial_damage_layer_ frame], new_frame)) |
| 254 [layer_ setFrame:new_frame]; | 294 [partial_damage_layer_ setFrame:new_frame]; |
| 295 |
| 296 gfx::RectF contents_rect = |
| 297 gfx::RectF(swap->pixel_partial_damage_rect); |
| 298 contents_rect.Scale( |
| 299 1. / swap->pixel_size.width(), 1. / swap->pixel_size.height()); |
| 300 CGRect cg_contents_rect = CGRectMake( |
| 301 contents_rect.x(), contents_rect.y(), |
| 302 contents_rect.width(), contents_rect.height()); |
| 303 [partial_damage_layer_ setContentsRect:cg_contents_rect]; |
| 304 } else { |
| 305 // Remove the partial damage layer. |
| 306 if ([partial_damage_layer_ superlayer]) { |
| 307 [partial_damage_layer_ removeFromSuperlayer]; |
| 308 [partial_damage_layer_ setContents:nil]; |
| 309 } |
| 310 |
| 311 // Note that calling setContents with the same IOSurface twice will result |
| 312 // in the screen not being updated, even if the IOSurface's content has |
| 313 // changed. Avoid this by calling setContentsChanged. |
| 314 if ([layer_ contents] == new_contents) |
| 315 [layer_ setContentsChanged]; |
| 316 else |
| 317 [layer_ setContents:new_contents]; |
| 318 |
| 319 CGRect new_frame = gfx::ConvertRectToDIP( |
| 320 swap->scale_factor, gfx::Rect(swap->pixel_size)).ToCGRect(); |
| 321 if (!CGRectEqualToRect([layer_ frame], new_frame)) |
| 322 [layer_ setFrame:new_frame]; |
| 323 } |
| 255 } | 324 } |
| 256 | 325 |
| 257 // Send acknowledgement to the browser. | 326 // Send acknowledgement to the browser. |
| 258 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 327 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
| 259 params.surface_handle = | 328 params.surface_handle = |
| 260 ui::SurfaceHandleFromCAContextID([ca_context_ contextId]); | 329 ui::SurfaceHandleFromCAContextID([ca_context_ contextId]); |
| 261 params.size = pixel_size_; | 330 params.size = pixel_size_; |
| 262 params.scale_factor = scale_factor_; | 331 params.scale_factor = scale_factor_; |
| 263 params.latency_info.swap(swap->latency_info); | 332 params.latency_info.swap(swap->latency_info); |
| 264 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 333 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 | 448 |
| 380 void ImageTransportSurfaceOverlayMac::SetLatencyInfo( | 449 void ImageTransportSurfaceOverlayMac::SetLatencyInfo( |
| 381 const std::vector<ui::LatencyInfo>& latency_info) { | 450 const std::vector<ui::LatencyInfo>& latency_info) { |
| 382 latency_info_.insert( | 451 latency_info_.insert( |
| 383 latency_info_.end(), latency_info.begin(), latency_info.end()); | 452 latency_info_.end(), latency_info.begin(), latency_info.end()); |
| 384 } | 453 } |
| 385 | 454 |
| 386 void ImageTransportSurfaceOverlayMac::WakeUpGpu() {} | 455 void ImageTransportSurfaceOverlayMac::WakeUpGpu() {} |
| 387 | 456 |
| 388 } // namespace content | 457 } // namespace content |
| OLD | NEW |