diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-09 20:20:34 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-09 20:20:34 +0000 |
commit | 7149c15fdeb1d036affdc5086bf76544257a7953 (patch) | |
tree | f37ba331ab79d9c960483669f7680056eaf15f2c | |
parent | 6cf6209313945db183394729a553be8097f1affd (diff) | |
download | chromium_src-7149c15fdeb1d036affdc5086bf76544257a7953.zip chromium_src-7149c15fdeb1d036affdc5086bf76544257a7953.tar.gz chromium_src-7149c15fdeb1d036affdc5086bf76544257a7953.tar.bz2 |
Shutdown GPU process if Direct 3D cannot be initialized in the browser process.
The GPU process cannot usefully do anything in this case since its output cannot be presented. This uses the existing machinery to recover from the GPU process crashing. It will reattempt 3 times as before.
Direct3D is initialized asynchronously off the main thread so the browser process does not learn of the failure until the GPU process attempts to present a surface.
I also discovered a bug where a SwapBuffers acknowledgement could be sent to the wrong instance of a GPU process because of a mismatch between client_id and host_id.
BUG=117468
Review URL: https://chromiumcodereview.appspot.com/9651012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@125886 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/gpu/gpu_process_host.cc | 29 | ||||
-rw-r--r-- | content/browser/gpu/gpu_surface_tracker.cc | 4 | ||||
-rw-r--r-- | content/browser/gpu/gpu_surface_tracker.h | 9 | ||||
-rw-r--r-- | ui/gfx/surface/accelerated_surface_win.cc | 20 | ||||
-rw-r--r-- | ui/gfx/surface/accelerated_surface_win.h | 36 |
5 files changed, 66 insertions, 32 deletions
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 2b0bb2c..51313a4 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -90,6 +90,29 @@ void SendGpuProcessMessage(int client_id, } } +void AcceleratedSurfaceBuffersSwappedCompleted(int host_id, + int route_id, + bool alive) { + if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { + GpuProcessHost* host = GpuProcessHost::FromID(host_id); + if (host) { + if (alive) + host->Send(new AcceleratedSurfaceMsg_BuffersSwappedACK(route_id)); + else { + host->ForceShutdown(); + } + } + } else { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted, + host_id, + route_id, + alive)); + } +} + } // anonymous namespace #if defined(TOOLKIT_USES_GTK) @@ -534,11 +557,9 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( params.surface_id, params.size, params.surface_handle, - base::Bind(SendOnIO, + base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted, host_id_, - content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, - new AcceleratedSurfaceMsg_BuffersSwappedACK( - params.route_id))); + params.route_id)); } void GpuProcessHost::OnAcceleratedSurfacePostSubBuffer( diff --git a/content/browser/gpu/gpu_surface_tracker.cc b/content/browser/gpu/gpu_surface_tracker.cc index c2aa9b1..ca1d078 100644 --- a/content/browser/gpu/gpu_surface_tracker.cc +++ b/content/browser/gpu/gpu_surface_tracker.cc @@ -96,12 +96,12 @@ void GpuSurfaceTracker::AsyncPresentAndAcknowledge( int surface_id, const gfx::Size& size, int64 surface_handle, - const base::Closure& completion_task) { + const base::Callback<void(bool)>& completion_task) { base::AutoLock lock(lock_); SurfaceMap::iterator it = surface_map_.find(surface_id); if (it == surface_map_.end() || !it->second.handle.accelerated_surface) { - completion_task.Run(); + completion_task.Run(true); return; } diff --git a/content/browser/gpu/gpu_surface_tracker.h b/content/browser/gpu/gpu_surface_tracker.h index 4532235..15d6bd2 100644 --- a/content/browser/gpu/gpu_surface_tracker.h +++ b/content/browser/gpu/gpu_surface_tracker.h @@ -65,10 +65,11 @@ class GpuSurfaceTracker { // on the IO thread. This function only posts tasks asynchronously. If it // were to synchronously call the UI thread, there would be a possiblity of // deadlock. - void AsyncPresentAndAcknowledge(int surface_id, - const gfx::Size& size, - int64 surface_handle, - const base::Closure& completion_task); + void AsyncPresentAndAcknowledge( + int surface_id, + const gfx::Size& size, + int64 surface_handle, + const base::Callback<void(bool)>& completion_task); void Suspend(int surface_id); #endif diff --git a/ui/gfx/surface/accelerated_surface_win.cc b/ui/gfx/surface/accelerated_surface_win.cc index 4edc1ee..70b5a98 100644 --- a/ui/gfx/surface/accelerated_surface_win.cc +++ b/ui/gfx/surface/accelerated_surface_win.cc @@ -140,9 +140,8 @@ void PresentThread::ResetDevice() { return; hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); - if (FAILED(hr)) { + if (FAILED(hr)) device_ = NULL; - } } void PresentThread::Init() { @@ -179,7 +178,7 @@ void AcceleratedPresenter::AsyncPresentAndAcknowledge( gfx::NativeWindow window, const gfx::Size& size, int64 surface_id, - const base::Closure& completion_task) { + const base::Callback<void(bool)>& completion_task) { present_thread_->message_loop()->PostTask( FROM_HERE, base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, @@ -260,15 +259,22 @@ void AcceleratedPresenter::DoPresentAndAcknowledge( gfx::NativeWindow window, const gfx::Size& size, int64 surface_id, - const base::Closure& completion_task) { + const base::Callback<void(bool)>& completion_task) { TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id); HRESULT hr; base::AutoLock locked(lock_); + if (!present_thread_->device()) { + if (!completion_task.is_null()) + completion_task.Run(false); + return; + } + // Ensure the task is always run and while the lock is taken. - base::ScopedClosureRunner scoped_completion_runner(completion_task); + base::ScopedClosureRunner scoped_completion_runner(base::Bind(completion_task, + true)); // Round up size so the swap chain is not continuously resized with the // surface, which could lead to memory fragmentation. @@ -380,7 +386,7 @@ void AcceleratedPresenter::DoPresentAndAcknowledge( scoped_completion_runner.Release(); if (!completion_task.is_null()) - completion_task.Run(); + completion_task.Run(true); { TRACE_EVENT0("surface", "Present"); @@ -411,7 +417,7 @@ void AcceleratedSurface::AsyncPresentAndAcknowledge( HWND window, const gfx::Size& size, int64 surface_id, - const base::Closure& completion_task) { + const base::Callback<void(bool)>& completion_task) { if (!surface_id) return; diff --git a/ui/gfx/surface/accelerated_surface_win.h b/ui/gfx/surface/accelerated_surface_win.h index 5ed3078..d027f19 100644 --- a/ui/gfx/surface/accelerated_surface_win.h +++ b/ui/gfx/surface/accelerated_surface_win.h @@ -18,30 +18,35 @@ class PresentThread; -class AcceleratedPresenter : public base::RefCounted<AcceleratedPresenter> { +class AcceleratedPresenter + : public base::RefCountedThreadSafe<AcceleratedPresenter> { public: + typedef base::Callback<void(bool)> CompletionTaskl; + AcceleratedPresenter(); // The public member functions are called on the main thread. - void AsyncPresentAndAcknowledge(gfx::NativeWindow window, - const gfx::Size& size, - int64 surface_id, - const base::Closure& completion_task); + void AsyncPresentAndAcknowledge( + gfx::NativeWindow window, + const gfx::Size& size, + int64 surface_id, + const base::Callback<void(bool)>& completion_task); bool Present(gfx::NativeWindow window); void Suspend(); void WaitForPendingTasks(); private: - friend class base::RefCounted<AcceleratedPresenter>; + friend class base::RefCountedThreadSafe<AcceleratedPresenter>; ~AcceleratedPresenter(); // These member functions are called on the PresentThread with which the // presenter has affinity. - void DoPresentAndAcknowledge(gfx::NativeWindow window, - const gfx::Size& size, - int64 surface_id, - const base::Closure& completion_task); + void DoPresentAndAcknowledge( + gfx::NativeWindow window, + const gfx::Size& size, + int64 surface_id, + const base::Callback<void(bool)>& completion_task); void DoSuspend(); // The thread with which this presenter has affinity. @@ -71,13 +76,14 @@ class SURFACE_EXPORT AcceleratedSurface { // Schedule a frame to be presented. The completion callback will be invoked // when it is safe to write to the surface on another thread. The lock for // this surface will be held while the completion callback runs. - void AsyncPresentAndAcknowledge(HWND window, - const gfx::Size& size, - int64 surface_id, - const base::Closure& completion_task); + void AsyncPresentAndAcknowledge( + gfx::NativeWindow window, + const gfx::Size& size, + int64 surface_id, + const base::Callback<void(bool)>& completion_task); // Synchronously present a frame with no acknowledgement. - bool Present(HWND window); + bool Present(gfx::NativeWindow window); // Temporarily release resources until a new surface is asynchronously // presented. Present will not be able to represent the last surface after |