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

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

Issue 11464017: Separate image processing logic from presentation logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make tests pass on Intel Mobile 965 Created 8 years 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
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/surface/accelerated_surface_win.h" 5 #include "ui/surface/accelerated_surface_win.h"
6 6
7 #include <dwmapi.h> 7 #include <dwmapi.h>
8 #include <windows.h> 8 #include <windows.h>
9 #include <algorithm> 9 #include <algorithm>
10 10
11 #include "accelerated_surface_win_hlsl_compiled.h"
12 #include "base/bind.h" 11 #include "base/bind.h"
13 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
14 #include "base/callback.h" 13 #include "base/callback.h"
15 #include "base/command_line.h" 14 #include "base/command_line.h"
16 #include "base/debug/trace_event.h" 15 #include "base/debug/trace_event.h"
17 #include "base/file_path.h" 16 #include "base/file_path.h"
18 #include "base/lazy_instance.h" 17 #include "base/lazy_instance.h"
19 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
20 #include "base/message_loop_proxy.h" 19 #include "base/message_loop_proxy.h"
21 #include "base/scoped_native_library.h" 20 #include "base/scoped_native_library.h"
22 #include "base/string_number_conversions.h" 21 #include "base/string_number_conversions.h"
23 #include "base/stringprintf.h" 22 #include "base/stringprintf.h"
24 #include "base/synchronization/waitable_event.h" 23 #include "base/synchronization/waitable_event.h"
25 #include "base/threading/thread.h" 24 #include "base/threading/thread.h"
26 #include "base/threading/thread_restrictions.h" 25 #include "base/threading/thread_restrictions.h"
27 #include "base/time.h" 26 #include "base/time.h"
28 #include "base/tracked_objects.h" 27 #include "base/tracked_objects.h"
29 #include "base/win/wrapped_window_proc.h" 28 #include "base/win/wrapped_window_proc.h"
30 #include "ui/base/win/hwnd_util.h" 29 #include "ui/base/win/hwnd_util.h"
31 #include "ui/gfx/rect.h" 30 #include "ui/gfx/rect.h"
32 #include "ui/gl/gl_switches.h" 31 #include "ui/gl/gl_switches.h"
32 #include "ui/surface/accelerated_surface_transformer_win.h"
33 #include "ui/surface/d3d9_utils_win.h"
33 34
34 35 namespace d3d_utils = ui_surface_d3d9_utils;
35 using ui_surface::AcceleratedSurfaceWinHLSL::kVsOneTexture;
36 using ui_surface::AcceleratedSurfaceWinHLSL::kPsOneTexture;
37
38 36
39 namespace { 37 namespace {
40 38
41 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version,
42 IDirect3D9Ex **d3d);
43
44 const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
45 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
46
47 const char kUseOcclusionQuery[] = "use-occlusion-query"; 39 const char kUseOcclusionQuery[] = "use-occlusion-query";
48 40
49 struct Vertex {
50 float x, y, z, w;
51 float u, v;
52 };
53
54 const static D3DVERTEXELEMENT9 g_vertexElements[] = {
55 { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 },
56 { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
57 D3DDECL_END()
58 };
59
60 UINT GetPresentationInterval() { 41 UINT GetPresentationInterval() {
61 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 42 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
62 return D3DPRESENT_INTERVAL_IMMEDIATE; 43 return D3DPRESENT_INTERVAL_IMMEDIATE;
63 else 44 else
64 return D3DPRESENT_INTERVAL_ONE; 45 return D3DPRESENT_INTERVAL_ONE;
65 } 46 }
66 47
67 bool UsingOcclusionQuery() { 48 bool UsingOcclusionQuery() {
68 return CommandLine::ForCurrentProcess()->HasSwitch(kUseOcclusionQuery); 49 return CommandLine::ForCurrentProcess()->HasSwitch(kUseOcclusionQuery);
69 } 50 }
70 51
71 // Calculate the number necessary to transform |src_subrect| into |dst_size|
72 // by repeating downsampling of the image of |src_subrect| by a factor no more
73 // than 2.
74 int GetResampleCount(const gfx::Rect& src_subrect,
75 const gfx::Size& dst_size,
76 const gfx::Size& back_buffer_size) {
77 // At least one copy is required, since the back buffer itself is not
78 // lockable.
79 int min_resample_count = 1;
80 int width_count = 0;
81 int width = src_subrect.width();
82 while (width > dst_size.width()) {
83 ++width_count;
84 width >>= 1;
85 }
86 int height_count = 0;
87 int height = src_subrect.height();
88 while (height > dst_size.height()) {
89 ++height_count;
90 height >>= 1;
91 }
92 return std::max(std::max(width_count, height_count),
93 min_resample_count);
94 }
95
96 // Returns half the size of |size| no smaller than |min_size|.
97 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
98 const gfx::Size& min_size) {
99 return gfx::Size(std::max(min_size.width(), size.width() / 2),
100 std::max(min_size.height(), size.height() / 2));
101 }
102
103 bool CreateTemporarySurface(IDirect3DDevice9* device,
104 const gfx::Size& size,
105 IDirect3DSurface9** surface) {
106 HRESULT hr = device->CreateRenderTarget(
107 size.width(),
108 size.height(),
109 D3DFMT_A8R8G8B8,
110 D3DMULTISAMPLE_NONE,
111 0,
112 TRUE,
113 surface,
114 NULL);
115 return SUCCEEDED(hr);
116 }
117
118 } // namespace 52 } // namespace
119 53
120 // A PresentThread is a thread that is dedicated to presenting surfaces to a 54 // A PresentThread is a thread that is dedicated to presenting surfaces to a
121 // window. It owns a Direct3D device and a Direct3D query for this purpose. 55 // window. It owns a Direct3D device and a Direct3D query for this purpose.
122 class PresentThread : public base::Thread, 56 class PresentThread : public base::Thread,
123 public base::RefCountedThreadSafe<PresentThread> { 57 public base::RefCountedThreadSafe<PresentThread> {
124 public: 58 public:
125 explicit PresentThread(const char* name); 59 explicit PresentThread(const char* name);
126 60
127 IDirect3DDevice9Ex* device() { return device_.get(); } 61 IDirect3DDevice9Ex* device() { return device_.get(); }
128 IDirect3DQuery9* query() { return query_.get(); } 62 IDirect3DQuery9* query() { return query_.get(); }
63 AcceleratedSurfaceTransformer* surface_transformer() {
64 return &surface_transformer_;
65 }
129 66
130 void InitDevice(); 67 void InitDevice();
131 void ResetDevice(); 68 void ResetDevice();
132 69
133 protected: 70 protected:
134 virtual void Init(); 71 virtual void Init();
135 virtual void CleanUp(); 72 virtual void CleanUp();
136 73
137 private: 74 private:
138 friend class base::RefCountedThreadSafe<PresentThread>; 75 friend class base::RefCountedThreadSafe<PresentThread>;
139 76
140 ~PresentThread(); 77 ~PresentThread();
141 78
142 base::ScopedNativeLibrary d3d_module_; 79 base::ScopedNativeLibrary d3d_module_;
143 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_; 80 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_;
144
145 // This query is used to wait until a certain amount of progress has been 81 // This query is used to wait until a certain amount of progress has been
146 // made by the GPU and it is safe for the producer to modify its shared 82 // made by the GPU and it is safe for the producer to modify its shared
147 // texture again. 83 // texture again.
148 base::win::ScopedComPtr<IDirect3DQuery9> query_; 84 base::win::ScopedComPtr<IDirect3DQuery9> query_;
85 AcceleratedSurfaceTransformer surface_transformer_;
149 86
150 DISALLOW_COPY_AND_ASSIGN(PresentThread); 87 DISALLOW_COPY_AND_ASSIGN(PresentThread);
151 }; 88 };
152 89
153 // There is a fixed sized pool of PresentThreads and therefore the maximum 90 // There is a fixed sized pool of PresentThreads and therefore the maximum
154 // number of Direct3D devices owned by those threads is bounded. 91 // number of Direct3D devices owned by those threads is bounded.
155 class PresentThreadPool { 92 class PresentThreadPool {
156 public: 93 public:
157 static const int kNumPresentThreads = 4; 94 static const int kNumPresentThreads = 4;
158 95
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 g_accelerated_presenter_map = LAZY_INSTANCE_INITIALIZER; 128 g_accelerated_presenter_map = LAZY_INSTANCE_INITIALIZER;
192 129
193 PresentThread::PresentThread(const char* name) : base::Thread(name) { 130 PresentThread::PresentThread(const char* name) : base::Thread(name) {
194 } 131 }
195 132
196 void PresentThread::InitDevice() { 133 void PresentThread::InitDevice() {
197 if (device_) 134 if (device_)
198 return; 135 return;
199 136
200 TRACE_EVENT0("gpu", "PresentThread::Init"); 137 TRACE_EVENT0("gpu", "PresentThread::Init");
201 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); 138 d3d_utils::LoadD3D9(&d3d_module_);
202 ResetDevice(); 139 ResetDevice();
203 } 140 }
204 141
205 void PresentThread::ResetDevice() { 142 void PresentThread::ResetDevice() {
206 TRACE_EVENT0("gpu", "PresentThread::ResetDevice"); 143 TRACE_EVENT0("gpu", "PresentThread::ResetDevice");
207 144
208 // This will crash some Intel drivers but we can't render anything without 145 // This will crash some Intel drivers but we can't render anything without
209 // reseting the device, which would be disappointing. 146 // reseting the device, which would be disappointing.
210 query_ = NULL; 147 query_ = NULL;
211 device_ = NULL; 148 device_ = NULL;
212 149
213 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( 150 if (!d3d_utils::CreateDevice(d3d_module_,
214 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); 151 D3DDEVTYPE_HAL,
215 if (!create_func) 152 GetPresentationInterval(),
153 device_.Receive())) {
216 return; 154 return;
217 155 }
218 base::win::ScopedComPtr<IDirect3D9Ex> d3d;
219 HRESULT hr = create_func(D3D_SDK_VERSION, d3d.Receive());
220 if (FAILED(hr))
221 return;
222
223 // Any old window will do to create the device. In practice the window to
224 // present to is an argument to IDirect3DDevice9::Present.
225 HWND window = GetShellWindow();
226
227 D3DPRESENT_PARAMETERS parameters = { 0 };
228 parameters.BackBufferWidth = 1;
229 parameters.BackBufferHeight = 1;
230 parameters.BackBufferCount = 1;
231 parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
232 parameters.hDeviceWindow = window;
233 parameters.Windowed = TRUE;
234 parameters.Flags = 0;
235 parameters.PresentationInterval = GetPresentationInterval();
236 parameters.SwapEffect = D3DSWAPEFFECT_COPY;
237
238 hr = d3d->CreateDeviceEx(
239 D3DADAPTER_DEFAULT,
240 D3DDEVTYPE_HAL,
241 window,
242 D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING |
243 D3DCREATE_DISABLE_PSGP_THREADING | D3DCREATE_MULTITHREADED,
244 &parameters,
245 NULL,
246 device_.Receive());
247 if (FAILED(hr))
248 return;
249 156
250 if (UsingOcclusionQuery()) { 157 if (UsingOcclusionQuery()) {
251 hr = device_->CreateQuery(D3DQUERYTYPE_OCCLUSION, query_.Receive()); 158 HRESULT hr = device_->CreateQuery(D3DQUERYTYPE_OCCLUSION, query_.Receive());
252 if (FAILED(hr)) { 159 if (FAILED(hr)) {
253 device_ = NULL; 160 device_ = NULL;
254 return; 161 return;
255 } 162 }
256 } else { 163 } else {
257 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); 164 HRESULT hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
258 if (FAILED(hr)) { 165 if (FAILED(hr)) {
259 device_ = NULL; 166 device_ = NULL;
260 return; 167 return;
261 } 168 }
262 } 169 }
263 170
264 base::win::ScopedComPtr<IDirect3DVertexShader9> vertex_shader; 171 if (!surface_transformer_.Init(device_)) {
265 hr = device_->CreateVertexShader( 172 query_ = NULL;
266 reinterpret_cast<const DWORD*>(kVsOneTexture),
267 vertex_shader.Receive());
268 if (FAILED(hr)) {
269 device_ = NULL; 173 device_ = NULL;
270 query_ = NULL;
271 return; 174 return;
272 } 175 }
273
274 device_->SetVertexShader(vertex_shader);
275
276 base::win::ScopedComPtr<IDirect3DPixelShader9> pixel_shader;
277 hr = device_->CreatePixelShader(
278 reinterpret_cast<const DWORD*>(kPsOneTexture),
279 pixel_shader.Receive());
280
281 if (FAILED(hr)) {
282 device_ = NULL;
283 query_ = NULL;
284 return;
285 }
286
287 device_->SetPixelShader(pixel_shader);
288
289 base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration;
290 hr = device_->CreateVertexDeclaration(g_vertexElements,
291 vertex_declaration.Receive());
292 if (FAILED(hr)) {
293 device_ = NULL;
294 query_ = NULL;
295 return;
296 }
297
298 device_->SetVertexDeclaration(vertex_declaration);
299 } 176 }
300 177
301 void PresentThread::Init() { 178 void PresentThread::Init() {
302 TRACE_EVENT0("gpu", "Initialize thread"); 179 TRACE_EVENT0("gpu", "Initialize thread");
303 } 180 }
304 181
305 void PresentThread::CleanUp() { 182 void PresentThread::CleanUp() {
306 // The D3D device and query are leaked because destroying the associated D3D 183 // The D3D device and query are leaked because destroying the associated D3D
307 // query crashes some Intel drivers. 184 // query crashes some Intel drivers.
185 surface_transformer_.DetachAll();
308 device_.Detach(); 186 device_.Detach();
309 query_.Detach(); 187 query_.Detach();
310 } 188 }
311 189
312 PresentThread::~PresentThread() { 190 PresentThread::~PresentThread() {
313 Stop(); 191 Stop();
314 } 192 }
315 193
316 PresentThreadPool::PresentThreadPool() : next_thread_(0) { 194 PresentThreadPool::PresentThreadPool() : next_thread_(0) {
317 } 195 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 return it->second; 253 return it->second;
376 } 254 }
377 255
378 AcceleratedPresenter::AcceleratedPresenter(gfx::PluginWindowHandle window) 256 AcceleratedPresenter::AcceleratedPresenter(gfx::PluginWindowHandle window)
379 : present_thread_(g_present_thread_pool.Pointer()->NextThread()), 257 : present_thread_(g_present_thread_pool.Pointer()->NextThread()),
380 window_(window), 258 window_(window),
381 event_(false, false), 259 event_(false, false),
382 hidden_(true) { 260 hidden_(true) {
383 } 261 }
384 262
263 // static
385 scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow( 264 scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow(
386 gfx::PluginWindowHandle window) { 265 gfx::PluginWindowHandle window) {
387 return g_accelerated_presenter_map.Pointer()->GetPresenter(window); 266 return g_accelerated_presenter_map.Pointer()->GetPresenter(window);
388 } 267 }
389 268
390 void AcceleratedPresenter::AsyncPresentAndAcknowledge( 269 void AcceleratedPresenter::AsyncPresentAndAcknowledge(
391 const gfx::Size& size, 270 const gfx::Size& size,
392 int64 surface_handle, 271 int64 surface_handle,
393 const CompletionTask& completion_task) { 272 const CompletionTask& completion_task) {
394 if (!surface_handle) { 273 if (!surface_handle) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 "width", dst_size.width(), 339 "width", dst_size.width(),
461 "height", dst_size.height()); 340 "height", dst_size.height());
462 341
463 base::AutoLock locked(lock_); 342 base::AutoLock locked(lock_);
464 343
465 TRACE_EVENT0("gpu", "CopyTo_locked"); 344 TRACE_EVENT0("gpu", "CopyTo_locked");
466 345
467 if (!swap_chain_) 346 if (!swap_chain_)
468 return false; 347 return false;
469 348
349 AcceleratedSurfaceTransformer* gpu_ops =
350 present_thread_->surface_transformer();
351
470 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer; 352 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer;
471 HRESULT hr = swap_chain_->GetBackBuffer(0, 353 HRESULT hr = swap_chain_->GetBackBuffer(0,
472 D3DBACKBUFFER_TYPE_MONO, 354 D3DBACKBUFFER_TYPE_MONO,
473 back_buffer.Receive()); 355 back_buffer.Receive());
474 if (FAILED(hr)) 356 if (FAILED(hr))
475 return false; 357 return false;
476 358
477 D3DSURFACE_DESC desc; 359 D3DSURFACE_DESC desc;
478 hr = back_buffer->GetDesc(&desc); 360 hr = back_buffer->GetDesc(&desc);
479 if (FAILED(hr)) 361 if (FAILED(hr))
480 return false; 362 return false;
481 363
482 const gfx::Size back_buffer_size(desc.Width, desc.Height); 364 const gfx::Size back_buffer_size(desc.Width, desc.Height);
483 if (back_buffer_size.IsEmpty()) 365 if (back_buffer_size.IsEmpty())
484 return false; 366 return false;
485 367
486 // With window resizing, it's possible that the back buffer is smaller than 368 // With window resizing, it's possible that the back buffer is smaller than
487 // the requested src subset. Clip to the actual back buffer. 369 // the requested src subset. Clip to the actual back buffer.
488 gfx::Rect src_subrect = requested_src_subrect; 370 gfx::Rect src_subrect = requested_src_subrect;
489 src_subrect.Intersect(gfx::Rect(back_buffer_size)); 371 src_subrect.Intersect(gfx::Rect(back_buffer_size));
372 base::win::ScopedComPtr<IDirect3DSurface9> final_surface;
373 {
374 TRACE_EVENT0("gpu", "CreateTemporaryLockableSurface");
375 if (!d3d_utils::CreateTemporaryLockableSurface(present_thread_->device(),
376 dst_size,
377 final_surface.Receive())) {
378 return false;
379 }
380 }
490 381
491 // Set up intermediate buffers needed for downsampling. 382 {
492 const int resample_count = 383 // Let the surface transformer start the resize into |final_surface|.
493 GetResampleCount(src_subrect, dst_size, back_buffer_size); 384 TRACE_EVENT0("gpu", "ResizeBilinear");
494 base::win::ScopedComPtr<IDirect3DSurface9> final_surface; 385 if (!gpu_ops->ResizeBilinear(back_buffer, src_subrect, final_surface))
495 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
496 if (resample_count == 0)
497 final_surface = back_buffer;
498 if (resample_count > 0) {
499 TRACE_EVENT0("gpu", "CreateTemporarySurface");
500 if (!CreateTemporarySurface(present_thread_->device(),
501 dst_size,
502 final_surface.Receive()))
503 return false;
504 }
505 const gfx::Size half_size =
506 GetHalfSizeNoLessThan(src_subrect.size(), dst_size);
507 if (resample_count > 1) {
508 TRACE_EVENT0("gpu", "CreateTemporarySurface");
509 if (!CreateTemporarySurface(present_thread_->device(),
510 half_size,
511 temp_buffer[0].Receive()))
512 return false;
513 }
514 if (resample_count > 2) {
515 TRACE_EVENT0("gpu", "CreateTemporarySurface");
516 const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, dst_size);
517 if (!CreateTemporarySurface(present_thread_->device(),
518 quarter_size,
519 temp_buffer[1].Receive()))
520 return false; 386 return false;
521 } 387 }
522 388
523 // Repeat downsampling the surface until its size becomes identical to
524 // |dst_size|. We keep the factor of each downsampling no more than two
525 // because using a factor more than two can introduce aliasing.
526 RECT read_rect = src_subrect.ToRECT();
527 gfx::Size write_size = half_size;
528 int read_buffer_index = 1;
529 int write_buffer_index = 0;
530 for (int i = 0; i < resample_count; ++i) {
531 TRACE_EVENT0("gpu", "StretchRect");
532 base::win::ScopedComPtr<IDirect3DSurface9> read_buffer =
533 (i == 0) ? back_buffer : temp_buffer[read_buffer_index];
534 base::win::ScopedComPtr<IDirect3DSurface9> write_buffer =
535 (i == resample_count - 1) ? final_surface :
536 temp_buffer[write_buffer_index];
537 RECT write_rect = gfx::Rect(write_size).ToRECT();
538 hr = present_thread_->device()->StretchRect(read_buffer,
539 &read_rect,
540 write_buffer,
541 &write_rect,
542 D3DTEXF_LINEAR);
543 if (FAILED(hr))
544 return false;
545 read_rect = write_rect;
546 write_size = GetHalfSizeNoLessThan(write_size, dst_size);
547 std::swap(read_buffer_index, write_buffer_index);
548 }
549 D3DLOCKED_RECT locked_rect; 389 D3DLOCKED_RECT locked_rect;
550 390
551 // Empirical evidence seems to suggest that LockRect and memcpy are faster 391 // Empirical evidence seems to suggest that LockRect and memcpy are faster
552 // than would be GetRenderTargetData to an offscreen surface wrapping *buf. 392 // than would be GetRenderTargetData to an offscreen surface wrapping *buf.
553 { 393 {
554 TRACE_EVENT0("gpu", "LockRect"); 394 TRACE_EVENT0("gpu", "LockRect");
555 hr = final_surface->LockRect(&locked_rect, NULL, 395 hr = final_surface->LockRect(&locked_rect, NULL,
556 D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); 396 D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
557 if (FAILED(hr)) 397 if (FAILED(hr))
558 return false; 398 return false;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 539
700 swap_chain_ = NULL; 540 swap_chain_ = NULL;
701 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain( 541 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain(
702 &parameters, 542 &parameters,
703 swap_chain_.Receive()); 543 swap_chain_.Receive());
704 if (FAILED(hr)) 544 if (FAILED(hr))
705 return; 545 return;
706 } 546 }
707 547
708 if (!source_texture_.get()) { 548 if (!source_texture_.get()) {
709 TRACE_EVENT0("gpu", "CreateTexture"); 549 TRACE_EVENT0("gpu", "OpenSharedTexture");
710 HANDLE handle = reinterpret_cast<HANDLE>(surface_handle); 550 if (!d3d_utils::OpenSharedTexture(present_thread_->device(),
711 hr = present_thread_->device()->CreateTexture(size.width(), 551 surface_handle,
712 size.height(), 552 size,
713 1, 553 source_texture_.Receive())) {
714 D3DUSAGE_RENDERTARGET,
715 D3DFMT_A8R8G8B8,
716 D3DPOOL_DEFAULT,
717 source_texture_.Receive(),
718 &handle);
719 if (FAILED(hr))
720 return; 554 return;
555 }
721 } 556 }
722 557
723 base::win::ScopedComPtr<IDirect3DSurface9> source_surface; 558 base::win::ScopedComPtr<IDirect3DSurface9> source_surface;
724 hr = source_texture_->GetSurfaceLevel(0, source_surface.Receive()); 559 hr = source_texture_->GetSurfaceLevel(0, source_surface.Receive());
725 if (FAILED(hr)) { 560 if (FAILED(hr)) {
726 TRACE_EVENT0("gpu", "EarlyOut_NoSurfaceLevel"); 561 TRACE_EVENT0("gpu", "EarlyOut_NoSurfaceLevel");
727 return; 562 return;
728 } 563 }
729 564
730 base::win::ScopedComPtr<IDirect3DSurface9> dest_surface; 565 base::win::ScopedComPtr<IDirect3DSurface9> dest_surface;
731 hr = swap_chain_->GetBackBuffer(0, 566 hr = swap_chain_->GetBackBuffer(0,
732 D3DBACKBUFFER_TYPE_MONO, 567 D3DBACKBUFFER_TYPE_MONO,
733 dest_surface.Receive()); 568 dest_surface.Receive());
734 if (FAILED(hr)) { 569 if (FAILED(hr)) {
735 TRACE_EVENT0("gpu", "EarlyOut_NoBackbuffer"); 570 TRACE_EVENT0("gpu", "EarlyOut_NoBackbuffer");
736 return; 571 return;
737 } 572 }
738 573
739 RECT rect = { 574 RECT rect = {
740 0, 0, 575 0, 0,
741 size.width(), size.height() 576 size.width(), size.height()
742 }; 577 };
743 578
744 { 579 {
745 TRACE_EVENT0("gpu", "Copy"); 580 TRACE_EVENT0("gpu", "Copy");
746 581
747 // Use a simple pixel / vertex shader pair to render a quad that flips the
748 // source texture on the vertical axis.
749 IDirect3DSurface9 *default_render_target = NULL;
750 present_thread_->device()->GetRenderTarget(0, &default_render_target);
751
752 present_thread_->device()->SetRenderTarget(0, dest_surface);
753 present_thread_->device()->SetTexture(0, source_texture_);
754
755 D3DVIEWPORT9 viewport = {
756 0, 0,
757 size.width(), size.height(),
758 0, 1
759 };
760 present_thread_->device()->SetViewport(&viewport);
761
762 float halfPixelX = -1.0f / size.width();
763 float halfPixelY = 1.0f / size.height();
764 Vertex vertices[] = {
765 { halfPixelX - 1, halfPixelY + 1, 0.5f, 1, 0, 1 },
766 { halfPixelX + 1, halfPixelY + 1, 0.5f, 1, 1, 1 },
767 { halfPixelX + 1, halfPixelY - 1, 0.5f, 1, 1, 0 },
768 { halfPixelX - 1, halfPixelY - 1, 0.5f, 1, 0, 0 }
769 };
770
771 if (UsingOcclusionQuery()) { 582 if (UsingOcclusionQuery()) {
772 present_thread_->query()->Issue(D3DISSUE_BEGIN); 583 present_thread_->query()->Issue(D3DISSUE_BEGIN);
773 } 584 }
774 585
775 present_thread_->device()->BeginScene(); 586 // Copy while flipping the source texture on the vertical axis.
776 present_thread_->device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 587 bool result = present_thread_->surface_transformer()->CopyInverted(
777 2, 588 source_texture_, dest_surface, size);
778 vertices, 589 if (!result)
779 sizeof(vertices[0])); 590 return;
780 present_thread_->device()->EndScene();
781
782 present_thread_->device()->SetTexture(0, NULL);
783 present_thread_->device()->SetRenderTarget(0, default_render_target);
784 default_render_target->Release();
785 } 591 }
786 592
787 hr = present_thread_->query()->Issue(D3DISSUE_END); 593 hr = present_thread_->query()->Issue(D3DISSUE_END);
788 if (FAILED(hr)) 594 if (FAILED(hr))
789 return; 595 return;
790 596
791 present_size_ = size; 597 present_size_ = size;
792 598
793 static const base::TimeDelta swap_delay = GetSwapDelay(); 599 static const base::TimeDelta swap_delay = GetSwapDelay();
794 if (swap_delay.ToInternalValue()) 600 if (swap_delay.ToInternalValue())
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 presenter_->AsyncCopyTo(src_subrect, dst_size, buf, callback); 807 presenter_->AsyncCopyTo(src_subrect, dst_size, buf, callback);
1002 } 808 }
1003 809
1004 void AcceleratedSurface::Suspend() { 810 void AcceleratedSurface::Suspend() {
1005 presenter_->Suspend(); 811 presenter_->Suspend();
1006 } 812 }
1007 813
1008 void AcceleratedSurface::WasHidden() { 814 void AcceleratedSurface::WasHidden() {
1009 presenter_->WasHidden(); 815 presenter_->WasHidden();
1010 } 816 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698