| 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 <AVFoundation/AVFoundation.h> |
| 7 #include <CoreGraphics/CoreGraphics.h> | 8 #include <CoreGraphics/CoreGraphics.h> |
| 8 #include <IOSurface/IOSurface.h> | 9 #include <IOSurface/IOSurface.h> |
| 9 #include <OpenGL/CGLRenderers.h> | 10 #include <OpenGL/CGLRenderers.h> |
| 10 #include <OpenGL/CGLTypes.h> | 11 #include <OpenGL/CGLTypes.h> |
| 11 #include <OpenGL/gl.h> | 12 #include <OpenGL/gl.h> |
| 12 #include <stddef.h> | 13 #include <stddef.h> |
| 13 | 14 |
| 14 #include <algorithm> | 15 #include <algorithm> |
| 15 | 16 |
| 16 // This type consistently causes problem on Mac, and needs to be dealt with | 17 // This type consistently causes problem on Mac, and needs to be dealt with |
| (...skipping 16 matching lines...) Expand all Loading... |
| 33 #include "ui/base/cocoa/remote_layer_api.h" | 34 #include "ui/base/cocoa/remote_layer_api.h" |
| 34 #include "ui/gfx/geometry/rect_conversions.h" | 35 #include "ui/gfx/geometry/rect_conversions.h" |
| 35 #include "ui/gfx/transform.h" | 36 #include "ui/gfx/transform.h" |
| 36 #include "ui/gl/gl_context.h" | 37 #include "ui/gl/gl_context.h" |
| 37 #include "ui/gl/gl_fence.h" | 38 #include "ui/gl/gl_fence.h" |
| 38 #include "ui/gl/gl_image_io_surface.h" | 39 #include "ui/gl/gl_image_io_surface.h" |
| 39 #include "ui/gl/gpu_switching_manager.h" | 40 #include "ui/gl/gpu_switching_manager.h" |
| 40 #include "ui/gl/scoped_api.h" | 41 #include "ui/gl/scoped_api.h" |
| 41 #include "ui/gl/scoped_cgl.h" | 42 #include "ui/gl/scoped_cgl.h" |
| 42 | 43 |
| 44 #if !defined(MAC_OS_X_VERSION_10_8) || \ |
| 45 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 |
| 46 extern NSString* const AVLayerVideoGravityResize; |
| 47 #endif // MAC_OS_X_VERSION_10_8 |
| 48 |
| 43 namespace { | 49 namespace { |
| 44 | 50 |
| 45 // Don't let a frame draw until 5% of the way through the next vsync interval | 51 // Don't let a frame draw until 5% of the way through the next vsync interval |
| 46 // after the call to SwapBuffers. This slight offset is to ensure that skew | 52 // after the call to SwapBuffers. This slight offset is to ensure that skew |
| 47 // doesn't result in the frame being presented to the previous vsync interval. | 53 // doesn't result in the frame being presented to the previous vsync interval. |
| 48 const double kVSyncIntervalFractionForEarliestDisplay = 0.05; | 54 const double kVSyncIntervalFractionForEarliestDisplay = 0.05; |
| 49 | 55 |
| 50 // After doing a glFlush and putting in a fence in SwapBuffers, post a task to | 56 // After doing a glFlush and putting in a fence in SwapBuffers, post a task to |
| 51 // query the fence 50% of the way through the next vsync interval. If we are | 57 // query the fence 50% of the way through the next vsync interval. If we are |
| 52 // trying to animate smoothly, then want to query the fence at the next | 58 // trying to animate smoothly, then want to query the fence at the next |
| (...skipping 19 matching lines...) Expand all Loading... |
| 72 } | 78 } |
| 73 | 79 |
| 74 } // namespace | 80 } // namespace |
| 75 | 81 |
| 76 @interface CALayer(Private) | 82 @interface CALayer(Private) |
| 77 -(void)setContentsChanged; | 83 -(void)setContentsChanged; |
| 78 @end | 84 @end |
| 79 | 85 |
| 80 namespace content { | 86 namespace content { |
| 81 | 87 |
| 88 void UpdateVideoLayer(AVSampleBufferDisplayLayer* sample_buffer_display_layer); |
| 89 |
| 82 scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( | 90 scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( |
| 83 GpuChannelManager* manager, | 91 GpuChannelManager* manager, |
| 84 GpuCommandBufferStub* stub, | 92 GpuCommandBufferStub* stub, |
| 85 gpu::SurfaceHandle handle) { | 93 gpu::SurfaceHandle handle) { |
| 86 return new ImageTransportSurfaceOverlayMac(manager, stub, handle); | 94 return new ImageTransportSurfaceOverlayMac(manager, stub, handle); |
| 87 } | 95 } |
| 88 | 96 |
| 89 class ImageTransportSurfaceOverlayMac::PendingSwap { | 97 class ImageTransportSurfaceOverlayMac::PendingSwap { |
| 90 public: | 98 public: |
| 91 PendingSwap() {} | 99 PendingSwap() {} |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 // Create the CAContext to send this to the GPU process, and the layer for | 162 // Create the CAContext to send this to the GPU process, and the layer for |
| 155 // the context. | 163 // the context. |
| 156 if (use_remote_layer_api_) { | 164 if (use_remote_layer_api_) { |
| 157 CGSConnectionID connection_id = CGSMainConnectionID(); | 165 CGSConnectionID connection_id = CGSMainConnectionID(); |
| 158 ca_context_.reset([ | 166 ca_context_.reset([ |
| 159 [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); | 167 [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); |
| 160 ca_root_layer_.reset([[CALayer alloc] init]); | 168 ca_root_layer_.reset([[CALayer alloc] init]); |
| 161 [ca_root_layer_ setGeometryFlipped:YES]; | 169 [ca_root_layer_ setGeometryFlipped:YES]; |
| 162 [ca_root_layer_ setOpaque:YES]; | 170 [ca_root_layer_ setOpaque:YES]; |
| 163 [ca_context_ setLayer:ca_root_layer_]; | 171 [ca_context_ setLayer:ca_root_layer_]; |
| 172 |
| 173 detached_ca_context_.reset([ |
| 174 [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); |
| 175 detached_av_layer_.reset([[AVSampleBufferDisplayLayer alloc] init]); |
| 176 [detached_av_layer_ setVideoGravity:AVLayerVideoGravityResize]; |
| 177 [detached_ca_context_ setLayer:detached_av_layer_]; |
| 178 [detached_av_layer_ setFrame:CGRectMake(0, 0, 1280, 720)]; |
| 164 } | 179 } |
| 165 return true; | 180 return true; |
| 166 } | 181 } |
| 167 | 182 |
| 168 void ImageTransportSurfaceOverlayMac::Destroy() { | 183 void ImageTransportSurfaceOverlayMac::Destroy() { |
| 169 DisplayAndClearAllPendingSwaps(); | 184 DisplayAndClearAllPendingSwaps(); |
| 170 | 185 |
| 171 current_partial_damage_tree_.reset(); | 186 current_partial_damage_tree_.reset(); |
| 172 current_ca_layer_tree_.reset(); | 187 current_ca_layer_tree_.reset(); |
| 173 } | 188 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 191 vsync_parameters_valid_ = (vsync_interval_ != base::TimeDelta()); | 206 vsync_parameters_valid_ = (vsync_interval_ != base::TimeDelta()); |
| 192 | 207 |
| 193 // Compute |vsync_timebase_| to be the first vsync after time zero. | 208 // Compute |vsync_timebase_| to be the first vsync after time zero. |
| 194 if (vsync_parameters_valid_) { | 209 if (vsync_parameters_valid_) { |
| 195 vsync_timebase_ -= | 210 vsync_timebase_ -= |
| 196 vsync_interval_ * | 211 vsync_interval_ * |
| 197 ((vsync_timebase_ - base::TimeTicks()) / vsync_interval_); | 212 ((vsync_timebase_ - base::TimeTicks()) / vsync_interval_); |
| 198 } | 213 } |
| 199 } | 214 } |
| 200 | 215 |
| 201 void ImageTransportSurfaceOverlayMac::SendAcceleratedSurfaceBuffersSwapped( | |
| 202 int32_t surface_id, | |
| 203 CAContextID ca_context_id, | |
| 204 const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface, | |
| 205 const gfx::Size& size, | |
| 206 float scale_factor, | |
| 207 std::vector<ui::LatencyInfo> latency_info) { | |
| 208 // TRACE_EVENT for gpu tests: | |
| 209 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", TRACE_EVENT_SCOPE_THREAD, | |
| 210 "GLImpl", static_cast<int>(gfx::GetGLImplementation()), | |
| 211 "width", size.width()); | |
| 212 // On mac, handle_ is a surface id. See | |
| 213 // GpuProcessTransportFactory::CreatePerCompositorData | |
| 214 manager_->delegate()->SendAcceleratedSurfaceBuffersSwapped( | |
| 215 surface_id, ca_context_id, io_surface, size, scale_factor, | |
| 216 std::move(latency_info)); | |
| 217 } | |
| 218 | |
| 219 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal( | 216 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal( |
| 220 const gfx::Rect& pixel_damage_rect) { | 217 const gfx::Rect& pixel_damage_rect) { |
| 221 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); | 218 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); |
| 222 | 219 |
| 223 // Use the same concept of 'now' for the entire function. The duration of | 220 // Use the same concept of 'now' for the entire function. The duration of |
| 224 // this function only affect the result if this function lasts across a vsync | 221 // this function only affect the result if this function lasts across a vsync |
| 225 // boundary, in which case smooth animation is out the window anyway. | 222 // boundary, in which case smooth animation is out the window anyway. |
| 226 const base::TimeTicks now = base::TimeTicks::Now(); | 223 const base::TimeTicks now = base::TimeTicks::Now(); |
| 227 | 224 |
| 228 // Decide if the frame should be drawn immediately, or if we should wait until | 225 // Decide if the frame should be drawn immediately, or if we should wait until |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 if (swap->gl_fence) { | 320 if (swap->gl_fence) { |
| 324 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; | 321 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; |
| 325 gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); | 322 gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context); |
| 326 | 323 |
| 327 CheckGLErrors("before deleting active fence"); | 324 CheckGLErrors("before deleting active fence"); |
| 328 swap->gl_fence.reset(); | 325 swap->gl_fence.reset(); |
| 329 CheckGLErrors("while deleting active fence"); | 326 CheckGLErrors("while deleting active fence"); |
| 330 } | 327 } |
| 331 | 328 |
| 332 // Update the CALayer hierarchy. | 329 // Update the CALayer hierarchy. |
| 330 bool use_detached_mode = false; |
| 333 { | 331 { |
| 334 gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect); | 332 gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect); |
| 335 ScopedCAActionDisabler disabler; | 333 ScopedCAActionDisabler disabler; |
| 336 if (swap->ca_layer_tree) { | 334 if (swap->ca_layer_tree) { |
| 337 swap->ca_layer_tree->CommitScheduledCALayers( | 335 swap->ca_layer_tree->CommitScheduledCALayers( |
| 338 ca_root_layer_.get(), std::move(current_ca_layer_tree_), | 336 ca_root_layer_.get(), &use_detached_mode, detached_av_layer_.get(), |
| 339 swap->scale_factor); | 337 std::move(current_ca_layer_tree_), swap->scale_factor); |
| 340 current_ca_layer_tree_.swap(swap->ca_layer_tree); | 338 current_ca_layer_tree_.swap(swap->ca_layer_tree); |
| 341 current_partial_damage_tree_.reset(); | 339 current_partial_damage_tree_.reset(); |
| 342 } else if (swap->partial_damage_tree) { | 340 } else if (swap->partial_damage_tree) { |
| 343 swap->partial_damage_tree->CommitCALayers( | 341 swap->partial_damage_tree->CommitCALayers( |
| 344 ca_root_layer_.get(), std::move(current_partial_damage_tree_), | 342 ca_root_layer_.get(), std::move(current_partial_damage_tree_), |
| 345 swap->scale_factor, swap->pixel_damage_rect); | 343 swap->scale_factor, swap->pixel_damage_rect); |
| 346 current_partial_damage_tree_.swap(swap->partial_damage_tree); | 344 current_partial_damage_tree_.swap(swap->partial_damage_tree); |
| 347 current_ca_layer_tree_.reset(); | 345 current_ca_layer_tree_.reset(); |
| 348 } else { | 346 } else { |
| 349 TRACE_EVENT0("gpu", "Blank frame: No overlays or CALayers"); | 347 TRACE_EVENT0("gpu", "Blank frame: No overlays or CALayers"); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 371 if (use_remote_layer_api_) { | 369 if (use_remote_layer_api_) { |
| 372 ca_context_id = [ca_context_ contextId]; | 370 ca_context_id = [ca_context_ contextId]; |
| 373 } else if (current_partial_damage_tree_) { | 371 } else if (current_partial_damage_tree_) { |
| 374 io_surface.reset(IOSurfaceCreateMachPort( | 372 io_surface.reset(IOSurfaceCreateMachPort( |
| 375 current_partial_damage_tree_->RootLayerIOSurface())); | 373 current_partial_damage_tree_->RootLayerIOSurface())); |
| 376 } | 374 } |
| 377 gfx::Size size = swap->pixel_size; | 375 gfx::Size size = swap->pixel_size; |
| 378 float scale_factor = swap->scale_factor; | 376 float scale_factor = swap->scale_factor; |
| 379 std::vector<ui::LatencyInfo> latency_info; | 377 std::vector<ui::LatencyInfo> latency_info; |
| 380 latency_info.swap(swap->latency_info); | 378 latency_info.swap(swap->latency_info); |
| 381 SendAcceleratedSurfaceBuffersSwapped(handle_, ca_context_id, io_surface, size, | 379 |
| 382 scale_factor, std::move(latency_info)); | 380 CAContextID detached_ca_context_id = [detached_ca_context_ contextId]; |
| 381 |
| 382 // TRACE_EVENT for gpu tests: |
| 383 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", TRACE_EVENT_SCOPE_THREAD, |
| 384 "GLImpl", static_cast<int>(gfx::GetGLImplementation()), |
| 385 "width", size.width()); |
| 386 manager_->delegate()->SendAcceleratedSurfaceBuffersSwapped( |
| 387 handle_, ca_context_id, io_surface, use_detached_mode, detached_ca_context
_id, |
| 388 size, scale_factor, std::move(latency_info)); |
| 383 | 389 |
| 384 // Remove this from the queue, and reset any callback timers. | 390 // Remove this from the queue, and reset any callback timers. |
| 385 pending_swaps_.pop_front(); | 391 pending_swaps_.pop_front(); |
| 386 } | 392 } |
| 387 | 393 |
| 388 void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() { | 394 void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() { |
| 389 TRACE_EVENT0("gpu", | 395 TRACE_EVENT0("gpu", |
| 390 "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps"); | 396 "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps"); |
| 391 while (!pending_swaps_.empty()) | 397 while (!pending_swaps_.empty()) |
| 392 DisplayFirstPendingSwapImmediately(); | 398 DisplayFirstPendingSwapImmediately(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 // Compute the previous vsync time. | 560 // Compute the previous vsync time. |
| 555 base::TimeTicks previous_vsync = | 561 base::TimeTicks previous_vsync = |
| 556 vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) + | 562 vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) + |
| 557 vsync_timebase_; | 563 vsync_timebase_; |
| 558 | 564 |
| 559 // Return |interval_fraction| through the next vsync. | 565 // Return |interval_fraction| through the next vsync. |
| 560 return previous_vsync + (1 + interval_fraction) * vsync_interval_; | 566 return previous_vsync + (1 + interval_fraction) * vsync_interval_; |
| 561 } | 567 } |
| 562 | 568 |
| 563 } // namespace content | 569 } // namespace content |
| OLD | NEW |