Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/gfx/surface/accelerated_surface_win.h" | 5 #include "ui/gfx/surface/accelerated_surface_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include <list> | 9 #include <list> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/debug/trace_event.h" | 14 #include "base/debug/trace_event.h" |
| 15 #include "base/file_path.h" | |
| 15 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
| 16 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
| 17 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
| 18 #include "base/stringprintf.h" | 19 #include "base/stringprintf.h" |
| 19 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
| 20 #include "base/tracked_objects.h" | 21 #include "base/tracked_objects.h" |
| 21 #include "base/win/wrapped_window_proc.h" | 22 #include "base/win/wrapped_window_proc.h" |
| 22 #include "ipc/ipc_message.h" | 23 #include "ipc/ipc_message.h" |
| 23 #include "ui/base/win/hwnd_util.h" | 24 #include "ui/base/win/hwnd_util.h" |
| 24 #include "ui/gfx/gl/gl_switches.h" | 25 #include "ui/gfx/gl/gl_switches.h" |
| 25 | 26 |
| 26 #pragma comment(lib, "d3d9.lib") | |
| 27 | |
| 28 namespace { | 27 namespace { |
| 29 | 28 |
| 30 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, | 29 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, |
| 31 IDirect3D9Ex **d3d); | 30 IDirect3D9Ex **d3d); |
| 32 | 31 |
| 33 const int64 kPollQueryInterval = 1; | |
| 34 | |
| 35 const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; | 32 const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; |
| 36 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; | 33 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; |
| 37 | 34 |
| 38 class QuerySyncThread | |
| 39 : public base::Thread, | |
| 40 public base::RefCounted<QuerySyncThread> { | |
| 41 public: | |
| 42 explicit QuerySyncThread(const char* name); | |
| 43 virtual ~QuerySyncThread(); | |
| 44 | |
| 45 // Invoke the completion task when the query completes. | |
| 46 void AcknowledgeQuery(const base::win::ScopedComPtr<IDirect3DQuery9>& query, | |
| 47 const base::Closure& completion_task); | |
| 48 | |
| 49 // Acknowledge all pending queries for the given device early then invoke | |
| 50 // the given task. | |
| 51 void AcknowledgeEarly( | |
| 52 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, | |
| 53 const base::Closure& completion_task); | |
| 54 | |
| 55 private: | |
| 56 void PollQueries(); | |
| 57 | |
| 58 struct PendingQuery { | |
| 59 base::win::ScopedComPtr<IDirect3DQuery9> query; | |
| 60 base::Closure completion_task; | |
| 61 }; | |
| 62 | |
| 63 typedef std::list<PendingQuery> PendingQueries; | |
| 64 PendingQueries pending_queries_; | |
| 65 base::WeakPtrFactory<QuerySyncThread> poll_factory_; | |
| 66 | |
| 67 DISALLOW_COPY_AND_ASSIGN(QuerySyncThread); | |
| 68 }; | |
| 69 | |
| 70 class PresentThreadPool { | 35 class PresentThreadPool { |
| 71 public: | 36 public: |
| 72 static const int kNumPresentThreads = 4; | 37 static const int kNumPresentThreads = 4; |
| 73 | 38 |
| 74 PresentThreadPool(); | 39 PresentThreadPool(); |
| 75 | 40 |
| 76 int NextThread(); | 41 int NextThread(); |
| 77 | 42 |
| 78 void PostTask(int thread, | 43 void PostTask(int thread, |
| 79 const tracked_objects::Location& from_here, | 44 const tracked_objects::Location& from_here, |
| 80 const base::Closure& task); | 45 const base::Closure& task); |
| 81 | 46 |
| 82 void AcknowledgeQuery(const tracked_objects::Location& from_here, | |
| 83 const base::win::ScopedComPtr<IDirect3DQuery9>& query, | |
| 84 const base::Closure& completion_task); | |
| 85 | |
| 86 void AcknowledgeEarly( | |
| 87 const tracked_objects::Location& from_here, | |
| 88 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, | |
| 89 const base::Closure& completion_task); | |
| 90 | |
| 91 private: | 47 private: |
| 92 int next_thread_; | 48 int next_thread_; |
| 93 scoped_ptr<base::Thread> present_threads_[kNumPresentThreads]; | 49 scoped_ptr<base::Thread> present_threads_[kNumPresentThreads]; |
| 94 scoped_refptr<QuerySyncThread> query_sync_thread_; | |
| 95 | 50 |
| 96 DISALLOW_COPY_AND_ASSIGN(PresentThreadPool); | 51 DISALLOW_COPY_AND_ASSIGN(PresentThreadPool); |
| 97 }; | 52 }; |
| 98 | 53 |
| 99 base::LazyInstance<PresentThreadPool> | 54 base::LazyInstance<PresentThreadPool> |
| 100 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER; | 55 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER; |
| 101 | 56 |
| 102 QuerySyncThread::QuerySyncThread(const char* name) | |
| 103 : base::Thread(name), | |
| 104 poll_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
| 105 } | |
| 106 | |
| 107 QuerySyncThread::~QuerySyncThread() { | |
| 108 } | |
| 109 | |
| 110 void QuerySyncThread::AcknowledgeQuery( | |
| 111 const base::win::ScopedComPtr<IDirect3DQuery9>& query, | |
| 112 const base::Closure& completion_task) { | |
| 113 PendingQuery pending_query; | |
| 114 pending_query.query = query; | |
| 115 pending_query.completion_task = completion_task; | |
| 116 pending_queries_.push_back(pending_query); | |
| 117 | |
| 118 // Cancel any pending poll tasks. There should only ever be one pending at a | |
| 119 // time. | |
| 120 poll_factory_.InvalidateWeakPtrs(); | |
| 121 | |
| 122 PollQueries(); | |
| 123 } | |
| 124 | |
| 125 void QuerySyncThread::AcknowledgeEarly( | |
| 126 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, | |
| 127 const base::Closure& completion_task) { | |
| 128 TRACE_EVENT0("surface", "AcknowledgeEarly"); | |
| 129 | |
| 130 PendingQueries::iterator it = pending_queries_.begin(); | |
| 131 while (it != pending_queries_.end()) { | |
| 132 const PendingQuery& pending_query = *it; | |
| 133 | |
| 134 base::win::ScopedComPtr<IDirect3DDevice9> query_device; | |
| 135 pending_query.query->GetDevice(query_device.Receive()); | |
| 136 | |
| 137 base::win::ScopedComPtr<IDirect3DDevice9Ex> query_device_ex; | |
| 138 query_device_ex.QueryFrom(query_device.get()); | |
| 139 | |
| 140 if (query_device_ex.get() != device.get()) { | |
| 141 ++it; | |
| 142 } else { | |
| 143 pending_query.completion_task.Run(); | |
| 144 it = pending_queries_.erase(it); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 if (!completion_task.is_null()) | |
| 149 completion_task.Run(); | |
| 150 } | |
| 151 | |
| 152 | |
| 153 void QuerySyncThread::PollQueries() { | |
| 154 TRACE_EVENT0("surface", "PollQueries"); | |
| 155 | |
| 156 PendingQueries::iterator it = pending_queries_.begin(); | |
| 157 while (it != pending_queries_.end()) { | |
| 158 const PendingQuery& pending_query = *it; | |
| 159 | |
| 160 HRESULT hr = pending_query.query->GetData(NULL, 0, D3DGETDATA_FLUSH); | |
| 161 if (hr == S_FALSE) { | |
| 162 ++it; | |
| 163 } else { | |
| 164 pending_query.completion_task.Run(); | |
| 165 it = pending_queries_.erase(it); | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 // Try again later if there are incomplete queries. Otherwise don't poll again | |
| 170 // until AcknowledgeQuery is called with a new query. | |
| 171 if (!pending_queries_.empty()) { | |
| 172 message_loop()->PostDelayedTask( | |
| 173 FROM_HERE, | |
| 174 base::Bind(&QuerySyncThread::PollQueries, poll_factory_.GetWeakPtr()), | |
| 175 kPollQueryInterval); | |
| 176 } | |
| 177 } | |
| 178 | |
| 179 PresentThreadPool::PresentThreadPool() : next_thread_(0) { | 57 PresentThreadPool::PresentThreadPool() : next_thread_(0) { |
| 180 for (int i = 0; i < kNumPresentThreads; ++i) { | 58 for (int i = 0; i < kNumPresentThreads; ++i) { |
| 181 present_threads_[i].reset(new base::Thread( | 59 present_threads_[i].reset(new base::Thread( |
| 182 base::StringPrintf("PresentThread #%d", i).c_str())); | 60 base::StringPrintf("PresentThread #%d", i).c_str())); |
| 183 present_threads_[i]->Start(); | 61 present_threads_[i]->Start(); |
| 184 } | 62 } |
| 185 | |
| 186 query_sync_thread_ = new QuerySyncThread("QuerySyncThread"); | |
| 187 query_sync_thread_->Start(); | |
| 188 } | 63 } |
| 189 | 64 |
| 190 int PresentThreadPool::NextThread() { | 65 int PresentThreadPool::NextThread() { |
| 191 next_thread_ = (next_thread_ + 1) % kNumPresentThreads; | 66 next_thread_ = (next_thread_ + 1) % kNumPresentThreads; |
| 192 return next_thread_; | 67 return next_thread_; |
| 193 } | 68 } |
| 194 | 69 |
| 195 void PresentThreadPool::PostTask(int thread, | 70 void PresentThreadPool::PostTask(int thread, |
| 196 const tracked_objects::Location& from_here, | 71 const tracked_objects::Location& from_here, |
| 197 const base::Closure& task) { | 72 const base::Closure& task) { |
| 198 DCHECK_GE(thread, 0); | 73 DCHECK_GE(thread, 0); |
| 199 DCHECK_LT(thread, kNumPresentThreads); | 74 DCHECK_LT(thread, kNumPresentThreads); |
| 200 | 75 |
| 201 present_threads_[thread]->message_loop()->PostTask(from_here, task); | 76 present_threads_[thread]->message_loop()->PostTask(from_here, task); |
| 202 } | 77 } |
| 203 | 78 |
| 204 void PresentThreadPool::AcknowledgeQuery( | |
| 205 const tracked_objects::Location& from_here, | |
| 206 const base::win::ScopedComPtr<IDirect3DQuery9>& query, | |
| 207 const base::Closure& completion_task) { | |
| 208 query_sync_thread_->message_loop()->PostTask( | |
| 209 from_here, | |
| 210 base::Bind(&QuerySyncThread::AcknowledgeQuery, | |
| 211 query_sync_thread_, | |
| 212 query, | |
| 213 completion_task)); | |
| 214 } | |
| 215 | |
| 216 void PresentThreadPool::AcknowledgeEarly( | |
| 217 const tracked_objects::Location& from_here, | |
| 218 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device, | |
| 219 const base::Closure& completion_task) { | |
| 220 query_sync_thread_->message_loop()->PostTask( | |
| 221 from_here, | |
| 222 base::Bind(&QuerySyncThread::AcknowledgeEarly, | |
| 223 query_sync_thread_, | |
| 224 device, | |
| 225 completion_task)); | |
| 226 } | |
| 227 | |
| 228 UINT GetPresentationInterval() { | 79 UINT GetPresentationInterval() { |
| 229 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) | 80 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) |
| 230 return D3DPRESENT_INTERVAL_IMMEDIATE; | 81 return D3DPRESENT_INTERVAL_IMMEDIATE; |
| 231 else | 82 else |
| 232 return D3DPRESENT_INTERVAL_ONE; | 83 return D3DPRESENT_INTERVAL_ONE; |
| 233 } | 84 } |
| 234 | 85 |
| 235 } // namespace anonymous | 86 } // namespace anonymous |
| 236 | 87 |
| 237 AcceleratedSurface::AcceleratedSurface(HWND parent) | 88 AcceleratedSurface::AcceleratedSurface(HWND parent) |
| 238 : thread_affinity_(g_present_thread_pool.Pointer()->NextThread()), | 89 : thread_affinity_(g_present_thread_pool.Pointer()->NextThread()), |
| 239 window_(parent), | 90 window_(parent), |
| 240 num_pending_resizes_(0) { | 91 num_pending_resizes_(0) { |
| 241 } | 92 } |
| 242 | 93 |
| 243 AcceleratedSurface::~AcceleratedSurface() { | 94 AcceleratedSurface::~AcceleratedSurface() { |
| 244 // Destroy should have been called prior to the last reference going away. | 95 // Destroy should have been called prior to the last reference going away. |
| 245 DCHECK(!device_); | 96 DCHECK(!device_); |
| 246 } | 97 } |
| 247 | 98 |
| 248 void AcceleratedSurface::Initialize() { | 99 void AcceleratedSurface::Initialize() { |
| 249 g_present_thread_pool.Pointer()->PostTask( | 100 g_present_thread_pool.Pointer()->PostTask( |
| 250 thread_affinity_, | 101 thread_affinity_, |
| 251 FROM_HERE, | 102 FROM_HERE, |
| 252 base::Bind(&AcceleratedSurface::DoInitialize, this)); | 103 base::Bind(&AcceleratedSurface::DoInitialize, this)); |
| 253 } | 104 } |
| 254 | 105 |
| 255 void AcceleratedSurface::Destroy() { | 106 void AcceleratedSurface::Destroy() { |
| 256 g_present_thread_pool.Pointer()->AcknowledgeEarly( | 107 g_present_thread_pool.Pointer()->PostTask( |
| 108 thread_affinity_, | |
| 257 FROM_HERE, | 109 FROM_HERE, |
| 258 device_, | 110 base::Bind(&AcceleratedSurface::DoDestroy, this)); |
| 259 base::Bind(&AcceleratedSurface::QueriesDestroyed, this)); | |
| 260 } | 111 } |
| 261 | 112 |
| 262 void AcceleratedSurface::AsyncPresentAndAcknowledge( | 113 void AcceleratedSurface::AsyncPresentAndAcknowledge( |
| 263 const gfx::Size& size, | 114 const gfx::Size& size, |
| 264 int64 surface_id, | 115 int64 surface_id, |
| 265 const base::Closure& completion_task) { | 116 const base::Closure& completion_task) { |
| 266 const int kRound = 64; | 117 const int kRound = 64; |
| 267 gfx::Size quantized_size( | 118 gfx::Size quantized_size( |
| 268 std::max(1, (size.width() + kRound - 1) / kRound * kRound), | 119 std::max(1, (size.width() + kRound - 1) / kRound * kRound), |
| 269 std::max(1, (size.height() + kRound - 1) / kRound * kRound)); | 120 std::max(1, (size.height() + kRound - 1) / kRound * kRound)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 Sleep(0); | 180 Sleep(0); |
| 330 } while (hr == S_FALSE); | 181 } while (hr == S_FALSE); |
| 331 } | 182 } |
| 332 } | 183 } |
| 333 | 184 |
| 334 void AcceleratedSurface::DoInitialize() { | 185 void AcceleratedSurface::DoInitialize() { |
| 335 TRACE_EVENT0("surface", "DoInitialize"); | 186 TRACE_EVENT0("surface", "DoInitialize"); |
| 336 | 187 |
| 337 HRESULT hr; | 188 HRESULT hr; |
| 338 | 189 |
| 339 HMODULE module = GetModuleHandle(kD3D9ModuleName); | 190 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); |
| 340 if (!module) | |
| 341 return; | |
| 342 | 191 |
| 343 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( | 192 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( |
| 344 GetProcAddress(module, kCreate3D9DeviceExName)); | 193 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); |
| 345 if (!create_func) | 194 if (!create_func) |
| 346 return; | 195 return; |
| 347 | 196 |
| 348 base::win::ScopedComPtr<IDirect3D9Ex> d3d; | 197 base::win::ScopedComPtr<IDirect3D9Ex> d3d; |
| 349 hr = create_func(D3D_SDK_VERSION, d3d.Receive()); | 198 hr = create_func(D3D_SDK_VERSION, d3d.Receive()); |
| 350 if (FAILED(hr)) | 199 if (FAILED(hr)) |
| 351 return; | 200 return; |
| 352 | 201 |
| 353 D3DPRESENT_PARAMETERS parameters = { 0 }; | 202 D3DPRESENT_PARAMETERS parameters = { 0 }; |
| 354 parameters.BackBufferWidth = 1; | 203 parameters.BackBufferWidth = 1; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 query_ = NULL; | 248 query_ = NULL; |
| 400 } | 249 } |
| 401 | 250 |
| 402 void AcceleratedSurface::DoResize(const gfx::Size& size) { | 251 void AcceleratedSurface::DoResize(const gfx::Size& size) { |
| 403 TRACE_EVENT0("surface", "DoResize"); | 252 TRACE_EVENT0("surface", "DoResize"); |
| 404 | 253 |
| 405 HRESULT hr; | 254 HRESULT hr; |
| 406 | 255 |
| 407 base::AtomicRefCountDec(&num_pending_resizes_); | 256 base::AtomicRefCountDec(&num_pending_resizes_); |
| 408 | 257 |
| 258 base::AutoLock locked(lock_); | |
| 259 | |
| 260 if (!device_) | |
| 261 return; | |
| 262 | |
| 409 D3DPRESENT_PARAMETERS parameters = { 0 }; | 263 D3DPRESENT_PARAMETERS parameters = { 0 }; |
| 410 parameters.BackBufferWidth = size.width(); | 264 parameters.BackBufferWidth = size.width(); |
| 411 parameters.BackBufferHeight = size.height(); | 265 parameters.BackBufferHeight = size.height(); |
| 412 parameters.BackBufferCount = 1; | 266 parameters.BackBufferCount = 1; |
| 413 parameters.BackBufferFormat = D3DFMT_A8R8G8B8; | 267 parameters.BackBufferFormat = D3DFMT_A8R8G8B8; |
| 414 parameters.hDeviceWindow = window_; | 268 parameters.hDeviceWindow = window_; |
| 415 parameters.Windowed = TRUE; | 269 parameters.Windowed = TRUE; |
| 416 parameters.Flags = 0; | 270 parameters.Flags = 0; |
| 417 parameters.PresentationInterval = GetPresentationInterval(); | 271 parameters.PresentationInterval = GetPresentationInterval(); |
| 418 parameters.SwapEffect = D3DSWAPEFFECT_COPY; | 272 parameters.SwapEffect = D3DSWAPEFFECT_COPY; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 432 const base::Closure& completion_task) { | 286 const base::Closure& completion_task) { |
| 433 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id); | 287 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id); |
| 434 | 288 |
| 435 HRESULT hr; | 289 HRESULT hr; |
| 436 | 290 |
| 437 base::AutoLock locked(lock_); | 291 base::AutoLock locked(lock_); |
| 438 | 292 |
| 439 // Ensure the task is always run and while the lock is taken. | 293 // Ensure the task is always run and while the lock is taken. |
| 440 base::ScopedClosureRunner scoped_completion_runner(completion_task); | 294 base::ScopedClosureRunner scoped_completion_runner(completion_task); |
| 441 | 295 |
| 296 if (!device_) | |
| 297 return; | |
| 298 | |
| 442 if (!window_) | 299 if (!window_) |
| 443 return; | 300 return; |
| 444 | 301 |
| 445 HANDLE handle = reinterpret_cast<HANDLE>(surface_id); | 302 HANDLE handle = reinterpret_cast<HANDLE>(surface_id); |
| 446 if (!handle) | 303 if (!handle) |
| 447 return; | 304 return; |
| 448 | 305 |
| 449 base::win::ScopedComPtr<IDirect3DTexture9> source_texture; | 306 base::win::ScopedComPtr<IDirect3DTexture9> source_texture; |
| 450 { | 307 { |
| 451 TRACE_EVENT0("surface", "CreateTexture"); | 308 TRACE_EVENT0("surface", "CreateTexture"); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 | 354 |
| 498 ::SetWindowPos( | 355 ::SetWindowPos( |
| 499 window_, | 356 window_, |
| 500 NULL, | 357 NULL, |
| 501 0, 0, | 358 0, 0, |
| 502 size.width(), size.height(), | 359 size.width(), size.height(), |
| 503 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER | | 360 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER | |
| 504 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING | | 361 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING | |
| 505 SWP_ASYNCWINDOWPOS); | 362 SWP_ASYNCWINDOWPOS); |
| 506 | 363 |
| 364 // Wait for the StretchRect to complete before notifying the GPU process | |
| 365 // that it is safe to write to its backing store again. | |
| 366 { | |
| 367 TRACE_EVENT0("surface", "spin"); | |
| 368 do { | |
| 369 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); | |
| 370 | |
| 371 if (hr == S_FALSE) | |
| 372 Sleep(0); | |
| 373 } 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
| |
| 374 } | |
| 375 | |
| 507 scoped_completion_runner.Release(); | 376 scoped_completion_runner.Release(); |
| 508 if (!completion_task.is_null()) { | 377 if (!completion_task.is_null()) |
| 509 g_present_thread_pool.Pointer()->AcknowledgeQuery(FROM_HERE, | 378 completion_task.Run(); |
| 510 query_, | |
| 511 completion_task); | |
| 512 } | |
| 513 | 379 |
| 514 { | 380 { |
| 515 TRACE_EVENT0("surface", "Present"); | 381 TRACE_EVENT0("surface", "Present"); |
| 516 hr = device_->Present(&rect, &rect, NULL, NULL); | 382 hr = device_->Present(&rect, &rect, NULL, NULL); |
| 517 if (FAILED(hr)) | 383 if (FAILED(hr)) |
| 518 return; | 384 return; |
| 519 } | 385 } |
| 520 } | 386 } |
| OLD | NEW |