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

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: Fix try bot errors 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 NULL, 179 NULL,
138 device_.Receive()); 180 device_.Receive());
139 if (FAILED(hr)) 181 if (FAILED(hr))
140 return; 182 return;
141 183
142 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); 184 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
143 if (FAILED(hr)) 185 if (FAILED(hr))
144 device_ = NULL; 186 device_ = NULL;
145 } 187 }
146 188
189 bool AcceleratedPresenter::CopyTo(const gfx::Size& size,
190 void* buf) {
191 base::AutoLock locked(lock_);
192
193 if (!swap_chain_)
194 return false;
195
196 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer;
197 HRESULT hr = swap_chain_->GetBackBuffer(0,
198 D3DBACKBUFFER_TYPE_MONO,
199 back_buffer.Receive());
200 if (FAILED(hr))
201 return false;
202
203 D3DSURFACE_DESC desc;
204 hr = back_buffer->GetDesc(&desc);
205 if (FAILED(hr))
206 return false;
207
208 const gfx::Size back_buffer_size(desc.Width, desc.Height);
209 if (back_buffer_size.IsEmpty())
210 return false;
211
212 // Set up intermediate buffers needed for downsampling.
213 const int resample_count =
214 GetResampleCount(gfx::Size(desc.Width, desc.Height), size);
215 base::win::ScopedComPtr<IDirect3DSurface9> final_surface;
216 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
217 if (resample_count == 0)
218 final_surface = back_buffer;
219 if (resample_count > 0) {
220 if (!CreateTemporarySurface(present_thread_->device(),
221 size,
222 final_surface.Receive()))
223 return false;
224 }
225 const gfx::Size half_size = GetHalfSizeNoLessThan(back_buffer_size, size);
226 if (resample_count > 1) {
227 if (!CreateTemporarySurface(present_thread_->device(),
228 half_size,
229 temp_buffer[0].Receive()))
230 return false;
231 }
232 if (resample_count > 2) {
233 const gfx::Size quater_size = GetHalfSizeNoLessThan(half_size, size);
apatrick_chromium 2012/03/12 20:25:06 quater -> quarter
mazda 2012/03/12 23:20:42 Done.
234 if (!CreateTemporarySurface(present_thread_->device(),
235 quater_size,
236 temp_buffer[1].Receive()))
237 return false;
238 }
239
240 // Repeat downsampling the surface until its size becomes identical to
241 // |size|. We keep the factor of each downsampling no more than two because
242 // using a factor more than two can introduce aliasing.
243 gfx::Size read_size = back_buffer_size;
244 gfx::Size write_size = half_size;
245 int read_buffer_index = 1;
246 int write_buffer_index = 0;
247 for (int i = 0; i < resample_count; ++i) {
248 base::win::ScopedComPtr<IDirect3DSurface9> read_buffer =
249 (i == 0) ? back_buffer : temp_buffer[read_buffer_index];
250 base::win::ScopedComPtr<IDirect3DSurface9> write_buffer =
251 (i == resample_count - 1) ? final_surface :
252 temp_buffer[write_buffer_index];
253 RECT read_rect = {0, 0, read_size.width() - 1, read_size.height() - 1};
apatrick_chromium 2012/03/12 20:25:06 The Windows convention is that right and bottom ar
mazda 2012/03/12 23:20:42 Fixed. Thanks.
254 RECT write_rect = {0, 0, write_size.width() - 1, write_size.height() - 1};
apatrick_chromium 2012/03/12 20:25:06 Ditto.
mazda 2012/03/12 23:20:42 Done.
255 hr = present_thread_->device()->StretchRect(read_buffer,
256 &read_rect,
257 write_buffer,
258 &write_rect,
259 D3DTEXF_LINEAR);
260 if (FAILED(hr))
261 return false;
262 read_size = write_size;
263 write_size = GetHalfSizeNoLessThan(write_size, size);
264 std::swap(read_buffer_index, write_buffer_index);
265 }
266
267 DCHECK(size == read_size);
268
269 base::win::ScopedComPtr<IDirect3DSurface9> temp_surface;
270 HANDLE handle = reinterpret_cast<HANDLE>(buf);
271 hr = present_thread_->device()->CreateOffscreenPlainSurface(
272 size.width(),
273 size.height(),
274 D3DFMT_A8R8G8B8,
275 D3DPOOL_SYSTEMMEM,
276 temp_surface.Receive(),
277 &handle);
278 if (FAILED(hr))
279 return false;
280
281 // Copy the data in the temporary buffer to the surface backed by |buf|.
282 hr = present_thread_->device()->GetRenderTargetData(final_surface,
283 temp_surface);
284 if (FAILED(hr))
285 return false;
286
287 return true;
288 }
289
147 void PresentThread::Init() { 290 void PresentThread::Init() {
148 TRACE_EVENT0("surface", "PresentThread::Init"); 291 TRACE_EVENT0("surface", "PresentThread::Init");
149 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); 292 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
150 ResetDevice(); 293 ResetDevice();
151 } 294 }
152 295
153 void PresentThread::CleanUp() { 296 void PresentThread::CleanUp() {
154 // The D3D device and query are leaked because destroying the associated D3D 297 // The D3D device and query are leaked because destroying the associated D3D
155 // query crashes some Intel drivers. 298 // query crashes some Intel drivers.
156 device_.Detach(); 299 device_.Detach();
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 completion_task); 573 completion_task);
431 } 574 }
432 575
433 bool AcceleratedSurface::Present(HWND window) { 576 bool AcceleratedSurface::Present(HWND window) {
434 if (presenter_) 577 if (presenter_)
435 return presenter_->Present(window); 578 return presenter_->Present(window);
436 else 579 else
437 return false; 580 return false;
438 } 581 }
439 582
583 bool AcceleratedSurface::CopyTo(const gfx::Size& size,
584 void* buf) {
585 return presenter_->CopyTo(size, buf);
586 }
587
440 void AcceleratedSurface::Suspend() { 588 void AcceleratedSurface::Suspend() {
441 if (presenter_) 589 if (presenter_)
442 presenter_->Suspend(); 590 presenter_->Suspend();
443 } 591 }
444
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