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 |