home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Tessa / source / D3D9 / Context_D3D9.cpp next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  43.1 KB  |  1,894 lines

  1. #include "stdafx.h"
  2. #include <d3d9.h>
  3. #include <vd2/Tessa/Context.h>
  4. #include "D3D9/Context_D3D9.h"
  5. #include "D3D9/FenceManager_D3D9.h"
  6.  
  7. ///////////////////////////////////////////////////////////////////////////////
  8.  
  9. VDTResourceD3D9::VDTResourceD3D9() {
  10.     mListNodePrev = NULL;
  11.     mpParent = NULL;
  12. }
  13.  
  14. VDTResourceD3D9::~VDTResourceD3D9() {
  15. }
  16.  
  17. void VDTResourceD3D9::Shutdown() {
  18.     if (mListNodePrev)
  19.         mpParent->RemoveResource(this);
  20. }
  21.  
  22. void VDTResourceD3D9::ShutdownDefaultPool() {
  23. }
  24.  
  25. void VDTResourceManagerD3D9::AddResource(VDTResourceD3D9 *res) {
  26.     VDASSERT(!res->mListNodePrev);
  27.  
  28.     mResources.push_back(res);
  29.     res->mpParent = this;
  30. }
  31.  
  32. void VDTResourceManagerD3D9::RemoveResource(VDTResourceD3D9 *res) {
  33.     VDASSERT(res->mListNodePrev);
  34.  
  35.     mResources.erase(res);
  36.     res->mListNodePrev = NULL;
  37. }
  38.  
  39. void VDTResourceManagerD3D9::ShutdownDefaultPoolResources() {
  40.     Resources::iterator it(mResources.begin()), itEnd(mResources.end());
  41.     for(; it != itEnd; ++it) {
  42.         VDTResourceD3D9 *res = *it;
  43.  
  44.         res->ShutdownDefaultPool();
  45.     }
  46. }
  47.  
  48. void VDTResourceManagerD3D9::ShutdownAllResources() {
  49.     while(!mResources.empty()) {
  50.         VDTResourceD3D9 *res = mResources.back();
  51.         mResources.pop_back();
  52.  
  53.         res->mListNodePrev = NULL;
  54.         res->Shutdown();
  55.     }
  56. }
  57.  
  58. ///////////////////////////////////////////////////////////////////////////////
  59.  
  60. VDTReadbackBufferD3D9::VDTReadbackBufferD3D9()
  61.     : mpSurface(NULL)
  62. {
  63. }
  64.  
  65. VDTReadbackBufferD3D9::~VDTReadbackBufferD3D9() {
  66.     Shutdown();
  67. }
  68.  
  69. bool VDTReadbackBufferD3D9::Init(VDTContextD3D9 *parent, uint32 width, uint32 height, uint32 format) {
  70.     IDirect3DDevice9 *dev = parent->GetDeviceD3D9();
  71.     HRESULT hr = dev->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &mpSurface, NULL);
  72.  
  73.     parent->AddResource(this);
  74.     return SUCCEEDED(hr);
  75. }
  76.  
  77. void VDTReadbackBufferD3D9::Shutdown() {
  78.     if (mpSurface) {
  79.         mpSurface->Release();
  80.         mpSurface = NULL;
  81.     }
  82.  
  83.     VDTResourceD3D9::Shutdown();
  84. }
  85.  
  86. bool VDTReadbackBufferD3D9::Lock(VDTLockData2D& lockData) {
  87.     D3DLOCKED_RECT lr;
  88.     HRESULT hr = mpSurface->LockRect(&lr, NULL, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
  89.  
  90.     if (FAILED(hr)) {
  91.         lockData.mpData = NULL;
  92.         lockData.mPitch = 0;
  93.         return false;
  94.     }
  95.  
  96.     lockData.mpData = lr.pBits;
  97.     lockData.mPitch = lr.Pitch;
  98.     return true;
  99. }
  100.  
  101. void VDTReadbackBufferD3D9::Unlock() {
  102.     HRESULT hr = mpSurface->UnlockRect();
  103.     VDASSERT(SUCCEEDED(hr));
  104. }
  105.  
  106. bool VDTReadbackBufferD3D9::Restore() {
  107.     return true;
  108. }
  109.  
  110. ///////////////////////////////////////////////////////////////////////////////
  111.  
  112. VDTSurfaceD3D9::VDTSurfaceD3D9()
  113.     : mpSurface(NULL)
  114. {
  115. }
  116.  
  117. VDTSurfaceD3D9::~VDTSurfaceD3D9() {
  118.     Shutdown();
  119. }
  120.  
  121. bool VDTSurfaceD3D9::Init(VDTContextD3D9 *parent, uint32 width, uint32 height, uint32 format, VDTUsage usage) {
  122.     IDirect3DDevice9 *dev = parent->GetDeviceD3D9();
  123.     HRESULT hr;
  124.     
  125.     mDesc.mWidth = width;
  126.     mDesc.mHeight = height;
  127.     mDesc.mFormat = format;
  128.  
  129.     mbDefaultPool = false;
  130.     switch(usage) {
  131.         case kVDTUsage_Default:
  132.             hr = dev->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &mpSurface, NULL);
  133.             break;
  134.  
  135.         case kVDTUsage_Render:
  136.             hr = dev->CreateRenderTarget(width, height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &mpSurface, NULL);
  137.             mbDefaultPool = true;
  138.             break;
  139.     }
  140.  
  141.     parent->AddResource(this);
  142.  
  143.     return SUCCEEDED(hr);
  144. }
  145.  
  146. bool VDTSurfaceD3D9::Init(VDTContextD3D9 *parent, IDirect3DSurface9 *surf) {
  147.     D3DSURFACE_DESC desc = {};
  148.  
  149.     HRESULT hr = surf->GetDesc(&desc);
  150.  
  151.     if (FAILED(hr)) {
  152.         parent->ProcessHRESULT(hr);
  153.         return false;
  154.     }
  155.  
  156.     mDesc.mWidth = desc.Width;
  157.     mDesc.mHeight = desc.Height;
  158.     mDesc.mFormat = 0;
  159.     mbDefaultPool = (desc.Pool == D3DPOOL_DEFAULT);
  160.  
  161.     parent->AddResource(this);
  162.  
  163.     mpSurface = surf;
  164.     mpSurface->AddRef();
  165.     return true;
  166. }
  167.  
  168. void VDTSurfaceD3D9::Shutdown() {
  169.     if (mpSurface) {
  170.         mpSurface->Release();
  171.         mpSurface = NULL;
  172.     }
  173.  
  174.     VDTResourceD3D9::Shutdown();
  175. }
  176.  
  177. bool VDTSurfaceD3D9::Restore() {
  178.     return true;
  179. }
  180.  
  181. bool VDTSurfaceD3D9::Readback(IVDTReadbackBuffer *target) {
  182.     VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  183.     IDirect3DDevice9 *dev = parent->GetDeviceD3D9();
  184.     VDTReadbackBufferD3D9 *targetd3d9 = static_cast<VDTReadbackBufferD3D9 *>(target);
  185.  
  186.     HRESULT hr = dev->GetRenderTargetData(mpSurface, targetd3d9->mpSurface);
  187.     if (FAILED(hr)) {
  188.         parent->ProcessHRESULT(hr);
  189.         return false;
  190.     }
  191.  
  192.     return true;
  193. }
  194.  
  195. void VDTSurfaceD3D9::Load(uint32 dx, uint32 dy, const VDTInitData2D& srcData, uint32 w, uint32 h) {
  196.     D3DLOCKED_RECT lr;
  197.     RECT r = { dx, dy, w, h };
  198.     HRESULT hr = mpSurface->LockRect(&lr, &r, D3DLOCK_NOSYSLOCK);
  199.     if (FAILED(hr)) {
  200.         VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  201.         parent->ProcessHRESULT(hr);
  202.         return;
  203.     }
  204.  
  205.     VDMemcpyRect(lr.pBits, lr.Pitch, srcData.mpData, srcData.mPitch, 4*w, h);
  206.  
  207.     hr = mpSurface->UnlockRect();
  208.     if (FAILED(hr)) {
  209.         VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  210.         parent->ProcessHRESULT(hr);
  211.         return;
  212.     }
  213. }
  214.  
  215. void VDTSurfaceD3D9::Copy(uint32 dx, uint32 dy, IVDTSurface *src0, uint32 sx, uint32 sy, uint32 w, uint32 h) {
  216.     VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  217.     IDirect3DDevice9 *dev = parent->GetDeviceD3D9();
  218.     VDTSurfaceD3D9 *src = static_cast<VDTSurfaceD3D9 *>(src0);
  219.  
  220.     const RECT rSrc = { sx, sy, sx+w, sy+h };
  221.     const RECT rDst = { dx, dy, dx+w, dy+h };
  222.     HRESULT hr = dev->StretchRect(src->mpSurface, &rSrc, mpSurface, &rDst, D3DTEXF_NONE);
  223.     if (FAILED(hr))
  224.         parent->ProcessHRESULT(hr);
  225. }
  226.  
  227. void VDTSurfaceD3D9::GetDesc(VDTSurfaceDesc& desc) {
  228.     desc = mDesc;
  229. }
  230.  
  231. bool VDTSurfaceD3D9::Lock(const vdrect32 *r, VDTLockData2D& lockData) {
  232.     if (!mpSurface)
  233.         return false;
  234.  
  235.     RECT r2;
  236.     const RECT *pr = NULL;
  237.     if (r) {
  238.         r2.left = r->left;
  239.         r2.top = r->top;
  240.         r2.right = r->right;
  241.         r2.bottom = r->bottom;
  242.         pr = &r2;
  243.     }
  244.  
  245.     D3DLOCKED_RECT lr;
  246.     HRESULT hr = mpSurface->LockRect(&lr, pr, D3DLOCK_NOSYSLOCK);
  247.     if (FAILED(hr)) {
  248.         VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  249.         parent->ProcessHRESULT(hr);
  250.         return false;
  251.     }
  252.  
  253.     lockData.mpData = lr.pBits;
  254.     lockData.mPitch = lr.Pitch;
  255.  
  256.     return true;
  257. }
  258.  
  259. void VDTSurfaceD3D9::Unlock() {
  260.     HRESULT hr = mpSurface->UnlockRect();
  261.  
  262.     if (FAILED(hr)) {
  263.         VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  264.         parent->ProcessHRESULT(hr);
  265.     }
  266. }
  267.  
  268. void VDTSurfaceD3D9::ShutdownDefaultPool() {
  269.     if (!mbDefaultPool)
  270.         return;
  271.  
  272.     if (mpSurface) {
  273.         mpSurface->Release();
  274.         mpSurface = NULL;
  275.     }
  276. }
  277.  
  278. ///////////////////////////////////////////////////////////////////////////////
  279.  
  280. VDTTexture2DD3D9::VDTTexture2DD3D9()
  281.     : mpTexture(NULL)
  282. {
  283. }
  284.  
  285. VDTTexture2DD3D9::~VDTTexture2DD3D9() {
  286.     Shutdown();
  287. }
  288.  
  289. void *VDTTexture2DD3D9::AsInterface(uint32 id) {
  290.     if (id == kTypeD3DTexture)
  291.         return mpTexture;
  292.  
  293.     if (id == IVDTTexture2D::kTypeID)
  294.         return static_cast<IVDTTexture2D *>(this);
  295.  
  296.     return NULL;
  297. }
  298.  
  299. bool VDTTexture2DD3D9::Init(VDTContextD3D9 *parent, uint32 width, uint32 height, uint32 format, uint32 mipcount, VDTUsage usage, const VDTInitData2D *initData) {
  300.     parent->AddResource(this);
  301.  
  302.     mWidth = width;
  303.     mHeight = height;
  304.     mMipCount = mipcount;
  305.     mUsage = usage;
  306.  
  307.     if (!Restore())
  308.         return false;
  309.  
  310.     uint32 mipCount = mpTexture->GetLevelCount();
  311.     mMipmaps.reserve(mipCount);
  312.  
  313.     for(uint32 i=0; i<mipCount; ++i) {
  314.         vdrefptr<VDTSurfaceD3D9> surf(new VDTSurfaceD3D9);
  315.         IDirect3DSurface9 *surfd3d9;
  316.  
  317.         HRESULT hr = mpTexture->GetSurfaceLevel(i, &surfd3d9);
  318.         if (FAILED(hr)) {
  319.             parent->ProcessHRESULT(hr);
  320.             Shutdown();
  321.             return false;
  322.         }
  323.  
  324.         surf->Init(parent, surfd3d9);
  325.         surfd3d9->Release();
  326.  
  327.         mMipmaps.push_back(surf.release());
  328.     }
  329.  
  330.     if (initData) {
  331.         D3DLOCKED_RECT lr;
  332.         HRESULT hr = mpTexture->LockRect(0, &lr, NULL, D3DLOCK_NOSYSLOCK);
  333.         if (SUCCEEDED(hr)) {
  334.             VDMemcpyRect(lr.pBits, lr.Pitch, initData->mpData, initData->mPitch, width*4, height);
  335.             mpTexture->UnlockRect(0);
  336.         }
  337.     }
  338.  
  339.     return true;
  340. }
  341.  
  342. void VDTTexture2DD3D9::Shutdown() {
  343.     while(!mMipmaps.empty()) {
  344.         VDTSurfaceD3D9 *surf = mMipmaps.back();
  345.         mMipmaps.pop_back();
  346.  
  347.         surf->Shutdown();
  348.         surf->Release();
  349.     }
  350.  
  351.     if (mpTexture) {
  352.         if (mpParent)
  353.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetTexture(this);
  354.  
  355.         mpTexture->Release();
  356.         mpTexture = NULL;
  357.     }
  358.  
  359.     VDTResourceD3D9::Shutdown();
  360. }
  361.  
  362. bool VDTTexture2DD3D9::Restore() {
  363.     if (mpTexture)
  364.         return true;
  365.  
  366.     VDTContextD3D9 *parent = static_cast<VDTContextD3D9 *>(mpParent);
  367.     IDirect3DDevice9 *dev = parent->GetDeviceD3D9();
  368.     if (!dev)
  369.         return false;
  370.  
  371.     IDirect3DTexture9 *texD3D9;
  372.     HRESULT hr;
  373.     switch(mUsage) {
  374.         case kVDTUsage_Default:
  375.             hr = dev->CreateTexture(mWidth, mHeight, mMipCount, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texD3D9, NULL);
  376.             break;
  377.  
  378.         case kVDTUsage_Render:
  379.             hr = dev->CreateTexture(mWidth, mHeight, mMipCount, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texD3D9, NULL);
  380.             break;
  381.  
  382.         default:
  383.             return false;
  384.     }
  385.     
  386.     if (FAILED(hr))
  387.         return false;
  388.  
  389.     mpTexture = texD3D9;
  390.  
  391.     uint32 n = (uint32)mMipmaps.size();
  392.     for(uint32 i=0; i<n; ++i) {
  393.         VDTSurfaceD3D9 *surf = mMipmaps[i];
  394.         IDirect3DSurface9 *surfd3d9;
  395.  
  396.         HRESULT hr = mpTexture->GetSurfaceLevel(i, &surfd3d9);
  397.         if (FAILED(hr)) {
  398.             parent->ProcessHRESULT(hr);
  399.             Shutdown();
  400.             return false;
  401.         }
  402.  
  403.         surf->Shutdown();
  404.         surf->Init(parent, surfd3d9);
  405.         surfd3d9->Release();
  406.     }
  407.  
  408.     return true;
  409. }
  410.  
  411. IVDTSurface *VDTTexture2DD3D9::GetLevelSurface(uint32 level) {
  412.     return mMipmaps[level];
  413. }
  414.  
  415. void VDTTexture2DD3D9::GetDesc(VDTTextureDesc& desc) {
  416.     desc.mWidth = mWidth;
  417.     desc.mHeight = mHeight;
  418.     desc.mMipCount = mMipCount;
  419.     desc.mFormat = 0;
  420. }
  421.  
  422. void VDTTexture2DD3D9::Load(uint32 mip, uint32 x, uint32 y, const VDTInitData2D& srcData, uint32 w, uint32 h) {
  423.     mMipmaps[mip]->Load(x, y, srcData, w, h);
  424. }
  425.  
  426. bool VDTTexture2DD3D9::Lock(uint32 mip, const vdrect32 *r, VDTLockData2D& lockData) {
  427.     return mMipmaps[mip]->Lock(r, lockData);
  428. }
  429.  
  430. void VDTTexture2DD3D9::Unlock(uint32 mip) {
  431.     mMipmaps[mip]->Unlock();
  432. }
  433.  
  434. void VDTTexture2DD3D9::ShutdownDefaultPool() {
  435.     if (mUsage != kVDTUsage_Render)
  436.         return;
  437.  
  438.     if (mpParent)
  439.         static_cast<VDTContextD3D9 *>(mpParent)->UnsetTexture(this);
  440.  
  441.     mpTexture->Release();
  442.     mpTexture = NULL;
  443. }
  444.  
  445. ///////////////////////////////////////////////////////////////////////////////
  446.  
  447. VDTVertexBufferD3D9::VDTVertexBufferD3D9()
  448.     : mpVB(NULL)
  449. {
  450. }
  451.  
  452. VDTVertexBufferD3D9::~VDTVertexBufferD3D9() {
  453.     Shutdown();
  454. }
  455.  
  456. bool VDTVertexBufferD3D9::Init(VDTContextD3D9 *parent, uint32 size, bool dynamic, const void *initData) {
  457.     parent->AddResource(this);
  458.  
  459.     mbDynamic = dynamic;
  460.     mByteSize = size;
  461.  
  462.     if (!Restore()) {
  463.         Shutdown();
  464.         return false;
  465.     }
  466.  
  467.     if (initData) {
  468.         if (!Load(0, size, initData)) {
  469.             Shutdown();
  470.             return false;
  471.         }
  472.     }
  473.  
  474.     return true;
  475. }
  476.  
  477. void VDTVertexBufferD3D9::Shutdown() {
  478.     if (mpVB) {
  479.         if (mpParent)
  480.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetVertexBuffer(this);
  481.  
  482.         mpVB->Release();
  483.         mpVB = NULL;
  484.     }
  485.  
  486.     VDTResourceD3D9::Shutdown();
  487. }
  488.  
  489. bool VDTVertexBufferD3D9::Restore() {
  490.     if (mpVB)
  491.         return true;
  492.  
  493.     IDirect3DDevice9 *dev = static_cast<VDTContextD3D9 *>(mpParent)->GetDeviceD3D9();
  494.     if (!dev)
  495.         return false;
  496.  
  497.     HRESULT hr = dev->CreateVertexBuffer(mByteSize, mbDynamic ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0, 0, mbDynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &mpVB, NULL);
  498.  
  499.     if (FAILED(hr))
  500.         return false;
  501.  
  502.     return true;
  503. }
  504.  
  505. bool VDTVertexBufferD3D9::Load(uint32 offset, uint32 size, const void *data) {
  506.     if (!size)
  507.         return true;
  508.  
  509.     if (offset > mByteSize || mByteSize - offset < size)
  510.         return false;
  511.  
  512.     DWORD flags = D3DLOCK_NOSYSLOCK;
  513.  
  514.     if (mbDynamic) {
  515.         if (offset)
  516.             flags |= D3DLOCK_NOOVERWRITE;
  517.         else
  518.             flags |= D3DLOCK_DISCARD;
  519.     }
  520.  
  521.     void *p;
  522.     HRESULT hr = mpVB->Lock(offset, size, &p, flags);
  523.     if (FAILED(hr)) {
  524.         static_cast<VDTContextD3D9 *>(mpParent)->ProcessHRESULT(hr);
  525.         return false;
  526.     }
  527.  
  528.     bool success = true;
  529.     if (mbDynamic)
  530.         success = VDMemcpyGuarded(p, data, size);
  531.     else
  532.         memcpy(p, data, size);
  533.  
  534.     hr = mpVB->Unlock();
  535.     if (FAILED(hr)) {
  536.         static_cast<VDTContextD3D9 *>(mpParent)->ProcessHRESULT(hr);
  537.         return false;
  538.     }
  539.  
  540.     return success;
  541. }
  542.  
  543. void VDTVertexBufferD3D9::ShutdownDefaultPool() {
  544.     if (!mbDynamic)
  545.         return;
  546.  
  547.     if (mpVB) {
  548.         if (mpParent)
  549.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetVertexBuffer(this);
  550.  
  551.         mpVB->Release();
  552.         mpVB = NULL;
  553.     }
  554. }
  555.  
  556. ///////////////////////////////////////////////////////////////////////////////
  557.  
  558. VDTIndexBufferD3D9::VDTIndexBufferD3D9()
  559.     : mpIB(NULL)
  560. {
  561. }
  562.  
  563. VDTIndexBufferD3D9::~VDTIndexBufferD3D9() {
  564.     Shutdown();
  565. }
  566.  
  567. bool VDTIndexBufferD3D9::Init(VDTContextD3D9 *parent, uint32 size, bool index32, bool dynamic, const void *initData) {
  568.     parent->AddResource(this);
  569.  
  570.     mByteSize = index32 ? size << 2 : size << 1;
  571.     mbDynamic = dynamic;
  572.     mbIndex32 = index32;
  573.  
  574.     if (!Restore()) {
  575.         Shutdown();
  576.         return false;
  577.     }
  578.  
  579.     if (initData) {
  580.         if (!Load(0, mByteSize, initData)) {
  581.             Shutdown();
  582.             return false;
  583.         }
  584.     }
  585.  
  586.  
  587.     return true;
  588. }
  589.  
  590. void VDTIndexBufferD3D9::Shutdown() {
  591.     if (mpIB) {
  592.         if (mpParent)
  593.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetIndexBuffer(this);
  594.  
  595.         mpIB->Release();
  596.         mpIB = NULL;
  597.     }
  598.  
  599.     VDTResourceD3D9::Shutdown();
  600. }
  601.  
  602. bool VDTIndexBufferD3D9::Restore() {
  603.     if (mpIB)
  604.         return true;
  605.  
  606.     IDirect3DDevice9 *dev = static_cast<VDTContextD3D9 *>(mpParent)->GetDeviceD3D9();
  607.     if (!dev)
  608.         return false;
  609.  
  610.     HRESULT hr = dev->CreateIndexBuffer(mByteSize, mbDynamic ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0, mbIndex32 ? D3DFMT_INDEX32 : D3DFMT_INDEX16, mbDynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &mpIB, NULL);
  611.  
  612.     if (FAILED(hr))
  613.         return false;
  614.  
  615.     return true;
  616. }
  617.  
  618. bool VDTIndexBufferD3D9::Load(uint32 offset, uint32 size, const void *data) {
  619.     if (!size)
  620.         return true;
  621.  
  622.     void *p;
  623.     HRESULT hr = mpIB->Lock(offset, size, &p, D3DLOCK_NOSYSLOCK);
  624.     if (FAILED(hr)) {
  625.         static_cast<VDTContextD3D9 *>(mpParent)->ProcessHRESULT(hr);
  626.         return false;
  627.     }
  628.  
  629.     bool success = true;
  630.     if (mbDynamic)
  631.         success = VDMemcpyGuarded(p, data, size);
  632.     else
  633.         memcpy(p, data, size);
  634.  
  635.     hr = mpIB->Unlock();
  636.     if (FAILED(hr)) {
  637.         static_cast<VDTContextD3D9 *>(mpParent)->ProcessHRESULT(hr);
  638.         return false;
  639.     }
  640.  
  641.     return success;
  642. }
  643.  
  644. void VDTIndexBufferD3D9::ShutdownDefaultPool() {
  645.     if (!mbDynamic)
  646.         return;
  647.  
  648.     if (mpIB) {
  649.         if (mpParent)
  650.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetIndexBuffer(this);
  651.  
  652.         mpIB->Release();
  653.         mpIB = NULL;
  654.     }
  655. }
  656.  
  657. ///////////////////////////////////////////////////////////////////////////////
  658.  
  659. VDTVertexFormatD3D9::VDTVertexFormatD3D9()
  660.     : mpVF(NULL)
  661. {
  662. }
  663.  
  664. VDTVertexFormatD3D9::~VDTVertexFormatD3D9() {
  665.     Shutdown();
  666. }
  667.  
  668. bool VDTVertexFormatD3D9::Init(VDTContextD3D9 *parent, const VDTVertexElement *elements, uint32 count) {
  669.     static const D3DDECLUSAGE kUsageD3D9[]={
  670.         D3DDECLUSAGE_POSITION,
  671.         D3DDECLUSAGE_BLENDWEIGHT,
  672.         D3DDECLUSAGE_BLENDINDICES,
  673.         D3DDECLUSAGE_NORMAL,
  674.         D3DDECLUSAGE_TEXCOORD,
  675.         D3DDECLUSAGE_TANGENT,
  676.         D3DDECLUSAGE_BINORMAL,
  677.         D3DDECLUSAGE_COLOR
  678.     };
  679.  
  680.     static const D3DDECLTYPE kTypeD3D9[]={
  681.         D3DDECLTYPE_FLOAT1,
  682.         D3DDECLTYPE_FLOAT2,
  683.         D3DDECLTYPE_FLOAT3,
  684.         D3DDECLTYPE_FLOAT4,
  685.         D3DDECLTYPE_UBYTE4
  686.     };
  687.  
  688.     if (count >= 16) {
  689.         VDASSERT(!"Too many vertex elements.");
  690.         return false;
  691.     }
  692.  
  693.     D3DVERTEXELEMENT9 vxe[16];
  694.     for(uint32 i=0; i<count; ++i) {
  695.         D3DVERTEXELEMENT9& dst = vxe[i];
  696.         const VDTVertexElement& src = elements[i];
  697.  
  698.         dst.Stream = 0;
  699.         dst.Offset = src.mOffset;
  700.         dst.Type = kTypeD3D9[src.mType];
  701.         dst.Method = D3DDECLMETHOD_DEFAULT;
  702.         dst.Usage = kUsageD3D9[src.mUsage];
  703.         dst.UsageIndex = src.mUsageIndex;
  704.     }
  705.  
  706.     memset(&vxe[count], 0, sizeof(vxe[count]));
  707.     vxe[count].Stream = 0xFF;
  708.     vxe[count].Type = D3DDECLTYPE_UNUSED;
  709.  
  710.     HRESULT hr = parent->GetDeviceD3D9()->CreateVertexDeclaration(vxe, &mpVF);
  711.  
  712.     if (FAILED(hr))
  713.         return false;
  714.  
  715.     parent->AddResource(this);
  716.     return true;
  717. }
  718.  
  719. void VDTVertexFormatD3D9::Shutdown() {
  720.     if (mpVF) {
  721.         if (mpParent)
  722.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetVertexFormat(this);
  723.  
  724.         mpVF->Release();
  725.         mpVF = NULL;
  726.     }
  727.  
  728.     VDTResourceD3D9::Shutdown();
  729. }
  730.  
  731. bool VDTVertexFormatD3D9::Restore() {
  732.     return true;
  733. }
  734.  
  735. ///////////////////////////////////////////////////////////////////////////////
  736.  
  737. VDTVertexProgramD3D9::VDTVertexProgramD3D9()
  738.     : mpVS(NULL)
  739. {
  740. }
  741.  
  742. VDTVertexProgramD3D9::~VDTVertexProgramD3D9() {
  743.     Shutdown();
  744. }
  745.  
  746. bool VDTVertexProgramD3D9::Init(VDTContextD3D9 *parent, VDTProgramFormat format, const void *data, uint32 size) {
  747.     HRESULT hr = parent->GetDeviceD3D9()->CreateVertexShader((const DWORD *)data, &mpVS);
  748.  
  749.     if (FAILED(hr))
  750.         return false;
  751.  
  752.     parent->AddResource(this);
  753.     return true;
  754. }
  755.  
  756. void VDTVertexProgramD3D9::Shutdown() {
  757.     if (mpVS) {
  758.         if (mpParent)
  759.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetVertexProgram(this);
  760.  
  761.         mpVS->Release();
  762.         mpVS = NULL;
  763.     }
  764.  
  765.     VDTResourceD3D9::Shutdown();
  766. }
  767.  
  768. bool VDTVertexProgramD3D9::Restore() {
  769.     return true;
  770. }
  771.  
  772. ///////////////////////////////////////////////////////////////////////////////
  773.  
  774. VDTFragmentProgramD3D9::VDTFragmentProgramD3D9()
  775.     : mpPS(NULL)
  776. {
  777. }
  778.  
  779. VDTFragmentProgramD3D9::~VDTFragmentProgramD3D9() {
  780.     Shutdown();
  781. }
  782.  
  783. bool VDTFragmentProgramD3D9::Init(VDTContextD3D9 *parent, VDTProgramFormat format, const void *data, uint32 size) {
  784.     HRESULT hr = parent->GetDeviceD3D9()->CreatePixelShader((const DWORD *)data, &mpPS);
  785.  
  786.     if (FAILED(hr))
  787.         return false;
  788.  
  789.     parent->AddResource(this);
  790.     return true;
  791. }
  792.  
  793. void VDTFragmentProgramD3D9::Shutdown() {
  794.     if (mpPS) {
  795.         if (mpParent)
  796.             static_cast<VDTContextD3D9 *>(mpParent)->UnsetFragmentProgram(this);
  797.  
  798.         mpPS->Release();
  799.         mpPS = NULL;
  800.     }
  801.  
  802.     VDTResourceD3D9::Shutdown();
  803. }
  804.  
  805. bool VDTFragmentProgramD3D9::Restore() {
  806.     return true;
  807. }
  808.  
  809. ///////////////////////////////////////////////////////////////////////////////
  810.  
  811. VDTBlendStateD3D9::VDTBlendStateD3D9() {
  812. }
  813.  
  814. VDTBlendStateD3D9::~VDTBlendStateD3D9() {
  815.     Shutdown();
  816. }
  817.  
  818. bool VDTBlendStateD3D9::Init(VDTContextD3D9 *parent, const VDTBlendStateDesc& desc) {
  819.     mDesc = desc;
  820.  
  821.     static const uint32 kD3DBlendStateLookup[]={
  822.         D3DBLEND_ZERO,
  823.         D3DBLEND_ONE,
  824.         D3DBLEND_SRCCOLOR,
  825.         D3DBLEND_INVSRCCOLOR,
  826.         D3DBLEND_SRCALPHA,
  827.         D3DBLEND_INVSRCALPHA,
  828.         D3DBLEND_DESTALPHA,
  829.         D3DBLEND_INVDESTALPHA,
  830.         D3DBLEND_DESTCOLOR,
  831.         D3DBLEND_INVDESTCOLOR
  832.     };
  833.  
  834.     static const uint32 kD3DBlendOpLookup[]={
  835.         D3DBLENDOP_ADD,
  836.         D3DBLENDOP_SUBTRACT,
  837.         D3DBLENDOP_REVSUBTRACT,
  838.         D3DBLENDOP_MIN,
  839.         D3DBLENDOP_MAX
  840.     };
  841.  
  842.     mRenderStates[0] = desc.mbEnable;
  843.     mRenderStates[1] = kD3DBlendStateLookup[desc.mSrc];
  844.     mRenderStates[2] = kD3DBlendStateLookup[desc.mDst];
  845.     mRenderStates[3] = kD3DBlendOpLookup[desc.mOp];
  846.  
  847.     parent->AddResource(this);
  848.     return true;
  849. }
  850.  
  851. void VDTBlendStateD3D9::Shutdown() {
  852.     if (mpParent)
  853.         static_cast<VDTContextD3D9 *>(mpParent)->UnsetBlendState(this);
  854.  
  855.     VDTResourceD3D9::Shutdown();
  856. }
  857.  
  858. bool VDTBlendStateD3D9::Restore() {
  859.     return true;
  860. }
  861.  
  862. const uint32 VDTBlendStateD3D9::kRenderStateIDs[kStateCount]={
  863.     D3DRS_ALPHABLENDENABLE,
  864.     D3DRS_SRCBLEND,
  865.     D3DRS_DESTBLEND,
  866.     D3DRS_BLENDOP
  867. };
  868.  
  869. ///////////////////////////////////////////////////////////////////////////////
  870.  
  871. VDTRasterizerStateD3D9::VDTRasterizerStateD3D9() {
  872. }
  873.  
  874. VDTRasterizerStateD3D9::~VDTRasterizerStateD3D9() {
  875.     Shutdown();
  876. }
  877.  
  878. bool VDTRasterizerStateD3D9::Init(VDTContextD3D9 *parent, const VDTRasterizerStateDesc& desc) {
  879.     mDesc = desc;
  880.  
  881.     parent->AddResource(this);
  882.  
  883.     if (desc.mCullMode == kVDTCull_None) {
  884.         mRenderStates[0] = D3DCULL_NONE;
  885.     } else {
  886.         bool cullCW = desc.mbFrontIsCCW;
  887.  
  888.         if (desc.mCullMode == kVDTCull_Back)
  889.             cullCW = !cullCW;
  890.  
  891.         if (cullCW)
  892.             mRenderStates[0] = D3DCULL_CW;
  893.         else
  894.             mRenderStates[0] = D3DCULL_CCW;
  895.     }
  896.  
  897.     mRenderStates[1] = desc.mbEnableScissor;
  898.  
  899.     return true;
  900. }
  901.  
  902. void VDTRasterizerStateD3D9::Shutdown() {
  903.     if (mpParent)
  904.         static_cast<VDTContextD3D9 *>(mpParent)->UnsetRasterizerState(this);
  905.  
  906.     VDTResourceD3D9::Shutdown();
  907. }
  908.  
  909. bool VDTRasterizerStateD3D9::Restore() {
  910.     return true;
  911. }
  912.  
  913. const uint32 VDTRasterizerStateD3D9::kRenderStateIDs[kStateCount]={
  914.     D3DRS_CULLMODE,
  915.     D3DRS_SCISSORTESTENABLE
  916. };
  917.  
  918. ///////////////////////////////////////////////////////////////////////////////
  919.  
  920. VDTSamplerStateD3D9::VDTSamplerStateD3D9() {
  921. }
  922.  
  923. VDTSamplerStateD3D9::~VDTSamplerStateD3D9() {
  924.     Shutdown();
  925. }
  926.  
  927. bool VDTSamplerStateD3D9::Init(VDTContextD3D9 *parent, const VDTSamplerStateDesc& desc) {
  928.     mDesc = desc;
  929.  
  930.     static const uint32 kD3DMinMagFilterLookup[]={
  931.         D3DTEXF_POINT,
  932.         D3DTEXF_LINEAR,
  933.         D3DTEXF_LINEAR,
  934.         D3DTEXF_LINEAR,
  935.         D3DTEXF_ANISOTROPIC
  936.     };
  937.  
  938.     static const uint32 kD3DMipFilterLookup[]={
  939.         D3DTEXF_NONE,
  940.         D3DTEXF_NONE,
  941.         D3DTEXF_POINT,
  942.         D3DTEXF_LINEAR,
  943.         D3DTEXF_ANISOTROPIC
  944.     };
  945.  
  946.     static const uint32 kD3DAddressLookup[]={
  947.         D3DTADDRESS_CLAMP,
  948.         D3DTADDRESS_WRAP
  949.     };
  950.  
  951.     mSamplerStates[0] = kD3DMinMagFilterLookup[desc.mFilterMode];
  952.     mSamplerStates[1] = kD3DMinMagFilterLookup[desc.mFilterMode];
  953.     mSamplerStates[2] = kD3DMipFilterLookup[desc.mFilterMode];
  954.     mSamplerStates[3] = kD3DAddressLookup[desc.mAddressU];
  955.     mSamplerStates[4] = kD3DAddressLookup[desc.mAddressV];
  956.     mSamplerStates[5] = kD3DAddressLookup[desc.mAddressW];
  957.  
  958.     parent->AddResource(this);
  959.     return true;
  960. }
  961.  
  962. void VDTSamplerStateD3D9::Shutdown() {
  963.     if (mpParent)
  964.         static_cast<VDTContextD3D9 *>(mpParent)->UnsetSamplerState(this);
  965.  
  966.     VDTResourceD3D9::Shutdown();
  967. }
  968.  
  969. bool VDTSamplerStateD3D9::Restore() {
  970.     return true;
  971. }
  972.  
  973. const uint32 VDTSamplerStateD3D9::kSamplerStateIDs[kStateCount] = {
  974.     D3DSAMP_MINFILTER,
  975.     D3DSAMP_MAGFILTER,
  976.     D3DSAMP_MIPFILTER,
  977.     D3DSAMP_ADDRESSU,
  978.     D3DSAMP_ADDRESSV,
  979.     D3DSAMP_ADDRESSW
  980. };
  981.  
  982. ///////////////////////////////////////////////////////////////////////////////
  983.  
  984. struct VDTContextD3D9::PrivateData {
  985.     D3DPRESENT_PARAMETERS mPresentParms;
  986.     HMODULE mhmodD3D9;
  987.  
  988.     VDTFenceManagerD3D9 mFenceManager;
  989. };
  990.  
  991. VDTContextD3D9::VDTContextD3D9()
  992.     : mRefCount(0)
  993.     , mpData(NULL)
  994.     , mpD3DHolder(NULL)
  995.     , mpD3DDevice(NULL)
  996.     , mDeviceLossCounter(0)
  997.     , mbDeviceLost(false)
  998.     , mbInScene(false)
  999.     , mpCurrentRT(NULL)
  1000.     , mpCurrentVB(NULL)
  1001.     , mCurrentVBOffset(NULL)
  1002.     , mCurrentVBStride(NULL)
  1003.     , mpCurrentIB(NULL)
  1004.     , mpCurrentVP(NULL)
  1005.     , mpCurrentFP(NULL)
  1006.     , mpCurrentVF(NULL)
  1007.     , mpCurrentBS(NULL)
  1008.     , mpCurrentRS(NULL)
  1009.     , mpDefaultRT(NULL)
  1010.     , mpDefaultBS(NULL)
  1011.     , mpDefaultRS(NULL)
  1012.     , mpDefaultSS(NULL)
  1013.     , mDirtySamplerStates(0)
  1014.     , mProfChan("Filter 3D accel")
  1015. {
  1016.     memset(mpCurrentSamplerStates, 0, sizeof mpCurrentSamplerStates);
  1017.     memset(mpCurrentTextures, 0, sizeof mpCurrentTextures);
  1018. }
  1019.  
  1020. VDTContextD3D9::~VDTContextD3D9() {
  1021.     Shutdown();
  1022. }
  1023.  
  1024. int VDTContextD3D9::AddRef() {
  1025.     return ++mRefCount;
  1026. }
  1027.  
  1028. int VDTContextD3D9::Release() {
  1029.     int rc = --mRefCount;
  1030.  
  1031.     if (!rc)
  1032.         delete this;
  1033.  
  1034.     return rc;
  1035. }
  1036.  
  1037. void *VDTContextD3D9::AsInterface(uint32 iid) {
  1038.     if (iid == IVDTProfiler::kTypeID)
  1039.         return static_cast<IVDTProfiler *>(this);
  1040.  
  1041.     return NULL;
  1042. }
  1043.  
  1044. bool VDTContextD3D9::Init(IDirect3DDevice9 *dev, IVDRefUnknown *pD3DHolder) {
  1045.     mpData = new PrivateData;
  1046.     mpData->mhmodD3D9 = LoadLibrary("d3d9");
  1047.  
  1048.     if (mpData->mhmodD3D9) {
  1049.         mpBeginEvent = GetProcAddress(mpData->mhmodD3D9, "D3DPERF_BeginEvent");
  1050.         mpEndEvent = GetProcAddress(mpData->mhmodD3D9, "D3DPERF_EndEvent");
  1051.     }
  1052.  
  1053.     mpD3DHolder = pD3DHolder;
  1054.     if (mpD3DHolder)
  1055.         mpD3DHolder->AddRef();
  1056.  
  1057.     mpD3DDevice = dev;
  1058.     mpD3DDevice->AddRef();
  1059.  
  1060.     mpData->mFenceManager.Init(mpD3DDevice);
  1061.  
  1062.     vdrefptr<IDirect3DSwapChain9> chain;
  1063.     HRESULT hr = mpD3DDevice->GetSwapChain(0, ~chain);
  1064.     if (FAILED(hr)) {
  1065.         Shutdown();
  1066.         return false;
  1067.     }
  1068.  
  1069.     hr = chain->GetPresentParameters(&mpData->mPresentParms);
  1070.     if (FAILED(hr)) {
  1071.         Shutdown();
  1072.         return false;
  1073.     }
  1074.  
  1075.     mpDefaultBS = new VDTBlendStateD3D9;
  1076.     mpDefaultBS->AddRef();
  1077.     mpDefaultBS->Init(this, VDTBlendStateDesc());
  1078.  
  1079.     mpDefaultRS = new VDTRasterizerStateD3D9;
  1080.     mpDefaultRS->AddRef();
  1081.     mpDefaultRS->Init(this, VDTRasterizerStateDesc());
  1082.  
  1083.     mpDefaultSS = new VDTSamplerStateD3D9;
  1084.     mpDefaultSS->AddRef();
  1085.     mpDefaultSS->Init(this, VDTSamplerStateDesc());
  1086.  
  1087.     mpDefaultRT = new VDTSurfaceD3D9;
  1088.     mpDefaultRT->AddRef();
  1089.  
  1090.     mpCurrentBS = mpDefaultBS;
  1091.     mpCurrentRS = mpDefaultRS;
  1092.     mpCurrentRT = mpDefaultRT;
  1093.  
  1094.     for(int i=0; i<16; ++i)
  1095.         mpCurrentSamplerStates[i] = mpDefaultSS;
  1096.  
  1097.     mbBSDirty = true;
  1098.     mbRSDirty = true;
  1099.     mDirtySamplerStates = 0xffff;
  1100.     memset(mD3DBlendStates, 0xA5, sizeof mD3DBlendStates);
  1101.     memset(mD3DRasterizerStates, 0xA5, sizeof mD3DRasterizerStates);
  1102.     memset(mD3DSamplerStates, 0xA5, sizeof mD3DSamplerStates);
  1103.  
  1104.     if (!ConnectSurfaces()) {
  1105.         Shutdown();
  1106.         return false;
  1107.     }
  1108.  
  1109.     return true;
  1110. }
  1111.  
  1112. void VDTContextD3D9::Shutdown() {
  1113.     ShutdownAllResources();
  1114.  
  1115.     if (mpDefaultSS) {
  1116.         mpDefaultSS->Release();
  1117.         mpDefaultSS = NULL;
  1118.     }
  1119.  
  1120.     if (mpDefaultRS) {
  1121.         mpDefaultRS->Release();
  1122.         mpDefaultRS = NULL;
  1123.     }
  1124.  
  1125.     if (mpDefaultBS) {
  1126.         mpDefaultBS->Release();
  1127.         mpDefaultBS = NULL;
  1128.     }
  1129.  
  1130.     if (mpDefaultRT) {
  1131.         mpDefaultRT->Release();
  1132.         mpDefaultRT = NULL;
  1133.     }
  1134.  
  1135.     mpData->mFenceManager.Shutdown();
  1136.  
  1137.     if (mpD3DDevice) {
  1138.         mpD3DDevice->Release();
  1139.         mpD3DDevice = NULL;
  1140.     }
  1141.  
  1142.     if (mpD3DHolder) {
  1143.         mpD3DHolder->Release();
  1144.         mpD3DHolder = NULL;
  1145.     }
  1146.  
  1147.     if (mpData) {
  1148.         if (mpData->mhmodD3D9)
  1149.             FreeLibrary(mpData->mhmodD3D9);
  1150.  
  1151.         delete mpData;
  1152.         mpData = NULL;
  1153.     }
  1154.  
  1155.     mpBeginEvent = NULL;
  1156.     mpEndEvent = NULL;
  1157. }
  1158.  
  1159. bool VDTContextD3D9::CreateReadbackBuffer(uint32 width, uint32 height, uint32 format, IVDTReadbackBuffer **ppbuffer) {
  1160.     vdrefptr<VDTReadbackBufferD3D9> surf(new VDTReadbackBufferD3D9);
  1161.  
  1162.     if (!surf->Init(this, width, height, format))
  1163.         return false;
  1164.  
  1165.     *ppbuffer = surf.release();
  1166.     return true;
  1167. }
  1168.  
  1169. bool VDTContextD3D9::CreateSurface(uint32 width, uint32 height, uint32 format, VDTUsage usage, IVDTSurface **ppsurface) {
  1170.     vdrefptr<VDTSurfaceD3D9> surf(new VDTSurfaceD3D9);
  1171.  
  1172.     if (!surf->Init(this, width, height, format, usage))
  1173.         return false;
  1174.  
  1175.     *ppsurface = surf.release();
  1176.     return true;
  1177. }
  1178.  
  1179. bool VDTContextD3D9::CreateTexture2D(uint32 width, uint32 height, uint32 format, uint32 mipcount, VDTUsage usage, const VDTInitData2D *initData, IVDTTexture2D **pptex) {
  1180.     vdrefptr<VDTTexture2DD3D9> tex(new VDTTexture2DD3D9);
  1181.  
  1182.     if (!tex->Init(this, width, height, format, mipcount, usage, initData))
  1183.         return false;
  1184.  
  1185.     *pptex = tex.release();
  1186.     return true;
  1187. }
  1188.  
  1189. bool VDTContextD3D9::CreateVertexProgram(VDTProgramFormat format, const void *data, uint32 length, IVDTVertexProgram **program) {
  1190.     vdrefptr<VDTVertexProgramD3D9> vp(new VDTVertexProgramD3D9);
  1191.  
  1192.     if (!vp->Init(this, format, data, length))
  1193.         return false;
  1194.  
  1195.     *program = vp.release();
  1196.     return true;
  1197. }
  1198.  
  1199. bool VDTContextD3D9::CreateFragmentProgram(VDTProgramFormat format, const void *data, uint32 length, IVDTFragmentProgram **program) {
  1200.     vdrefptr<VDTFragmentProgramD3D9> fp(new VDTFragmentProgramD3D9);
  1201.  
  1202.     if (!fp->Init(this, format, data, length))
  1203.         return false;
  1204.  
  1205.     *program = fp.release();
  1206.     return true;
  1207. }
  1208.  
  1209. bool VDTContextD3D9::CreateVertexFormat(const VDTVertexElement *elements, uint32 count, IVDTVertexFormat **format) {
  1210.     vdrefptr<VDTVertexFormatD3D9> vf(new VDTVertexFormatD3D9);
  1211.  
  1212.     if (!vf->Init(this, elements, count))
  1213.         return false;
  1214.  
  1215.     *format = vf.release();
  1216.     return true;
  1217. }
  1218.  
  1219. bool VDTContextD3D9::CreateVertexBuffer(uint32 size, bool dynamic, const void *initData, IVDTVertexBuffer **ppbuffer) {
  1220.     vdrefptr<VDTVertexBufferD3D9> vb(new VDTVertexBufferD3D9);
  1221.  
  1222.     if (!vb->Init(this, size, dynamic, initData))
  1223.         return false;
  1224.  
  1225.     *ppbuffer = vb.release();
  1226.     return true;
  1227. }
  1228.  
  1229. bool VDTContextD3D9::CreateIndexBuffer(uint32 size, bool index32, bool dynamic, const void *initData, IVDTIndexBuffer **ppbuffer) {
  1230.     vdrefptr<VDTIndexBufferD3D9> ib(new VDTIndexBufferD3D9);
  1231.  
  1232.     if (!ib->Init(this, size, index32, dynamic, initData))
  1233.         return false;
  1234.  
  1235.     *ppbuffer = ib.release();
  1236.     return true;
  1237. }
  1238.  
  1239. bool VDTContextD3D9::CreateBlendState(const VDTBlendStateDesc& desc, IVDTBlendState **state) {
  1240.     vdrefptr<VDTBlendStateD3D9> bs(new VDTBlendStateD3D9);
  1241.  
  1242.     if (!bs->Init(this, desc))
  1243.         return false;
  1244.  
  1245.     *state = bs.release();
  1246.     return true;
  1247. }
  1248.  
  1249. bool VDTContextD3D9::CreateRasterizerState(const VDTRasterizerStateDesc& desc, IVDTRasterizerState **state) {
  1250.     vdrefptr<VDTRasterizerStateD3D9> rs(new VDTRasterizerStateD3D9);
  1251.  
  1252.     if (!rs->Init(this, desc))
  1253.         return false;
  1254.  
  1255.     *state = rs.release();
  1256.     return true;
  1257. }
  1258.  
  1259. bool VDTContextD3D9::CreateSamplerState(const VDTSamplerStateDesc& desc, IVDTSamplerState **state) {
  1260.     vdrefptr<VDTSamplerStateD3D9> ss(new VDTSamplerStateD3D9);
  1261.  
  1262.     if (!ss->Init(this, desc))
  1263.         return false;
  1264.  
  1265.     *state = ss.release();
  1266.     return true;
  1267. }
  1268.  
  1269. IVDTSurface *VDTContextD3D9::GetRenderTarget(uint32 index) const {
  1270.     return index ? NULL : mpCurrentRT;
  1271. }
  1272.  
  1273. void VDTContextD3D9::SetVertexFormat(IVDTVertexFormat *format) {
  1274.     if (format == mpCurrentVF)
  1275.         return;
  1276.  
  1277.     mpCurrentVF = static_cast<VDTVertexFormatD3D9 *>(format);
  1278.  
  1279.     HRESULT hr = mpD3DDevice->SetVertexDeclaration(mpCurrentVF ? mpCurrentVF->mpVF : NULL);
  1280.     if (FAILED(hr))
  1281.         ProcessHRESULT(hr);
  1282. }
  1283.  
  1284. void VDTContextD3D9::SetVertexProgram(IVDTVertexProgram *program) {
  1285.     if (program == mpCurrentVP)
  1286.         return;
  1287.  
  1288.     mpCurrentVP = static_cast<VDTVertexProgramD3D9 *>(program);
  1289.  
  1290.     HRESULT hr = mpD3DDevice->SetVertexShader(mpCurrentVP ? mpCurrentVP->mpVS : NULL);
  1291.     if (FAILED(hr))
  1292.         ProcessHRESULT(hr);
  1293. }
  1294.  
  1295. void VDTContextD3D9::SetFragmentProgram(IVDTFragmentProgram *program) {
  1296.     if (program == mpCurrentFP)
  1297.         return;
  1298.  
  1299.     mpCurrentFP = static_cast<VDTFragmentProgramD3D9 *>(program);
  1300.  
  1301.     HRESULT hr = mpD3DDevice->SetPixelShader(mpCurrentFP ? mpCurrentFP->mpPS : NULL);
  1302.     if (FAILED(hr))
  1303.         ProcessHRESULT(hr);
  1304. }
  1305.  
  1306. void VDTContextD3D9::SetVertexStream(uint32 index, IVDTVertexBuffer *buffer, uint32 offset, uint32 stride) {
  1307.     VDASSERT(index == 0);
  1308.  
  1309.     if (buffer == mpCurrentVB && offset == mCurrentVBOffset && offset == mCurrentVBStride)
  1310.         return;
  1311.  
  1312.     mpCurrentVB = static_cast<VDTVertexBufferD3D9 *>(buffer);
  1313.     mCurrentVBOffset = offset;
  1314.     mCurrentVBStride = stride;
  1315.  
  1316.     HRESULT hr = mpD3DDevice->SetStreamSource(0, mpCurrentVB ? mpCurrentVB->mpVB : NULL, offset, stride);
  1317.     if (FAILED(hr))
  1318.         ProcessHRESULT(hr);
  1319. }
  1320.  
  1321. void VDTContextD3D9::SetIndexStream(IVDTIndexBuffer *buffer) {
  1322.     if (buffer == mpCurrentIB)
  1323.         return;
  1324.  
  1325.     mpCurrentIB = static_cast<VDTIndexBufferD3D9 *>(buffer);
  1326.  
  1327.     HRESULT hr = mpD3DDevice->SetIndices(mpCurrentIB ? mpCurrentIB->mpIB : NULL);
  1328.     if (FAILED(hr))
  1329.         ProcessHRESULT(hr);
  1330. }
  1331.  
  1332. void VDTContextD3D9::SetRenderTarget(uint32 index, IVDTSurface *surface) {
  1333.     VDASSERT(index == 0);
  1334.  
  1335.     if (!index && !surface)
  1336.         surface = mpDefaultRT;
  1337.  
  1338.     if (mpCurrentRT == surface)
  1339.         return;
  1340.  
  1341.     mpCurrentRT = static_cast<VDTSurfaceD3D9 *>(surface);
  1342.  
  1343.     IDirect3DSurface9 *surf = NULL;
  1344.     if (mpCurrentRT)
  1345.         surf = mpCurrentRT->mpSurface;
  1346.  
  1347.     HRESULT hr = mpD3DDevice->SetRenderTarget(0, surf);
  1348.  
  1349.     if (FAILED(hr))
  1350.         ProcessHRESULT(hr);
  1351. }
  1352.  
  1353. void VDTContextD3D9::SetBlendState(IVDTBlendState *state) {
  1354.     if (!state)
  1355.         state = mpDefaultBS;
  1356.  
  1357.     if (mpCurrentBS == state)
  1358.         return;
  1359.  
  1360.     mpCurrentBS = static_cast<VDTBlendStateD3D9 *>(state);
  1361.     mbBSDirty = true;
  1362. }
  1363.  
  1364. void VDTContextD3D9::SetRasterizerState(IVDTRasterizerState *state) {
  1365.     if (!state)
  1366.         state = mpDefaultRS;
  1367.  
  1368.     if (mpCurrentRS == state)
  1369.         return;
  1370.  
  1371.     mpCurrentRS = static_cast<VDTRasterizerStateD3D9 *>(state);
  1372.     mbRSDirty = true;
  1373. }
  1374.  
  1375. void VDTContextD3D9::SetSamplerStates(uint32 baseIndex, uint32 count, IVDTSamplerState *const *states) {
  1376.     VDASSERT(baseIndex <= 16 && 16 - baseIndex >= count);
  1377.  
  1378.     for(uint32 i=0; i<count; ++i) {
  1379.         uint32 stage = baseIndex + i;
  1380.         VDTSamplerStateD3D9 *state = static_cast<VDTSamplerStateD3D9 *>(states[stage]);
  1381.         if (!state)
  1382.             state = mpDefaultSS;
  1383.  
  1384.         if (mpCurrentSamplerStates[stage] != state) {
  1385.             mpCurrentSamplerStates[stage] = state;
  1386.             mDirtySamplerStates |= 1 << stage;
  1387.         }
  1388.     }
  1389. }
  1390.  
  1391. void VDTContextD3D9::SetTextures(uint32 baseIndex, uint32 count, IVDTTexture *const *textures) {
  1392.     VDASSERT(baseIndex <= 16 && 16 - baseIndex >= count);
  1393.  
  1394.     for(uint32 i=0; i<count; ++i) {
  1395.         uint32 stage = baseIndex + i;
  1396.         IVDTTexture *tex = textures[i];
  1397.  
  1398.         if (mpCurrentTextures[stage] != tex) {
  1399.             mpCurrentTextures[stage] = tex;
  1400.  
  1401.             HRESULT hr = mpD3DDevice->SetTexture(stage, tex ? (IDirect3DBaseTexture9 *)tex->AsInterface(VDTTextureD3D9::kTypeD3DTexture) : NULL);
  1402.             if (FAILED(hr)) {
  1403.                 ProcessHRESULT(hr);
  1404.                 break;
  1405.             }
  1406.         }
  1407.     }
  1408. }
  1409.  
  1410. void VDTContextD3D9::SetVertexProgramConstF(uint32 baseIndex, uint32 count, const float *data) {
  1411.     HRESULT hr = mpD3DDevice->SetVertexShaderConstantF(baseIndex, data, count);
  1412.     if (FAILED(hr))
  1413.         ProcessHRESULT(hr);
  1414. }
  1415.  
  1416. void VDTContextD3D9::SetFragmentProgramConstF(uint32 baseIndex, uint32 count, const float *data) {
  1417.     HRESULT hr = mpD3DDevice->SetPixelShaderConstantF(baseIndex, data, count);
  1418.     if (FAILED(hr))
  1419.         ProcessHRESULT(hr);
  1420. }
  1421.  
  1422. void VDTContextD3D9::Clear(VDTClearFlags clearFlags, uint32 color, float depth, uint32 stencil) {
  1423.     DWORD flags = 0;
  1424.  
  1425.     if (clearFlags & kVDTClear_Color)
  1426.         flags |= D3DCLEAR_TARGET;
  1427.  
  1428.     if (clearFlags & kVDTClear_Depth)
  1429.         flags |= D3DCLEAR_ZBUFFER;
  1430.  
  1431.     if (clearFlags & kVDTClear_Stencil)
  1432.         flags |= D3DCLEAR_STENCIL;
  1433.  
  1434.     if (flags) {
  1435.         HRESULT hr = mpD3DDevice->Clear(0, NULL, flags, color, depth, stencil);
  1436.         if (FAILED(hr))
  1437.             ProcessHRESULT(hr);
  1438.     }
  1439. }
  1440.  
  1441. namespace {
  1442.     const D3DPRIMITIVETYPE kPTLookup[]={
  1443.         D3DPT_TRIANGLELIST,
  1444.         D3DPT_TRIANGLESTRIP,
  1445.         D3DPT_TRIANGLEFAN
  1446.     };
  1447. }
  1448.  
  1449. void VDTContextD3D9::DrawPrimitive(VDTPrimitiveType type, uint32 startVertex, uint32 primitiveCount) {
  1450.     if (!mbInScene && !OpenScene())
  1451.         return;
  1452.  
  1453.     if (!CommitState())
  1454.         return;
  1455.  
  1456.     HRESULT hr = mpD3DDevice->DrawPrimitive(kPTLookup[type], startVertex, primitiveCount);
  1457.     if (FAILED(hr))
  1458.         ProcessHRESULT(hr);
  1459. }
  1460.  
  1461. void VDTContextD3D9::DrawIndexedPrimitive(VDTPrimitiveType type, uint32 baseVertexIndex, uint32 minVertex, uint32 vertexCount, uint32 startIndex, uint32 primitiveCount) {
  1462.     if (!mbInScene && !OpenScene())
  1463.         return;
  1464.  
  1465.     if (!CommitState())
  1466.         return;
  1467.  
  1468.     HRESULT hr = mpD3DDevice->DrawIndexedPrimitive(kPTLookup[type], baseVertexIndex, minVertex, vertexCount, startIndex, primitiveCount);
  1469.     if (FAILED(hr))
  1470.         ProcessHRESULT(hr);
  1471. }
  1472.  
  1473. uint32 VDTContextD3D9::InsertFence() {
  1474.     return mpData->mFenceManager.InsertFence();
  1475. }
  1476.  
  1477. bool VDTContextD3D9::CheckFence(uint32 id) {
  1478.     return mpData->mFenceManager.CheckFence(id);
  1479. }
  1480.  
  1481. bool VDTContextD3D9::RecoverDevice() {
  1482.     if (!mbDeviceLost)
  1483.         return true;
  1484.  
  1485.     HRESULT hr = mpD3DDevice->TestCooperativeLevel();
  1486.     if (hr != D3DERR_DEVICENOTRESET && !SUCCEEDED(hr))
  1487.         return false;
  1488.  
  1489.     ShutdownDefaultPoolResources();
  1490.     mpData->mFenceManager.FlushDefaultResources();
  1491.  
  1492.     hr = mpD3DDevice->Reset(&mpData->mPresentParms);
  1493.     if (FAILED(hr) || !ConnectSurfaces()) {
  1494.         mbInScene = false;
  1495.         mbDeviceLost = true;
  1496.         ++mDeviceLossCounter;
  1497.         return false;
  1498.     }
  1499.  
  1500.     mbDeviceLost = false;
  1501.     mbBSDirty = true;
  1502.     mbRSDirty = true;
  1503.     mDirtySamplerStates = true;
  1504.  
  1505.     mpCurrentVB = NULL;
  1506.     mCurrentVBOffset = 0;
  1507.     mCurrentVBStride = 0;
  1508.     mpCurrentIB = NULL;
  1509.     mpCurrentVP = NULL;
  1510.     mpCurrentFP = NULL;
  1511.     mpCurrentVF = NULL;
  1512.  
  1513.     mpCurrentBS = mpDefaultBS;
  1514.     mpCurrentRS = mpDefaultRS;
  1515.     mpCurrentRT = mpDefaultRT;
  1516.  
  1517.     for(int i=0; i<16; ++i) {
  1518.         mpCurrentSamplerStates[i] = mpDefaultSS;
  1519.         mpCurrentTextures[i] = NULL;
  1520.  
  1521.     }
  1522.  
  1523.     return true;
  1524. }
  1525.  
  1526. bool VDTContextD3D9::OpenScene() {
  1527.     if (mbDeviceLost)
  1528.         return false;
  1529.  
  1530.     if (mbInScene)
  1531.         return true;
  1532.  
  1533.     HRESULT hr = mpD3DDevice->BeginScene();
  1534.     if (FAILED(hr)) {
  1535.         ProcessHRESULT(hr);
  1536.         return false;
  1537.     }
  1538.  
  1539.     mbInScene = true;
  1540.     return true;
  1541. }
  1542.  
  1543. bool VDTContextD3D9::CloseScene() {
  1544.     if (mbInScene) {
  1545.         mbInScene = false;
  1546.         HRESULT hr = mpD3DDevice->EndScene();
  1547.         if (FAILED(hr))
  1548.             ProcessHRESULT(hr);
  1549.     }
  1550.  
  1551.     return !mbDeviceLost;
  1552. }
  1553.  
  1554. uint32 VDTContextD3D9::GetDeviceLossCounter() const {
  1555.     return mDeviceLossCounter;
  1556. }
  1557.  
  1558. void VDTContextD3D9::Present() {
  1559.     if (mbInScene)
  1560.         CloseScene();
  1561.  
  1562.     if (mbDeviceLost)
  1563.         return;
  1564.  
  1565.     HRESULT hr = mpD3DDevice->Present(NULL, NULL, NULL, NULL);
  1566.  
  1567.     if (FAILED(hr))
  1568.         ProcessHRESULT(hr);
  1569. }
  1570.  
  1571. void VDTContextD3D9::BeginScope(uint32 color, const char *message) {
  1572.     typedef int (WINAPI *tpBeginEvent)(D3DCOLOR, LPCWSTR);
  1573.     if (mpBeginEvent) {
  1574.         WCHAR wbuf[64];
  1575.         WCHAR *t = wbuf;
  1576.         const char *s = message;
  1577.  
  1578.         for(int i=0; i<63; ++i) {
  1579.             char c = s[i];
  1580.             if (!c)
  1581.                 break;
  1582.  
  1583.             *t++ = c;
  1584.         }
  1585.  
  1586.         *t = 0;
  1587.  
  1588.         ((tpBeginEvent)mpBeginEvent)(color, wbuf);
  1589.     }
  1590.  
  1591.     mProfChan.Begin(color, message);
  1592. }
  1593.  
  1594. void VDTContextD3D9::EndScope() {
  1595.     mProfChan.End();
  1596.  
  1597.     typedef int (WINAPI *tpEndEvent)();
  1598.     if (mpEndEvent)
  1599.         ((tpEndEvent)mpEndEvent)();
  1600. }
  1601.  
  1602. VDRTProfileChannel *VDTContextD3D9::GetProfileChannel() {
  1603.     return &mProfChan;
  1604. }
  1605.  
  1606. void VDTContextD3D9::UnsetVertexFormat(IVDTVertexFormat *format) {
  1607.     if (mpCurrentVF == format)
  1608.         SetVertexFormat(NULL);
  1609. }
  1610.  
  1611. void VDTContextD3D9::UnsetVertexProgram(IVDTVertexProgram *program) {
  1612.     if (mpCurrentVP == program)
  1613.         SetVertexProgram(NULL);
  1614. }
  1615.  
  1616. void VDTContextD3D9::UnsetFragmentProgram(IVDTFragmentProgram *program) {
  1617.     if (mpCurrentFP == program)
  1618.         SetFragmentProgram(NULL);
  1619. }
  1620.  
  1621. void VDTContextD3D9::UnsetVertexBuffer(IVDTVertexBuffer *buffer) {
  1622.     if (mpCurrentVB == buffer)
  1623.         SetVertexStream(0, NULL, 0, 0);
  1624. }
  1625.  
  1626. void VDTContextD3D9::UnsetIndexBuffer(IVDTIndexBuffer *buffer) {
  1627.     if (mpCurrentIB == buffer)
  1628.         SetIndexStream(NULL);
  1629. }
  1630.  
  1631. void VDTContextD3D9::UnsetRenderTarget(IVDTSurface *surface) {
  1632.     if (mpCurrentRT == surface)
  1633.         SetRenderTarget(0, NULL);
  1634. }
  1635.  
  1636. void VDTContextD3D9::UnsetBlendState(IVDTBlendState *state) {
  1637.     if (mpCurrentBS == state && state != mpDefaultBS)
  1638.         SetBlendState(NULL);
  1639. }
  1640.  
  1641. void VDTContextD3D9::UnsetRasterizerState(IVDTRasterizerState *state) {
  1642.     if (mpCurrentRS == state && state != mpDefaultRS)
  1643.         SetRasterizerState(NULL);
  1644. }
  1645.  
  1646. void VDTContextD3D9::UnsetSamplerState(IVDTSamplerState *state) {
  1647.     if (state == mpDefaultSS)
  1648.         return;
  1649.  
  1650.     for(int i=0; i<16; ++i) {
  1651.         if (mpCurrentSamplerStates[i] == state) {
  1652.             IVDTSamplerState *ssnull = NULL;
  1653.             SetSamplerStates(i, 1, &ssnull);
  1654.         }
  1655.     }
  1656. }
  1657.  
  1658. void VDTContextD3D9::UnsetTexture(IVDTTexture *tex) {
  1659.     for(int i=0; i<16; ++i) {
  1660.         if (mpCurrentTextures[i] == tex) {
  1661.             IVDTTexture *tex = NULL;
  1662.             SetTextures(i, 1, &tex);
  1663.         }
  1664.     }
  1665. }
  1666.  
  1667. void VDTContextD3D9::ProcessHRESULT(uint32 hr) {
  1668.     if (hr == D3DERR_DEVICELOST) {
  1669.         if (!mbDeviceLost) {
  1670.             mbDeviceLost = true;
  1671.             ++mDeviceLossCounter;
  1672.         }
  1673.  
  1674.         mbInScene = false;
  1675.     }
  1676. }
  1677.  
  1678. bool VDTContextD3D9::ConnectSurfaces() {
  1679.     vdrefptr<IDirect3DSwapChain9> sc;
  1680.     HRESULT hr = mpD3DDevice->GetSwapChain(0, ~sc);
  1681.     if (FAILED(hr)) {
  1682.         ProcessHRESULT(hr);
  1683.         return false;
  1684.     }
  1685.  
  1686.     IDirect3DSurface9 *surf;
  1687.     sc->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surf);
  1688.     if (FAILED(hr)) {
  1689.         ProcessHRESULT(hr);
  1690.         return false;
  1691.     }
  1692.  
  1693.     mpDefaultRT->Shutdown();
  1694.     bool success = mpDefaultRT->Init(this, surf);
  1695.     surf->Release();
  1696.  
  1697.     return success;
  1698. }
  1699.  
  1700. bool VDTContextD3D9::CommitState() {
  1701.     if (mbBSDirty) {
  1702.         mbBSDirty = false;
  1703.  
  1704.         UpdateRenderStates(VDTBlendStateD3D9::kRenderStateIDs, VDTBlendStateD3D9::kStateCount, mD3DBlendStates, mpCurrentBS->mRenderStates);
  1705.     }
  1706.  
  1707.     if (mbRSDirty) {
  1708.         mbRSDirty = false;
  1709.  
  1710.         UpdateRenderStates(VDTRasterizerStateD3D9::kRenderStateIDs, VDTRasterizerStateD3D9::kStateCount, mD3DRasterizerStates, mpCurrentRS->mRenderStates);
  1711.     }
  1712.  
  1713.     if (mDirtySamplerStates) {
  1714.         for(int i=0; i<16; ++i) {
  1715.             if (mDirtySamplerStates & (1 << i)) {
  1716.                 const uint32 *values = mpCurrentSamplerStates[i]->mSamplerStates;
  1717.                 uint32 *shadow = mD3DSamplerStates[i];
  1718.  
  1719.                 for(uint32 j=0; j<VDTSamplerStateD3D9::kStateCount; ++j) {
  1720.                     const uint32 v = values[j];
  1721.  
  1722.                     if (shadow[j] != v) {
  1723.                         shadow[j] = v;
  1724.  
  1725.                         HRESULT hr = mpD3DDevice->SetSamplerState(i, (D3DSAMPLERSTATETYPE)VDTSamplerStateD3D9::kSamplerStateIDs[j], v);
  1726.                         if (FAILED(hr)) {
  1727.                             ProcessHRESULT(hr);
  1728.                             break;
  1729.                         }
  1730.                     }
  1731.                 }
  1732.             }
  1733.         }
  1734.  
  1735.         mDirtySamplerStates = 0;
  1736.     }
  1737.  
  1738.     return true;
  1739. }
  1740.  
  1741. void VDTContextD3D9::UpdateRenderStates(const uint32 *ids, uint32 count, uint32 *shadow, const uint32 *values) {
  1742.     for(uint32 i=0; i<count; ++i) {
  1743.         const uint32 v = values[i];
  1744.  
  1745.         if (shadow[i] != v) {
  1746.             shadow[i] = v;
  1747.  
  1748.             HRESULT hr = mpD3DDevice->SetRenderState((D3DRENDERSTATETYPE)ids[i], v);
  1749.             if (FAILED(hr)) {
  1750.                 ProcessHRESULT(hr);
  1751.                 break;
  1752.             }
  1753.         }
  1754.     }
  1755. }
  1756.  
  1757. ///////////////////////////////////////////////////////////////////////////////
  1758.  
  1759. class VDDirect3DHolder : public vdrefcounted<IVDRefUnknown> {
  1760. public:
  1761.     VDDirect3DHolder();
  1762.     ~VDDirect3DHolder();
  1763.  
  1764.     void *AsInterface(uint32 iid);
  1765.  
  1766.     IDirect3D9 *GetD3D9() const { return mpD3D9; }
  1767.  
  1768.     bool Init();
  1769.     void Shutdown();
  1770.  
  1771. protected:
  1772.     HMODULE mhmodD3D9;
  1773.     IDirect3D9 *mpD3D9;
  1774. };
  1775.  
  1776. VDDirect3DHolder::VDDirect3DHolder()
  1777.     : mhmodD3D9(NULL)
  1778.     , mpD3D9(NULL)
  1779. {
  1780. }
  1781.  
  1782. VDDirect3DHolder::~VDDirect3DHolder() {
  1783.     Shutdown();
  1784. }
  1785.  
  1786. void *VDDirect3DHolder::AsInterface(uint32 iid) {
  1787.     return NULL;
  1788. }
  1789.  
  1790. bool VDDirect3DHolder::Init() {
  1791.     if (!mhmodD3D9) {
  1792.         mhmodD3D9 = LoadLibrary("d3d9");
  1793.  
  1794.         if (!mhmodD3D9) {
  1795.             Shutdown();
  1796.             return false;
  1797.         }
  1798.     }
  1799.  
  1800.     if (!mpD3D9) {
  1801.         IDirect3D9 *(APIENTRY *pDirect3DCreate9)(UINT) = (IDirect3D9 *(APIENTRY *)(UINT))GetProcAddress(mhmodD3D9, "Direct3DCreate9");
  1802.         if (!pDirect3DCreate9) {
  1803.             Shutdown();
  1804.             return false;
  1805.         }
  1806.  
  1807.         mpD3D9 = pDirect3DCreate9(D3D_SDK_VERSION);
  1808.         if (!mpD3D9) {
  1809.             Shutdown();
  1810.             return false;
  1811.         }
  1812.     }
  1813.  
  1814.     return true;
  1815. }
  1816.  
  1817. void VDDirect3DHolder::Shutdown() {
  1818.     if (mpD3D9) {
  1819.         mpD3D9->Release();
  1820.         mpD3D9 = NULL;
  1821.     }
  1822.  
  1823.     if (mhmodD3D9) {
  1824.         FreeLibrary(mhmodD3D9);
  1825.         mhmodD3D9 = NULL;
  1826.     }
  1827. }
  1828.  
  1829. ///////////////////////////////////////////////////////////////////////////////
  1830.  
  1831. bool VDTCreateContextD3D9(int width, int height, int refresh, bool fullscreen, bool vsync, void *hwnd, IVDTContext **ppctx) {
  1832.     vdrefptr<VDDirect3DHolder> holder(new VDDirect3DHolder);
  1833.  
  1834.     if (!holder->Init())
  1835.         return false;
  1836.  
  1837.     IDirect3D9 *d3d9 = holder->GetD3D9();
  1838.  
  1839.     D3DPRESENT_PARAMETERS parms;
  1840.     parms.BackBufferWidth = width;
  1841.     parms.BackBufferHeight = height;
  1842.     parms.BackBufferFormat = fullscreen ? D3DFMT_A8R8G8B8 : D3DFMT_UNKNOWN;
  1843.     parms.BackBufferCount = fullscreen ? 3 : 1;
  1844.     parms.MultiSampleType = D3DMULTISAMPLE_NONE;
  1845.     parms.MultiSampleQuality = 0;
  1846.     parms.SwapEffect = D3DSWAPEFFECT_DISCARD;
  1847.     parms.hDeviceWindow = NULL;
  1848.     parms.Windowed = fullscreen ? FALSE : TRUE;
  1849.     parms.EnableAutoDepthStencil = FALSE;
  1850.     parms.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
  1851.     parms.Flags = 0;
  1852.     parms.FullScreen_RefreshRateInHz = refresh;
  1853.     parms.PresentationInterval = vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
  1854.  
  1855.     UINT adapter = D3DADAPTER_DEFAULT;
  1856.     D3DDEVTYPE devType = D3DDEVTYPE_HAL;
  1857.  
  1858.     UINT adapterCount = d3d9->GetAdapterCount();
  1859.     for(UINT i=0; i<adapterCount; ++i) {
  1860.         D3DADAPTER_IDENTIFIER9 ident;
  1861.  
  1862.         HRESULT hr = d3d9->GetAdapterIdentifier(i, 0, &ident);
  1863.         if (SUCCEEDED(hr)) {
  1864.             if (strstr(ident.Description, "PerfHUD")) {
  1865.                 adapter = i;
  1866.                 devType = D3DDEVTYPE_REF;
  1867.                 break;
  1868.             }
  1869.         }
  1870.     }
  1871.  
  1872.     vdrefptr<IDirect3DDevice9> dev;
  1873.     HRESULT hr = d3d9->CreateDevice(adapter, devType, (HWND)hwnd, D3DCREATE_FPU_PRESERVE | D3DCREATE_HARDWARE_VERTEXPROCESSING, &parms, ~dev);
  1874.     if (FAILED(hr))
  1875.         return false;
  1876.  
  1877.     vdrefptr<VDTContextD3D9> ctx(new VDTContextD3D9);
  1878.     if (!ctx->Init(dev, holder))
  1879.         return false;
  1880.  
  1881.     *ppctx = ctx.release();
  1882.     return true;
  1883. }
  1884.  
  1885. bool VDTCreateContextD3D9(IDirect3DDevice9 *dev, IVDTContext **ppctx) {
  1886.     vdrefptr<VDTContextD3D9> ctx(new VDTContextD3D9);
  1887.  
  1888.     if (!ctx->Init(dev, NULL))
  1889.         return false;
  1890.  
  1891.     *ppctx = ctx.release();
  1892.     return true;
  1893. }
  1894.