| 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 "gpu/ipc/service/image_transport_surface_overlay_mac.h" | 5 #include "gpu/ipc/service/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> |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 fullscreen_low_power_ca_context_.reset([ | 105 fullscreen_low_power_ca_context_.reset([ |
| 106 [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); | 106 [CAContext contextWithCGSConnection:connection_id options:@{}] retain]); |
| 107 [fullscreen_low_power_ca_context_ setLayer: | 107 [fullscreen_low_power_ca_context_ setLayer: |
| 108 ca_layer_tree_coordinator_->GetFullscreenLowPowerLayerForDisplay()]; | 108 ca_layer_tree_coordinator_->GetFullscreenLowPowerLayerForDisplay()]; |
| 109 } | 109 } |
| 110 return true; | 110 return true; |
| 111 } | 111 } |
| 112 | 112 |
| 113 void ImageTransportSurfaceOverlayMac::Destroy() { | 113 void ImageTransportSurfaceOverlayMac::Destroy() { |
| 114 ca_layer_tree_coordinator_.reset(); | 114 ca_layer_tree_coordinator_.reset(); |
| 115 if (previous_frame_fence_) { |
| 116 gl::ScopedSetGLToRealGLApi scoped_set_gl_api; |
| 117 // Ensure we are using the context with which the fence was created. |
| 118 gl::ScopedCGLSetCurrentContext scoped_set_current(fence_context_obj_); |
| 119 CheckGLErrors("Before destroy fence"); |
| 120 previous_frame_fence_.reset(); |
| 121 CheckGLErrors("After destroy fence"); |
| 122 } |
| 115 } | 123 } |
| 116 | 124 |
| 117 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { | 125 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { |
| 118 return false; | 126 return false; |
| 119 } | 127 } |
| 120 | 128 |
| 121 void ImageTransportSurfaceOverlayMac::SetLatencyInfo( | 129 void ImageTransportSurfaceOverlayMac::SetLatencyInfo( |
| 122 const std::vector<ui::LatencyInfo>& latency_info) { | 130 const std::vector<ui::LatencyInfo>& latency_info) { |
| 123 latency_info_.insert(latency_info_.end(), latency_info.begin(), | 131 latency_info_.insert(latency_info_.end(), latency_info.begin(), |
| 124 latency_info.end()); | 132 latency_info.end()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 150 params.scale_factor = scale_factor; | 158 params.scale_factor = scale_factor; |
| 151 params.latency_info = std::move(latency_info); | 159 params.latency_info = std::move(latency_info); |
| 152 params.result = gfx::SwapResult::SWAP_ACK; | 160 params.result = gfx::SwapResult::SWAP_ACK; |
| 153 stub_->SendSwapBuffersCompleted(params); | 161 stub_->SendSwapBuffersCompleted(params); |
| 154 } | 162 } |
| 155 | 163 |
| 156 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal( | 164 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal( |
| 157 const gfx::Rect& pixel_damage_rect) { | 165 const gfx::Rect& pixel_damage_rect) { |
| 158 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); | 166 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal"); |
| 159 | 167 |
| 160 // A glFlush is necessary to ensure correct content appears. A glFinish | 168 // If supported, use GLFence to ensure that we haven't gotten more than one |
| 161 // appears empirically to be the best way to get maximum performance when | 169 // frame ahead of GL. |
| 162 // GPU bound. | 170 if (gl::GLFence::IsSupported()) { |
| 163 { | 171 gl::ScopedSetGLToRealGLApi scoped_set_gl_api; |
| 172 CheckGLErrors("Before fence/flush"); |
| 173 |
| 174 // If we have gotten more than one frame ahead of GL, wait for the previous |
| 175 // frame to complete. |
| 176 if (previous_frame_fence_) { |
| 177 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::ClientWait"); |
| 178 |
| 179 // Ensure we are using the context with which the fence was created. |
| 180 gl::ScopedCGLSetCurrentContext scoped_set_current(fence_context_obj_); |
| 181 |
| 182 // While we could call GLFence::ClientWait, this performs a busy wait on |
| 183 // Mac, leading to high CPU usage. Instead we poll with a 1ms delay. This |
| 184 // should have minimal impact, as we will only hit this path when we are |
| 185 // more than one frame (16ms) behind. |
| 186 while (!previous_frame_fence_->HasCompleted()) { |
| 187 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); |
| 188 } |
| 189 } |
| 190 |
| 191 // Create a fence for the current frame's work and save the context. |
| 192 previous_frame_fence_.reset(gl::GLFence::Create()); |
| 193 fence_context_obj_.reset(CGLGetCurrentContext(), |
| 194 base::scoped_policy::RETAIN); |
| 195 |
| 196 // A glFlush is necessary to ensure correct content appears. |
| 197 glFlush(); |
| 198 |
| 199 CheckGLErrors("After fence/flush"); |
| 200 } else { |
| 201 // GLFence isn't supported - issue a glFinish on each frame to ensure |
| 202 // there is backpressure from GL. |
| 164 gl::ScopedSetGLToRealGLApi scoped_set_gl_api; | 203 gl::ScopedSetGLToRealGLApi scoped_set_gl_api; |
| 165 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFinish"); | 204 TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFinish"); |
| 166 CheckGLErrors("Before finish"); | 205 CheckGLErrors("Before finish"); |
| 167 glFinish(); | 206 glFinish(); |
| 168 CheckGLErrors("After finish"); | 207 CheckGLErrors("After finish"); |
| 169 } | 208 } |
| 170 | 209 |
| 171 base::TimeTicks finish_time = base::TimeTicks::Now(); | 210 base::TimeTicks finish_time = base::TimeTicks::Now(); |
| 172 | 211 |
| 173 bool fullscreen_low_power_layer_valid = false; | 212 bool fullscreen_low_power_layer_valid = false; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 gl_renderer_id_ = context_renderer_id & kCGLRendererIDMatchingMask; | 355 gl_renderer_id_ = context_renderer_id & kCGLRendererIDMatchingMask; |
| 317 | 356 |
| 318 // Post a task holding a reference to the new GL context. The reason for | 357 // Post a task holding a reference to the new GL context. The reason for |
| 319 // this is to avoid creating-then-destroying the context for every image | 358 // this is to avoid creating-then-destroying the context for every image |
| 320 // transport surface that is observing the GPU switch. | 359 // transport surface that is observing the GPU switch. |
| 321 base::MessageLoop::current()->PostTask( | 360 base::MessageLoop::current()->PostTask( |
| 322 FROM_HERE, base::Bind(&IOSurfaceContextNoOp, context_on_new_gpu)); | 361 FROM_HERE, base::Bind(&IOSurfaceContextNoOp, context_on_new_gpu)); |
| 323 } | 362 } |
| 324 | 363 |
| 325 } // namespace gpu | 364 } // namespace gpu |
| OLD | NEW |