home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Riza / source / displayd3dfx.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-24  |  53.4 KB  |  1,827 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    A/V interface library
  3. //    Copyright (C) 1998-2005 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <d3d9.h>
  20. #include <d3dx9.h>
  21. #include <vd2/system/VDString.h>
  22. #include <vd2/system/w32assist.h>
  23. #include <vd2/system/math.h>
  24. #include <vd2/system/filesys.h>
  25. #include <vd2/system/time.h>
  26. #include <vd2/system/error.h>
  27. #include <vd2/Kasumi/pixmap.h>
  28. #include <vd2/Kasumi/pixmapops.h>
  29. #include <vd2/Kasumi/pixmaputils.h>
  30. #include <vd2/Riza/direct3d.h>
  31. #include "d3dxfx.h"
  32. #include "displaydrv.h"
  33. #include <vd2/Riza/displaydrvdx9.h>
  34.  
  35. ///////////////////////////////////////////////////////////////////////////
  36.  
  37. class VDD3D9TextureGeneratorFullSizeRTT : public vdrefcounted<IVDD3D9TextureGenerator> {
  38. public:
  39.     bool GenerateTexture(VDD3D9Manager *pManager, IVDD3D9Texture *pTexture) {
  40.         const D3DPRESENT_PARAMETERS& parms = pManager->GetPresentParms();
  41.  
  42.         int w = parms.BackBufferWidth;
  43.         int h = parms.BackBufferHeight;
  44.  
  45.         pManager->AdjustTextureSize(w, h);
  46.  
  47.         IDirect3DDevice9 *dev = pManager->GetDevice();
  48.         IDirect3DTexture9 *tex;
  49.         HRESULT hr = dev->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL);
  50.         if (FAILED(hr))
  51.             return false;
  52.  
  53.         pTexture->SetD3DTexture(tex);
  54.         tex->Release();
  55.         return true;
  56.     }
  57. };
  58.  
  59. bool VDCreateD3D9TextureGeneratorFullSizeRTT(IVDD3D9TextureGenerator **ppGenerator) {
  60.     *ppGenerator = new VDD3D9TextureGeneratorFullSizeRTT;
  61.     if (!*ppGenerator)
  62.         return false;
  63.     (*ppGenerator)->AddRef();
  64.     return true;
  65. }
  66.  
  67. ///////////////////////////////////////////////////////////////////////////
  68.  
  69. class VDD3D9TextureGeneratorFullSizeRTT16F : public vdrefcounted<IVDD3D9TextureGenerator> {
  70. public:
  71.     bool GenerateTexture(VDD3D9Manager *pManager, IVDD3D9Texture *pTexture) {
  72.         const D3DPRESENT_PARAMETERS& parms = pManager->GetPresentParms();
  73.  
  74.         int w = parms.BackBufferWidth;
  75.         int h = parms.BackBufferHeight;
  76.  
  77.         pManager->AdjustTextureSize(w, h);
  78.  
  79.         IDirect3DDevice9 *dev = pManager->GetDevice();
  80.         IDirect3DTexture9 *tex;
  81.         HRESULT hr = dev->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &tex, NULL);
  82.         if (FAILED(hr))
  83.             return false;
  84.  
  85.         pTexture->SetD3DTexture(tex);
  86.         tex->Release();
  87.         return true;
  88.     }
  89. };
  90.  
  91. bool VDCreateD3D9TextureGeneratorFullSizeRTT16F(IVDD3D9TextureGenerator **ppGenerator) {
  92.     *ppGenerator = new VDD3D9TextureGeneratorFullSizeRTT16F;
  93.     if (!*ppGenerator)
  94.         return false;
  95.     (*ppGenerator)->AddRef();
  96.     return true;
  97. }
  98.  
  99. ///////////////////////////////////////////////////////////////////////////
  100.  
  101.  
  102. #define D3D_AUTOBREAK_2(x) if (FAILED(hr = x)) { VDASSERT(!"VideoDriver/D3DFX: Direct3D call failed: "#x); goto d3d_failed; } else ((void)0)
  103. #define D3D_AUTOBREAK(x) if ((hr = mpD3DDevice->x), FAILED(hr)) { VDASSERT(!"VideoDriver/D3DFX: Direct3D call failed: "#x); goto d3d_failed; } else ((void)0)
  104.  
  105. #define VDDEBUG_D3DFXDISP VDDEBUG
  106.  
  107. using namespace nsVDD3D9;
  108.  
  109. namespace {
  110.     VDStringW g_VDVideoDisplayD3DFXEffectFileName;
  111. }
  112.  
  113. namespace {
  114.     typedef BOOL (WINAPI *tpD3DXCheckVersion)(UINT D3DSDKVersion, UINT D3DXSDKVersion);
  115.     typedef HRESULT (WINAPI *tpD3DXCreateEffectCompilerFromFileA)(
  116.                 LPCSTR pSrcFile,
  117.                 const D3DXMACRO *pDefines,
  118.                 LPD3DXINCLUDE pInclude,
  119.                 DWORD Flags,
  120.                 ID3DXEffectCompilerVersion25 **ppEffect,
  121.                 ID3DXBuffer **ppCompilationErrors);
  122.     typedef HRESULT (WINAPI *tpD3DXCreateEffectCompilerFromFileW)(
  123.                 LPCWSTR pSrcFile,
  124.                 const D3DXMACRO *pDefines,
  125.                 LPD3DXINCLUDE pInclude,
  126.                 DWORD Flags,
  127.                 ID3DXEffectCompilerVersion25 **ppEffect,
  128.                 ID3DXBuffer **ppCompilationErrors);
  129.     typedef HRESULT (WINAPI *tpD3DXCreateEffect)(
  130.                 LPDIRECT3DDEVICE9 pDevice,
  131.                 LPCVOID pSrcData,
  132.                 UINT SrcDataLen,
  133.                 const D3DXMACRO *pDefines,
  134.                 LPD3DXINCLUDE pInclude,
  135.                 DWORD Flags,
  136.                 ID3DXEffectPool *pPool,
  137.                 ID3DXEffectVersion25 **ppEffect,
  138.                 ID3DXBuffer **ppCompilationErrors);
  139.     typedef HRESULT (WINAPI *tpD3DXCreateTextureShader)(CONST DWORD *pFunction, LPD3DXTEXTURESHADER *ppTextureShader);
  140.     typedef HRESULT (WINAPI *tpD3DXFillTextureTX)(LPDIRECT3DTEXTURE9 pTexture, LPD3DXTEXTURESHADER pTextureShader);
  141.     typedef HRESULT (WINAPI *tpD3DXFillCubeTextureTX)(LPDIRECT3DCUBETEXTURE9 pCubeTexture, LPD3DXTEXTURESHADER pTextureShader);
  142.     typedef HRESULT (WINAPI *tpD3DXFillVolumeTextureTX)(LPDIRECT3DVOLUMETEXTURE9 pVolumeTexture, LPD3DXTEXTURESHADER pTextureShader);
  143.  
  144.     struct StdParamData {
  145.         float vpsize[4];            // (viewport size)            vpwidth, vpheight, 1/vpheight, 1/vpwidth
  146.         float texsize[4];            // (texture size)            texwidth, texheight, 1/texheight, 1/texwidth
  147.         float srcsize[4];            // (source size)            srcwidth, srcheight, 1/srcheight, 1/srcwidth
  148.         float tempsize[4];            // (temp rtt size)            tempwidth, tempheight, 1/tempheight, 1/tempwidth
  149.         float temp2size[4];            // (temp2 rtt size)            tempwidth, tempheight, 1/tempheight, 1/tempwidth
  150.         float vpcorrect[4];            // (viewport correction)    2/vpwidth, 2/vpheight, -1/vpheight, 1/vpwidth
  151.         float vpcorrect2[4];        // (viewport correction)    2/vpwidth, -2/vpheight, 1+1/vpheight, -1-1/vpwidth
  152.         float tvpcorrect[4];        // (temp vp correction)        2/tvpwidth, 2/tvpheight, -1/tvpheight, 1/tvpwidth
  153.         float tvpcorrect2[4];        // (temp vp correction)        2/tvpwidth, -2/tvpheight, 1+1/tvpheight, -1-1/tvpwidth
  154.         float t2vpcorrect[4];        // (temp2 vp correction)    2/tvpwidth, 2/tvpheight, -1/tvpheight, 1/tvpwidth
  155.         float t2vpcorrect2[4];        // (temp2 vp correction)    2/tvpwidth, -2/tvpheight, 1+1/tvpheight, -1-1/tvpwidth
  156.         float time[4];                // (time)
  157.     };
  158.  
  159.     static const struct StdParam {
  160.         const char *name;
  161.         int offset;
  162.     } kStdParamInfo[]={
  163.         { "vd_vpsize",        offsetof(StdParamData, vpsize) },
  164.         { "vd_texsize",        offsetof(StdParamData, texsize) },
  165.         { "vd_srcsize",        offsetof(StdParamData, srcsize) },
  166.         { "vd_tempsize",    offsetof(StdParamData, tempsize) },
  167.         { "vd_temp2size",    offsetof(StdParamData, temp2size) },
  168.         { "vd_vpcorrect",    offsetof(StdParamData, vpcorrect) },
  169.         { "vd_vpcorrect2",    offsetof(StdParamData, vpcorrect2) },
  170.         { "vd_tvpcorrect",    offsetof(StdParamData, tvpcorrect) },
  171.         { "vd_tvpcorrect2",    offsetof(StdParamData, tvpcorrect2) },
  172.         { "vd_t2vpcorrect",        offsetof(StdParamData, t2vpcorrect) },
  173.         { "vd_t2vpcorrect2",    offsetof(StdParamData, t2vpcorrect2) },
  174.         { "vd_time",        offsetof(StdParamData, time) },
  175.     };
  176.  
  177.     enum { kStdParamCount = sizeof kStdParamInfo / sizeof kStdParamInfo[0] };
  178.  
  179.     struct FormatInfo {
  180.         const char *mpName;
  181.         D3DFORMAT    mFormat;
  182.     } kFormats[]={
  183. #define X(name) { #name, D3DFMT_##name },
  184.     X(R8G8B8)
  185.     X(A8R8G8B8)
  186.     X(X8R8G8B8)
  187.     X(R5G6B5)
  188.     X(X1R5G5B5)
  189.     X(A1R5G5B5)
  190.     X(A4R4G4B4)
  191.     X(R3G3B2)
  192.     X(A8)
  193.     X(A8R3G3B2)
  194.     X(X4R4G4B4)
  195.     X(A2B10G10R10)
  196.     X(A8B8G8R8)
  197.     X(X8B8G8R8)
  198.     X(G16R16)
  199.     X(A2R10G10B10)
  200.     X(A16B16G16R16)
  201.     X(A8P8)
  202.     X(P8)
  203.     X(L8)
  204.     X(A8L8)
  205.     X(A4L4)
  206.     X(V8U8)
  207.     X(L6V5U5)
  208.     X(X8L8V8U8)
  209.     X(Q8W8V8U8)
  210.     X(V16U16)
  211.     X(A2W10V10U10)
  212.     X(UYVY)
  213.     X(R8G8_B8G8)
  214.     X(YUY2)
  215.     X(G8R8_G8B8)
  216.     X(DXT1)
  217.     X(DXT2)
  218.     X(DXT3)
  219.     X(DXT4)
  220.     X(DXT5)
  221.     X(D16_LOCKABLE)
  222.     X(D32)
  223.     X(D15S1)
  224.     X(D24S8)
  225.     X(D24X8)
  226.     X(D24X4S4)
  227.     X(D16)
  228.     X(D32F_LOCKABLE)
  229.     X(D24FS8)
  230.     X(L16)
  231.     X(VERTEXDATA)
  232.     X(INDEX16)
  233.     X(INDEX32)
  234.     X(Q16W16V16U16)
  235.     X(MULTI2_ARGB8)
  236.     X(R16F)
  237.     X(G16R16F)
  238.     X(A16B16G16R16F)
  239.     X(R32F)
  240.     X(G32R32F)
  241.     X(A32B32G32R32F)
  242.     X(CxV8U8)
  243. #undef X
  244.     };
  245. }
  246.  
  247. class VDVideoDisplayMinidriverD3DFX : public VDVideoDisplayMinidriver, protected VDD3D9Client {
  248. public:
  249.     VDVideoDisplayMinidriverD3DFX(bool clipToMonitor);
  250.     ~VDVideoDisplayMinidriverD3DFX();
  251.  
  252. protected:
  253.     bool Init(HWND hwnd, const VDVideoDisplaySourceInfo& info);
  254.     void ShutdownEffect();
  255.     void Shutdown();
  256.  
  257.     bool ModifySource(const VDVideoDisplaySourceInfo& info);
  258.  
  259.     bool IsValid();
  260.     bool IsFramePending() { return mbSwapChainPresentPending; }
  261.     void SetFilterMode(FilterMode mode);
  262.     void SetFullScreen(bool fs);
  263.  
  264.     bool Tick(int id);
  265.     void Poll();
  266.     bool Resize();
  267.     bool Update(UpdateMode);
  268.     void Refresh(UpdateMode);
  269.     bool Paint(HDC hdc, const RECT& rClient, UpdateMode mode);
  270.  
  271.     void SetLogicalPalette(const uint8 *pLogicalPalette);
  272.     float GetSyncDelta() const { return mSyncDelta; }
  273.  
  274. protected:
  275.     struct ParamBinding;
  276.  
  277.     typedef void (VDVideoDisplayMinidriverD3DFX::*ParamUploadMethod)(const ParamBinding& binding);
  278.  
  279.     struct ParamBinding {
  280.         D3DXHANDLE    mhParam;
  281.         ParamUploadMethod    mpFn;
  282.     };
  283.  
  284.     void OnPreDeviceReset() {
  285.         DestroyCustomTextures(true);
  286.  
  287.         mpSwapChain = NULL;
  288.         mSwapChainW = 0;
  289.         mSwapChainH = 0;
  290.  
  291.         if (mpEffect)
  292.             mpEffect->OnLostDevice();
  293.  
  294.         mpD3DTempTexture = NULL;
  295.         mpD3DTempSurface = NULL;
  296.         mpD3DTempTexture2 = NULL;
  297.         mpD3DTempSurface2 = NULL;
  298.     }
  299.  
  300.     void OnPostDeviceReset() {
  301.         if (mpEffect)
  302.             mpEffect->OnResetDevice();
  303.  
  304.         if (mpTempTexture) {
  305.             mpD3DTempTexture = mpTempTexture->GetD3DTexture();
  306.  
  307.             if (mpD3DTempTexture)
  308.                 mpD3DTempTexture->GetSurfaceLevel(0, ~mpD3DTempSurface);
  309.         }
  310.  
  311.         if (mpTempTexture2) {
  312.             mpD3DTempTexture2 = mpTempTexture2->GetD3DTexture();
  313.  
  314.             if (mpD3DTempTexture2)
  315.                 mpD3DTempTexture2->GetSurfaceLevel(0, ~mpD3DTempSurface2);
  316.         }
  317.  
  318.         CreateCustomTextures(true, NULL);
  319.     }
  320.  
  321.     bool UpdateBackbuffer(const RECT& rClient, UpdateMode updateMode);
  322.     bool UpdateScreen(const RECT& rClient, UpdateMode updateMode, bool polling);
  323.     void DisplayError();
  324.     void PreprocessEffectParameters();
  325.     void UpdateParam_RenderTargetDimensions(const ParamBinding& binding);
  326.     void UpdateParam_ViewportPixelSize(const ParamBinding& binding);
  327.     void UpdateEffectParameters(const D3DVIEWPORT9& vp, const D3DSURFACE_DESC& texdesc);
  328.  
  329.     void CreateCustomTextureBindings();
  330.     bool CreateCustomTextures(bool vramOnly, const vdsize32 *vpsize);
  331.     void DestroyCustomTextures(bool vramOnly);
  332.     void DestroyCustomTextureBindings();
  333.  
  334.     HWND                mhwnd;
  335.     HWND                mhwndError;
  336.     HMODULE                mhmodD3DX;
  337.     RECT                mrClient;
  338.  
  339.     VDD3D9Manager        *mpManager;
  340.     IDirect3DDevice9    *mpD3DDevice;            // weak ref
  341.  
  342.     vdrefptr<IVDVideoUploadContextD3D9>    mpUploadContext;
  343.  
  344.     vdrefptr<IVDD3D9SwapChain>    mpSwapChain;
  345.     int                    mSwapChainW;
  346.     int                    mSwapChainH;
  347.     bool                mbSwapChainPresentPending;
  348.     bool                mbSwapChainPresentPolling;
  349.     bool                mbSwapChainImageValid;
  350.     bool                mbFirstPresent;
  351.     bool                mbFullScreen;
  352.     bool                mbClipToMonitor;
  353.  
  354.     VDAtomicInt            mTickPending;
  355.  
  356.     vdrefptr<IVDD3D9Texture>    mpTempTexture;
  357.     IDirect3DTexture9            *mpD3DTempTexture;        // weak ref
  358.     vdrefptr<IDirect3DSurface9>    mpD3DTempSurface;
  359.  
  360.     vdrefptr<IVDD3D9Texture>    mpTempTexture2;
  361.     IDirect3DTexture9            *mpD3DTempTexture2;        // weak ref
  362.     vdrefptr<IDirect3DSurface9>    mpD3DTempSurface2;
  363.  
  364.     FilterMode            mPreferredFilter;
  365.  
  366.     ID3DXEffectVersion25 *mpEffect;
  367.     ID3DXEffectCompilerVersion25    *mpEffectCompiler;
  368.  
  369.     VDVideoDisplaySourceInfo    mSource;
  370.     bool                mbForceFrameUpload;
  371.  
  372.     float                mSyncDelta;
  373.     VDD3DPresentHistory    mPresentHistory;
  374.  
  375.     VDStringA            mTimingString;
  376.     int                    mTimingStringCounter;
  377.     float                mLastLongestPresentTime;
  378.     float                mLastLongestFrameTime;
  379.     uint64                mLastFrameTime;
  380.  
  381.     uint32                mLatencyFence;
  382.     uint32                mLatencyFenceNext;
  383.  
  384.     VDStringW            mError;
  385.  
  386.     D3DXHANDLE            mhSrcTexture;
  387.     D3DXHANDLE            mhPrevSrcTexture;
  388.     D3DXHANDLE            mhPrevSrc2Texture;
  389.     D3DXHANDLE            mhTempTexture;
  390.     D3DXHANDLE            mhTempTexture2;
  391.     D3DXHANDLE            mhTechniques[kFilterModeCount - 1];
  392.     D3DXHANDLE            mhStdParamHandles[kStdParamCount];
  393.  
  394.     typedef vdfastvector<ParamBinding> ParamBindings;
  395.     ParamBindings mParamBindings;
  396.  
  397.     struct TextureBinding {
  398.         IDirect3DBaseTexture9 *mpTexture;
  399.         ID3DXTextureShader *mpTextureShader;
  400.  
  401.         D3DXHANDLE        mhParam;
  402.         D3DXHANDLE        mhSizeParam;
  403.         D3DFORMAT        mFormat;
  404.         D3DPOOL            mPool;
  405.         DWORD            mUsage;
  406.         D3DRESOURCETYPE    mResType;
  407.         float            mViewportRatioW;
  408.         float            mViewportRatioH;
  409.         int                mWidth;
  410.         int                mHeight;
  411.         int                mDepth;
  412.         int                mMipLevels;
  413.     };
  414.  
  415.     typedef vdfastvector<TextureBinding> TextureBindings;
  416.     TextureBindings    mTextureBindings;
  417.  
  418.     tpD3DXCreateEffect            mpD3DXCreateEffect;
  419.     tpD3DXCreateTextureShader    mpD3DXCreateTextureShader;
  420.     tpD3DXFillTextureTX            mpD3DXFillTextureTX;
  421.     tpD3DXFillCubeTextureTX        mpD3DXFillCubeTextureTX;
  422.     tpD3DXFillVolumeTextureTX    mpD3DXFillVolumeTextureTX;
  423.  
  424.     vdrefptr<IVDFontRendererD3D9>    mpFontRenderer;
  425. };
  426.  
  427.  
  428. IVDVideoDisplayMinidriver *VDCreateVideoDisplayMinidriverD3DFX(bool clipToMonitor) {
  429.     return new VDVideoDisplayMinidriverD3DFX(clipToMonitor);
  430. }
  431.  
  432. VDVideoDisplayMinidriverD3DFX::VDVideoDisplayMinidriverD3DFX(bool clipToMonitor)
  433.     : mhwnd(NULL)
  434.     , mhwndError(NULL)
  435.     , mhmodD3DX(NULL)
  436.     , mpManager(NULL)
  437.     , mSwapChainW(0)
  438.     , mSwapChainH(0)
  439.     , mbSwapChainImageValid(false)
  440.     , mbSwapChainPresentPending(false)
  441.     , mbSwapChainPresentPolling(false)
  442.     , mbFirstPresent(false)
  443.     , mbFullScreen(false)
  444.     , mbClipToMonitor(clipToMonitor)
  445.     , mTickPending(0)
  446.     , mpD3DTempTexture(NULL)
  447.     , mpD3DTempTexture2(NULL)
  448.     , mpD3DTempSurface(NULL)
  449.     , mpD3DTempSurface2(NULL)
  450.     , mpEffect(NULL)
  451.     , mpEffectCompiler(NULL)
  452.     , mPreferredFilter(kFilterAnySuitable)
  453.     , mbForceFrameUpload(false)
  454.     , mSyncDelta(0.0f)
  455.     , mLastLongestPresentTime(0.0f)
  456.     , mLastLongestFrameTime(0.0f)
  457.     , mTimingStringCounter(0)
  458.     , mLatencyFence(0)
  459.     , mLatencyFenceNext(0)
  460. {
  461.     mrClient.top = mrClient.left = mrClient.right = mrClient.bottom = 0;
  462. }
  463.  
  464. VDVideoDisplayMinidriverD3DFX::~VDVideoDisplayMinidriverD3DFX() {
  465. }
  466.  
  467. bool VDVideoDisplayMinidriverD3DFX::Init(HWND hwnd, const VDVideoDisplaySourceInfo& info) {
  468.     GetClientRect(hwnd, &mrClient);
  469.     mhwnd = hwnd;
  470.     mSource = info;
  471.     mSyncDelta = 0.0f;
  472.  
  473.     mLastFrameTime = VDGetPreciseTick();
  474.  
  475.     // attempt to load d3dx9_25.dll
  476.     mhmodD3DX = LoadLibrary("d3dx9_25.dll");
  477.  
  478.     if (!mhmodD3DX) {
  479.         mError = L"Cannot initialize the Direct3D FX system: Unable to load d3dx9_25.dll.";
  480.         DisplayError();
  481.         return true;
  482.     }
  483.  
  484.     // make sure we're using the right version
  485.     tpD3DXCheckVersion pD3DXCheckVersion = (tpD3DXCheckVersion)GetProcAddress(mhmodD3DX, "D3DXCheckVersion");
  486.     if (!pD3DXCheckVersion || !pD3DXCheckVersion(D3D_SDK_VERSION, 25)) {
  487.         VDASSERT(!"Incorrect D3DX version.");
  488.         Shutdown();
  489.         return false;
  490.     }
  491.  
  492.     // pull the effect compiler pointer
  493.     tpD3DXCreateEffectCompilerFromFileA pD3DXCreateEffectCompilerFromFileA = NULL;
  494.     tpD3DXCreateEffectCompilerFromFileW pD3DXCreateEffectCompilerFromFileW = NULL;
  495.  
  496.     if (VDIsWindowsNT())
  497.         pD3DXCreateEffectCompilerFromFileW = (tpD3DXCreateEffectCompilerFromFileW)GetProcAddress(mhmodD3DX, "D3DXCreateEffectCompilerFromFileW");
  498.  
  499.     if (!pD3DXCreateEffectCompilerFromFileW) {
  500.         pD3DXCreateEffectCompilerFromFileA = (tpD3DXCreateEffectCompilerFromFileA)GetProcAddress(mhmodD3DX, "D3DXCreateEffectCompilerFromFileA");
  501.  
  502.         if (!pD3DXCreateEffectCompilerFromFileA) {
  503.             Shutdown();
  504.             return false;
  505.         }
  506.     }
  507.  
  508.     mpD3DXCreateEffect            = (tpD3DXCreateEffect)            GetProcAddress(mhmodD3DX, "D3DXCreateEffect");
  509.     mpD3DXCreateTextureShader    = (tpD3DXCreateTextureShader)    GetProcAddress(mhmodD3DX, "D3DXCreateTextureShader");
  510.     mpD3DXFillTextureTX            = (tpD3DXFillTextureTX)            GetProcAddress(mhmodD3DX, "D3DXFillTextureTX");
  511.     mpD3DXFillCubeTextureTX        = (tpD3DXFillCubeTextureTX)        GetProcAddress(mhmodD3DX, "D3DXFillCubeTextureTX");
  512.     mpD3DXFillVolumeTextureTX    = (tpD3DXFillVolumeTextureTX)    GetProcAddress(mhmodD3DX, "D3DXFillVolumeTextureTX");
  513.  
  514.     if (!mpD3DXCreateEffect || !mpD3DXCreateTextureShader || !mpD3DXFillTextureTX || !mpD3DXFillCubeTextureTX || !mpD3DXFillVolumeTextureTX) {
  515.         Shutdown();
  516.         return false;
  517.     }
  518.  
  519.     // attempt to initialize D3D9
  520.     mpManager = VDInitDirect3D9(this);
  521.     if (!mpManager) {
  522.         Shutdown();
  523.         return false;
  524.     }
  525.  
  526.     if (mbFullScreen)
  527.         mpManager->AdjustFullScreen(true);
  528.  
  529.     mpD3DDevice = mpManager->GetDevice();
  530.  
  531.     // init font renderer
  532.     if (mbDisplayDebugInfo) {
  533.         if (!VDCreateFontRendererD3D9(~mpFontRenderer)) {
  534.             Shutdown();
  535.             return false;
  536.         }
  537.  
  538.         mpFontRenderer->Init(mpManager);        // we explicitly allow this to fail
  539.     }
  540.  
  541.     // attempt to compile effect
  542.     ID3DXBuffer *pError = NULL;
  543.  
  544.     const VDStringW& fxfile = g_VDVideoDisplayD3DFXEffectFileName;
  545.  
  546.     VDStringW srcfile;
  547.  
  548.     if (fxfile.find(':') != VDStringW::npos || (fxfile.size() >= 2 && fxfile[0] == '\\' && fxfile[1] == '\\'))
  549.         srcfile = fxfile;
  550.     else
  551.         srcfile = VDGetProgramPath() + fxfile;
  552.  
  553.     ID3DXBuffer *pEffectBuffer = NULL;
  554.  
  555.     HRESULT hr;
  556.     if (pD3DXCreateEffectCompilerFromFileW)
  557.         hr = pD3DXCreateEffectCompilerFromFileW(srcfile.c_str(), NULL, NULL, 0, &mpEffectCompiler, &pError);
  558.     else
  559.         hr = pD3DXCreateEffectCompilerFromFileA(VDTextWToA(srcfile).c_str(), NULL, NULL, 0, &mpEffectCompiler, &pError);
  560.  
  561.     if (SUCCEEDED(hr)) {
  562.         if (pError) {
  563.             pError->Release();
  564.             pError = NULL;
  565.         }
  566.  
  567.         // compile the effect
  568.         hr = mpEffectCompiler->CompileEffect(0, &pEffectBuffer, &pError);
  569.  
  570.         if (SUCCEEDED(hr)) {
  571.             if (pError) {
  572.                 pError->Release();
  573.                 pError = NULL;
  574.             }
  575.  
  576.             // create the effect
  577.             hr = mpD3DXCreateEffect(mpD3DDevice, pEffectBuffer->GetBufferPointer(), pEffectBuffer->GetBufferSize(), NULL, NULL, 0, NULL, &mpEffect, &pError);
  578.  
  579.             pEffectBuffer->Release();
  580.         }
  581.     }
  582.  
  583.     if (FAILED(hr)) {
  584.         if (pError)
  585.             mError.sprintf(L"Couldn't compile effect file %ls due to the following error:\r\n\r\n%hs\r\n\r\nIf you have Direct3D effects support enabled by mistake, it can be disabled under Options > Preferences > Display.", srcfile.c_str(), (const char *)pError->GetBufferPointer());
  586.         else
  587.             mError.sprintf(L"Couldn't compile effect file %ls.\r\n\r\nIf you have Direct3D effects support enabled by mistake, it can be disabled under Options > Preferences > Display.", srcfile.c_str());
  588.  
  589.         if (pError)
  590.             pError->Release();
  591.  
  592.         ShutdownEffect();
  593.  
  594.         DisplayError();
  595.         return true;
  596.     }
  597.  
  598.     // scan for textures
  599.     D3DXEFFECT_DESC effDesc;
  600.     hr = mpEffect->GetDesc(&effDesc);
  601.     if (FAILED(hr)) {
  602.         Shutdown();
  603.         return false;
  604.     }
  605.  
  606.     // scan for standard parameter handles (ok for these to fail)
  607.     for(int i=0; i<sizeof kStdParamInfo/sizeof kStdParamInfo[0]; ++i)
  608.         mhStdParamHandles[i] = mpEffect->GetParameterByName(NULL, kStdParamInfo[i].name);
  609.  
  610.     // scan for standard techniques
  611.     static const char *const kTechniqueNames[]={
  612.         "point",
  613.         "bilinear",
  614.         "bicubic",
  615.     };
  616.  
  617.     VDASSERTCT(sizeof kTechniqueNames / sizeof kTechniqueNames[0] == kFilterModeCount - 1);
  618.  
  619.     D3DXHANDLE hTechniqueLastValid = NULL;
  620.  
  621.     for(int i=kFilterModeCount - 2; i >= 0; --i) {
  622.         const char *baseName = kTechniqueNames[i];
  623.         size_t baseNameLen = strlen(baseName);
  624.  
  625.         mhTechniques[i] = NULL;
  626.  
  627.         for(UINT tech=0; tech<effDesc.Techniques; ++tech) {
  628.             D3DXHANDLE hTechnique = mpEffect->GetTechnique(tech);
  629.  
  630.             if (!hTechnique)
  631.                 continue;
  632.  
  633.             D3DXTECHNIQUE_DESC techDesc;
  634.  
  635.             hr = mpEffect->GetTechniqueDesc(hTechnique, &techDesc);
  636.             if (FAILED(hr))
  637.                 continue;
  638.  
  639.             hTechniqueLastValid = hTechnique;
  640.             if (techDesc.Name && !strncmp(techDesc.Name, baseName, baseNameLen)) {
  641.                 char c = techDesc.Name[baseNameLen];
  642.  
  643.                 if (!c || c=='_') {
  644.                     for(int j=i; j < kFilterModeCount - 1 && !mhTechniques[j]; ++j)
  645.                         mhTechniques[j] = hTechnique;
  646.                     break;
  647.                 }
  648.             }
  649.         }
  650.  
  651.         if (!mhTechniques[i])
  652.             mhTechniques[i] = hTechniqueLastValid;
  653.     }
  654.  
  655.     // check if we don't have any recognizable techniques
  656.     if (!hTechniqueLastValid) {
  657.         mError.sprintf(L"Couldn't find a valid technique in effect file %ls:\nMust be one of 'point', 'bilinear', or 'bicubic.'", srcfile.c_str());
  658.         DisplayError();
  659.         ShutdownEffect();
  660.         return true;
  661.     }
  662.  
  663.     // backfill lowest level techniques that may be missing
  664.     for(int i=0; !mhTechniques[i]; ++i)
  665.         mhTechniques[i] = hTechniqueLastValid;
  666.  
  667.     // check if we need the temp texture
  668.     mhTempTexture = mpEffect->GetParameterByName(NULL, "vd_temptexture");
  669.     if (mhTempTexture) {
  670.         if (!mpManager->CreateSharedTexture<VDD3D9TextureGeneratorFullSizeRTT>("rtt1", ~mpTempTexture)) {
  671.             mError = L"Unable to allocate temporary texture.";
  672.             DisplayError();
  673.             ShutdownEffect();
  674.             return true;
  675.         }
  676.  
  677.         mpD3DTempTexture = mpTempTexture->GetD3DTexture();
  678.  
  679.         hr = mpD3DTempTexture->GetSurfaceLevel(0, ~mpD3DTempSurface);
  680.         if (FAILED(hr)) {
  681.             Shutdown();
  682.             return false;
  683.         }
  684.     }
  685.  
  686.     // check if we need the second temp texture
  687.     mhTempTexture2 = mpEffect->GetParameterByName(NULL, "vd_temptexture2");
  688.     if (!mhTempTexture2)
  689.         mhTempTexture2 = mpEffect->GetParameterByName(NULL, "vd_temp2texture");
  690.     if (mhTempTexture2) {
  691.         if (!mpManager->CreateSharedTexture<VDD3D9TextureGeneratorFullSizeRTT>("rtt2", ~mpTempTexture2)) {
  692.             mError = L"Unable to allocate second temporary texture.";
  693.             DisplayError();
  694.             ShutdownEffect();
  695.             return true;
  696.         }
  697.  
  698.         mpD3DTempTexture2 = mpTempTexture2->GetD3DTexture();
  699.  
  700.         hr = mpD3DTempTexture2->GetSurfaceLevel(0, ~mpD3DTempSurface2);
  701.         if (FAILED(hr)) {
  702.             Shutdown();
  703.             return false;
  704.         }
  705.     }
  706.  
  707.     // get handle for src texture
  708.     mhSrcTexture = mpEffect->GetParameterByName(NULL, "vd_srctexture");
  709.  
  710.     mbForceFrameUpload = false;
  711.     if (mhSrcTexture) {
  712.         D3DXHANDLE hForceFrameAnno = mpEffect->GetAnnotationByName(mhSrcTexture, "vd_forceframeupload");
  713.  
  714.         BOOL b;
  715.         if (hForceFrameAnno && SUCCEEDED(mpEffect->GetBool(hForceFrameAnno, &b)) && b) {
  716.             mbForceFrameUpload = true;
  717.         }
  718.     }
  719.  
  720.     // get handle for prev src texture
  721.     mhPrevSrcTexture = mpEffect->GetParameterByName(NULL, "vd_prevsrctexture");
  722.     mhPrevSrc2Texture = mpEffect->GetParameterByName(NULL, "vd_prevsrc2texture");
  723.  
  724.     try {
  725.         PreprocessEffectParameters();
  726.         CreateCustomTextureBindings();
  727.         CreateCustomTextures(false, NULL);
  728.     } catch(const MyError& e) {
  729.         mError.sprintf(L"%hs", e.gets());
  730.         DisplayError();
  731.         ShutdownEffect();
  732.         return true;        
  733.     }
  734.  
  735.     if (mpEffectCompiler) {
  736.         mpEffectCompiler->Release();
  737.         mpEffectCompiler = NULL;
  738.     }
  739.  
  740.     // create upload context
  741.     if (!VDCreateVideoUploadContextD3D9(~mpUploadContext)) {
  742.         Shutdown();
  743.         return false;
  744.     }
  745.  
  746.     if (!mpUploadContext->Init(info.pixmap, info.bAllowConversion, false, mhPrevSrc2Texture ? 3 : mhPrevSrcTexture ? 2 : 1)) {
  747.         Shutdown();
  748.         return false;
  749.     }
  750.  
  751.     VDDEBUG_D3DFXDISP("VideoDisplay/D3DFX: Initialization successful for %dx%d source image.\n", mSource.pixmap.w, mSource.pixmap.h);
  752.  
  753.     mbFirstPresent = true;
  754.     return true;
  755. }
  756.  
  757. void VDVideoDisplayMinidriverD3DFX::ShutdownEffect() {
  758.     mParamBindings.clear();
  759.     DestroyCustomTextureBindings();
  760.  
  761.     mpSwapChain = NULL;
  762.     mSwapChainW = 0;
  763.     mSwapChainH = 0;
  764.  
  765.     if (mpEffectCompiler) {
  766.         mpEffectCompiler->Release();
  767.         mpEffectCompiler = NULL;
  768.     }
  769.  
  770.     if (mpEffect) {
  771.         mpEffect->Release();
  772.         mpEffect = NULL;
  773.     }
  774. }
  775.  
  776. void VDVideoDisplayMinidriverD3DFX::Shutdown() {
  777.     if (mhwndError) {
  778.         DestroyWindow(mhwndError);
  779.         mhwndError = NULL;
  780.     }
  781.  
  782.     ShutdownEffect();
  783.  
  784.     if (mpFontRenderer) {
  785.         mpFontRenderer->Shutdown();
  786.         mpFontRenderer = NULL;
  787.     }
  788.  
  789.     mpD3DTempSurface2 = NULL;
  790.     mpD3DTempSurface = NULL;
  791.  
  792.     mpD3DTempTexture2 = NULL;
  793.     mpTempTexture2 = NULL;
  794.  
  795.     mpD3DTempTexture = NULL;
  796.     mpTempTexture = NULL;
  797.  
  798.     mpUploadContext = NULL;
  799.  
  800.     if (mpManager) {
  801.         if (mbFullScreen)
  802.             mpManager->AdjustFullScreen(false);
  803.         VDDeinitDirect3D9(mpManager, this);
  804.         mpManager = NULL;
  805.     }
  806.  
  807.     if (mhmodD3DX) {
  808.         FreeLibrary(mhmodD3DX);
  809.         mhmodD3DX = NULL;
  810.     }
  811. }
  812.  
  813. bool VDVideoDisplayMinidriverD3DFX::ModifySource(const VDVideoDisplaySourceInfo& info) {
  814.     if (mSource.pixmap.w == info.pixmap.w && mSource.pixmap.h == info.pixmap.h && mSource.pixmap.format == info.pixmap.format && mSource.pixmap.pitch == info.pixmap.pitch) {
  815.         mSource = info;
  816.         return true;
  817.     }
  818.     return false;
  819. }
  820.  
  821. bool VDVideoDisplayMinidriverD3DFX::IsValid() {
  822.     return mpD3DDevice != 0;
  823. }
  824.  
  825. void VDVideoDisplayMinidriverD3DFX::SetFilterMode(FilterMode mode) {
  826.     mPreferredFilter = mode;
  827. }
  828.  
  829. void VDVideoDisplayMinidriverD3DFX::SetFullScreen(bool fs) {
  830.     if (mbFullScreen != fs) {
  831.         mbFullScreen = fs;
  832.  
  833.         if (mpManager)
  834.             mpManager->AdjustFullScreen(fs);
  835.     }
  836. }
  837.  
  838. bool VDVideoDisplayMinidriverD3DFX::Tick(int id) {
  839.     return true;
  840. }
  841.  
  842. void VDVideoDisplayMinidriverD3DFX::Poll() {
  843.     if (mbSwapChainPresentPending) {
  844.         UpdateScreen(mrClient, kModeVSync, true);
  845.     }
  846. }
  847.  
  848. bool VDVideoDisplayMinidriverD3DFX::Resize() {
  849.     mbSwapChainImageValid = false;
  850.     mbSwapChainPresentPending = false;
  851.     mbSwapChainPresentPolling = false;
  852.     if (GetClientRect(mhwnd, &mrClient)) {
  853.         if (mhwndError)
  854.             SetWindowPos(mhwndError, NULL, 0, 0, mrClient.right, mrClient.bottom, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  855.     }
  856.     return true;
  857. }
  858.  
  859. bool VDVideoDisplayMinidriverD3DFX::Update(UpdateMode mode) {
  860.     if (!mpEffect)
  861.         return true;
  862.  
  863.     uint32 fieldMode = mode & kModeFieldMask;
  864.     if (mbForceFrameUpload) {
  865.         if (mode & kModeFirstField)
  866.             fieldMode = kModeAllFields;
  867.         else if ((mode & kModeFieldMask) != kModeAllFields) {
  868.             UpdateBackbuffer(mrClient, mode);
  869.             mSource.mpCB->ReleaseActiveFrame();
  870.             return true;
  871.         }
  872.     }
  873.  
  874.     int fieldMask = 3;
  875.  
  876.     switch(fieldMode) {
  877.         case kModeEvenField:
  878.             fieldMask = 1;
  879.             break;
  880.  
  881.         case kModeOddField:
  882.             fieldMask = 2;
  883.             break;
  884.  
  885.         case kModeAllFields:
  886.             break;
  887.     }
  888.  
  889.     bool success = mpUploadContext->Update(mSource.pixmap, fieldMask);
  890.  
  891.     mSource.mpCB->ReleaseActiveFrame();
  892.  
  893.     if (!success)
  894.         return false;
  895.  
  896.     UpdateBackbuffer(mrClient, mode);
  897.  
  898.     return true;
  899. }
  900.  
  901. void VDVideoDisplayMinidriverD3DFX::Refresh(UpdateMode mode) {
  902.     RECT r;
  903.     GetClientRect(mhwnd, &r);
  904.     if (r.right > 0 && r.bottom > 0) {
  905.         Paint(NULL, r, mode);
  906.     }
  907. }
  908.  
  909. bool VDVideoDisplayMinidriverD3DFX::Paint(HDC hdc, const RECT& rClient, UpdateMode updateMode) {
  910.     if (!mpEffect) {
  911.         mSource.mpCB->ReleaseActiveFrame();
  912.         return true;
  913.     }
  914.  
  915.     return (mbSwapChainImageValid || UpdateBackbuffer(rClient, updateMode)) && UpdateScreen(rClient, updateMode, (updateMode & kModeVSync) != 0);
  916. }
  917.  
  918. void VDVideoDisplayMinidriverD3DFX::SetLogicalPalette(const uint8 *pLogicalPalette) {
  919. }
  920.  
  921. bool VDVideoDisplayMinidriverD3DFX::UpdateBackbuffer(const RECT& rClient0, UpdateMode updateMode) {
  922.     VDASSERT(!mbSwapChainPresentPending);
  923.     uint64 startTime = VDGetPreciseTick();
  924.     RECT rClient = rClient0;
  925.  
  926.     int rtw = mpManager->GetMainRTWidth();
  927.     int rth = mpManager->GetMainRTHeight();
  928.     if (mbFullScreen) {
  929.         rClient.right = rtw;
  930.         rClient.bottom = rth;
  931.     }
  932.     RECT rClippedClient={0,0,std::min<int>(rClient.right, mpManager->GetMainRTWidth()), std::min<int>(rClient.bottom, mpManager->GetMainRTHeight())};
  933.  
  934.     vdsize32 vpsize(rClippedClient.right, rClippedClient.bottom);
  935.     CreateCustomTextures(false, &vpsize);
  936.  
  937.     // Make sure the device is sane.
  938.     if (!mpManager->CheckDevice())
  939.         return false;
  940.  
  941.     IDirect3DTexture9 *tex = mpUploadContext->GetD3DTexture(0);
  942.     D3DSURFACE_DESC texdesc;
  943.     HRESULT hr = tex->GetLevelDesc(0, &texdesc);
  944.     if (FAILED(hr))
  945.         return false;
  946.  
  947.     // Check if we need to create or resize the swap chain.
  948.     if (mSwapChainW >= rClippedClient.right + 128 || mSwapChainH >= rClippedClient.bottom + 128) {
  949.         mpSwapChain = NULL;
  950.         mSwapChainW = 0;
  951.         mSwapChainH = 0;
  952.     }
  953.  
  954.     if (!mbFullScreen && (!mpSwapChain || mSwapChainW < rClippedClient.right || mSwapChainH < rClippedClient.bottom)) {
  955.         int scw = std::min<int>((rClippedClient.right + 127) & ~127, rtw);
  956.         int sch = std::min<int>((rClippedClient.bottom + 127) & ~127, rth);
  957.  
  958.         VDDEBUG("Resizing swap chain to %dx%d\n", scw, sch);
  959.  
  960.         if (!mpManager->CreateSwapChain(scw, sch, mbClipToMonitor, ~mpSwapChain))
  961.             return false;
  962.  
  963.         mSwapChainW = scw;
  964.         mSwapChainH = sch;
  965.     }
  966.  
  967.     // Do we need to switch bicubic modes?
  968.     FilterMode mode = mPreferredFilter;
  969.  
  970.     if (mode == kFilterAnySuitable)
  971.         mode = kFilterBicubic;
  972.  
  973.     // begin rendering
  974. //    mLatencyFence = mLatencyFenceNext;
  975. //    mLatencyFenceNext = mpManager->InsertFence();
  976. //    mLatencyFence = mpManager->InsertFence();
  977.  
  978.     if (mColorOverride) {
  979.         mpManager->SetSwapChainActive(mpSwapChain);
  980.  
  981.         D3DRECT rClear;
  982.         rClear.x1 = rClient.left;
  983.         rClear.y1 = rClient.top;
  984.         rClear.x2 = rClient.right;
  985.         rClear.y2 = rClient.bottom;
  986.  
  987.         HRESULT hr = mpD3DDevice->Clear(1, &rClear, D3DCLEAR_TARGET, mColorOverride, 0.0f, 0);
  988.         mpManager->SetSwapChainActive(NULL);
  989.  
  990.         if (FAILED(hr))
  991.             return false;
  992.     } else {
  993.         D3D_AUTOBREAK(SetStreamSource(0, mpManager->GetVertexBuffer(), 0, sizeof(Vertex)));
  994.         D3D_AUTOBREAK(SetIndices(mpManager->GetIndexBuffer()));
  995.         D3D_AUTOBREAK(SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2));
  996.         D3D_AUTOBREAK(SetRenderState(D3DRS_LIGHTING, FALSE));
  997.         D3D_AUTOBREAK(SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE));
  998.         D3D_AUTOBREAK(SetRenderState(D3DRS_ZENABLE, FALSE));
  999.         D3D_AUTOBREAK(SetRenderState(D3DRS_ALPHATESTENABLE, FALSE));
  1000.         D3D_AUTOBREAK(SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE));
  1001.         D3D_AUTOBREAK(SetRenderState(D3DRS_STENCILENABLE, FALSE));
  1002.         D3D_AUTOBREAK(SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD));
  1003.  
  1004.         vdrefptr<IDirect3DSurface9> pRTMain;
  1005.  
  1006.         if (mpSwapChain) {
  1007.             IDirect3DSwapChain9 *sc = mpSwapChain->GetD3DSwapChain();
  1008.             hr = sc->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, ~pRTMain);
  1009.             if (FAILED(hr))
  1010.                 return false;
  1011.         } else {
  1012.             mpManager->SetSwapChainActive(NULL);
  1013.             mpD3DDevice->GetRenderTarget(0, ~pRTMain);
  1014.         }
  1015.  
  1016.         mbSwapChainImageValid = false;
  1017.  
  1018.         D3D_AUTOBREAK(SetRenderTarget(0, pRTMain));
  1019.         D3D_AUTOBREAK(BeginScene());
  1020.  
  1021.         D3DVIEWPORT9 vp = {
  1022.             0,
  1023.             0,
  1024.             rClippedClient.right,
  1025.             rClippedClient.bottom,
  1026.             0.f,
  1027.             1.f
  1028.         };
  1029.  
  1030.         D3D_AUTOBREAK(SetViewport(&vp));
  1031.  
  1032.         // fill vertex/index buffers
  1033.         if (Vertex *pvx = mpManager->LockVertices(4)) {
  1034.             float umax = (float)mSource.pixmap.w / (float)(int)texdesc.Width;
  1035.             float vmax = (float)mSource.pixmap.h / (float)(int)texdesc.Height;
  1036.             float x0 = -1.f - 1.f/rClippedClient.right;
  1037.             float x1 = x0 + 2.0f*(rClient.right / rClippedClient.right);
  1038.             float y0 = 1.f + 1.f/rClippedClient.bottom;
  1039.             float y1 = y0 - 2.0f*(rClient.bottom / rClippedClient.bottom);
  1040.  
  1041.             pvx[0].SetFF2(x0, y0, 0, 0, 0, 0, 0);
  1042.             pvx[1].SetFF2(x0, y1, 0, 0, vmax, 0, 1);
  1043.             pvx[2].SetFF2(x1, y0, 0, umax, 0, 1, 0);
  1044.             pvx[3].SetFF2(x1, y1, 0, umax, vmax, 1, 1);
  1045.  
  1046.             mpManager->UnlockVertices();
  1047.         }
  1048.  
  1049.         if (uint16 *dst = mpManager->LockIndices(6)) {
  1050.             dst[0] = 0;
  1051.             dst[1] = 1;
  1052.             dst[2] = 2;
  1053.             dst[3] = 2;
  1054.             dst[4] = 1;
  1055.             dst[5] = 3;
  1056.  
  1057.             mpManager->UnlockIndices();
  1058.         }
  1059.  
  1060.         UpdateEffectParameters(vp, texdesc);
  1061.  
  1062.         UINT passes;
  1063.         D3DXHANDLE hTechnique = mhTechniques[mode - 1];
  1064.         D3D_AUTOBREAK_2(mpEffect->SetTechnique(hTechnique));
  1065.         D3D_AUTOBREAK_2(mpEffect->Begin(&passes, 0));
  1066.  
  1067.         IDirect3DSurface9 *pLastRT = pRTMain;
  1068.  
  1069.         for(UINT pass=0; pass<passes; ++pass) {
  1070.             D3DXHANDLE hPass = mpEffect->GetPass(hTechnique, pass);
  1071.  
  1072.             D3DXHANDLE hFieldAnno = mpEffect->GetAnnotationByName(hPass, "vd_fieldmask");
  1073.             if (hFieldAnno) {
  1074.                 INT fieldMask;
  1075.  
  1076.                 if (SUCCEEDED(mpEffect->GetInt(hFieldAnno, &fieldMask))) {
  1077.                     const uint32 fieldMode = updateMode & kModeFieldMask;
  1078.  
  1079.                     if (!(fieldMode & fieldMask))
  1080.                         continue;
  1081.                 }
  1082.             }
  1083.  
  1084.             vdrefptr<IDirect3DSurface9> pNewRTRef;
  1085.             IDirect3DSurface9 *pNewRT = NULL;
  1086.  
  1087.             if (D3DXHANDLE hTarget = mpEffect->GetAnnotationByName(hPass, "vd_target")) {
  1088.                 const char *s;
  1089.  
  1090.                 if (SUCCEEDED(mpEffect->GetString(hTarget, &s)) && s) {
  1091.                     if (!strcmp(s, "temp"))
  1092.                         pNewRT = mpD3DTempSurface;
  1093.                     else if (!strcmp(s, "temp2"))
  1094.                         pNewRT = mpD3DTempSurface2;
  1095.                     else if (!*s)
  1096.                         pNewRT = pRTMain;
  1097.                     else {
  1098.                         D3DXHANDLE hTextureParam = mpEffect->GetParameterByName(NULL, s);
  1099.                         if (SUCCEEDED(hr)) {
  1100.                             vdrefptr<IDirect3DBaseTexture9> pBaseTex;
  1101.                             hr = mpEffect->GetTexture(hTextureParam, ~pBaseTex);
  1102.                             if (SUCCEEDED(hr) && pBaseTex) {
  1103.                                 switch(pBaseTex->GetType()) {
  1104.                                     case D3DRTYPE_TEXTURE:
  1105.                                         {
  1106.                                             vdrefptr<IDirect3DTexture9> pTex;
  1107.                                             hr = pBaseTex->QueryInterface(IID_IDirect3DTexture9, (void **)~pTex);
  1108.                                             if (SUCCEEDED(hr))
  1109.                                                 hr = pTex->GetSurfaceLevel(0, ~pNewRTRef);
  1110.                                         }
  1111.                                         break;
  1112.                                     case D3DRTYPE_CUBETEXTURE:
  1113.                                         {
  1114.                                             vdrefptr<IDirect3DCubeTexture9> pTex;
  1115.                                             hr = pBaseTex->QueryInterface(IID_IDirect3DCubeTexture9, (void **)~pTex);
  1116.                                             if (SUCCEEDED(hr))
  1117.                                                 hr = pTex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, ~pNewRTRef);
  1118.                                         }
  1119.                                         break;
  1120.                                 }
  1121.  
  1122.                                 pNewRT = pNewRTRef;
  1123.                             }
  1124.                         }
  1125.                     }
  1126.                 }
  1127.             }
  1128.  
  1129.             if (pNewRT && pLastRT != pNewRT) {
  1130.                 pLastRT = pNewRT;
  1131.  
  1132.                 D3D_AUTOBREAK(SetRenderTarget(0, pNewRT));
  1133.  
  1134.                 if (pNewRT == pRTMain)
  1135.                     D3D_AUTOBREAK(SetViewport(&vp));
  1136.             }
  1137.  
  1138.             if (D3DXHANDLE hClear = mpEffect->GetAnnotationByName(hPass, "vd_clear")) {
  1139.                 float clearColor[4];
  1140.  
  1141.                 if (SUCCEEDED(mpEffect->GetVector(hClear, (D3DXVECTOR4 *)clearColor))) {
  1142.                     int r = VDRoundToInt(clearColor[0]);
  1143.                     int g = VDRoundToInt(clearColor[1]);
  1144.                     int b = VDRoundToInt(clearColor[2]);
  1145.                     int a = VDRoundToInt(clearColor[3]);
  1146.  
  1147.                     if ((unsigned)r >= 256) r = (~r >> 31) & 255;
  1148.                     if ((unsigned)g >= 256) g = (~g >> 31) & 255;
  1149.                     if ((unsigned)b >= 256) b = (~b >> 31) & 255;
  1150.                     if ((unsigned)a >= 256) a = (~a >> 31) & 255;
  1151.  
  1152.                     D3DCOLOR clearColor = (a<<24) + (r<<16) + (g<<8) + b;
  1153.  
  1154.                     D3D_AUTOBREAK(Clear(0, NULL, D3DCLEAR_TARGET, clearColor, 1.f, 0));
  1155.                 }
  1156.             }
  1157.  
  1158.             D3D_AUTOBREAK_2(mpEffect->BeginPass(pass));
  1159.  
  1160.             mpManager->DrawElements(D3DPT_TRIANGLELIST, 0, 4, 0, 2);
  1161.  
  1162.             D3D_AUTOBREAK_2(mpEffect->EndPass());
  1163.         }
  1164.  
  1165.         D3D_AUTOBREAK_2(mpEffect->End());
  1166.  
  1167.         if (mbDisplayDebugInfo && mpFontRenderer) {
  1168.             if (!(++mTimingStringCounter & 63)) {
  1169.                 mTimingString.sprintf("Longest present: %4.2fms  Longest frame: %4.2fms", mLastLongestPresentTime * 1000.0f, mLastLongestFrameTime * 1000.0f);
  1170.                 mLastLongestPresentTime = 0.0f;
  1171.                 mLastLongestFrameTime = 0.0f;
  1172.             }
  1173.  
  1174.             if (mpFontRenderer->Begin()) {
  1175.                 VDStringA s;
  1176.  
  1177.                 VDStringA desc;
  1178.                 GetFormatString(mSource, desc);
  1179.                 s.sprintf("D3DFX minidriver - %s", desc.c_str());
  1180.                 mpFontRenderer->DrawTextLine(10, rClient.bottom - 40, 0xFFFFFF00, 0, s.c_str());
  1181.  
  1182.                 mpFontRenderer->DrawTextLine(10, rClient.bottom - 20, 0xFFFFFF00, 0, mTimingString.c_str());
  1183.                 mpFontRenderer->End();
  1184.             }
  1185.         }
  1186.  
  1187.         D3D_AUTOBREAK(EndScene());
  1188.     }
  1189.  
  1190.     mpManager->Flush();
  1191.     mpManager->SetSwapChainActive(NULL);
  1192.     mbSwapChainImageValid = true;
  1193.     mbSwapChainPresentPending = true;
  1194.     mbSwapChainPresentPolling = false;
  1195. //    mLatencyFence = mLatencyFenceNext;
  1196. //    mLatencyFenceNext = mpManager->InsertFence();
  1197.  
  1198. d3d_failed:
  1199.     return true;
  1200. }
  1201.  
  1202. bool VDVideoDisplayMinidriverD3DFX::UpdateScreen(const RECT& rClient, UpdateMode updateMode, bool polling) {
  1203.     if (!mbSwapChainImageValid || (!mbFullScreen && !mpSwapChain))
  1204.         return false;
  1205.  
  1206.     if (polling) {
  1207.         if (mLatencyFence) {
  1208.             if (!mpManager->IsFencePassed(mLatencyFence))
  1209.                 return true;
  1210.  
  1211.             mLatencyFence = 0;
  1212.         }
  1213.     }
  1214.  
  1215.     HRESULT hr;
  1216.     if (mbFullScreen) {
  1217.         uint64 tstart = VDGetPreciseTick();
  1218.         hr = mpManager->PresentFullScreen(!polling);
  1219.  
  1220.         float tdelta = (float)((VDGetPreciseTick() - tstart) * VDGetPreciseSecondsPerTick());
  1221.  
  1222.         if (tdelta > mLastLongestPresentTime)
  1223.             mLastLongestPresentTime = tdelta;
  1224.     } else {
  1225.         hr = mpManager->PresentSwapChain(mpSwapChain, &rClient, mhwnd, (updateMode & kModeVSync) != 0, !polling || !mbSwapChainPresentPolling, polling, mSyncDelta, mPresentHistory);
  1226.         mbSwapChainPresentPolling = true;
  1227.     }
  1228.  
  1229.     bool dec = false;
  1230.     if (hr == S_FALSE)
  1231.         return true;
  1232.     else if (hr == S_OK) {
  1233.         uint64 curTime = VDGetPreciseTick();
  1234.         float ft = (float)((curTime - mLastFrameTime) * VDGetPreciseSecondsPerTick());
  1235.         if (mLastLongestFrameTime < ft)
  1236.             mLastLongestFrameTime = ft;
  1237.         mLastFrameTime = curTime;
  1238.     }
  1239.  
  1240.     if (mbSwapChainPresentPending) {
  1241.         mbSwapChainPresentPending = false;
  1242.         mbSwapChainPresentPolling = false;
  1243.         dec = true;
  1244.     }
  1245.  
  1246.     mLatencyFence = mLatencyFenceNext;
  1247.     mLatencyFenceNext = 0;
  1248.  
  1249.     // Workaround for Windows Vista DWM composition chain not updating.
  1250.     if (!mbFullScreen && mbFirstPresent) {
  1251.         SetWindowPos(mhwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED);
  1252.         mbFirstPresent = false;
  1253.     }
  1254.  
  1255.     if (FAILED(hr)) {
  1256.         VDDEBUG("VideoDisplay/D3DFX: Render failed -- applying boot to the head.\n");
  1257.  
  1258.         if (!mpManager->Reset())
  1259.             return false;
  1260.     } else if (dec) {
  1261.         mSource.mpCB->RequestNextFrame();
  1262.     }
  1263.  
  1264.     return true;
  1265. }
  1266.  
  1267. void VDVideoDisplayMinidriverD3DFX::DisplayError() {
  1268.     if (mhwndError) {
  1269.         DestroyWindow(mhwndError);
  1270.         mhwndError = NULL;
  1271.     }
  1272.  
  1273.     HINSTANCE hInst = VDGetLocalModuleHandleW32();
  1274.     if (VDIsWindowsNT())
  1275.         mhwndError = CreateWindowW(L"EDIT", mError.c_str(), WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY, 0, 0, mrClient.right, mrClient.bottom, mhwnd, NULL, hInst, NULL);
  1276.     else
  1277.         mhwndError = CreateWindowA("EDIT", VDTextWToA(mError).c_str(), WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY, 0, 0, mrClient.right, mrClient.bottom, mhwnd, NULL, hInst, NULL);
  1278.  
  1279.     if (mhwndError)
  1280.         SendMessage(mhwndError, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
  1281. }
  1282.  
  1283. void VDVideoDisplayMinidriverD3DFX::PreprocessEffectParameters() {
  1284.     mParamBindings.clear();
  1285.  
  1286.     D3DXEFFECT_DESC effdesc;
  1287.     HRESULT hr = mpEffect->GetDesc(&effdesc);
  1288.  
  1289.     ParamBinding binding={};
  1290.     if (VDINLINEASSERT(SUCCEEDED(hr))) {
  1291.         for(UINT parmidx = 0; parmidx < effdesc.Parameters; ++parmidx) {
  1292.             D3DXHANDLE hparm = mpEffect->GetParameter(NULL, parmidx);
  1293.             if (!hparm)
  1294.                 continue;
  1295.  
  1296.             D3DXPARAMETER_DESC parmdesc;
  1297.             hr = mpEffect->GetParameterDesc(hparm, &parmdesc);
  1298.             if (VDINLINEASSERTFALSE(FAILED(hr)))
  1299.                 continue;
  1300.  
  1301.             static const struct ParamInfo {
  1302.                 D3DXPARAMETER_CLASS    mClass;
  1303.                 D3DXPARAMETER_TYPE    mType;
  1304.                 const char            *mpSemantic;
  1305.                 ParamUploadMethod    mpMethod;
  1306.             } kParamInfo[]={
  1307.                 { D3DXPC_VECTOR, D3DXPT_FLOAT,    "RenderTargetDimensions",    &VDVideoDisplayMinidriverD3DFX::UpdateParam_RenderTargetDimensions },
  1308.                 { D3DXPC_VECTOR, D3DXPT_FLOAT,    "ViewportPixelSize",        &VDVideoDisplayMinidriverD3DFX::UpdateParam_ViewportPixelSize }
  1309.             };
  1310.  
  1311.             binding.mpFn = NULL;
  1312.             for(int i=0; i<sizeof(kParamInfo)/sizeof(kParamInfo[0]); ++i) {
  1313.                 const ParamInfo& pi = kParamInfo[i];
  1314.  
  1315.                 if (parmdesc.Class == pi.mClass && parmdesc.Type == pi.mType && parmdesc.Semantic && !_stricmp(parmdesc.Semantic, pi.mpSemantic)) {
  1316.                     binding.mpFn = pi.mpMethod;
  1317.                     break;
  1318.                 }
  1319.             }
  1320.  
  1321.             if (binding.mpFn) {
  1322.                 binding.mhParam = hparm;
  1323.                 mParamBindings.push_back(binding);
  1324.             }
  1325.         }
  1326.     }
  1327. }
  1328.  
  1329. void VDVideoDisplayMinidriverD3DFX::UpdateParam_RenderTargetDimensions(const ParamBinding& binding) {
  1330.     vdrefptr<IDirect3DSurface9> rt;
  1331.     HRESULT hr = mpD3DDevice->GetRenderTarget(0, ~rt);
  1332.     if (SUCCEEDED(hr)) {
  1333.         D3DSURFACE_DESC surfdesc;
  1334.         hr = rt->GetDesc(&surfdesc);
  1335.         if (SUCCEEDED(hr)) {
  1336.             D3DXVECTOR4 v4;
  1337.             v4.x = (float)surfdesc.Width;
  1338.             v4.y = (float)surfdesc.Height;
  1339.             v4.z = 0.0f;
  1340.             v4.w = 1.0f;
  1341.  
  1342.             mpEffect->SetVector(binding.mhParam, &v4);
  1343.         }
  1344.     }
  1345. }
  1346.  
  1347. void VDVideoDisplayMinidriverD3DFX::UpdateParam_ViewportPixelSize(const ParamBinding& binding) {
  1348.     D3DVIEWPORT9 vp;
  1349.     HRESULT hr = mpD3DDevice->GetViewport(&vp);
  1350.  
  1351.     if (SUCCEEDED(hr)) {
  1352.         D3DXVECTOR4 v4;
  1353.         v4.x = (float)vp.Width;
  1354.         v4.y = (float)vp.Height;
  1355.         v4.z = 0.0f;
  1356.         v4.w = 1.0f;
  1357.     }
  1358. }
  1359.  
  1360. void VDVideoDisplayMinidriverD3DFX::UpdateEffectParameters(const D3DVIEWPORT9& vp, const D3DSURFACE_DESC& texdesc) {
  1361.     // render the effect
  1362.     StdParamData data;
  1363.  
  1364.     data.vpsize[0] = (float)vp.Width;
  1365.     data.vpsize[1] = (float)vp.Height;
  1366.     data.vpsize[2] = 1.0f / (float)vp.Height;
  1367.     data.vpsize[3] = 1.0f / (float)vp.Width;
  1368.     data.texsize[0] = (float)(int)texdesc.Width;
  1369.     data.texsize[1] = (float)(int)texdesc.Height;
  1370.     data.texsize[2] = 1.0f / (float)(int)texdesc.Height;
  1371.     data.texsize[3] = 1.0f / (float)(int)texdesc.Width;
  1372.     data.srcsize[0] = (float)mSource.pixmap.w;
  1373.     data.srcsize[1] = (float)mSource.pixmap.h;
  1374.     data.srcsize[2] = 1.0f / (float)mSource.pixmap.h;
  1375.     data.srcsize[3] = 1.0f / (float)mSource.pixmap.w;
  1376.     data.tempsize[0] = 1.f;
  1377.     data.tempsize[1] = 1.f;
  1378.     data.tempsize[2] = 1.f;
  1379.     data.tempsize[3] = 1.f;
  1380.     data.temp2size[0] = 1.f;
  1381.     data.temp2size[1] = 1.f;
  1382.     data.temp2size[2] = 1.f;
  1383.     data.temp2size[3] = 1.f;
  1384.     data.vpcorrect[0] = 2.0f / vp.Width;
  1385.     data.vpcorrect[1] = 2.0f / vp.Height;
  1386.     data.vpcorrect[2] = -1.0f / (float)vp.Height;
  1387.     data.vpcorrect[3] = 1.0f / (float)vp.Width;
  1388.     data.vpcorrect2[0] = 2.0f / vp.Width;
  1389.     data.vpcorrect2[1] = -2.0f / vp.Height;
  1390.     data.vpcorrect2[2] = 1.0f + 1.0f / (float)vp.Height;
  1391.     data.vpcorrect2[3] = -1.0f - 1.0f / (float)vp.Width;
  1392.     data.tvpcorrect[0] = 2.0f;
  1393.     data.tvpcorrect[1] = 2.0f;
  1394.     data.tvpcorrect[2] = -1.0f;
  1395.     data.tvpcorrect[3] = 1.0f;
  1396.     data.tvpcorrect2[0] = 2.0f;
  1397.     data.tvpcorrect2[1] = -2.0f;
  1398.     data.tvpcorrect2[2] = 0.f;
  1399.     data.tvpcorrect2[3] = 2.0f;
  1400.     data.t2vpcorrect[0] = 2.0f;
  1401.     data.t2vpcorrect[1] = 2.0f;
  1402.     data.t2vpcorrect[2] = -1.0f;
  1403.     data.t2vpcorrect[3] = 1.0f;
  1404.     data.t2vpcorrect2[0] = 2.0f;
  1405.     data.t2vpcorrect2[1] = -2.0f;
  1406.     data.t2vpcorrect2[2] = 0.f;
  1407.     data.t2vpcorrect2[3] = 2.0f;
  1408.     data.time[0] = (GetTickCount() % 30000) / 30000.0f;
  1409.     data.time[1] = 1;
  1410.     data.time[2] = 2;
  1411.     data.time[3] = 3;
  1412.  
  1413.     if (mhSrcTexture)
  1414.         mpEffect->SetTexture(mhSrcTexture, mpUploadContext->GetD3DTexture(0));
  1415.  
  1416.     if (mhPrevSrcTexture)
  1417.         mpEffect->SetTexture(mhPrevSrcTexture, mpUploadContext->GetD3DTexture(1));
  1418.  
  1419.     if (mhPrevSrc2Texture)
  1420.         mpEffect->SetTexture(mhPrevSrc2Texture, mpUploadContext->GetD3DTexture(2));
  1421.  
  1422.     if (mhTempTexture) {
  1423.         mpEffect->SetTexture(mhTempTexture, mpD3DTempTexture);
  1424.  
  1425.         float tempw = (float)mpTempTexture->GetWidth();
  1426.         float temph = (float)mpTempTexture->GetHeight();
  1427.  
  1428.         data.tempsize[0] = tempw;
  1429.         data.tempsize[1] = temph;
  1430.         data.tempsize[2] = 1.0f / temph;
  1431.         data.tempsize[3] = 1.0f / tempw;
  1432.         data.tvpcorrect[0] = 2.0f * data.tempsize[3];
  1433.         data.tvpcorrect[1] = 2.0f * data.tempsize[2];
  1434.         data.tvpcorrect[2] = -data.tempsize[2];
  1435.         data.tvpcorrect[3] = data.tempsize[3];
  1436.         data.tvpcorrect2[0] = 2.0f * data.tempsize[3];
  1437.         data.tvpcorrect2[1] = -2.0f * data.tempsize[2];
  1438.         data.tvpcorrect2[2] = 1.0f + data.tempsize[2];
  1439.         data.tvpcorrect2[3] = -1.0f - data.tempsize[3];
  1440.     }
  1441.  
  1442.     if (mhTempTexture2) {
  1443.         mpEffect->SetTexture(mhTempTexture2, mpD3DTempTexture2);
  1444.  
  1445.         float temp2w = (float)mpTempTexture2->GetWidth();
  1446.         float temp2h = (float)mpTempTexture2->GetHeight();
  1447.  
  1448.         data.temp2size[0] = temp2w;
  1449.         data.temp2size[1] = temp2h;
  1450.         data.temp2size[2] = 1.0f / temp2h;
  1451.         data.temp2size[3] = 1.0f / temp2w;
  1452.         data.t2vpcorrect[0] = 2.0f * data.temp2size[3];
  1453.         data.t2vpcorrect[1] = 2.0f * data.temp2size[2];
  1454.         data.t2vpcorrect[2] = -data.temp2size[2];
  1455.         data.t2vpcorrect[3] = data.temp2size[3];
  1456.         data.t2vpcorrect2[0] = 2.0f * data.temp2size[3];
  1457.         data.t2vpcorrect2[1] = -2.0f * data.temp2size[2];
  1458.         data.t2vpcorrect2[2] = 1.0f + data.temp2size[2];
  1459.         data.t2vpcorrect2[3] = -1.0f - data.temp2size[3];
  1460.     }
  1461.  
  1462.     for(int i=0; i<kStdParamCount; ++i) {
  1463.         D3DXHANDLE h = mhStdParamHandles[i];
  1464.  
  1465.         if (h)
  1466.             mpEffect->SetVector(h, (const D3DXVECTOR4 *)((const char *)&data + kStdParamInfo[i].offset));
  1467.     }
  1468.  
  1469.     ParamBindings::const_iterator it(mParamBindings.begin()), itEnd(mParamBindings.end());
  1470.     for(; it!=itEnd; ++it) {
  1471.         const ParamBinding& binding = *it;
  1472.  
  1473.         (this->*binding.mpFn)(binding);
  1474.     }
  1475. }
  1476.  
  1477. void VDVideoDisplayMinidriverD3DFX::CreateCustomTextureBindings() {
  1478.     mParamBindings.clear();
  1479.  
  1480.     D3DXEFFECT_DESC effdesc;
  1481.     HRESULT hr = mpEffect->GetDesc(&effdesc);
  1482.  
  1483.     TextureBinding binding = {};
  1484.     VDStringA    sizename;
  1485.     if (VDINLINEASSERT(SUCCEEDED(hr))) {
  1486.         for(UINT parmidx = 0; parmidx < effdesc.Parameters; ++parmidx) {
  1487.             D3DXHANDLE hparm = mpEffect->GetParameter(NULL, parmidx);
  1488.             if (!hparm)
  1489.                 continue;
  1490.  
  1491.             D3DXPARAMETER_DESC parmdesc;
  1492.             hr = mpEffect->GetParameterDesc(hparm, &parmdesc);
  1493.             if (VDINLINEASSERTFALSE(FAILED(hr)))
  1494.                 continue;
  1495.  
  1496.             switch(parmdesc.Type) {
  1497.                 case D3DXPT_TEXTURE:
  1498.                 case D3DXPT_TEXTURE1D:
  1499.                 case D3DXPT_TEXTURE2D:
  1500.                     binding.mResType = D3DRTYPE_TEXTURE;
  1501.                     break;
  1502.                 case D3DXPT_TEXTURE3D:
  1503.                     binding.mResType = D3DRTYPE_VOLUMETEXTURE;
  1504.                     break;
  1505.                 case D3DXPT_TEXTURECUBE:
  1506.                     binding.mResType = D3DRTYPE_CUBETEXTURE;
  1507.                     break;
  1508.                 default:
  1509.                     continue;
  1510.             }
  1511.  
  1512.             D3DXHANDLE hAnnoResourceType    = mpEffect->GetAnnotationByName(hparm, "ResourceType");
  1513.             D3DXHANDLE hAnnoDimensions        = mpEffect->GetAnnotationByName(hparm, "Dimensions");
  1514.             D3DXHANDLE hAnnoFormat            = mpEffect->GetAnnotationByName(hparm, "Format");
  1515.             D3DXHANDLE hAnnoFunction        = mpEffect->GetAnnotationByName(hparm, "Function");
  1516.             D3DXHANDLE hAnnoMIPLevels        = mpEffect->GetAnnotationByName(hparm, "MIPLevels");
  1517.             D3DXHANDLE hAnnoViewportRatio    = mpEffect->GetAnnotationByName(hparm, "ViewportRatio");
  1518.  
  1519.             D3DXHANDLE hAnnoWidth            = mpEffect->GetAnnotationByName(hparm, "width");
  1520.             D3DXHANDLE hAnnoHeight            = mpEffect->GetAnnotationByName(hparm, "height");
  1521.  
  1522.             if (!hAnnoFormat)
  1523.                 hAnnoFormat = mpEffect->GetAnnotationByName(hparm, "format");
  1524.  
  1525.             if (!hAnnoFunction)
  1526.                 hAnnoFunction = mpEffect->GetAnnotationByName(hparm, "function");
  1527.  
  1528.             binding.mpTexture        = NULL;
  1529.             binding.mpTextureShader    = NULL;
  1530.             binding.mhParam            = hparm;
  1531.             binding.mFormat            = D3DFMT_A8R8G8B8;
  1532.             binding.mPool            = D3DPOOL_MANAGED;
  1533.             binding.mUsage            = 0;
  1534.             binding.mWidth            = 64;
  1535.             binding.mHeight            = 64;
  1536.             binding.mDepth            = 1;
  1537.             binding.mMipLevels        = 1;
  1538.             binding.mViewportRatioW    = 0;
  1539.             binding.mViewportRatioH    = 0;
  1540.  
  1541.             if (parmdesc.Semantic) {
  1542.                 if (!_stricmp(parmdesc.Semantic, "RenderColorTarget")) {
  1543.                     binding.mUsage    = D3DUSAGE_RENDERTARGET;
  1544.                     binding.mPool    = D3DPOOL_DEFAULT;
  1545.                 } else if (!_stricmp(parmdesc.Semantic, "RenderDepthStencilTarget")) {
  1546.                     binding.mUsage    = D3DUSAGE_DEPTHSTENCIL;
  1547.                     binding.mPool    = D3DPOOL_DEFAULT;
  1548.                 }
  1549.             }
  1550.  
  1551.             if (hAnnoResourceType) {
  1552.                 LPCSTR s;
  1553.  
  1554.                 hr = mpEffect->GetString(hAnnoResourceType, &s);
  1555.                 if (SUCCEEDED(hr)) {
  1556.                     if (!_stricmp(s, "1D"))
  1557.                         binding.mResType = D3DRTYPE_TEXTURE;
  1558.                     else if (!_stricmp(s, "2D"))
  1559.                         binding.mResType = D3DRTYPE_TEXTURE;
  1560.                     else if (!_stricmp(s, "3D"))
  1561.                         binding.mResType = D3DRTYPE_VOLUMETEXTURE;
  1562.                     else if (!_stricmp(s, "cube"))
  1563.                         binding.mResType = D3DRTYPE_CUBETEXTURE;
  1564.                     else
  1565.                         throw MyError("Texture parameter %s has an unrecognizable resource type: %s", parmdesc.Name, s);
  1566.                 }
  1567.             }
  1568.  
  1569.             if (hAnnoDimensions) {
  1570.                 D3DXVECTOR4 v4dim;
  1571.  
  1572.                 hr = mpEffect->GetVector(hAnnoDimensions, &v4dim);
  1573.                 if (SUCCEEDED(hr)) {
  1574.                     binding.mWidth    = VDRoundToInt(v4dim.x);
  1575.                     binding.mHeight    = VDRoundToInt(v4dim.y);
  1576.                     binding.mDepth    = VDRoundToInt(v4dim.z);
  1577.                 }
  1578.             } else if (hAnnoWidth && hAnnoHeight) {
  1579.                 int w;
  1580.                 int h;
  1581.                 hr = mpEffect->GetInt(hAnnoWidth, &w);
  1582.                 if (SUCCEEDED(hr)) {
  1583.                     hr = mpEffect->GetInt(hAnnoHeight, &h);
  1584.                     if (SUCCEEDED(hr)) {
  1585.                         binding.mWidth = w;
  1586.                         binding.mHeight = h;
  1587.                     }
  1588.                 }
  1589.             }
  1590.  
  1591.             if (hAnnoFormat) {
  1592.                 LPCSTR s;
  1593.  
  1594.                 hr = mpEffect->GetString(hAnnoFormat, &s);
  1595.                 if (SUCCEEDED(hr)) {
  1596.                     for(int fidx=0; fidx<sizeof(kFormats)/sizeof(kFormats[0]); ++fidx) {
  1597.                         if (!_stricmp(s, kFormats[fidx].mpName)) {
  1598.                             binding.mFormat = kFormats[fidx].mFormat;
  1599.                             break;
  1600.                         }
  1601.                     }
  1602.                 }
  1603.             }
  1604.  
  1605.             if (hAnnoFunction) {
  1606.                 LPCSTR name;
  1607.  
  1608.                 hr = mpEffect->GetString(hAnnoFunction, &name);
  1609.                 if (SUCCEEDED(hr)) {
  1610.                     const char *profile = "tx_1_0";
  1611.  
  1612.                     D3DXHANDLE hAnno;
  1613.                     if (hAnno = mpEffect->GetAnnotationByName(hparm, "target"))
  1614.                         mpEffect->GetString(hAnno, &profile);
  1615.  
  1616.                     // check that the function exists (CompileShader just gives us the dreaded INVALIDCALL
  1617.                     // error in this case)
  1618.         #if 0
  1619.                     if (!mpEffect->GetFunctionByName(pName)) {
  1620.                         mError.sprintf(L"Couldn't create procedural texture '%hs' in effect file %ls:\nUnknown function '%hs'", parmDesc.Name, srcfile.c_str(), pName);
  1621.                         if (pError)
  1622.                             pError->Release();
  1623.                         ShutdownEffect();
  1624.                         return true;
  1625.                     }
  1626.         #endif
  1627.  
  1628.                     // attempt to compile the texture shader
  1629.                     vdrefptr<ID3DXBuffer> pEffectBuffer;
  1630.                     vdrefptr<ID3DXBuffer> pError;
  1631.                     hr = mpEffectCompiler->CompileShader(name, profile, 0, ~pEffectBuffer, ~pError, NULL);
  1632.                     if (FAILED(hr))
  1633.                         throw MyError("Couldn't compile texture shader '%hs':\n%hs", name, pError ? (const char *)pError->GetBufferPointer() : "unknown error");
  1634.  
  1635.                     // create the texture shader
  1636.                     hr = mpD3DXCreateTextureShader((const DWORD *)pEffectBuffer->GetBufferPointer(), &binding.mpTextureShader);
  1637.                     if (FAILED(hr))
  1638.                         throw MyError("Couldn't create texture shader '%hs':\n%hs", name, pError ? (const char *)pError->GetBufferPointer() : "unknown error");
  1639.                 }
  1640.             }
  1641.  
  1642.             if (hAnnoMIPLevels) {
  1643.                 INT mipcount;
  1644.  
  1645.                 hr = mpEffect->GetInt(hAnnoMIPLevels, &mipcount);
  1646.                 if (SUCCEEDED(hr)) {
  1647.                     binding.mMipLevels = mipcount;
  1648.                 }
  1649.             }
  1650.  
  1651.             if (hAnnoViewportRatio) {
  1652.                 D3DXVECTOR4 v4ratio;
  1653.  
  1654.                 hr = mpEffect->GetVector(hAnnoViewportRatio, &v4ratio);
  1655.                 if (SUCCEEDED(hr)) {
  1656.                     binding.mViewportRatioW = v4ratio.x;
  1657.                     binding.mViewportRatioH = v4ratio.y;
  1658.                 }
  1659.             }
  1660.  
  1661.             binding.mhSizeParam = NULL;
  1662.  
  1663.             sizename = parmdesc.Name;
  1664.             sizename += "_size";
  1665.  
  1666.             D3DXHANDLE hsizeparm = mpEffect->GetParameterByName(NULL, sizename.c_str());
  1667.             if (hsizeparm) {
  1668.                 D3DXPARAMETER_DESC sizedesc;
  1669.                 hr = mpEffect->GetParameterDesc(hsizeparm, &sizedesc);
  1670.                 if (SUCCEEDED(hr)) {
  1671.                     if (sizedesc.Class == D3DXPC_VECTOR && sizedesc.Type == D3DXPT_FLOAT)
  1672.                         binding.mhSizeParam = hsizeparm;
  1673.                 }
  1674.             }
  1675.  
  1676.             mTextureBindings.push_back(binding);
  1677.         }
  1678.     }    
  1679. }
  1680.  
  1681. bool VDVideoDisplayMinidriverD3DFX::CreateCustomTextures(bool vramOnly, const vdsize32 *vpsize) {
  1682.     TextureBindings::iterator it(mTextureBindings.begin()), itEnd(mTextureBindings.end());
  1683.     bool success = true;
  1684.  
  1685.     for(; it!=itEnd; ++it) {
  1686.         TextureBinding& binding = *it;
  1687.  
  1688.         if (binding.mPool == D3DPOOL_DEFAULT || !vramOnly) {
  1689.             HRESULT hr = E_FAIL;
  1690.  
  1691.             if (binding.mViewportRatioW > 0 || binding.mViewportRatioH > 0) {
  1692.                 if (!vpsize)
  1693.                     continue;
  1694.  
  1695.                 int w = binding.mWidth;
  1696.                 int h = binding.mHeight;
  1697.  
  1698.                 if (binding.mViewportRatioW > 0)
  1699.                     w = VDCeilToInt((float)vpsize->w * binding.mViewportRatioW);
  1700.                 if (binding.mViewportRatioH > 0)
  1701.                     h = VDCeilToInt((float)vpsize->h * binding.mViewportRatioH);
  1702.  
  1703.                 if (binding.mpTexture) {
  1704.                     if (w == binding.mWidth && h == binding.mHeight)
  1705.                         continue;
  1706.  
  1707.                     binding.mpTexture->Release();
  1708.                     binding.mpTexture = NULL;
  1709.                 }
  1710.  
  1711.                 binding.mWidth = w;
  1712.                 binding.mHeight = h;
  1713.             } else {
  1714.                 if (vpsize)
  1715.                     continue;
  1716.  
  1717.                 if (binding.mpTexture)
  1718.                     continue;
  1719.             }
  1720.             
  1721.             switch(binding.mResType) {
  1722.             case D3DRTYPE_TEXTURE:
  1723.                 {
  1724.                     IDirect3DTexture9 *pTexture;
  1725.                     hr = mpD3DDevice->CreateTexture(binding.mWidth, binding.mHeight, binding.mMipLevels, binding.mUsage, binding.mFormat, binding.mPool, &pTexture, NULL);
  1726.                     if (SUCCEEDED(hr)) {
  1727.                         binding.mpTexture = pTexture;
  1728.                         if (binding.mpTextureShader) {
  1729.                             // fill the texture
  1730.                             hr = mpD3DXFillTextureTX(pTexture, binding.mpTextureShader);
  1731.  
  1732.                             if (FAILED(hr))
  1733.                                 success = false;
  1734.                         }
  1735.                     } else
  1736.                         success = false;
  1737.                 }
  1738.                 break;
  1739.             case D3DRTYPE_CUBETEXTURE:
  1740.                 {
  1741.                     IDirect3DCubeTexture9 *pCubeTexture;
  1742.                     hr = mpD3DDevice->CreateCubeTexture(binding.mWidth, binding.mMipLevels, binding.mUsage, binding.mFormat, binding.mPool, &pCubeTexture, NULL);
  1743.                     if (SUCCEEDED(hr)) {
  1744.                         binding.mpTexture = pCubeTexture;
  1745.                         if (binding.mpTextureShader) {
  1746.                             // fill the texture
  1747.                             hr = mpD3DXFillCubeTextureTX(pCubeTexture, binding.mpTextureShader);
  1748.  
  1749.                             if (FAILED(hr))
  1750.                                 success = false;
  1751.                         }
  1752.                     } else
  1753.                         success = false;
  1754.                 }
  1755.                 break;
  1756.             case D3DRTYPE_VOLUMETEXTURE:
  1757.                 {
  1758.                     IDirect3DVolumeTexture9 *pVolumeTexture;
  1759.                     hr = mpD3DDevice->CreateVolumeTexture(binding.mWidth, binding.mHeight, binding.mDepth, binding.mMipLevels, binding.mUsage, binding.mFormat, binding.mPool, &pVolumeTexture, NULL);
  1760.                     if (SUCCEEDED(hr)) {
  1761.                         binding.mpTexture = pVolumeTexture;
  1762.                         if (binding.mpTextureShader) {
  1763.                             // fill the texture
  1764.                             hr = mpD3DXFillVolumeTextureTX(pVolumeTexture, binding.mpTextureShader);
  1765.  
  1766.                             if (FAILED(hr))
  1767.                                 success = false;
  1768.                         }
  1769.                     } else
  1770.                         success = false;
  1771.                 }
  1772.                 break;
  1773.             }
  1774.  
  1775.             mpEffect->SetTexture(binding.mhParam, binding.mpTexture);
  1776.  
  1777.             if (binding.mhSizeParam) {
  1778.                 D3DXVECTOR4 v4size;
  1779.                 v4size.x = (float)binding.mWidth;
  1780.                 v4size.y = (float)binding.mHeight;
  1781.                 v4size.z = 1.0f / (float)binding.mHeight;
  1782.                 v4size.w = 1.0f / (float)binding.mWidth;
  1783.  
  1784.                 mpEffect->SetVector(binding.mhSizeParam, &v4size);
  1785.             }
  1786.         }
  1787.     }
  1788.  
  1789.     return success;
  1790. }
  1791.  
  1792. void VDVideoDisplayMinidriverD3DFX::DestroyCustomTextures(bool vramOnly) {
  1793.     TextureBindings::iterator it(mTextureBindings.begin()), itEnd(mTextureBindings.end());
  1794.     for(; it!=itEnd; ++it) {
  1795.         TextureBinding& binding = *it;
  1796.  
  1797.         if (binding.mPool == D3DPOOL_DEFAULT || !vramOnly) {
  1798.             mpEffect->SetTexture(binding.mhParam, NULL);
  1799.  
  1800.             if (binding.mpTexture) {
  1801.                 binding.mpTexture->Release();
  1802.                 binding.mpTexture = NULL;
  1803.             }
  1804.         }
  1805.     }
  1806. }
  1807.  
  1808. void VDVideoDisplayMinidriverD3DFX::DestroyCustomTextureBindings() {
  1809.     while(!mTextureBindings.empty()) {
  1810.         TextureBinding& binding = mTextureBindings.back();
  1811.  
  1812.         if (binding.mpTextureShader)
  1813.             binding.mpTextureShader->Release();
  1814.  
  1815.         if (binding.mpTexture)
  1816.             binding.mpTexture->Release();
  1817.  
  1818.         mTextureBindings.pop_back();
  1819.     }
  1820. }
  1821.  
  1822. ///////////////////////////////////////////////////////////////////////////
  1823.  
  1824. void VDVideoDisplaySetD3DFXFileName(const wchar_t *fileName) {
  1825.     g_VDVideoDisplayD3DFXEffectFileName = fileName;
  1826. }
  1827.