| 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 <windows.h> | 7 #include <windows.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 base::LazyInstance<AcceleratedPresenterMap> | 154 base::LazyInstance<AcceleratedPresenterMap> |
| 155 g_accelerated_presenter_map = LAZY_INSTANCE_INITIALIZER; | 155 g_accelerated_presenter_map = LAZY_INSTANCE_INITIALIZER; |
| 156 | 156 |
| 157 PresentThread::PresentThread(const char* name) : base::Thread(name) { | 157 PresentThread::PresentThread(const char* name) : base::Thread(name) { |
| 158 } | 158 } |
| 159 | 159 |
| 160 void PresentThread::InitDevice() { | 160 void PresentThread::InitDevice() { |
| 161 if (device_) | 161 if (device_) |
| 162 return; | 162 return; |
| 163 | 163 |
| 164 TRACE_EVENT0("surface", "PresentThread::Init"); | 164 TRACE_EVENT0("gpu", "PresentThread::Init"); |
| 165 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); | 165 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); |
| 166 ResetDevice(); | 166 ResetDevice(); |
| 167 } | 167 } |
| 168 | 168 |
| 169 void PresentThread::ResetDevice() { | 169 void PresentThread::ResetDevice() { |
| 170 TRACE_EVENT0("surface", "PresentThread::ResetDevice"); | 170 TRACE_EVENT0("gpu", "PresentThread::ResetDevice"); |
| 171 | 171 |
| 172 // This will crash some Intel drivers but we can't render anything without | 172 // This will crash some Intel drivers but we can't render anything without |
| 173 // reseting the device, which would be disappointing. | 173 // reseting the device, which would be disappointing. |
| 174 query_ = NULL; | 174 query_ = NULL; |
| 175 device_ = NULL; | 175 device_ = NULL; |
| 176 | 176 |
| 177 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( | 177 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( |
| 178 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); | 178 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); |
| 179 if (!create_func) | 179 if (!create_func) |
| 180 return; | 180 return; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 present_thread_->message_loop()->PostTask( | 305 present_thread_->message_loop()->PostTask( |
| 306 FROM_HERE, | 306 FROM_HERE, |
| 307 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, | 307 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, |
| 308 this, | 308 this, |
| 309 size, | 309 size, |
| 310 surface_handle, | 310 surface_handle, |
| 311 completion_task)); | 311 completion_task)); |
| 312 } | 312 } |
| 313 | 313 |
| 314 bool AcceleratedPresenter::Present() { | 314 bool AcceleratedPresenter::Present() { |
| 315 TRACE_EVENT0("surface", "Present"); | 315 TRACE_EVENT0("gpu", "Present"); |
| 316 | 316 |
| 317 bool result; | 317 bool result; |
| 318 | 318 |
| 319 present_thread_->message_loop()->PostTask( | 319 present_thread_->message_loop()->PostTask( |
| 320 FROM_HERE, | 320 FROM_HERE, |
| 321 base::Bind(&AcceleratedPresenter::DoPresent, | 321 base::Bind(&AcceleratedPresenter::DoPresent, |
| 322 this, | 322 this, |
| 323 &result)); | 323 &result)); |
| 324 // http://crbug.com/125391 | 324 // http://crbug.com/125391 |
| 325 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 325 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 326 event_.Wait(); | 326 event_.Wait(); |
| 327 return result; | 327 return result; |
| 328 } | 328 } |
| 329 | 329 |
| 330 void AcceleratedPresenter::DoPresent(bool* result) | 330 void AcceleratedPresenter::DoPresent(bool* result) |
| 331 { | 331 { |
| 332 *result = DoRealPresent(); | 332 *result = DoRealPresent(); |
| 333 event_.Signal(); | 333 event_.Signal(); |
| 334 } | 334 } |
| 335 | 335 |
| 336 bool AcceleratedPresenter::DoRealPresent() | 336 bool AcceleratedPresenter::DoRealPresent() |
| 337 { | 337 { |
| 338 TRACE_EVENT0("surface", "DoRealPresent"); | 338 TRACE_EVENT0("gpu", "DoRealPresent"); |
| 339 HRESULT hr; | 339 HRESULT hr; |
| 340 | 340 |
| 341 base::AutoLock locked(lock_); | 341 base::AutoLock locked(lock_); |
| 342 | 342 |
| 343 // Signal the caller to recomposite if the presenter has been suspended or no | 343 // Signal the caller to recomposite if the presenter has been suspended or no |
| 344 // surface has ever been presented. | 344 // surface has ever been presented. |
| 345 if (!swap_chain_) | 345 if (!swap_chain_) |
| 346 return false; | 346 return false; |
| 347 | 347 |
| 348 // If invalidated, do nothing. The window is gone. | 348 // If invalidated, do nothing. The window is gone. |
| 349 if (!window_) | 349 if (!window_) |
| 350 return true; | 350 return true; |
| 351 | 351 |
| 352 RECT rect = { | 352 RECT rect = { |
| 353 0, 0, | 353 0, 0, |
| 354 size_.width(), size_.height() | 354 size_.width(), size_.height() |
| 355 }; | 355 }; |
| 356 | 356 |
| 357 { | 357 { |
| 358 TRACE_EVENT0("surface", "PresentEx"); | 358 TRACE_EVENT0("gpu", "PresentEx"); |
| 359 hr = swap_chain_->Present(&rect, | 359 hr = swap_chain_->Present(&rect, |
| 360 &rect, | 360 &rect, |
| 361 window_, | 361 window_, |
| 362 NULL, | 362 NULL, |
| 363 D3DPRESENT_INTERVAL_IMMEDIATE); | 363 D3DPRESENT_INTERVAL_IMMEDIATE); |
| 364 if (FAILED(hr)) | 364 if (FAILED(hr)) |
| 365 return false; | 365 return false; |
| 366 } | 366 } |
| 367 | 367 |
| 368 return true; | 368 return true; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 switches::kGpuSwapDelay).c_str(), &delay); | 502 switches::kGpuSwapDelay).c_str(), &delay); |
| 503 } | 503 } |
| 504 return base::TimeDelta::FromMilliseconds(delay); | 504 return base::TimeDelta::FromMilliseconds(delay); |
| 505 } | 505 } |
| 506 | 506 |
| 507 void AcceleratedPresenter::DoPresentAndAcknowledge( | 507 void AcceleratedPresenter::DoPresentAndAcknowledge( |
| 508 const gfx::Size& size, | 508 const gfx::Size& size, |
| 509 int64 surface_handle, | 509 int64 surface_handle, |
| 510 const base::Callback<void(bool)>& completion_task) { | 510 const base::Callback<void(bool)>& completion_task) { |
| 511 TRACE_EVENT1( | 511 TRACE_EVENT1( |
| 512 "surface", "DoPresentAndAcknowledge", "surface_handle", surface_handle); | 512 "gpu", "DoPresentAndAcknowledge", "surface_handle", surface_handle); |
| 513 | 513 |
| 514 HRESULT hr; | 514 HRESULT hr; |
| 515 | 515 |
| 516 base::AutoLock locked(lock_); | 516 base::AutoLock locked(lock_); |
| 517 | 517 |
| 518 // Initialize the device lazily since calling Direct3D can crash bots. | 518 // Initialize the device lazily since calling Direct3D can crash bots. |
| 519 present_thread_->InitDevice(); | 519 present_thread_->InitDevice(); |
| 520 | 520 |
| 521 if (!present_thread_->device()) { | 521 if (!present_thread_->device()) { |
| 522 if (!completion_task.is_null()) | 522 if (!completion_task.is_null()) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 535 // Round up size so the swap chain is not continuously resized with the | 535 // Round up size so the swap chain is not continuously resized with the |
| 536 // surface, which could lead to memory fragmentation. | 536 // surface, which could lead to memory fragmentation. |
| 537 const int kRound = 64; | 537 const int kRound = 64; |
| 538 gfx::Size quantized_size( | 538 gfx::Size quantized_size( |
| 539 std::max(1, (size.width() + kRound - 1) / kRound * kRound), | 539 std::max(1, (size.width() + kRound - 1) / kRound * kRound), |
| 540 std::max(1, (size.height() + kRound - 1) / kRound * kRound)); | 540 std::max(1, (size.height() + kRound - 1) / kRound * kRound)); |
| 541 | 541 |
| 542 // Ensure the swap chain exists and is the same size (rounded up) as the | 542 // Ensure the swap chain exists and is the same size (rounded up) as the |
| 543 // surface to be presented. | 543 // surface to be presented. |
| 544 if (!swap_chain_ || size_ != quantized_size) { | 544 if (!swap_chain_ || size_ != quantized_size) { |
| 545 TRACE_EVENT0("surface", "CreateAdditionalSwapChain"); | 545 TRACE_EVENT0("gpu", "CreateAdditionalSwapChain"); |
| 546 size_ = quantized_size; | 546 size_ = quantized_size; |
| 547 | 547 |
| 548 D3DPRESENT_PARAMETERS parameters = { 0 }; | 548 D3DPRESENT_PARAMETERS parameters = { 0 }; |
| 549 parameters.BackBufferWidth = quantized_size.width(); | 549 parameters.BackBufferWidth = quantized_size.width(); |
| 550 parameters.BackBufferHeight = quantized_size.height(); | 550 parameters.BackBufferHeight = quantized_size.height(); |
| 551 parameters.BackBufferCount = 1; | 551 parameters.BackBufferCount = 1; |
| 552 parameters.BackBufferFormat = D3DFMT_A8R8G8B8; | 552 parameters.BackBufferFormat = D3DFMT_A8R8G8B8; |
| 553 parameters.hDeviceWindow = GetShellWindow(); | 553 parameters.hDeviceWindow = GetShellWindow(); |
| 554 parameters.Windowed = TRUE; | 554 parameters.Windowed = TRUE; |
| 555 parameters.Flags = 0; | 555 parameters.Flags = 0; |
| 556 parameters.PresentationInterval = GetPresentationInterval(); | 556 parameters.PresentationInterval = GetPresentationInterval(); |
| 557 parameters.SwapEffect = D3DSWAPEFFECT_COPY; | 557 parameters.SwapEffect = D3DSWAPEFFECT_COPY; |
| 558 | 558 |
| 559 swap_chain_ = NULL; | 559 swap_chain_ = NULL; |
| 560 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain( | 560 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain( |
| 561 ¶meters, | 561 ¶meters, |
| 562 swap_chain_.Receive()); | 562 swap_chain_.Receive()); |
| 563 if (FAILED(hr)) | 563 if (FAILED(hr)) |
| 564 return; | 564 return; |
| 565 } | 565 } |
| 566 | 566 |
| 567 if (!source_texture_.get()) { | 567 if (!source_texture_.get()) { |
| 568 TRACE_EVENT0("surface", "CreateTexture"); | 568 TRACE_EVENT0("gpu", "CreateTexture"); |
| 569 HANDLE handle = reinterpret_cast<HANDLE>(surface_handle); | 569 HANDLE handle = reinterpret_cast<HANDLE>(surface_handle); |
| 570 hr = present_thread_->device()->CreateTexture(size.width(), | 570 hr = present_thread_->device()->CreateTexture(size.width(), |
| 571 size.height(), | 571 size.height(), |
| 572 1, | 572 1, |
| 573 D3DUSAGE_RENDERTARGET, | 573 D3DUSAGE_RENDERTARGET, |
| 574 D3DFMT_A8R8G8B8, | 574 D3DFMT_A8R8G8B8, |
| 575 D3DPOOL_DEFAULT, | 575 D3DPOOL_DEFAULT, |
| 576 source_texture_.Receive(), | 576 source_texture_.Receive(), |
| 577 &handle); | 577 &handle); |
| 578 if (FAILED(hr)) | 578 if (FAILED(hr)) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 590 dest_surface.Receive()); | 590 dest_surface.Receive()); |
| 591 if (FAILED(hr)) | 591 if (FAILED(hr)) |
| 592 return; | 592 return; |
| 593 | 593 |
| 594 RECT rect = { | 594 RECT rect = { |
| 595 0, 0, | 595 0, 0, |
| 596 size.width(), size.height() | 596 size.width(), size.height() |
| 597 }; | 597 }; |
| 598 | 598 |
| 599 { | 599 { |
| 600 TRACE_EVENT0("surface", "StretchRect"); | 600 TRACE_EVENT0("gpu", "StretchRect"); |
| 601 hr = present_thread_->device()->StretchRect(source_surface, | 601 hr = present_thread_->device()->StretchRect(source_surface, |
| 602 &rect, | 602 &rect, |
| 603 dest_surface, | 603 dest_surface, |
| 604 &rect, | 604 &rect, |
| 605 D3DTEXF_NONE); | 605 D3DTEXF_NONE); |
| 606 if (FAILED(hr)) | 606 if (FAILED(hr)) |
| 607 return; | 607 return; |
| 608 } | 608 } |
| 609 | 609 |
| 610 hr = present_thread_->query()->Issue(D3DISSUE_END); | 610 hr = present_thread_->query()->Issue(D3DISSUE_END); |
| 611 if (FAILED(hr)) | 611 if (FAILED(hr)) |
| 612 return; | 612 return; |
| 613 | 613 |
| 614 // Flush so the StretchRect can be processed by the GPU while the window is | 614 // Flush so the StretchRect can be processed by the GPU while the window is |
| 615 // being resized. | 615 // being resized. |
| 616 present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); | 616 present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); |
| 617 | 617 |
| 618 ::SetWindowPos( | 618 ::SetWindowPos( |
| 619 window_, | 619 window_, |
| 620 NULL, | 620 NULL, |
| 621 0, 0, | 621 0, 0, |
| 622 size.width(), size.height(), | 622 size.width(), size.height(), |
| 623 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER | | 623 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER | |
| 624 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING | | 624 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING | |
| 625 SWP_ASYNCWINDOWPOS | SWP_NOZORDER); | 625 SWP_ASYNCWINDOWPOS | SWP_NOZORDER); |
| 626 | 626 |
| 627 // Wait for the StretchRect to complete before notifying the GPU process | 627 // Wait for the StretchRect to complete before notifying the GPU process |
| 628 // that it is safe to write to its backing store again. | 628 // that it is safe to write to its backing store again. |
| 629 { | 629 { |
| 630 TRACE_EVENT0("surface", "spin"); | 630 TRACE_EVENT0("gpu", "spin"); |
| 631 do { | 631 do { |
| 632 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); | 632 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); |
| 633 | 633 |
| 634 if (hr == S_FALSE) | 634 if (hr == S_FALSE) |
| 635 Sleep(1); | 635 Sleep(1); |
| 636 } while (hr == S_FALSE); | 636 } while (hr == S_FALSE); |
| 637 } | 637 } |
| 638 | 638 |
| 639 static const base::TimeDelta swap_delay = GetSwapDelay(); | 639 static const base::TimeDelta swap_delay = GetSwapDelay(); |
| 640 if (swap_delay.ToInternalValue()) | 640 if (swap_delay.ToInternalValue()) |
| 641 base::PlatformThread::Sleep(swap_delay); | 641 base::PlatformThread::Sleep(swap_delay); |
| 642 | 642 |
| 643 { | 643 { |
| 644 TRACE_EVENT0("surface", "Present"); | 644 TRACE_EVENT0("gpu", "Present"); |
| 645 hr = swap_chain_->Present(&rect, &rect, window_, NULL, 0); | 645 hr = swap_chain_->Present(&rect, &rect, window_, NULL, 0); |
| 646 if (FAILED(hr) && | 646 if (FAILED(hr) && |
| 647 FAILED(present_thread_->device()->CheckDeviceState(window_))) { | 647 FAILED(present_thread_->device()->CheckDeviceState(window_))) { |
| 648 present_thread_->ResetDevice(); | 648 present_thread_->ResetDevice(); |
| 649 } | 649 } |
| 650 } | 650 } |
| 651 } | 651 } |
| 652 | 652 |
| 653 void AcceleratedPresenter::DoSuspend() { | 653 void AcceleratedPresenter::DoSuspend() { |
| 654 base::AutoLock locked(lock_); | 654 base::AutoLock locked(lock_); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 674 return presenter_->Present(); | 674 return presenter_->Present(); |
| 675 } | 675 } |
| 676 | 676 |
| 677 bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) { | 677 bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) { |
| 678 return presenter_->CopyTo(size, buf); | 678 return presenter_->CopyTo(size, buf); |
| 679 } | 679 } |
| 680 | 680 |
| 681 void AcceleratedSurface::Suspend() { | 681 void AcceleratedSurface::Suspend() { |
| 682 presenter_->Suspend(); | 682 presenter_->Suspend(); |
| 683 } | 683 } |
| OLD | NEW |