Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: ui/gfx/surface/accelerated_surface_win.cc

Issue 10351002: ui: Move surface/ directory out of gfx/, up to ui/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix gpu DEPS Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/surface/accelerated_surface_win.h ('k') | ui/gfx/surface/io_surface_support_mac.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/gfx/surface/accelerated_surface_win.h"
6
7 #include <windows.h>
8 #include <algorithm>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/command_line.h"
14 #include "base/string_number_conversions.h"
15 #include "base/time.h"
16 #include "base/debug/trace_event.h"
17 #include "base/file_path.h"
18 #include "base/lazy_instance.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/scoped_native_library.h"
21 #include "base/stringprintf.h"
22 #include "base/synchronization/waitable_event.h"
23 #include "base/threading/thread.h"
24 #include "base/threading/thread_restrictions.h"
25 #include "base/tracked_objects.h"
26 #include "base/win/wrapped_window_proc.h"
27 #include "ui/base/win/hwnd_util.h"
28 #include "ui/gfx/gl/gl_switches.h"
29
30 namespace {
31
32 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version,
33 IDirect3D9Ex **d3d);
34
35 const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
36 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
37
38 UINT GetPresentationInterval() {
39 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
40 return D3DPRESENT_INTERVAL_IMMEDIATE;
41 else
42 return D3DPRESENT_INTERVAL_ONE;
43 }
44
45 // Calculate the number necessary to transform |source_size| into |dest_size|
46 // by repeating downsampling of the image of |source_size| by a factor no more
47 // than 2.
48 int GetResampleCount(const gfx::Size& source_size, const gfx::Size& dest_size) {
49 int width_count = 0;
50 int width = source_size.width();
51 while (width > dest_size.width()) {
52 ++width_count;
53 width >>= 1;
54 }
55 int height_count = 0;
56 int height = source_size.height();
57 while (height > dest_size.height()) {
58 ++height_count;
59 height >>= 1;
60 }
61 return std::max(width_count, height_count);
62 }
63
64 // Returns half the size of |size| no smaller than |min_size|.
65 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
66 const gfx::Size& min_size) {
67 return gfx::Size(std::max(min_size.width(), size.width() / 2),
68 std::max(min_size.height(), size.height() / 2));
69 }
70
71 bool CreateTemporarySurface(IDirect3DDevice9* device,
72 const gfx::Size& size,
73 IDirect3DSurface9** surface) {
74 HRESULT hr = device->CreateRenderTarget(
75 size.width(),
76 size.height(),
77 D3DFMT_A8R8G8B8,
78 D3DMULTISAMPLE_NONE,
79 0,
80 TRUE,
81 surface,
82 NULL);
83 return SUCCEEDED(hr);
84 }
85
86 } // namespace anonymous
87
88 // A PresentThread is a thread that is dedicated to presenting surfaces to a
89 // window. It owns a Direct3D device and a Direct3D query for this purpose.
90 class PresentThread : public base::Thread,
91 public base::RefCountedThreadSafe<PresentThread> {
92 public:
93 explicit PresentThread(const char* name);
94
95 IDirect3DDevice9Ex* device() { return device_.get(); }
96 IDirect3DQuery9* query() { return query_.get(); }
97
98 void InitDevice();
99 void ResetDevice();
100
101 protected:
102 virtual void CleanUp();
103
104 private:
105 friend class base::RefCountedThreadSafe<PresentThread>;
106
107 ~PresentThread();
108
109 base::ScopedNativeLibrary d3d_module_;
110 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_;
111
112 // This query is used to wait until a certain amount of progress has been
113 // made by the GPU and it is safe for the producer to modify its shared
114 // texture again.
115 base::win::ScopedComPtr<IDirect3DQuery9> query_;
116
117 DISALLOW_COPY_AND_ASSIGN(PresentThread);
118 };
119
120 // There is a fixed sized pool of PresentThreads and therefore the maximum
121 // number of Direct3D devices owned by those threads is bounded.
122 class PresentThreadPool {
123 public:
124 static const int kNumPresentThreads = 4;
125
126 PresentThreadPool();
127 PresentThread* NextThread();
128
129 private:
130 int next_thread_;
131 scoped_refptr<PresentThread> present_threads_[kNumPresentThreads];
132
133 DISALLOW_COPY_AND_ASSIGN(PresentThreadPool);
134 };
135
136 // A thread safe map of presenters by surface ID that returns presenters via
137 // a scoped_refptr to keep them alive while they are referenced.
138 class AcceleratedPresenterMap {
139 public:
140 AcceleratedPresenterMap();
141 scoped_refptr<AcceleratedPresenter> CreatePresenter(gfx::NativeWindow window);
142 void RemovePresenter(const scoped_refptr<AcceleratedPresenter>& presenter);
143 scoped_refptr<AcceleratedPresenter> GetPresenter(gfx::NativeWindow window);
144 private:
145 base::Lock lock_;
146 typedef std::map<gfx::NativeWindow, AcceleratedPresenter*> PresenterMap;
147 PresenterMap presenters_;
148 DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenterMap);
149 };
150
151 base::LazyInstance<PresentThreadPool>
152 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER;
153
154 base::LazyInstance<AcceleratedPresenterMap>
155 g_accelerated_presenter_map = LAZY_INSTANCE_INITIALIZER;
156
157 PresentThread::PresentThread(const char* name) : base::Thread(name) {
158 }
159
160 void PresentThread::InitDevice() {
161 if (device_)
162 return;
163
164 TRACE_EVENT0("surface", "PresentThread::Init");
165 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
166 ResetDevice();
167 }
168
169 void PresentThread::ResetDevice() {
170 TRACE_EVENT0("surface", "PresentThread::ResetDevice");
171
172 // This will crash some Intel drivers but we can't render anything without
173 // reseting the device, which would be disappointing.
174 query_ = NULL;
175 device_ = NULL;
176
177 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>(
178 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName));
179 if (!create_func)
180 return;
181
182 base::win::ScopedComPtr<IDirect3D9Ex> d3d;
183 HRESULT hr = create_func(D3D_SDK_VERSION, d3d.Receive());
184 if (FAILED(hr))
185 return;
186
187 // Any old window will do to create the device. In practice the window to
188 // present to is an argument to IDirect3DDevice9::Present.
189 HWND window = GetShellWindow();
190
191 D3DPRESENT_PARAMETERS parameters = { 0 };
192 parameters.BackBufferWidth = 1;
193 parameters.BackBufferHeight = 1;
194 parameters.BackBufferCount = 1;
195 parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
196 parameters.hDeviceWindow = window;
197 parameters.Windowed = TRUE;
198 parameters.Flags = 0;
199 parameters.PresentationInterval = GetPresentationInterval();
200 parameters.SwapEffect = D3DSWAPEFFECT_COPY;
201
202 hr = d3d->CreateDeviceEx(
203 D3DADAPTER_DEFAULT,
204 D3DDEVTYPE_HAL,
205 window,
206 D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING |
207 D3DCREATE_DISABLE_PSGP_THREADING | D3DCREATE_MULTITHREADED,
208 &parameters,
209 NULL,
210 device_.Receive());
211 if (FAILED(hr))
212 return;
213
214 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
215 if (FAILED(hr))
216 device_ = NULL;
217 }
218
219 void PresentThread::CleanUp() {
220 // The D3D device and query are leaked because destroying the associated D3D
221 // query crashes some Intel drivers.
222 device_.Detach();
223 query_.Detach();
224 }
225
226 PresentThread::~PresentThread() {
227 Stop();
228 }
229
230 PresentThreadPool::PresentThreadPool() : next_thread_(0) {
231 // Do this in the constructor so present_threads_ is initialized before any
232 // other thread sees it. See LazyInstance documentation.
233 for (int i = 0; i < kNumPresentThreads; ++i) {
234 present_threads_[i] = new PresentThread(
235 base::StringPrintf("PresentThread #%d", i).c_str());
236 present_threads_[i]->Start();
237 }
238 }
239
240 PresentThread* PresentThreadPool::NextThread() {
241 next_thread_ = (next_thread_ + 1) % kNumPresentThreads;
242 return present_threads_[next_thread_].get();
243 }
244
245 AcceleratedPresenterMap::AcceleratedPresenterMap() {
246 }
247
248 scoped_refptr<AcceleratedPresenter> AcceleratedPresenterMap::CreatePresenter(
249 gfx::NativeWindow window) {
250 scoped_refptr<AcceleratedPresenter> presenter(
251 new AcceleratedPresenter(window));
252
253 base::AutoLock locked(lock_);
254 DCHECK(presenters_.find(window) == presenters_.end());
255 presenters_[window] = presenter.get();
256
257 return presenter;
258 }
259
260 void AcceleratedPresenterMap::RemovePresenter(
261 const scoped_refptr<AcceleratedPresenter>& presenter) {
262 base::AutoLock locked(lock_);
263 for (PresenterMap::iterator it = presenters_.begin();
264 it != presenters_.end();
265 ++it) {
266 if (it->second == presenter.get()) {
267 presenters_.erase(it);
268 return;
269 }
270 }
271
272 NOTREACHED();
273 }
274
275 scoped_refptr<AcceleratedPresenter> AcceleratedPresenterMap::GetPresenter(
276 gfx::NativeWindow window) {
277 base::AutoLock locked(lock_);
278 PresenterMap::iterator it = presenters_.find(window);
279 if (it == presenters_.end())
280 return scoped_refptr<AcceleratedPresenter>();
281
282 return it->second;
283 }
284
285 AcceleratedPresenter::AcceleratedPresenter(gfx::NativeWindow window)
286 : present_thread_(g_present_thread_pool.Pointer()->NextThread()),
287 window_(window),
288 event_(false, false) {
289 }
290
291 scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow(
292 gfx::NativeWindow window) {
293 return g_accelerated_presenter_map.Pointer()->GetPresenter(window);
294 }
295
296 void AcceleratedPresenter::AsyncPresentAndAcknowledge(
297 const gfx::Size& size,
298 int64 surface_handle,
299 const base::Callback<void(bool)>& completion_task) {
300 if (!surface_handle) {
301 completion_task.Run(true);
302 return;
303 }
304
305 present_thread_->message_loop()->PostTask(
306 FROM_HERE,
307 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge,
308 this,
309 size,
310 surface_handle,
311 completion_task));
312 }
313
314 bool AcceleratedPresenter::Present() {
315 TRACE_EVENT0("surface", "Present");
316
317 bool result;
318
319 present_thread_->message_loop()->PostTask(
320 FROM_HERE,
321 base::Bind(&AcceleratedPresenter::DoPresent,
322 this,
323 &result));
324 // http://crbug.com/125391
325 base::ThreadRestrictions::ScopedAllowWait allow_wait;
326 event_.Wait();
327 return result;
328 }
329
330 void AcceleratedPresenter::DoPresent(bool* result)
331 {
332 *result = DoRealPresent();
333 event_.Signal();
334 }
335
336 bool AcceleratedPresenter::DoRealPresent()
337 {
338 TRACE_EVENT0("surface", "DoRealPresent");
339 HRESULT hr;
340
341 base::AutoLock locked(lock_);
342
343 // Signal the caller to recomposite if the presenter has been suspended or no
344 // surface has ever been presented.
345 if (!swap_chain_)
346 return false;
347
348 // If invalidated, do nothing. The window is gone.
349 if (!window_)
350 return true;
351
352 RECT rect = {
353 0, 0,
354 size_.width(), size_.height()
355 };
356
357 {
358 TRACE_EVENT0("surface", "PresentEx");
359 hr = swap_chain_->Present(&rect,
360 &rect,
361 window_,
362 NULL,
363 D3DPRESENT_INTERVAL_IMMEDIATE);
364 if (FAILED(hr))
365 return false;
366 }
367
368 return true;
369 }
370
371 bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) {
372 base::AutoLock locked(lock_);
373
374 if (!swap_chain_)
375 return false;
376
377 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer;
378 HRESULT hr = swap_chain_->GetBackBuffer(0,
379 D3DBACKBUFFER_TYPE_MONO,
380 back_buffer.Receive());
381 if (FAILED(hr))
382 return false;
383
384 D3DSURFACE_DESC desc;
385 hr = back_buffer->GetDesc(&desc);
386 if (FAILED(hr))
387 return false;
388
389 const gfx::Size back_buffer_size(desc.Width, desc.Height);
390 if (back_buffer_size.IsEmpty())
391 return false;
392
393 // Set up intermediate buffers needed for downsampling.
394 const int resample_count =
395 GetResampleCount(gfx::Size(desc.Width, desc.Height), size);
396 base::win::ScopedComPtr<IDirect3DSurface9> final_surface;
397 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
398 if (resample_count == 0)
399 final_surface = back_buffer;
400 if (resample_count > 0) {
401 if (!CreateTemporarySurface(present_thread_->device(),
402 size,
403 final_surface.Receive()))
404 return false;
405 }
406 const gfx::Size half_size = GetHalfSizeNoLessThan(back_buffer_size, size);
407 if (resample_count > 1) {
408 if (!CreateTemporarySurface(present_thread_->device(),
409 half_size,
410 temp_buffer[0].Receive()))
411 return false;
412 }
413 if (resample_count > 2) {
414 const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, size);
415 if (!CreateTemporarySurface(present_thread_->device(),
416 quarter_size,
417 temp_buffer[1].Receive()))
418 return false;
419 }
420
421 // Repeat downsampling the surface until its size becomes identical to
422 // |size|. We keep the factor of each downsampling no more than two because
423 // using a factor more than two can introduce aliasing.
424 gfx::Size read_size = back_buffer_size;
425 gfx::Size write_size = half_size;
426 int read_buffer_index = 1;
427 int write_buffer_index = 0;
428 for (int i = 0; i < resample_count; ++i) {
429 base::win::ScopedComPtr<IDirect3DSurface9> read_buffer =
430 (i == 0) ? back_buffer : temp_buffer[read_buffer_index];
431 base::win::ScopedComPtr<IDirect3DSurface9> write_buffer =
432 (i == resample_count - 1) ? final_surface :
433 temp_buffer[write_buffer_index];
434 RECT read_rect = {0, 0, read_size.width(), read_size.height()};
435 RECT write_rect = {0, 0, write_size.width(), write_size.height()};
436 hr = present_thread_->device()->StretchRect(read_buffer,
437 &read_rect,
438 write_buffer,
439 &write_rect,
440 D3DTEXF_LINEAR);
441 if (FAILED(hr))
442 return false;
443 read_size = write_size;
444 write_size = GetHalfSizeNoLessThan(write_size, size);
445 std::swap(read_buffer_index, write_buffer_index);
446 }
447
448 DCHECK(size == read_size);
449
450 base::win::ScopedComPtr<IDirect3DSurface9> temp_surface;
451 HANDLE handle = reinterpret_cast<HANDLE>(buf);
452 hr = present_thread_->device()->CreateOffscreenPlainSurface(
453 size.width(),
454 size.height(),
455 D3DFMT_A8R8G8B8,
456 D3DPOOL_SYSTEMMEM,
457 temp_surface.Receive(),
458 &handle);
459 if (FAILED(hr))
460 return false;
461
462 // Copy the data in the temporary buffer to the surface backed by |buf|.
463 hr = present_thread_->device()->GetRenderTargetData(final_surface,
464 temp_surface);
465 if (FAILED(hr))
466 return false;
467
468 return true;
469 }
470
471 void AcceleratedPresenter::Suspend() {
472 present_thread_->message_loop()->PostTask(
473 FROM_HERE,
474 base::Bind(&AcceleratedPresenter::DoSuspend,
475 this));
476 }
477
478 void AcceleratedPresenter::ReleaseSurface() {
479 present_thread_->message_loop()->PostTask(
480 FROM_HERE,
481 base::Bind(&AcceleratedPresenter::DoReleaseSurface,
482 this));
483 }
484
485 void AcceleratedPresenter::Invalidate() {
486 // Make any pending or future presentation tasks do nothing. Once the last
487 // last pending task has been ignored, the reference count on the presenter
488 // will go to zero and the presenter, and potentially also the present thread
489 // it has a reference count on, will be destroyed.
490 base::AutoLock locked(lock_);
491 window_ = NULL;
492 }
493
494 AcceleratedPresenter::~AcceleratedPresenter() {
495 }
496
497 static base::TimeDelta GetSwapDelay() {
498 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
499 int delay = 0;
500 if (cmd_line->HasSwitch(switches::kGpuSwapDelay)) {
501 base::StringToInt(cmd_line->GetSwitchValueNative(
502 switches::kGpuSwapDelay).c_str(), &delay);
503 }
504 return base::TimeDelta::FromMilliseconds(delay);
505 }
506
507 void AcceleratedPresenter::DoPresentAndAcknowledge(
508 const gfx::Size& size,
509 int64 surface_handle,
510 const base::Callback<void(bool)>& completion_task) {
511 TRACE_EVENT1(
512 "surface", "DoPresentAndAcknowledge", "surface_handle", surface_handle);
513
514 HRESULT hr;
515
516 base::AutoLock locked(lock_);
517
518 // Initialize the device lazily since calling Direct3D can crash bots.
519 present_thread_->InitDevice();
520
521 if (!present_thread_->device()) {
522 if (!completion_task.is_null())
523 completion_task.Run(false);
524 return;
525 }
526
527 // Ensure the task is always run and while the lock is taken.
528 base::ScopedClosureRunner scoped_completion_runner(base::Bind(completion_task,
529 true));
530
531 // If invalidated, do nothing, the window is gone.
532 if (!window_)
533 return;
534
535 // Round up size so the swap chain is not continuously resized with the
536 // surface, which could lead to memory fragmentation.
537 const int kRound = 64;
538 gfx::Size quantized_size(
539 std::max(1, (size.width() + kRound - 1) / kRound * kRound),
540 std::max(1, (size.height() + kRound - 1) / kRound * kRound));
541
542 // Ensure the swap chain exists and is the same size (rounded up) as the
543 // surface to be presented.
544 if (!swap_chain_ || size_ != quantized_size) {
545 TRACE_EVENT0("surface", "CreateAdditionalSwapChain");
546 size_ = quantized_size;
547
548 D3DPRESENT_PARAMETERS parameters = { 0 };
549 parameters.BackBufferWidth = quantized_size.width();
550 parameters.BackBufferHeight = quantized_size.height();
551 parameters.BackBufferCount = 1;
552 parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
553 parameters.hDeviceWindow = GetShellWindow();
554 parameters.Windowed = TRUE;
555 parameters.Flags = 0;
556 parameters.PresentationInterval = GetPresentationInterval();
557 parameters.SwapEffect = D3DSWAPEFFECT_COPY;
558
559 swap_chain_ = NULL;
560 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain(
561 &parameters,
562 swap_chain_.Receive());
563 if (FAILED(hr))
564 return;
565 }
566
567 if (!source_texture_.get()) {
568 TRACE_EVENT0("surface", "CreateTexture");
569 HANDLE handle = reinterpret_cast<HANDLE>(surface_handle);
570 hr = present_thread_->device()->CreateTexture(size.width(),
571 size.height(),
572 1,
573 D3DUSAGE_RENDERTARGET,
574 D3DFMT_A8R8G8B8,
575 D3DPOOL_DEFAULT,
576 source_texture_.Receive(),
577 &handle);
578 if (FAILED(hr))
579 return;
580 }
581
582 base::win::ScopedComPtr<IDirect3DSurface9> source_surface;
583 hr = source_texture_->GetSurfaceLevel(0, source_surface.Receive());
584 if (FAILED(hr))
585 return;
586
587 base::win::ScopedComPtr<IDirect3DSurface9> dest_surface;
588 hr = swap_chain_->GetBackBuffer(0,
589 D3DBACKBUFFER_TYPE_MONO,
590 dest_surface.Receive());
591 if (FAILED(hr))
592 return;
593
594 RECT rect = {
595 0, 0,
596 size.width(), size.height()
597 };
598
599 {
600 TRACE_EVENT0("surface", "StretchRect");
601 hr = present_thread_->device()->StretchRect(source_surface,
602 &rect,
603 dest_surface,
604 &rect,
605 D3DTEXF_NONE);
606 if (FAILED(hr))
607 return;
608 }
609
610 hr = present_thread_->query()->Issue(D3DISSUE_END);
611 if (FAILED(hr))
612 return;
613
614 // Flush so the StretchRect can be processed by the GPU while the window is
615 // being resized.
616 present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH);
617
618 ::SetWindowPos(
619 window_,
620 NULL,
621 0, 0,
622 size.width(), size.height(),
623 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER |
624 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING |
625 SWP_ASYNCWINDOWPOS | SWP_NOZORDER);
626
627 // Wait for the StretchRect to complete before notifying the GPU process
628 // that it is safe to write to its backing store again.
629 {
630 TRACE_EVENT0("surface", "spin");
631 do {
632 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH);
633
634 if (hr == S_FALSE)
635 Sleep(1);
636 } while (hr == S_FALSE);
637 }
638
639 static const base::TimeDelta swap_delay = GetSwapDelay();
640 if (swap_delay.ToInternalValue())
641 base::PlatformThread::Sleep(swap_delay);
642
643 {
644 TRACE_EVENT0("surface", "Present");
645 hr = swap_chain_->Present(&rect, &rect, window_, NULL, 0);
646 if (FAILED(hr) &&
647 FAILED(present_thread_->device()->CheckDeviceState(window_))) {
648 present_thread_->ResetDevice();
649 }
650 }
651 }
652
653 void AcceleratedPresenter::DoSuspend() {
654 base::AutoLock locked(lock_);
655 swap_chain_ = NULL;
656 }
657
658 void AcceleratedPresenter::DoReleaseSurface() {
659 base::AutoLock locked(lock_);
660 source_texture_.Release();
661 }
662
663 AcceleratedSurface::AcceleratedSurface(gfx::NativeWindow window)
664 : presenter_(g_accelerated_presenter_map.Pointer()->CreatePresenter(
665 window)) {
666 }
667
668 AcceleratedSurface::~AcceleratedSurface() {
669 g_accelerated_presenter_map.Pointer()->RemovePresenter(presenter_);
670 presenter_->Invalidate();
671 }
672
673 bool AcceleratedSurface::Present() {
674 return presenter_->Present();
675 }
676
677 bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) {
678 return presenter_->CopyTo(size, buf);
679 }
680
681 void AcceleratedSurface::Suspend() {
682 presenter_->Suspend();
683 }
OLDNEW
« no previous file with comments | « ui/gfx/surface/accelerated_surface_win.h ('k') | ui/gfx/surface/io_surface_support_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698