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 13namespace { 14 15const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; 16const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; 17typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, 18 IDirect3D9Ex **d3d); 19} // namespace 20 21namespace ui_surface_d3d9_utils { 22 23bool LoadD3D9(base::ScopedNativeLibrary* storage) { 24 storage->Reset( 25 base::LoadNativeLibrary(base::FilePath(kD3D9ModuleName), NULL)); 26 return storage->is_valid(); 27} 28 29bool 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 ¶meters, 84 NULL, 85 device); 86 return SUCCEEDED(hr); 87} 88 89bool 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 106bool 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 128bool 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 152gfx::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 160gfx::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