| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/command_buffer/service/gpu_scheduler.h" | 5 #include "gpu/command_buffer/service/gpu_scheduler.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "ui/gfx/gl/gl_context.h" | 13 #include "ui/gfx/gl/gl_context.h" |
| 14 #include "ui/gfx/gl/gl_bindings.h" | 14 #include "ui/gfx/gl/gl_bindings.h" |
| 15 #include "ui/gfx/gl/gl_surface.h" | 15 #include "ui/gfx/gl/gl_surface.h" |
| 16 #include "ui/gfx/gl/gl_switches.h" | 16 #include "ui/gfx/gl/gl_switches.h" |
| 17 | 17 |
| 18 using ::base::SharedMemory; | 18 using ::base::SharedMemory; |
| 19 | 19 |
| 20 namespace gpu { | 20 namespace gpu { |
| 21 | 21 |
| 22 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, | 22 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, |
| 23 SurfaceManager* surface_manager, | 23 SurfaceManager* surface_manager, |
| 24 gles2::ContextGroup* group) | 24 gles2::ContextGroup* group) |
| 25 : command_buffer_(command_buffer), | 25 : command_buffer_(command_buffer), |
| 26 commands_per_update_(100), | 26 commands_per_update_(100), |
| 27 unscheduled_count_(0), | 27 unscheduled_count_(0), |
| 28 #if defined(OS_MACOSX) || defined(TOUCH_UI) | 28 #if defined(OS_MACOSX) |
| 29 swap_buffers_count_(0), | 29 swap_buffers_count_(0), |
| 30 acknowledged_swap_buffers_count_(0), | 30 acknowledged_swap_buffers_count_(0), |
| 31 #endif | 31 #endif |
| 32 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 32 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 33 DCHECK(command_buffer); | 33 DCHECK(command_buffer); |
| 34 decoder_.reset(gles2::GLES2Decoder::Create(surface_manager, group)); | 34 decoder_.reset(gles2::GLES2Decoder::Create(surface_manager, group)); |
| 35 decoder_->set_engine(this); | 35 decoder_->set_engine(this); |
| 36 if (CommandLine::ForCurrentProcess()->HasSwitch( | 36 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 37 switches::kEnableGPUServiceLogging)) { | 37 switches::kEnableGPUServiceLogging)) { |
| 38 decoder_->set_debug(true); | 38 decoder_->set_debug(true); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 | 41 |
| 42 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, | 42 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, |
| 43 gles2::GLES2Decoder* decoder, | 43 gles2::GLES2Decoder* decoder, |
| 44 CommandParser* parser, | 44 CommandParser* parser, |
| 45 int commands_per_update) | 45 int commands_per_update) |
| 46 : command_buffer_(command_buffer), | 46 : command_buffer_(command_buffer), |
| 47 commands_per_update_(commands_per_update), | 47 commands_per_update_(commands_per_update), |
| 48 unscheduled_count_(0), | 48 unscheduled_count_(0), |
| 49 #if defined(OS_MACOSX) || defined(TOUCH_UI) | 49 #if defined(OS_MACOSX) |
| 50 swap_buffers_count_(0), | 50 swap_buffers_count_(0), |
| 51 acknowledged_swap_buffers_count_(0), | 51 acknowledged_swap_buffers_count_(0), |
| 52 #endif | 52 #endif |
| 53 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 53 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 54 DCHECK(command_buffer); | 54 DCHECK(command_buffer); |
| 55 decoder_.reset(decoder); | 55 decoder_.reset(decoder); |
| 56 parser_.reset(parser); | 56 parser_.reset(parser); |
| 57 } | 57 } |
| 58 | 58 |
| 59 GpuScheduler::~GpuScheduler() { | 59 GpuScheduler::~GpuScheduler() { |
| 60 Destroy(); | 60 Destroy(); |
| 61 } | 61 } |
| 62 | 62 |
| 63 bool GpuScheduler::InitializeCommon( | 63 bool GpuScheduler::InitializeCommon( |
| 64 const scoped_refptr<gfx::GLSurface>& surface, | 64 const scoped_refptr<gfx::GLSurface>& surface, |
| 65 const scoped_refptr<gfx::GLContext>& context, | 65 const scoped_refptr<gfx::GLContext>& context, |
| 66 const gfx::Size& size, | 66 const gfx::Size& size, |
| 67 const gles2::DisallowedExtensions& disallowed_extensions, | 67 const gles2::DisallowedExtensions& disallowed_extensions, |
| 68 const char* allowed_extensions, | 68 const char* allowed_extensions, |
| 69 const std::vector<int32>& attribs) { | 69 const std::vector<int32>& attribs) { |
| 70 DCHECK(context); | 70 DCHECK(context); |
| 71 | 71 |
| 72 if (!context->MakeCurrent(surface)) | 72 if (!context->MakeCurrent(surface)) |
| 73 return false; | 73 return false; |
| 74 | 74 |
| 75 #if !defined(OS_MACOSX) | 75 #if !defined(OS_MACOSX) && !defined(TOUCH_UI) |
| 76 // Set up swap interval for onscreen contexts. | 76 // Set up swap interval for onscreen contexts. |
| 77 if (!surface->IsOffscreen()) { | 77 if (!surface->IsOffscreen()) { |
| 78 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) | 78 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) |
| 79 context->SetSwapInterval(0); | 79 context->SetSwapInterval(0); |
| 80 else | 80 else |
| 81 context->SetSwapInterval(1); | 81 context->SetSwapInterval(1); |
| 82 } | 82 } |
| 83 #endif | 83 #endif |
| 84 | 84 |
| 85 // Do not limit to a certain number of commands before scheduling another | 85 // Do not limit to a certain number of commands before scheduling another |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 | 131 |
| 132 bool GpuScheduler::SetParent(GpuScheduler* parent_scheduler, | 132 bool GpuScheduler::SetParent(GpuScheduler* parent_scheduler, |
| 133 uint32 parent_texture_id) { | 133 uint32 parent_texture_id) { |
| 134 if (parent_scheduler) | 134 if (parent_scheduler) |
| 135 return decoder_->SetParent(parent_scheduler->decoder_.get(), | 135 return decoder_->SetParent(parent_scheduler->decoder_.get(), |
| 136 parent_texture_id); | 136 parent_texture_id); |
| 137 else | 137 else |
| 138 return decoder_->SetParent(NULL, 0); | 138 return decoder_->SetParent(NULL, 0); |
| 139 } | 139 } |
| 140 | 140 |
| 141 #if defined(OS_MACOSX) || defined(TOUCH_UI) | 141 #if defined(OS_MACOSX) |
| 142 namespace { | 142 namespace { |
| 143 const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1; | 143 const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1; |
| 144 } | 144 } |
| 145 #endif | 145 #endif |
| 146 | 146 |
| 147 void GpuScheduler::PutChanged(bool sync) { | 147 void GpuScheduler::PutChanged(bool sync) { |
| 148 TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this); | 148 TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this); |
| 149 CommandBuffer::State state = command_buffer_->GetState(); | 149 CommandBuffer::State state = command_buffer_->GetState(); |
| 150 parser_->set_put(state.put_offset); | 150 parser_->set_put(state.put_offset); |
| 151 | 151 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 171 if (!decoder_->MakeCurrent()) { | 171 if (!decoder_->MakeCurrent()) { |
| 172 LOG(ERROR) << "Context lost because MakeCurrent failed."; | 172 LOG(ERROR) << "Context lost because MakeCurrent failed."; |
| 173 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); | 173 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); |
| 174 command_buffer_->SetParseError(error::kLostContext); | 174 command_buffer_->SetParseError(error::kLostContext); |
| 175 return; | 175 return; |
| 176 } | 176 } |
| 177 } | 177 } |
| 178 | 178 |
| 179 #if defined(OS_MACOSX) | 179 #if defined(OS_MACOSX) |
| 180 bool do_rate_limiting = surface_.get() != NULL; | 180 bool do_rate_limiting = surface_.get() != NULL; |
| 181 #elif defined(TOUCH_UI) | |
| 182 bool do_rate_limiting = back_surface_.get() != NULL; | |
| 183 #endif | |
| 184 | |
| 185 #if defined(OS_MACOSX) || defined(TOUCH_UI) | |
| 186 // Don't swamp the browser process with SwapBuffers calls it can't handle. | 181 // Don't swamp the browser process with SwapBuffers calls it can't handle. |
| 187 if (do_rate_limiting && | 182 if (do_rate_limiting && |
| 188 swap_buffers_count_ - acknowledged_swap_buffers_count_ >= | 183 swap_buffers_count_ - acknowledged_swap_buffers_count_ >= |
| 189 kMaxOutstandingSwapBuffersCallsPerOnscreenContext) { | 184 kMaxOutstandingSwapBuffersCallsPerOnscreenContext) { |
| 190 TRACE_EVENT0("gpu", "EarlyOut_OSX_Throttle"); | 185 TRACE_EVENT0("gpu", "EarlyOut_OSX_Throttle"); |
| 191 // Stop doing work on this command buffer. In the GPU process, | 186 // Stop doing work on this command buffer. In the GPU process, |
| 192 // receipt of the GpuMsg_AcceleratedSurfaceBuffersSwappedACK | 187 // receipt of the GpuMsg_AcceleratedSurfaceBuffersSwappedACK |
| 193 // message causes ProcessCommands to be scheduled again. | 188 // message causes ProcessCommands to be scheduled again. |
| 194 return; | 189 return; |
| 195 } | 190 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 283 |
| 289 int32 GpuScheduler::GetGetOffset() { | 284 int32 GpuScheduler::GetGetOffset() { |
| 290 return parser_->get(); | 285 return parser_->get(); |
| 291 } | 286 } |
| 292 | 287 |
| 293 void GpuScheduler::ResizeOffscreenFrameBuffer(const gfx::Size& size) { | 288 void GpuScheduler::ResizeOffscreenFrameBuffer(const gfx::Size& size) { |
| 294 decoder_->ResizeOffscreenFrameBuffer(size); | 289 decoder_->ResizeOffscreenFrameBuffer(size); |
| 295 } | 290 } |
| 296 | 291 |
| 297 void GpuScheduler::SetResizeCallback(Callback1<gfx::Size>::Type* callback) { | 292 void GpuScheduler::SetResizeCallback(Callback1<gfx::Size>::Type* callback) { |
| 298 wrapped_resize_callback_.reset(callback); | 293 decoder_->SetResizeCallback(callback); |
| 299 decoder_->SetResizeCallback( | |
| 300 NewCallback(this, | |
| 301 &GpuScheduler::WillResize)); | |
| 302 } | 294 } |
| 303 | 295 |
| 304 void GpuScheduler::SetSwapBuffersCallback( | 296 void GpuScheduler::SetSwapBuffersCallback( |
| 305 Callback0::Type* callback) { | 297 Callback0::Type* callback) { |
| 306 wrapped_swap_buffers_callback_.reset(callback); | 298 wrapped_swap_buffers_callback_.reset(callback); |
| 307 decoder_->SetSwapBuffersCallback( | 299 decoder_->SetSwapBuffersCallback( |
| 308 NewCallback(this, | 300 NewCallback(this, |
| 309 &GpuScheduler::WillSwapBuffers)); | 301 &GpuScheduler::WillSwapBuffers)); |
| 310 } | 302 } |
| 311 | 303 |
| 312 void GpuScheduler::SetCommandProcessedCallback( | 304 void GpuScheduler::SetCommandProcessedCallback( |
| 313 Callback0::Type* callback) { | 305 Callback0::Type* callback) { |
| 314 command_processed_callback_.reset(callback); | 306 command_processed_callback_.reset(callback); |
| 315 } | 307 } |
| 316 | 308 |
| 317 void GpuScheduler::SetTokenCallback( | 309 void GpuScheduler::SetTokenCallback( |
| 318 const base::Callback<void(int32)>& callback) { | 310 const base::Callback<void(int32)>& callback) { |
| 319 DCHECK(set_token_callback_.is_null()); | 311 DCHECK(set_token_callback_.is_null()); |
| 320 set_token_callback_ = callback; | 312 set_token_callback_ = callback; |
| 321 } | 313 } |
| 322 | 314 |
| 323 void GpuScheduler::ScheduleProcessCommands() { | 315 void GpuScheduler::ScheduleProcessCommands() { |
| 324 MessageLoop::current()->PostTask( | 316 MessageLoop::current()->PostTask( |
| 325 FROM_HERE, | 317 FROM_HERE, |
| 326 method_factory_.NewRunnableMethod(&GpuScheduler::ProcessCommands)); | 318 method_factory_.NewRunnableMethod(&GpuScheduler::ProcessCommands)); |
| 327 } | 319 } |
| 328 | 320 |
| 329 void GpuScheduler::WillResize(gfx::Size size) { | |
| 330 if (wrapped_resize_callback_.get()) { | |
| 331 wrapped_resize_callback_->Run(size); | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 } // namespace gpu | 321 } // namespace gpu |
| OLD | NEW |