| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/surface/accelerated_surface_win.h" | 5 #include "ui/surface/accelerated_surface_win.h" |
| 6 | 6 |
| 7 #include <dwmapi.h> | 7 #include <dwmapi.h> |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 | 262 |
| 263 // static | 263 // static |
| 264 scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow( | 264 scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow( |
| 265 gfx::PluginWindowHandle window) { | 265 gfx::PluginWindowHandle window) { |
| 266 return g_accelerated_presenter_map.Pointer()->GetPresenter(window); | 266 return g_accelerated_presenter_map.Pointer()->GetPresenter(window); |
| 267 } | 267 } |
| 268 | 268 |
| 269 void AcceleratedPresenter::AsyncPresentAndAcknowledge( | 269 void AcceleratedPresenter::AsyncPresentAndAcknowledge( |
| 270 const gfx::Size& size, | 270 const gfx::Size& size, |
| 271 int64 surface_handle, | 271 int64 surface_handle, |
| 272 const CopyCompletionTask& copy_completion_task, | 272 const CompletionTask& completion_task) { |
| 273 const PresentCompletionTask& present_completion_task) { | |
| 274 if (!surface_handle) { | 273 if (!surface_handle) { |
| 275 TRACE_EVENT1("gpu", "EarlyOut_ZeroSurfaceHandle", | 274 TRACE_EVENT1("gpu", "EarlyOut_ZeroSurfaceHandle", |
| 276 "surface_handle", surface_handle); | 275 "surface_handle", surface_handle); |
| 277 copy_completion_task.Run(true); | 276 completion_task.Run(true, base::TimeTicks(), base::TimeDelta()); |
| 278 present_completion_task.Run(base::TimeTicks(), base::TimeDelta()); | |
| 279 return; | 277 return; |
| 280 } | 278 } |
| 281 | 279 |
| 282 present_thread_->message_loop()->PostTask( | 280 present_thread_->message_loop()->PostTask( |
| 283 FROM_HERE, | 281 FROM_HERE, |
| 284 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, | 282 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, |
| 285 this, | 283 this, |
| 286 size, | 284 size, |
| 287 surface_handle, | 285 surface_handle, |
| 288 copy_completion_task, | 286 completion_task)); |
| 289 present_completion_task)); | |
| 290 } | 287 } |
| 291 | 288 |
| 292 void AcceleratedPresenter::Present(HDC dc) { | 289 void AcceleratedPresenter::Present(HDC dc) { |
| 293 TRACE_EVENT0("gpu", "Present"); | 290 TRACE_EVENT0("gpu", "Present"); |
| 294 | 291 |
| 295 base::AutoLock locked(lock_); | 292 base::AutoLock locked(lock_); |
| 296 | 293 |
| 297 // If invalidated, do nothing. The window is gone. | 294 // If invalidated, do nothing. The window is gone. |
| 298 if (!window_) | 295 if (!window_) |
| 299 return; | 296 return; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 if (cmd_line->HasSwitch(switches::kGpuSwapDelay)) { | 462 if (cmd_line->HasSwitch(switches::kGpuSwapDelay)) { |
| 466 base::StringToInt(cmd_line->GetSwitchValueNative( | 463 base::StringToInt(cmd_line->GetSwitchValueNative( |
| 467 switches::kGpuSwapDelay).c_str(), &delay); | 464 switches::kGpuSwapDelay).c_str(), &delay); |
| 468 } | 465 } |
| 469 return base::TimeDelta::FromMilliseconds(delay); | 466 return base::TimeDelta::FromMilliseconds(delay); |
| 470 } | 467 } |
| 471 | 468 |
| 472 void AcceleratedPresenter::DoPresentAndAcknowledge( | 469 void AcceleratedPresenter::DoPresentAndAcknowledge( |
| 473 const gfx::Size& size, | 470 const gfx::Size& size, |
| 474 int64 surface_handle, | 471 int64 surface_handle, |
| 475 const CopyCompletionTask& copy_completion_task, | 472 const CompletionTask& completion_task) { |
| 476 const PresentCompletionTask& present_completion_task) { | |
| 477 TRACE_EVENT2( | 473 TRACE_EVENT2( |
| 478 "gpu", "DoPresentAndAcknowledge", | 474 "gpu", "DoPresentAndAcknowledge", |
| 479 "width", size.width(), | 475 "width", size.width(), |
| 480 "height", size.height()); | 476 "height", size.height()); |
| 481 | 477 |
| 482 HRESULT hr; | 478 HRESULT hr; |
| 483 | 479 |
| 484 base::AutoLock locked(lock_); | 480 base::AutoLock locked(lock_); |
| 485 | 481 |
| 486 // Initialize the device lazily since calling Direct3D can crash bots. | 482 // Initialize the device lazily since calling Direct3D can crash bots. |
| 487 present_thread_->InitDevice(); | 483 present_thread_->InitDevice(); |
| 488 | 484 |
| 489 if (!present_thread_->device()) { | 485 if (!present_thread_->device()) { |
| 490 if (!copy_completion_task.is_null()) | 486 if (!completion_task.is_null()) |
| 491 copy_completion_task.Run(false); | 487 completion_task.Run(false, base::TimeTicks(), base::TimeDelta()); |
| 492 if (!present_completion_task.is_null()) | |
| 493 present_completion_task.Run(base::TimeTicks(), base::TimeDelta()); | |
| 494 TRACE_EVENT0("gpu", "EarlyOut_NoDevice"); | 488 TRACE_EVENT0("gpu", "EarlyOut_NoDevice"); |
| 495 return; | 489 return; |
| 496 } | 490 } |
| 497 | 491 |
| 498 // Ensure the task is always run and while the lock is taken. | 492 // Ensure the task is always run and while the lock is taken. |
| 499 base::ScopedClosureRunner scoped_copy_completion_runner( | 493 base::ScopedClosureRunner scoped_completion_runner( |
| 500 base::Bind(copy_completion_task, true)); | 494 base::Bind(completion_task, true, base::TimeTicks(), base::TimeDelta())); |
| 501 base::ScopedClosureRunner scoped_present_completion_runner( | |
| 502 base::Bind(present_completion_task, | |
| 503 base::TimeTicks(), | |
| 504 base::TimeDelta())); | |
| 505 | 495 |
| 506 // If invalidated, do nothing, the window is gone. | 496 // If invalidated, do nothing, the window is gone. |
| 507 if (!window_) { | 497 if (!window_) { |
| 508 TRACE_EVENT0("gpu", "EarlyOut_NoWindow"); | 498 TRACE_EVENT0("gpu", "EarlyOut_NoWindow"); |
| 509 return; | 499 return; |
| 510 } | 500 } |
| 511 | 501 |
| 512 #if !defined(USE_AURA) | 502 #if !defined(USE_AURA) |
| 513 // If the window is a different size than the swap chain that is being | 503 // If the window is a different size than the swap chain that is being |
| 514 // presented then drop the frame. | 504 // presented then drop the frame. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 bool result = present_thread_->surface_transformer()->CopyInverted( | 587 bool result = present_thread_->surface_transformer()->CopyInverted( |
| 598 source_texture_, dest_surface, size); | 588 source_texture_, dest_surface, size); |
| 599 if (!result) | 589 if (!result) |
| 600 return; | 590 return; |
| 601 } | 591 } |
| 602 | 592 |
| 603 hr = present_thread_->query()->Issue(D3DISSUE_END); | 593 hr = present_thread_->query()->Issue(D3DISSUE_END); |
| 604 if (FAILED(hr)) | 594 if (FAILED(hr)) |
| 605 return; | 595 return; |
| 606 | 596 |
| 607 // Wait for the StretchRect to complete before notifying the GPU process | |
| 608 // that it is safe to write to its backing store again. | |
| 609 { | |
| 610 TRACE_EVENT0("gpu", "spin"); | |
| 611 do { | |
| 612 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); | |
| 613 | |
| 614 if (hr == S_FALSE) | |
| 615 Sleep(1); | |
| 616 } while (hr == S_FALSE); | |
| 617 } | |
| 618 | |
| 619 // Acknowledge that the copy is complete and it is safe to modify the shared | |
| 620 // texture. | |
| 621 scoped_copy_completion_runner.Release(); | |
| 622 copy_completion_task.Run(true); | |
| 623 | |
| 624 present_size_ = size; | 597 present_size_ = size; |
| 625 | 598 |
| 626 static const base::TimeDelta swap_delay = GetSwapDelay(); | 599 static const base::TimeDelta swap_delay = GetSwapDelay(); |
| 627 if (swap_delay.ToInternalValue()) | 600 if (swap_delay.ToInternalValue()) |
| 628 base::PlatformThread::Sleep(swap_delay); | 601 base::PlatformThread::Sleep(swap_delay); |
| 629 | 602 |
| 630 // If it is expected that Direct3D cannot be used reliably because the window | 603 // If it is expected that Direct3D cannot be used reliably because the window |
| 631 // is resizing, fall back to presenting with GDI. | 604 // is resizing, fall back to presenting with GDI. |
| 632 if (CheckDirect3DWillWork()) { | 605 if (CheckDirect3DWillWork()) { |
| 633 TRACE_EVENT0("gpu", "PresentD3D"); | 606 TRACE_EVENT0("gpu", "PresentD3D"); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 base::TimeTicks last_vsync_time; | 652 base::TimeTicks last_vsync_time; |
| 680 base::TimeDelta refresh_period; | 653 base::TimeDelta refresh_period; |
| 681 if (display_mode.Height) { | 654 if (display_mode.Height) { |
| 682 last_vsync_time = current_time - | 655 last_vsync_time = current_time - |
| 683 base::TimeDelta::FromMilliseconds((clamped_scanline * 1000) / | 656 base::TimeDelta::FromMilliseconds((clamped_scanline * 1000) / |
| 684 (display_mode.RefreshRate * display_mode.Height)); | 657 (display_mode.RefreshRate * display_mode.Height)); |
| 685 refresh_period = base::TimeDelta::FromMicroseconds( | 658 refresh_period = base::TimeDelta::FromMicroseconds( |
| 686 1000000 / display_mode.RefreshRate); | 659 1000000 / display_mode.RefreshRate); |
| 687 } | 660 } |
| 688 | 661 |
| 689 scoped_present_completion_runner.Release(); | 662 // Wait for the StretchRect to complete before notifying the GPU process |
| 690 present_completion_task.Run(last_vsync_time, refresh_period); | 663 // that it is safe to write to its backing store again. |
| 664 { |
| 665 TRACE_EVENT0("gpu", "spin"); |
| 666 do { |
| 667 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); |
| 668 |
| 669 if (hr == S_FALSE) |
| 670 Sleep(1); |
| 671 } while (hr == S_FALSE); |
| 672 } |
| 673 |
| 674 scoped_completion_runner.Release(); |
| 675 completion_task.Run(true, last_vsync_time, refresh_period); |
| 691 } | 676 } |
| 692 | 677 |
| 693 void AcceleratedPresenter::DoSuspend() { | 678 void AcceleratedPresenter::DoSuspend() { |
| 694 base::AutoLock locked(lock_); | 679 base::AutoLock locked(lock_); |
| 695 swap_chain_ = NULL; | 680 swap_chain_ = NULL; |
| 696 } | 681 } |
| 697 | 682 |
| 698 void AcceleratedPresenter::DoReleaseSurface() { | 683 void AcceleratedPresenter::DoReleaseSurface() { |
| 699 base::AutoLock locked(lock_); | 684 base::AutoLock locked(lock_); |
| 700 present_thread_->InitDevice(); | 685 present_thread_->InitDevice(); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 presenter_->AsyncCopyTo(src_subrect, dst_size, buf, callback); | 807 presenter_->AsyncCopyTo(src_subrect, dst_size, buf, callback); |
| 823 } | 808 } |
| 824 | 809 |
| 825 void AcceleratedSurface::Suspend() { | 810 void AcceleratedSurface::Suspend() { |
| 826 presenter_->Suspend(); | 811 presenter_->Suspend(); |
| 827 } | 812 } |
| 828 | 813 |
| 829 void AcceleratedSurface::WasHidden() { | 814 void AcceleratedSurface::WasHidden() { |
| 830 presenter_->WasHidden(); | 815 presenter_->WasHidden(); |
| 831 } | 816 } |
| OLD | NEW |