Home | History | Annotate | Download | only in surface
      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 
     23 bool LoadD3D9(base::ScopedNativeLibrary* storage) {
     24   storage->Reset(
     25       base::LoadNativeLibrary(base::FilePath(kD3D9ModuleName), NULL));
     26   return storage->is_valid();
     27 }
     28 
     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 
     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 
    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 
    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 
    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 
    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