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

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

Issue 9582003: Support browser side thumbnailing for GPU composited pages on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 9 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/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 #include <algorithm>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
11 #include "base/callback.h" 12 #include "base/callback.h"
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
14 #include "base/file_path.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/scoped_native_library.h" 18 #include "base/scoped_native_library.h"
(...skipping 13 matching lines...) Expand all
31 const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; 32 const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
32 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; 33 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
33 34
34 UINT GetPresentationInterval() { 35 UINT GetPresentationInterval() {
35 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 36 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
36 return D3DPRESENT_INTERVAL_IMMEDIATE; 37 return D3DPRESENT_INTERVAL_IMMEDIATE;
37 else 38 else
38 return D3DPRESENT_INTERVAL_ONE; 39 return D3DPRESENT_INTERVAL_ONE;
39 } 40 }
40 41
42 // Calculate the number necessary to transform |source_size| into |dest_size|
43 // by repeating downsampling of the image of |source_size| by a factor no more
44 // than 2.
45 int GetResampleCount(const gfx::Size& source_size, const gfx::Size& dest_size) {
46 int width_count = 0;
47 int width = source_size.width();
48 while (width > dest_size.width()) {
49 ++width_count;
50 width >>= 1;
51 }
52 int height_count = 0;
53 int height = source_size.height();
54 while (height > dest_size.height()) {
55 ++height_count;
56 height >>= 1;
57 }
58 return std::max(width_count, height_count);
59 }
60
61 // Returns half the size of |size| no smaller than |min_size|.
62 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
63 const gfx::Size& min_size) {
64 return gfx::Size(std::max(min_size.width(), size.width() / 2),
65 std::max(min_size.height(), size.height() / 2));
66 }
67
68 bool CreateTemporarySurface(IDirect3DDevice9* device,
69 const gfx::Size& size,
70 IDirect3DSurface9** surface) {
71 HRESULT hr = device->CreateRenderTarget(
72 size.width(),
73 size.height(),
74 D3DFMT_A8R8G8B8,
75 D3DMULTISAMPLE_NONE,
76 0,
77 TRUE,
78 surface,
79 NULL);
80 return SUCCEEDED(hr);
81 }
82
41 } // namespace anonymous 83 } // namespace anonymous
42 84
43 // A PresentThread is a thread that is dedicated to presenting surfaces to a 85 // A PresentThread is a thread that is dedicated to presenting surfaces to a
44 // window. It owns a Direct3D device and a Direct3D query for this purpose. 86 // window. It owns a Direct3D device and a Direct3D query for this purpose.
45 class PresentThread : public base::Thread { 87 class PresentThread : public base::Thread {
46 public: 88 public:
47 PresentThread(const char* name); 89 PresentThread(const char* name);
48 ~PresentThread(); 90 ~PresentThread();
49 91
50 IDirect3DDevice9* device() { return device_.get(); } 92 IDirect3DDevice9* device() { return device_.get(); }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); 275 hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH);
234 276
235 if (hr == S_FALSE) 277 if (hr == S_FALSE)
236 Sleep(0); 278 Sleep(0);
237 } while (hr == S_FALSE); 279 } while (hr == S_FALSE);
238 } 280 }
239 281
240 return true; 282 return true;
241 } 283 }
242 284
285 bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) {
286 base::AutoLock locked(lock_);
287
288 if (!swap_chain_)
289 return false;
290
291 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer;
292 HRESULT hr = swap_chain_->GetBackBuffer(0,
293 D3DBACKBUFFER_TYPE_MONO,
294 back_buffer.Receive());
295 if (FAILED(hr))
296 return false;
297
298 D3DSURFACE_DESC desc;
299 hr = back_buffer->GetDesc(&desc);
300 if (FAILED(hr))
301 return false;
302
303 const gfx::Size back_buffer_size(desc.Width, desc.Height);
304 if (back_buffer_size.IsEmpty())
305 return false;
306
307 // Set up intermediate buffers needed for downsampling.
308 const int resample_count =
309 GetResampleCount(gfx::Size(desc.Width, desc.Height), size);
310 base::win::ScopedComPtr<IDirect3DSurface9> final_surface;
311 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
312 if (resample_count == 0)
313 final_surface = back_buffer;
314 if (resample_count > 0) {
315 if (!CreateTemporarySurface(present_thread_->device(),
316 size,
317 final_surface.Receive()))
318 return false;
319 }
320 const gfx::Size half_size = GetHalfSizeNoLessThan(back_buffer_size, size);
321 if (resample_count > 1) {
322 if (!CreateTemporarySurface(present_thread_->device(),
323 half_size,
324 temp_buffer[0].Receive()))
325 return false;
326 }
327 if (resample_count > 2) {
328 const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, size);
329 if (!CreateTemporarySurface(present_thread_->device(),
330 quarter_size,
331 temp_buffer[1].Receive()))
332 return false;
333 }
334
335 // Repeat downsampling the surface until its size becomes identical to
336 // |size|. We keep the factor of each downsampling no more than two because
337 // using a factor more than two can introduce aliasing.
338 gfx::Size read_size = back_buffer_size;
339 gfx::Size write_size = half_size;
340 int read_buffer_index = 1;
341 int write_buffer_index = 0;
342 for (int i = 0; i < resample_count; ++i) {
343 base::win::ScopedComPtr<IDirect3DSurface9> read_buffer =
344 (i == 0) ? back_buffer : temp_buffer[read_buffer_index];
345 base::win::ScopedComPtr<IDirect3DSurface9> write_buffer =
346 (i == resample_count - 1) ? final_surface :
347 temp_buffer[write_buffer_index];
348 RECT read_rect = {0, 0, read_size.width(), read_size.height()};
349 RECT write_rect = {0, 0, write_size.width(), write_size.height()};
350 hr = present_thread_->device()->StretchRect(read_buffer,
351 &read_rect,
352 write_buffer,
353 &write_rect,
354 D3DTEXF_LINEAR);
355 if (FAILED(hr))
356 return false;
357 read_size = write_size;
358 write_size = GetHalfSizeNoLessThan(write_size, size);
359 std::swap(read_buffer_index, write_buffer_index);
360 }
361
362 DCHECK(size == read_size);
363
364 base::win::ScopedComPtr<IDirect3DSurface9> temp_surface;
365 HANDLE handle = reinterpret_cast<HANDLE>(buf);
366 hr = present_thread_->device()->CreateOffscreenPlainSurface(
367 size.width(),
368 size.height(),
369 D3DFMT_A8R8G8B8,
370 D3DPOOL_SYSTEMMEM,
371 temp_surface.Receive(),
372 &handle);
373 if (FAILED(hr))
374 return false;
375
376 // Copy the data in the temporary buffer to the surface backed by |buf|.
377 hr = present_thread_->device()->GetRenderTargetData(final_surface,
378 temp_surface);
379 if (FAILED(hr))
380 return false;
381
382 return true;
383 }
384
243 void AcceleratedPresenter::Suspend() { 385 void AcceleratedPresenter::Suspend() {
244 present_thread_->message_loop()->PostTask( 386 present_thread_->message_loop()->PostTask(
245 FROM_HERE, 387 FROM_HERE,
246 base::Bind(&AcceleratedPresenter::DoSuspend, 388 base::Bind(&AcceleratedPresenter::DoSuspend,
247 this)); 389 this));
248 } 390 }
249 391
250 void AcceleratedPresenter::WaitForPendingTasks() { 392 void AcceleratedPresenter::WaitForPendingTasks() {
251 base::WaitableEvent event(true, false); 393 base::WaitableEvent event(true, false);
252 present_thread_->message_loop()->PostTask( 394 present_thread_->message_loop()->PostTask(
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 presenter_->AsyncPresentAndAcknowledge(window, 579 presenter_->AsyncPresentAndAcknowledge(window,
438 size, 580 size,
439 surface_id, 581 surface_id,
440 completion_task); 582 completion_task);
441 } 583 }
442 584
443 bool AcceleratedSurface::Present(HWND window) { 585 bool AcceleratedSurface::Present(HWND window) {
444 return presenter_->Present(window); 586 return presenter_->Present(window);
445 } 587 }
446 588
589 bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) {
590 return presenter_->CopyTo(size, buf);
591 }
592
447 void AcceleratedSurface::Suspend() { 593 void AcceleratedSurface::Suspend() {
448 presenter_->Suspend(); 594 presenter_->Suspend();
449 } 595 }
450
OLDNEW
« no previous file with comments | « ui/gfx/surface/accelerated_surface_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698