Index: ui/gfx/surface/accelerated_surface_win.cc |
=================================================================== |
--- ui/gfx/surface/accelerated_surface_win.cc (revision 113398) |
+++ ui/gfx/surface/accelerated_surface_win.cc (working copy) |
@@ -12,6 +12,7 @@ |
#include "base/callback.h" |
#include "base/command_line.h" |
#include "base/debug/trace_event.h" |
+#include "base/file_path.h" |
#include "base/lazy_instance.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/weak_ptr.h" |
@@ -23,50 +24,14 @@ |
#include "ui/base/win/hwnd_util.h" |
#include "ui/gfx/gl/gl_switches.h" |
-#pragma comment(lib, "d3d9.lib") |
- |
namespace { |
typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, |
IDirect3D9Ex **d3d); |
-const int64 kPollQueryInterval = 1; |
- |
const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; |
const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; |
-class QuerySyncThread |
- : public base::Thread, |
- public base::RefCounted<QuerySyncThread> { |
- public: |
- explicit QuerySyncThread(const char* name); |
- virtual ~QuerySyncThread(); |
- |
- // Invoke the completion task when the query completes. |
- void AcknowledgeQuery(const base::win::ScopedComPtr<IDirect3DQuery9>& query, |
- const base::Closure& completion_task); |
- |
- // Acknowledge all pending queries for the given device early then invoke |
- // the given task. |
- void AcknowledgeEarly( |
- const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, |
- const base::Closure& completion_task); |
- |
- private: |
- void PollQueries(); |
- |
- struct PendingQuery { |
- base::win::ScopedComPtr<IDirect3DQuery9> query; |
- base::Closure completion_task; |
- }; |
- |
- typedef std::list<PendingQuery> PendingQueries; |
- PendingQueries pending_queries_; |
- base::WeakPtrFactory<QuerySyncThread> poll_factory_; |
- |
- DISALLOW_COPY_AND_ASSIGN(QuerySyncThread); |
-}; |
- |
class PresentThreadPool { |
public: |
static const int kNumPresentThreads = 4; |
@@ -79,19 +44,9 @@ |
const tracked_objects::Location& from_here, |
const base::Closure& task); |
- void AcknowledgeQuery(const tracked_objects::Location& from_here, |
- const base::win::ScopedComPtr<IDirect3DQuery9>& query, |
- const base::Closure& completion_task); |
- |
- void AcknowledgeEarly( |
- const tracked_objects::Location& from_here, |
- const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, |
- const base::Closure& completion_task); |
- |
private: |
int next_thread_; |
scoped_ptr<base::Thread> present_threads_[kNumPresentThreads]; |
- scoped_refptr<QuerySyncThread> query_sync_thread_; |
DISALLOW_COPY_AND_ASSIGN(PresentThreadPool); |
}; |
@@ -99,92 +54,12 @@ |
base::LazyInstance<PresentThreadPool> |
g_present_thread_pool = LAZY_INSTANCE_INITIALIZER; |
-QuerySyncThread::QuerySyncThread(const char* name) |
- : base::Thread(name), |
- poll_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
-} |
- |
-QuerySyncThread::~QuerySyncThread() { |
-} |
- |
-void QuerySyncThread::AcknowledgeQuery( |
- const base::win::ScopedComPtr<IDirect3DQuery9>& query, |
- const base::Closure& completion_task) { |
- PendingQuery pending_query; |
- pending_query.query = query; |
- pending_query.completion_task = completion_task; |
- pending_queries_.push_back(pending_query); |
- |
- // Cancel any pending poll tasks. There should only ever be one pending at a |
- // time. |
- poll_factory_.InvalidateWeakPtrs(); |
- |
- PollQueries(); |
-} |
- |
-void QuerySyncThread::AcknowledgeEarly( |
- const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, |
- const base::Closure& completion_task) { |
- TRACE_EVENT0("surface", "AcknowledgeEarly"); |
- |
- PendingQueries::iterator it = pending_queries_.begin(); |
- while (it != pending_queries_.end()) { |
- const PendingQuery& pending_query = *it; |
- |
- base::win::ScopedComPtr<IDirect3DDevice9> query_device; |
- pending_query.query->GetDevice(query_device.Receive()); |
- |
- base::win::ScopedComPtr<IDirect3DDevice9Ex> query_device_ex; |
- query_device_ex.QueryFrom(query_device.get()); |
- |
- if (query_device_ex.get() != device.get()) { |
- ++it; |
- } else { |
- pending_query.completion_task.Run(); |
- it = pending_queries_.erase(it); |
- } |
- } |
- |
- if (!completion_task.is_null()) |
- completion_task.Run(); |
-} |
- |
- |
-void QuerySyncThread::PollQueries() { |
- TRACE_EVENT0("surface", "PollQueries"); |
- |
- PendingQueries::iterator it = pending_queries_.begin(); |
- while (it != pending_queries_.end()) { |
- const PendingQuery& pending_query = *it; |
- |
- HRESULT hr = pending_query.query->GetData(NULL, 0, D3DGETDATA_FLUSH); |
- if (hr == S_FALSE) { |
- ++it; |
- } else { |
- pending_query.completion_task.Run(); |
- it = pending_queries_.erase(it); |
- } |
- } |
- |
- // Try again later if there are incomplete queries. Otherwise don't poll again |
- // until AcknowledgeQuery is called with a new query. |
- if (!pending_queries_.empty()) { |
- message_loop()->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&QuerySyncThread::PollQueries, poll_factory_.GetWeakPtr()), |
- kPollQueryInterval); |
- } |
-} |
- |
PresentThreadPool::PresentThreadPool() : next_thread_(0) { |
for (int i = 0; i < kNumPresentThreads; ++i) { |
present_threads_[i].reset(new base::Thread( |
base::StringPrintf("PresentThread #%d", i).c_str())); |
present_threads_[i]->Start(); |
} |
- |
- query_sync_thread_ = new QuerySyncThread("QuerySyncThread"); |
- query_sync_thread_->Start(); |
} |
int PresentThreadPool::NextThread() { |
@@ -201,30 +76,6 @@ |
present_threads_[thread]->message_loop()->PostTask(from_here, task); |
} |
-void PresentThreadPool::AcknowledgeQuery( |
- const tracked_objects::Location& from_here, |
- const base::win::ScopedComPtr<IDirect3DQuery9>& query, |
- const base::Closure& completion_task) { |
- query_sync_thread_->message_loop()->PostTask( |
- from_here, |
- base::Bind(&QuerySyncThread::AcknowledgeQuery, |
- query_sync_thread_, |
- query, |
- completion_task)); |
-} |
- |
-void PresentThreadPool::AcknowledgeEarly( |
- const tracked_objects::Location& from_here, |
- const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, |
- const base::Closure& completion_task) { |
- query_sync_thread_->message_loop()->PostTask( |
- from_here, |
- base::Bind(&QuerySyncThread::AcknowledgeEarly, |
- query_sync_thread_, |
- device, |
- completion_task)); |
-} |
- |
UINT GetPresentationInterval() { |
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) |
return D3DPRESENT_INTERVAL_IMMEDIATE; |
@@ -253,10 +104,10 @@ |
} |
void AcceleratedSurface::Destroy() { |
- g_present_thread_pool.Pointer()->AcknowledgeEarly( |
+ g_present_thread_pool.Pointer()->PostTask( |
+ thread_affinity_, |
FROM_HERE, |
- device_, |
- base::Bind(&AcceleratedSurface::QueriesDestroyed, this)); |
+ base::Bind(&AcceleratedSurface::DoDestroy, this)); |
} |
void AcceleratedSurface::AsyncPresentAndAcknowledge( |
@@ -336,12 +187,10 @@ |
HRESULT hr; |
- HMODULE module = GetModuleHandle(kD3D9ModuleName); |
- if (!module) |
- return; |
+ d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); |
Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( |
- GetProcAddress(module, kCreate3D9DeviceExName)); |
+ d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); |
if (!create_func) |
return; |
@@ -406,6 +255,11 @@ |
base::AtomicRefCountDec(&num_pending_resizes_); |
+ base::AutoLock locked(lock_); |
+ |
+ if (!device_) |
+ return; |
+ |
D3DPRESENT_PARAMETERS parameters = { 0 }; |
parameters.BackBufferWidth = size.width(); |
parameters.BackBufferHeight = size.height(); |
@@ -439,6 +293,9 @@ |
// Ensure the task is always run and while the lock is taken. |
base::ScopedClosureRunner scoped_completion_runner(completion_task); |
+ if (!device_) |
+ return; |
+ |
if (!window_) |
return; |
@@ -504,13 +361,22 @@ |
SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING | |
SWP_ASYNCWINDOWPOS); |
- scoped_completion_runner.Release(); |
- if (!completion_task.is_null()) { |
- g_present_thread_pool.Pointer()->AcknowledgeQuery(FROM_HERE, |
- query_, |
- completion_task); |
+ // Wait for the StretchRect to complete before notifying the GPU process |
+ // that it is safe to write to its backing store again. |
+ { |
+ TRACE_EVENT0("surface", "spin"); |
+ do { |
+ hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); |
+ |
+ if (hr == S_FALSE) |
+ Sleep(0); |
+ } while (hr == S_FALSE); |
Ken Russell (switch to Gerrit)
2011/12/08 01:55:07
As an FYI a problem in a similarly structured loop
|
} |
+ scoped_completion_runner.Release(); |
+ if (!completion_task.is_null()) |
+ completion_task.Run(); |
+ |
{ |
TRACE_EVENT0("surface", "Present"); |
hr = device_->Present(&rect, &rect, NULL, NULL); |