OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/in_process_command_buffer.h" | 5 #include "gpu/command_buffer/service/in_process_command_buffer.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include <GLES2/gl2.h> | 10 #include <GLES2/gl2.h> |
(...skipping 25 matching lines...) Expand all Loading... | |
36 | 36 |
37 #if defined(OS_ANDROID) | 37 #if defined(OS_ANDROID) |
38 #include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h " | 38 #include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h " |
39 #include "ui/gl/android/surface_texture.h" | 39 #include "ui/gl/android/surface_texture.h" |
40 #endif | 40 #endif |
41 | 41 |
42 namespace gpu { | 42 namespace gpu { |
43 | 43 |
44 namespace { | 44 namespace { |
45 | 45 |
46 static base::LazyInstance<std::set<InProcessCommandBuffer*> > | |
47 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER; | |
48 | |
49 static bool g_use_virtualized_gl_context = false; | 46 static bool g_use_virtualized_gl_context = false; |
50 static bool g_uses_explicit_scheduling = false; | 47 static bool g_uses_explicit_scheduling = false; |
51 static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; | 48 static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; |
52 | 49 |
53 template <typename T> | 50 template <typename T> |
54 static void RunTaskWithResult(base::Callback<T(void)> task, | 51 static void RunTaskWithResult(base::Callback<T(void)> task, |
55 T* result, | 52 T* result, |
56 base::WaitableEvent* completion) { | 53 base::WaitableEvent* completion) { |
57 *result = task.Run(); | 54 *result = task.Run(); |
58 completion->Signal(); | 55 completion->Signal(); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 ~ScopedEvent() { event_->Signal(); } | 241 ~ScopedEvent() { event_->Signal(); } |
245 | 242 |
246 private: | 243 private: |
247 base::WaitableEvent* event_; | 244 base::WaitableEvent* event_; |
248 }; | 245 }; |
249 | 246 |
250 } // anonyous namespace | 247 } // anonyous namespace |
251 | 248 |
252 InProcessCommandBuffer::InProcessCommandBuffer() | 249 InProcessCommandBuffer::InProcessCommandBuffer() |
253 : context_lost_(false), | 250 : context_lost_(false), |
254 share_group_id_(0), | |
255 last_put_offset_(-1), | 251 last_put_offset_(-1), |
256 flush_event_(false, false), | 252 flush_event_(false, false), |
257 queue_(CreateSchedulerClient()), | 253 queue_(CreateSchedulerClient()), |
258 gpu_thread_weak_ptr_factory_(this) {} | 254 gpu_thread_weak_ptr_factory_(this) {} |
259 | 255 |
260 InProcessCommandBuffer::~InProcessCommandBuffer() { | 256 InProcessCommandBuffer::~InProcessCommandBuffer() { |
261 Destroy(); | 257 Destroy(); |
262 } | 258 } |
263 | 259 |
264 bool InProcessCommandBuffer::IsContextLost() { | |
265 CheckSequencedThread(); | |
266 if (context_lost_ || !command_buffer_) { | |
267 return true; | |
268 } | |
269 CommandBuffer::State state = GetState(); | |
270 return error::IsError(state.error); | |
271 } | |
272 | |
273 void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) { | 260 void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) { |
274 CheckSequencedThread(); | 261 CheckSequencedThread(); |
275 DCHECK(!surface_->IsOffscreen()); | 262 DCHECK(!surface_->IsOffscreen()); |
276 surface_->Resize(size); | 263 surface_->Resize(size); |
277 } | 264 } |
278 | 265 |
279 bool InProcessCommandBuffer::MakeCurrent() { | 266 bool InProcessCommandBuffer::MakeCurrent() { |
280 CheckSequencedThread(); | 267 CheckSequencedThread(); |
281 command_buffer_lock_.AssertAcquired(); | 268 command_buffer_lock_.AssertAcquired(); |
282 | 269 |
(...skipping 18 matching lines...) Expand all Loading... | |
301 bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) { | 288 bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) { |
302 CheckSequencedThread(); | 289 CheckSequencedThread(); |
303 command_buffer_lock_.AssertAcquired(); | 290 command_buffer_lock_.AssertAcquired(); |
304 command_buffer_->SetGetBuffer(transfer_buffer_id); | 291 command_buffer_->SetGetBuffer(transfer_buffer_id); |
305 return true; | 292 return true; |
306 } | 293 } |
307 | 294 |
308 bool InProcessCommandBuffer::Initialize( | 295 bool InProcessCommandBuffer::Initialize( |
309 scoped_refptr<gfx::GLSurface> surface, | 296 scoped_refptr<gfx::GLSurface> surface, |
310 bool is_offscreen, | 297 bool is_offscreen, |
311 bool share_resources, | |
312 gfx::AcceleratedWidget window, | 298 gfx::AcceleratedWidget window, |
313 const gfx::Size& size, | 299 const gfx::Size& size, |
314 const std::vector<int32>& attribs, | 300 const std::vector<int32>& attribs, |
315 gfx::GpuPreference gpu_preference, | 301 gfx::GpuPreference gpu_preference, |
316 const base::Closure& context_lost_callback, | 302 const base::Closure& context_lost_callback, |
317 unsigned int share_group_id) { | 303 InProcessCommandBuffer* share_group) { |
318 | 304 |
319 share_resources_ = share_resources; | |
320 context_lost_callback_ = WrapCallback(context_lost_callback); | 305 context_lost_callback_ = WrapCallback(context_lost_callback); |
321 share_group_id_ = share_group_id; | |
322 | 306 |
323 if (surface) { | 307 if (surface) { |
324 // GPU thread must be the same as client thread due to GLSurface not being | 308 // GPU thread must be the same as client thread due to GLSurface not being |
325 // thread safe. | 309 // thread safe. |
326 sequence_checker_.reset(new base::SequenceChecker); | 310 sequence_checker_.reset(new base::SequenceChecker); |
327 surface_ = surface; | 311 surface_ = surface; |
328 } | 312 } |
329 | 313 |
330 gpu::Capabilities capabilities; | 314 gpu::Capabilities capabilities; |
331 InitializeOnGpuThreadParams params( | 315 InitializeOnGpuThreadParams params(is_offscreen, |
332 is_offscreen, window, size, attribs, gpu_preference, &capabilities); | 316 window, |
317 size, | |
318 attribs, | |
319 gpu_preference, | |
320 &capabilities, | |
321 share_group); | |
333 | 322 |
334 base::Callback<bool(void)> init_task = | 323 base::Callback<bool(void)> init_task = |
335 base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread, | 324 base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread, |
336 base::Unretained(this), | 325 base::Unretained(this), |
337 params); | 326 params); |
338 | 327 |
339 base::WaitableEvent completion(true, false); | 328 base::WaitableEvent completion(true, false); |
340 bool result = false; | 329 bool result = false; |
341 QueueTask( | 330 QueueTask( |
342 base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion)); | 331 base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion)); |
343 completion.Wait(); | 332 completion.Wait(); |
344 | 333 |
345 if (result) | 334 if (result) |
346 capabilities_ = capabilities; | 335 capabilities_ = capabilities; |
347 return result; | 336 return result; |
348 } | 337 } |
349 | 338 |
350 bool InProcessCommandBuffer::InitializeOnGpuThread( | 339 bool InProcessCommandBuffer::InitializeOnGpuThread( |
351 const InitializeOnGpuThreadParams& params) { | 340 const InitializeOnGpuThreadParams& params) { |
352 CheckSequencedThread(); | 341 CheckSequencedThread(); |
353 gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr(); | 342 gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr(); |
354 // Use one share group for all contexts. | |
355 CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group, | |
356 (new gfx::GLShareGroup)); | |
357 | 343 |
358 DCHECK(params.size.width() >= 0 && params.size.height() >= 0); | 344 DCHECK(params.size.width() >= 0 && params.size.height() >= 0); |
359 | 345 |
360 TransferBufferManager* manager = new TransferBufferManager(); | 346 TransferBufferManager* manager = new TransferBufferManager(); |
361 transfer_buffer_manager_.reset(manager); | 347 transfer_buffer_manager_.reset(manager); |
362 manager->Initialize(); | 348 manager->Initialize(); |
363 | 349 |
364 scoped_ptr<CommandBufferService> command_buffer( | 350 scoped_ptr<CommandBufferService> command_buffer( |
365 new CommandBufferService(transfer_buffer_manager_.get())); | 351 new CommandBufferService(transfer_buffer_manager_.get())); |
366 command_buffer->SetPutOffsetChangeCallback(base::Bind( | 352 command_buffer->SetPutOffsetChangeCallback(base::Bind( |
367 &InProcessCommandBuffer::PumpCommands, gpu_thread_weak_ptr_)); | 353 &InProcessCommandBuffer::PumpCommands, gpu_thread_weak_ptr_)); |
368 command_buffer->SetParseErrorCallback(base::Bind( | 354 command_buffer->SetParseErrorCallback(base::Bind( |
369 &InProcessCommandBuffer::OnContextLost, gpu_thread_weak_ptr_)); | 355 &InProcessCommandBuffer::OnContextLost, gpu_thread_weak_ptr_)); |
370 | 356 |
371 if (!command_buffer->Initialize()) { | 357 if (!command_buffer->Initialize()) { |
372 LOG(ERROR) << "Could not initialize command buffer."; | 358 LOG(ERROR) << "Could not initialize command buffer."; |
373 DestroyOnGpuThread(); | 359 DestroyOnGpuThread(); |
374 return false; | 360 return false; |
375 } | 361 } |
376 | 362 |
377 InProcessCommandBuffer* context_group = NULL; | 363 gl_share_group_ = params.context_group |
378 | 364 ? params.context_group->gl_share_group_.get() |
379 if (share_resources_ && !g_all_shared_contexts.Get().empty()) { | 365 : new gfx::GLShareGroup; |
380 DCHECK(share_group_id_); | |
381 for (std::set<InProcessCommandBuffer*>::iterator it = | |
382 g_all_shared_contexts.Get().begin(); | |
383 it != g_all_shared_contexts.Get().end(); | |
384 ++it) { | |
385 if ((*it)->share_group_id_ == share_group_id_) { | |
386 context_group = *it; | |
387 DCHECK(context_group->share_resources_); | |
388 context_lost_ = context_group->IsContextLost(); | |
389 break; | |
390 } | |
391 } | |
392 if (!context_group) | |
393 share_group = new gfx::GLShareGroup; | |
394 } | |
395 | 366 |
396 #if defined(OS_ANDROID) | 367 #if defined(OS_ANDROID) |
397 stream_texture_manager_.reset(new StreamTextureManagerInProcess); | 368 stream_texture_manager_.reset(new StreamTextureManagerInProcess); |
398 #endif | 369 #endif |
399 | 370 |
400 bool bind_generates_resource = false; | 371 bool bind_generates_resource = false; |
401 decoder_.reset(gles2::GLES2Decoder::Create( | 372 decoder_.reset(gles2::GLES2Decoder::Create( |
402 context_group ? context_group->decoder_->GetContextGroup() | 373 params.context_group ? params.context_group->decoder_->GetContextGroup() |
403 : new gles2::ContextGroup(NULL, | 374 : new gles2::ContextGroup(NULL, |
404 NULL, | 375 NULL, |
405 NULL, | 376 NULL, |
406 NULL, | 377 NULL, |
407 bind_generates_resource))); | 378 bind_generates_resource))); |
408 | 379 |
409 gpu_scheduler_.reset( | 380 gpu_scheduler_.reset( |
410 new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get())); | 381 new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get())); |
411 command_buffer->SetGetBufferChangeCallback(base::Bind( | 382 command_buffer->SetGetBufferChangeCallback(base::Bind( |
412 &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); | 383 &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); |
413 command_buffer_ = command_buffer.Pass(); | 384 command_buffer_ = command_buffer.Pass(); |
414 | 385 |
415 decoder_->set_engine(gpu_scheduler_.get()); | 386 decoder_->set_engine(gpu_scheduler_.get()); |
416 | 387 |
417 if (!surface_) { | 388 if (!surface_) { |
418 if (params.is_offscreen) | 389 if (params.is_offscreen) |
419 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(params.size); | 390 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(params.size); |
420 else | 391 else |
421 surface_ = gfx::GLSurface::CreateViewGLSurface(params.window); | 392 surface_ = gfx::GLSurface::CreateViewGLSurface(params.window); |
422 } | 393 } |
423 | 394 |
424 if (!surface_.get()) { | 395 if (!surface_.get()) { |
425 LOG(ERROR) << "Could not create GLSurface."; | 396 LOG(ERROR) << "Could not create GLSurface."; |
426 DestroyOnGpuThread(); | 397 DestroyOnGpuThread(); |
427 return false; | 398 return false; |
428 } | 399 } |
429 | 400 |
430 if (g_use_virtualized_gl_context) { | 401 if (g_use_virtualized_gl_context) { |
431 context_ = share_group->GetSharedContext(); | 402 context_ = gl_share_group_->GetSharedContext(); |
432 if (!context_.get()) { | 403 if (!context_.get()) { |
433 context_ = gfx::GLContext::CreateGLContext( | 404 context_ = gfx::GLContext::CreateGLContext( |
434 share_group.get(), surface_.get(), params.gpu_preference); | 405 gl_share_group_.get(), surface_.get(), params.gpu_preference); |
435 share_group->SetSharedContext(context_.get()); | 406 gl_share_group_->SetSharedContext(context_.get()); |
436 } | 407 } |
437 | 408 |
438 context_ = new GLContextVirtual( | 409 context_ = new GLContextVirtual( |
439 share_group.get(), context_.get(), decoder_->AsWeakPtr()); | 410 gl_share_group_.get(), context_.get(), decoder_->AsWeakPtr()); |
440 if (context_->Initialize(surface_.get(), params.gpu_preference)) { | 411 if (context_->Initialize(surface_.get(), params.gpu_preference)) { |
441 VLOG(1) << "Created virtual GL context."; | 412 VLOG(1) << "Created virtual GL context."; |
442 } else { | 413 } else { |
443 context_ = NULL; | 414 context_ = NULL; |
444 } | 415 } |
445 } else { | 416 } else { |
446 context_ = gfx::GLContext::CreateGLContext( | 417 context_ = gfx::GLContext::CreateGLContext( |
447 share_group.get(), surface_.get(), params.gpu_preference); | 418 gl_share_group_.get(), surface_.get(), params.gpu_preference); |
448 } | 419 } |
449 | 420 |
450 if (!context_.get()) { | 421 if (!context_.get()) { |
451 LOG(ERROR) << "Could not create GLContext."; | 422 LOG(ERROR) << "Could not create GLContext."; |
452 DestroyOnGpuThread(); | 423 DestroyOnGpuThread(); |
453 return false; | 424 return false; |
454 } | 425 } |
455 | 426 |
456 if (!context_->MakeCurrent(surface_.get())) { | 427 if (!context_->MakeCurrent(surface_.get())) { |
457 LOG(ERROR) << "Could not make context current."; | 428 LOG(ERROR) << "Could not make context current."; |
(...skipping 21 matching lines...) Expand all Loading... | |
479 decoder_->GetQueryManager(), | 450 decoder_->GetQueryManager(), |
480 decoder_->GetCapabilities())); | 451 decoder_->GetCapabilities())); |
481 | 452 |
482 *params.capabilities = gpu_control_->GetCapabilities(); | 453 *params.capabilities = gpu_control_->GetCapabilities(); |
483 | 454 |
484 if (!params.is_offscreen) { | 455 if (!params.is_offscreen) { |
485 decoder_->SetResizeCallback(base::Bind( | 456 decoder_->SetResizeCallback(base::Bind( |
486 &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_)); | 457 &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_)); |
487 } | 458 } |
488 | 459 |
489 if (share_resources_) { | |
490 g_all_shared_contexts.Pointer()->insert(this); | |
491 } | |
492 | |
493 return true; | 460 return true; |
494 } | 461 } |
495 | 462 |
496 void InProcessCommandBuffer::Destroy() { | 463 void InProcessCommandBuffer::Destroy() { |
497 CheckSequencedThread(); | 464 CheckSequencedThread(); |
498 | 465 |
499 base::WaitableEvent completion(true, false); | 466 base::WaitableEvent completion(true, false); |
500 bool result = false; | 467 bool result = false; |
501 base::Callback<bool(void)> destroy_task = base::Bind( | 468 base::Callback<bool(void)> destroy_task = base::Bind( |
502 &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this)); | 469 &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this)); |
503 QueueTask( | 470 QueueTask( |
504 base::Bind(&RunTaskWithResult<bool>, destroy_task, &result, &completion)); | 471 base::Bind(&RunTaskWithResult<bool>, destroy_task, &result, &completion)); |
505 completion.Wait(); | 472 completion.Wait(); |
506 } | 473 } |
507 | 474 |
508 bool InProcessCommandBuffer::DestroyOnGpuThread() { | 475 bool InProcessCommandBuffer::DestroyOnGpuThread() { |
509 CheckSequencedThread(); | 476 CheckSequencedThread(); |
510 gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs(); | 477 gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs(); |
511 command_buffer_.reset(); | 478 command_buffer_.reset(); |
512 // Clean up GL resources if possible. | 479 // Clean up GL resources if possible. |
513 bool have_context = context_ && context_->MakeCurrent(surface_); | 480 bool have_context = context_ && context_->MakeCurrent(surface_); |
514 if (decoder_) { | 481 if (decoder_) { |
515 decoder_->Destroy(have_context); | 482 decoder_->Destroy(have_context); |
516 decoder_.reset(); | 483 decoder_.reset(); |
517 } | 484 } |
518 context_ = NULL; | 485 context_ = NULL; |
519 surface_ = NULL; | 486 surface_ = NULL; |
487 gl_share_group_ = NULL; | |
520 #if defined(OS_ANDROID) | 488 #if defined(OS_ANDROID) |
521 stream_texture_manager_.reset(); | 489 stream_texture_manager_.reset(); |
522 #endif | 490 #endif |
523 | 491 |
524 g_all_shared_contexts.Pointer()->erase(this); | |
525 return true; | 492 return true; |
526 } | 493 } |
527 | 494 |
528 void InProcessCommandBuffer::CheckSequencedThread() { | 495 void InProcessCommandBuffer::CheckSequencedThread() { |
529 DCHECK(!sequence_checker_ || | 496 DCHECK(!sequence_checker_ || |
530 sequence_checker_->CalledOnValidSequencedThread()); | 497 sequence_checker_->CalledOnValidSequencedThread()); |
531 } | 498 } |
532 | 499 |
533 void InProcessCommandBuffer::OnContextLost() { | 500 void InProcessCommandBuffer::OnContextLost() { |
534 CheckSequencedThread(); | 501 CheckSequencedThread(); |
535 if (!context_lost_callback_.is_null()) { | 502 if (!context_lost_callback_.is_null()) { |
536 context_lost_callback_.Run(); | 503 context_lost_callback_.Run(); |
537 context_lost_callback_.Reset(); | 504 context_lost_callback_.Reset(); |
538 } | 505 } |
539 | 506 |
540 context_lost_ = true; | 507 context_lost_ = true; |
541 if (share_resources_) { | |
542 for (std::set<InProcessCommandBuffer*>::iterator it = | |
543 g_all_shared_contexts.Get().begin(); | |
544 it != g_all_shared_contexts.Get().end(); | |
545 ++it) { | |
546 (*it)->context_lost_ = true; | |
no sievers
2014/02/12 01:24:32
glLoseContextCHROMIUM() already propagates the los
| |
547 } | |
548 } | |
549 } | 508 } |
550 | 509 |
551 CommandBuffer::State InProcessCommandBuffer::GetStateFast() { | 510 CommandBuffer::State InProcessCommandBuffer::GetStateFast() { |
552 CheckSequencedThread(); | 511 CheckSequencedThread(); |
553 base::AutoLock lock(state_after_last_flush_lock_); | 512 base::AutoLock lock(state_after_last_flush_lock_); |
554 if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U) | 513 if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U) |
555 last_state_ = state_after_last_flush_; | 514 last_state_ = state_after_last_flush_; |
556 return last_state_; | 515 return last_state_; |
557 } | 516 } |
558 | 517 |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 g_gpu_queue.Get().RunTasks(); | 800 g_gpu_queue.Get().RunTasks(); |
842 } | 801 } |
843 | 802 |
844 // static | 803 // static |
845 void InProcessCommandBuffer::SetGpuMemoryBufferFactory( | 804 void InProcessCommandBuffer::SetGpuMemoryBufferFactory( |
846 GpuMemoryBufferFactory* factory) { | 805 GpuMemoryBufferFactory* factory) { |
847 g_gpu_memory_buffer_factory = factory; | 806 g_gpu_memory_buffer_factory = factory; |
848 } | 807 } |
849 | 808 |
850 } // namespace gpu | 809 } // namespace gpu |
OLD | NEW |