• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/surface/d3d9_utils_win.h"
6 
7 #include "base/debug/trace_event.h"
8 #include "base/files/file_path.h"
9 #include "base/scoped_native_library.h"
10 #include "base/win/scoped_comptr.h"
11 #include "ui/gfx/size.h"
12 
13 namespace {
14 
15 const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
16 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
17 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version,
18                                                 IDirect3D9Ex **d3d);
19 }  // namespace
20 
21 namespace ui_surface_d3d9_utils {
22 
LoadD3D9(base::ScopedNativeLibrary * storage)23 bool LoadD3D9(base::ScopedNativeLibrary* storage) {
24   storage->Reset(
25       base::LoadNativeLibrary(base::FilePath(kD3D9ModuleName), NULL));
26   return storage->is_valid();
27 }
28 
CreateDevice(const base::ScopedNativeLibrary & d3d_module,uint64 adapter_luid,D3DDEVTYPE device_type,uint32 presentation_interval,IDirect3DDevice9Ex ** device)29 bool CreateDevice(const base::ScopedNativeLibrary& d3d_module,
30                   uint64 adapter_luid,
31                   D3DDEVTYPE device_type,
32                   uint32 presentation_interval,
33                   IDirect3DDevice9Ex** device) {
34   Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>(
35       d3d_module.GetFunctionPointer(kCreate3D9DeviceExName));
36   if (!create_func)
37     return false;
38 
39   base::win::ScopedComPtr<IDirect3D9Ex> d3d;
40   HRESULT hr = create_func(D3D_SDK_VERSION, d3d.Receive());
41   if (FAILED(hr))
42     return false;
43 
44   UINT adapter = D3DADAPTER_DEFAULT;
45 
46   if (adapter_luid) {
47     UINT adapter_count = d3d->GetAdapterCount();
48     for (adapter = 0; adapter < adapter_count; ++adapter) {
49       LUID luid;
50       HRESULT hr = d3d->GetAdapterLUID(adapter, &luid);
51       if (FAILED(hr))
52         return false;
53 
54       if (memcmp(&luid, &adapter_luid, sizeof(adapter_luid)) == 0)
55         break;
56     }
57 
58     if (adapter == adapter_count)
59       return false;
60   }
61 
62   // Any old window will do to create the device. In practice the window to
63   // present to is an argument to IDirect3DDevice9::Present.
64   HWND window = GetDesktopWindow();
65 
66   D3DPRESENT_PARAMETERS parameters = { 0 };
67   parameters.BackBufferWidth = 1;
68   parameters.BackBufferHeight = 1;
69   parameters.BackBufferCount = 1;
70   parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
71   parameters.hDeviceWindow = window;
72   parameters.Windowed = TRUE;
73   parameters.Flags = 0;
74   parameters.PresentationInterval = presentation_interval;
75   parameters.SwapEffect = D3DSWAPEFFECT_COPY;
76 
77   hr = d3d->CreateDeviceEx(
78       adapter,
79       device_type,
80       window,
81       D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING |
82           D3DCREATE_DISABLE_PSGP_THREADING | D3DCREATE_MULTITHREADED,
83       &parameters,
84       NULL,
85       device);
86   return SUCCEEDED(hr);
87 }
88 
OpenSharedTexture(IDirect3DDevice9 * device,int64 surface_handle,const gfx::Size & size,IDirect3DTexture9 ** opened_texture)89 bool OpenSharedTexture(IDirect3DDevice9* device,
90                        int64 surface_handle,
91                        const gfx::Size& size,
92                        IDirect3DTexture9** opened_texture) {
93   TRACE_EVENT0("gpu", "OpenSharedTexture");
94   HANDLE handle = reinterpret_cast<HANDLE>(surface_handle);
95   HRESULT hr = device->CreateTexture(size.width(),
96                                      size.height(),
97                                      1,
98                                      D3DUSAGE_RENDERTARGET,
99                                      D3DFMT_A8R8G8B8,
100                                      D3DPOOL_DEFAULT,
101                                      opened_texture,
102                                      &handle);
103   return SUCCEEDED(hr);
104 }
105 
CreateOrReuseLockableSurface(IDirect3DDevice9 * device,const gfx::Size & size,base::win::ScopedComPtr<IDirect3DSurface9> * surface)106 bool CreateOrReuseLockableSurface(
107     IDirect3DDevice9* device,
108     const gfx::Size& size,
109     base::win::ScopedComPtr<IDirect3DSurface9>* surface) {
110   if (!*surface || GetSize(*surface) != size) {
111     TRACE_EVENT0("gpu", "CreateRenderTarget");
112     surface->Release();
113     HRESULT hr = device->CreateRenderTarget(
114           size.width(),
115           size.height(),
116           D3DFMT_A8R8G8B8,
117           D3DMULTISAMPLE_NONE,
118           0,
119           TRUE,
120           surface->Receive(),
121           NULL);
122     if (FAILED(hr))
123       return false;
124   }
125   return true;
126 }
127 
CreateOrReuseRenderTargetTexture(IDirect3DDevice9 * device,const gfx::Size & size,base::win::ScopedComPtr<IDirect3DTexture9> * texture,IDirect3DSurface9 ** render_target)128 bool CreateOrReuseRenderTargetTexture(
129     IDirect3DDevice9* device,
130     const gfx::Size& size,
131     base::win::ScopedComPtr<IDirect3DTexture9>* texture,
132     IDirect3DSurface9** render_target) {
133   if (!*texture || GetSize(*texture) != size) {
134     TRACE_EVENT0("gpu", "CreateTexture");
135     texture->Release();
136     HRESULT hr = device->CreateTexture(
137           size.width(),
138           size.height(),
139           1,  // Levels
140           D3DUSAGE_RENDERTARGET,
141           D3DFMT_A8R8G8B8,
142           D3DPOOL_DEFAULT,
143           texture->Receive(),
144           NULL);
145     if (!SUCCEEDED(hr))
146       return false;
147   }
148   HRESULT hr = (*texture)->GetSurfaceLevel(0, render_target);
149   return SUCCEEDED(hr);
150 }
151 
GetSize(IDirect3DSurface9 * surface)152 gfx::Size GetSize(IDirect3DSurface9* surface) {
153   D3DSURFACE_DESC surface_description;
154   HRESULT hr = surface->GetDesc(&surface_description);
155   if (FAILED(hr))
156     return gfx::Size(0, 0);
157   return gfx::Size(surface_description.Width, surface_description.Height);
158 }
159 
GetSize(IDirect3DTexture9 * texture)160 gfx::Size GetSize(IDirect3DTexture9* texture) {
161   D3DSURFACE_DESC surface_description;
162   HRESULT hr = texture->GetLevelDesc(0, &surface_description);
163   if (FAILED(hr))
164     return gfx::Size(0, 0);
165   return gfx::Size(surface_description.Width, surface_description.Height);
166 }
167 
168 }  // namespace ui_surface_d3d9_utils
169