Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreD3D9RenderSystem.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://ogre.sourceforge.net/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreD3D9RenderSystem.h"
00026 #include "OgreD3D9Prerequisites.h"
00027 #include "OgreD3D9DriverList.h"
00028 #include "OgreD3D9Driver.h"
00029 #include "OgreD3D9VideoModeList.h"
00030 #include "OgreD3D9VideoMode.h"
00031 #include "OgreD3D9RenderWindow.h"
00032 #include "OgreD3D9TextureManager.h"
00033 #include "OgreD3D9Texture.h"
00034 #include "OgreLogManager.h"
00035 #include "OgreLight.h"
00036 #include "OgreMath.h"
00037 #include "OgreD3D9HardwareBufferManager.h"
00038 #include "OgreD3D9HardwareIndexBuffer.h"
00039 #include "OgreD3D9HardwareVertexBuffer.h"
00040 #include "OgreD3D9VertexDeclaration.h"
00041 #include "OgreD3D9GpuProgram.h"
00042 #include "OgreD3D9GpuProgramManager.h"
00043 #include "OgreD3D9HLSLProgramFactory.h"
00044 #include "OgreHighLevelGpuProgramManager.h"
00045 
00046 namespace Ogre 
00047 {
00048     //---------------------------------------------------------------------
00049     D3D9RenderSystem::D3D9RenderSystem( HINSTANCE hInstance )
00050     {
00051         OgreGuard( "D3D9RenderSystem::D3D9RenderSystem" );
00052         LogManager::getSingleton().logMessage( "D3D9 : " + getName() + " created." );
00053 
00054         // set the instance being passed 
00055         mhInstance = hInstance;
00056 
00057         // set pointers to NULL
00058         mpD3D = NULL;
00059         mpD3DDevice = NULL;
00060         mDriverList = NULL;
00061         mActiveD3DDriver = NULL;
00062         mExternalHandle = NULL;
00063         mTextureManager = NULL;
00064         mHardwareBufferManager = NULL;
00065         mGpuProgramManager = NULL;
00066         mHLSLProgramFactory = NULL;
00067 
00068         // init lights
00069         for(int i = 0; i < MAX_LIGHTS; i++ )
00070             mLights[i] = 0;
00071 
00072         // Create our Direct3D object
00073         if( NULL == (mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
00074             Except( Exception::ERR_INTERNAL_ERROR, "Failed to create Direct3D9 object", "D3D9RenderSystem::D3D9RenderSystem" );
00075 
00076         // set config options defaults
00077         initConfigOptions();
00078 
00079         // fsaa options
00080         mFSAAType = D3DMULTISAMPLE_NONE;
00081         mFSAAQuality = 0;
00082 
00083         // set stages desc. to defaults
00084         for (size_t n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++)
00085         {
00086             mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
00087             mTexStageDesc[n].coordIndex = 0;
00088             mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
00089             mTexStageDesc[n].pTex = 0;
00090         }
00091 
00092         mLastVertexSourceCount = 0;
00093 
00094         mForcedNormalisation = false;
00095         mCurrentLights = 0;
00096 
00097 
00098         OgreUnguard();
00099     }
00100     //---------------------------------------------------------------------
00101     D3D9RenderSystem::~D3D9RenderSystem()
00102     {
00103         OgreGuard( "D3D9RenderSystem::~D3D9RenderSystem" );
00104 
00105         // Unbind any vertex streams to avoid memory leaks
00106         for (unsigned int i = 0; i < mLastVertexSourceCount; ++i)
00107         {
00108             HRESULT hr = mpD3DDevice->SetStreamSource(i, NULL, 0, 0);
00109         }
00110         
00111         
00112         SAFE_DELETE( mDriverList );
00113         SAFE_DELETE( mTextureManager );
00114         SAFE_DELETE(mHardwareBufferManager);
00115         SAFE_DELETE(mHLSLProgramFactory);
00116         SAFE_DELETE(mGpuProgramManager);
00117         SAFE_RELEASE( mpD3D );
00118 
00119         if (mCapabilities)
00120         {
00121             delete mCapabilities;
00122             mCapabilities = NULL;
00123         }
00124 
00125         LogManager::getSingleton().logMessage( "D3D9 : " + getName() + " destroyed." );
00126         OgreUnguard();
00127     }
00128     //---------------------------------------------------------------------
00129     const String& D3D9RenderSystem::getName() const
00130     {
00131         static String strName( "Direct3D9 Rendering SubSystem");
00132         return strName;
00133     }
00134     //---------------------------------------------------------------------
00135     D3D9DriverList* D3D9RenderSystem::getDirect3DDrivers()
00136     {
00137         if( !mDriverList )
00138             mDriverList = new D3D9DriverList( mpD3D );
00139 
00140         return mDriverList;
00141     }
00142     //---------------------------------------------------------------------
00143     bool D3D9RenderSystem::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
00144     {
00145         HRESULT hr;
00146         hr = mpD3D->CheckDeviceMultiSampleType( 
00147                 adapterNum, 
00148                 deviceType, 
00149                 format, 
00150                 fullScreen, 
00151                 type, 
00152                 outQuality);
00153 
00154         if (SUCCEEDED(hr))
00155             return true;
00156         else
00157             return false;
00158     }
00159     //---------------------------------------------------------------------
00160     D3D9RenderSystem::initConfigOptions()
00161     {
00162         OgreGuard( "D3D9RenderSystem::initConfigOptions" );
00163 
00164         D3D9DriverList* driverList;
00165         D3D9Driver* driver;
00166 
00167         ConfigOption optDevice;
00168         ConfigOption optVideoMode;
00169         ConfigOption optFullScreen;
00170         ConfigOption optVSync;
00171         ConfigOption optAA;
00172 
00173         driverList = this->getDirect3DDrivers();
00174 
00175         optDevice.name = "Rendering Device";
00176         optDevice.currentValue = "";
00177         optDevice.possibleValues.clear();
00178         optDevice.immutable = false;
00179 
00180         optVideoMode.name = "Video Mode";
00181         optVideoMode.currentValue = "800 x 600 @ 32-bit colour";
00182         optVideoMode.immutable = false;
00183 
00184         optFullScreen.name = "Full Screen";
00185         optFullScreen.possibleValues.push_back( "Yes" );
00186         optFullScreen.possibleValues.push_back( "No" );
00187         optFullScreen.currentValue = "Yes";
00188         optFullScreen.immutable = false;
00189 
00190         for( unsigned j=0; j < driverList->count(); j++ )
00191         {
00192             driver = driverList->item(j);
00193             optDevice.possibleValues.push_back( driver->DriverDescription() );
00194             // Make first one default
00195             if( j==0 )
00196                 optDevice.currentValue = driver->DriverDescription();
00197         }
00198 
00199         optVSync.name = "VSync";
00200         optVSync.immutable = false;
00201         optVSync.possibleValues.push_back( "Yes" );
00202         optVSync.possibleValues.push_back( "No" );
00203         optVSync.currentValue = "No";
00204 
00205         optAA.name = "Anti aliasing";
00206         optAA.immutable = false;
00207         optAA.possibleValues.push_back( "None" );
00208         optAA.currentValue = "None";
00209 
00210         mOptions[optDevice.name] = optDevice;
00211         mOptions[optVideoMode.name] = optVideoMode;
00212         mOptions[optFullScreen.name] = optFullScreen;
00213         mOptions[optVSync.name] = optVSync;
00214         mOptions[optAA.name] = optAA;
00215 
00216         refreshD3DSettings();
00217 
00218         OgreUnguard();
00219     }
00220     //---------------------------------------------------------------------
00221     void D3D9RenderSystem::refreshD3DSettings()
00222     {
00223         OgreGuard( "D3D9RenderSystem::refreshD3DSettings" );
00224 
00225         ConfigOption* optVideoMode;
00226         D3D9Driver* driver;
00227         D3D9VideoMode* videoMode;
00228 
00229         ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
00230         if( opt != mOptions.end() )
00231         {
00232             for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
00233             {
00234                 driver = getDirect3DDrivers()->item(j);
00235                 if( driver->DriverDescription() == opt->second.currentValue )
00236                     break;
00237             }
00238 
00239             opt = mOptions.find( "Video Mode" );
00240             optVideoMode = &opt->second;
00241             optVideoMode->possibleValues.clear();
00242             // get vide modes for this device
00243             for( unsigned k=0; k < driver->getVideoModeList()->count(); k++ )
00244             {
00245                 videoMode = driver->getVideoModeList()->item( k );
00246                 optVideoMode->possibleValues.push_back( videoMode->getDescription() );
00247             }
00248         }
00249 
00250         OgreUnguard();
00251     }
00252     //---------------------------------------------------------------------
00253     void D3D9RenderSystem::setConfigOption( const String &name, const String &value )
00254     {
00255         OgreGuard( "D3D9RenderSystem::setConfigOption" );
00256 
00257         char msg[128];
00258         sprintf( msg, "D3D9 : RenderSystem Option: %s = %s", name.c_str(), value.c_str() );
00259         LogManager::getSingleton().logMessage( msg );
00260 
00261         // Find option
00262         ConfigOptionMap::iterator it = mOptions.find( name );
00263 
00264         // Update
00265         if( it != mOptions.end() )
00266             it->second.currentValue = value;
00267         else
00268         {
00269             sprintf( msg, "Option named '%s' does not exist.", name.c_str() );
00270             Except( Exception::ERR_INVALIDPARAMS, msg, "D3D9RenderSystem::setConfigOption" );
00271         }
00272 
00273         // Refresh other options if D3DDriver changed
00274         if( name == "Rendering Device" )
00275             refreshD3DSettings();
00276 
00277         if( name == "Full Screen" )
00278         {
00279             // Video mode is applicable
00280             it = mOptions.find( "Video Mode" );
00281             if (it->second.currentValue == "")
00282                 it->second.currentValue = "800 x 600 @ 32-bit colour";
00283         }
00284 
00285         if( name == "Anti aliasing" )
00286         {
00287             if (value == "None")
00288                 _setFSAA(D3DMULTISAMPLE_NONE, 0);
00289             else 
00290             {
00291                 D3DMULTISAMPLE_TYPE fsaa = D3DMULTISAMPLE_NONE;
00292                 DWORD level = 0;
00293 
00294                 if (value.find_first_of("NonMaskable") != -1)
00295                 {
00296                     fsaa = D3DMULTISAMPLE_NONMASKABLE;
00297                     size_t pos = value.find_last_of(" ");
00298                     String sNum = value.substr(pos + 1);
00299                     level = StringConverter::parseInt(sNum);
00300                     level -= 1;
00301                 }
00302                 else if (value.find_first_of("Level") != -1)
00303                 {
00304                     size_t pos = value.find_last_of(" ");
00305                     String sNum = value.substr(pos + 1);
00306                     fsaa = (D3DMULTISAMPLE_TYPE)StringConverter::parseInt(sNum);
00307                 }
00308 
00309                 _setFSAA(fsaa, level);
00310             }
00311         }
00312 
00313         if( name == "VSync" )
00314         {
00315             if (value == "Yes")
00316                 mVSync = true;
00317             else
00318                 mVSync = false;
00319         }
00320 
00321         if( name == "Video Mode" )
00322         {
00323             ConfigOption* optFSAA;
00324             it = mOptions.find( "Anti aliasing" );
00325             optFSAA = &it->second;
00326             optFSAA->possibleValues.clear();
00327             optFSAA->possibleValues.push_back("None");
00328 
00329             it = mOptions.find("Rendering Device");
00330             D3D9Driver *driver = getDirect3DDrivers()->item(it->second.currentValue);
00331             if (driver)
00332             {
00333                 it = mOptions.find("Video Mode");
00334                 D3D9VideoMode *videoMode = driver->getVideoModeList()->item(it->second.currentValue);
00335                 if (videoMode)
00336                 {
00337                     // get non maskable FSAA for this VMODE
00338                     DWORD numLevels = 0;
00339                     bool bOK = this->_checkMultiSampleQuality(
00340                         D3DMULTISAMPLE_NONMASKABLE, 
00341                         &numLevels, 
00342                         videoMode->getFormat(), 
00343                         driver->getAdapterNumber(),
00344                         D3DDEVTYPE_HAL,
00345                         TRUE);
00346                     if (bOK && numLevels > 0)
00347                     {
00348                         for (DWORD n = 0; n < numLevels; n++)
00349                             optFSAA->possibleValues.push_back("NonMaskable " + StringConverter::toString(n + 1));
00350                     }
00351 
00352                     // set maskable levels supported
00353                     for (unsigned int n = 2; n < 17; n++)
00354                     {
00355                         bOK = this->_checkMultiSampleQuality(
00356                             (D3DMULTISAMPLE_TYPE)n, 
00357                             &numLevels, 
00358                             videoMode->getFormat(), 
00359                             driver->getAdapterNumber(),
00360                             D3DDEVTYPE_HAL,
00361                             TRUE);
00362                         if (bOK)
00363                             optFSAA->possibleValues.push_back("Level " + StringConverter::toString(n));
00364                     }
00365                 }
00366             }
00367         }
00368 
00369         OgreUnguard();
00370     }
00371     //---------------------------------------------------------------------
00372     String D3D9RenderSystem::validateConfigOptions()
00373     {
00374         ConfigOptionMap::iterator it;
00375         
00376         // check if video mode is selected
00377         it = mOptions.find( "Video Mode" );
00378         if( it->second.currentValue == "" )
00379             return "A video mode must be selected.";
00380 
00381         it = mOptions.find( "Rendering Device" );
00382         bool foundDriver = false;
00383         D3D9DriverList* driverList = getDirect3DDrivers();
00384         for( ushort j=0; j < driverList->count(); j++ )
00385         {
00386             if( driverList->item(j)->DriverDescription() == it->second.currentValue )
00387             {
00388                 foundDriver = true;
00389                 break;
00390             }
00391         }
00392 
00393         if (!foundDriver)
00394         {
00395             // Just pick the first driver
00396             setConfigOption("Rendering Device", driverList->item(0)->DriverDescription());
00397             return "Your DirectX driver name has changed since the last time you ran OGRE; "
00398                 "the 'Rendering Device' has been changed.";
00399         }
00400 
00401         it = mOptions.find( "VSync" );
00402         if( it->second.currentValue == "Yes" )
00403             mVSync = true;
00404         else
00405             mVSync = false;
00406 
00407         return "";
00408     }
00409     //---------------------------------------------------------------------
00410     ConfigOptionMap& D3D9RenderSystem::getConfigOptions()
00411     {
00412         // return a COPY of the current config options
00413         return mOptions;
00414     }
00415     //---------------------------------------------------------------------
00416     RenderWindow* D3D9RenderSystem::initialise( bool autoCreateWindow )
00417     {
00418         RenderWindow* autoWindow = NULL;
00419         LogManager::getSingleton().logMessage( "D3D9 : Subsystem Initialising" );
00420 
00421         // Init using current settings
00422         mActiveD3DDriver = NULL;
00423         ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
00424         for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
00425         {
00426             if( getDirect3DDrivers()->item(j)->DriverDescription() == opt->second.currentValue )
00427             {
00428                 mActiveD3DDriver = getDirect3DDrivers()->item(j);
00429                 break;
00430             }
00431         }
00432 
00433         if( !mActiveD3DDriver )
00434             Except( Exception::ERR_INVALIDPARAMS, "Problems finding requested Direct3D driver!", "D3D9RenderSystem::initialise" );
00435 
00436         if( autoCreateWindow )
00437         {
00438             bool fullScreen;
00439             opt = mOptions.find( "Full Screen" );
00440             if( opt == mOptions.end() )
00441                 Exception( Exception::ERR_INTERNAL_ERROR, "Can't find full screen option!", "D3D9RenderSystem::initialise" );
00442             fullScreen = opt->second.currentValue == "Yes";
00443 
00444             D3D9VideoMode* videoMode = NULL;
00445             unsigned int width, height, colourDepth;
00446             String temp;
00447 
00448             opt = mOptions.find( "Video Mode" );
00449             if( opt == mOptions.end() )
00450                 Exception( Exception::ERR_INTERNAL_ERROR, "Can't find Video Mode option!", "D3D9RenderSystem::initialise" );
00451 
00452             for( unsigned j=0; j < mActiveD3DDriver->getVideoModeList()->count(); j++ )
00453             {
00454                 temp = mActiveD3DDriver->getVideoModeList()->item(j)->getDescription();
00455                 if( temp == opt->second.currentValue )
00456                 {
00457                     videoMode = mActiveD3DDriver->getVideoModeList()->item(j);
00458                     break;
00459                 }
00460             }
00461 
00462             if( !videoMode )
00463                 Except( Exception::ERR_INTERNAL_ERROR, "Can't find requested video mode.", "D3D9RenderSystem::initialise" );
00464 
00465             width = videoMode->getWidth();
00466             height = videoMode->getHeight();
00467             colourDepth = videoMode->getColourDepth();
00468 
00469             autoWindow = this->createRenderWindow( "OGRE Render Window", width, height, colourDepth, fullScreen );
00470         }
00471 
00472         LogManager::getSingleton().logMessage("***************************************");
00473 
00474         LogManager::getSingleton().logMessage("*** D3D9 : Subsystem Initialised OK ***");
00475         LogManager::getSingleton().logMessage("***************************************");
00476 
00477         // call superclass method
00478         RenderSystem::initialise( autoCreateWindow );
00479 
00480 
00481 
00482         return autoWindow;
00483     }
00484     //---------------------------------------------------------------------
00485     void D3D9RenderSystem::_setFSAA(D3DMULTISAMPLE_TYPE type, DWORD qualityLevel)
00486     {
00487         if (!mpD3DDevice)
00488         {
00489             mFSAAType = type;
00490             mFSAAQuality = qualityLevel;
00491         }
00492     }
00493     //---------------------------------------------------------------------
00494     void D3D9RenderSystem::reinitialise()
00495     {
00496         LogManager::getSingleton().logMessage( "D3D9 : Reinitialising" );
00497         this->shutdown();
00498         this->initialise( true );
00499     }
00500     //---------------------------------------------------------------------
00501     void D3D9RenderSystem::shutdown()
00502     {
00503         RenderSystem::shutdown();
00504         SAFE_DELETE( mDriverList );
00505         mActiveD3DDriver = NULL;
00506         LogManager::getSingleton().logMessage("D3D9 : Shutting down cleanly.");
00507     }
00508     //---------------------------------------------------------------------
00509     RenderWindow* D3D9RenderSystem::createRenderWindow( const String &name, unsigned int width, unsigned int height, unsigned int colourDepth,
00510         bool fullScreen, int left, int top, bool depthBuffer, RenderWindow* parentWindowHandle)
00511     {
00512         static bool firstWindow = true;
00513         
00514         OgreGuard( "D3D9RenderSystem::createRenderWindow" );
00515 
00516         String msg;
00517 
00518         // Make sure we don't already have a render target of the 
00519         // sam name as the one supplied
00520         if( mRenderTargets.find( name ) != mRenderTargets.end() )
00521         {
00522             msg = "A render target of the same name '" + name + "' already "
00523                 "exists.  You cannot create a new window with this name.";
00524             Except( Exception::ERR_INTERNAL_ERROR, msg, "D3D9RenderSystem::createRenderWindow" );
00525         }
00526 
00527         RenderWindow* win = new D3D9RenderWindow();
00528         if (!fullScreen && mExternalHandle)
00529         {
00530             D3D9RenderWindow *pWin32Window = (D3D9RenderWindow *)win;
00531             pWin32Window->SetExternalWindowHandle(mExternalHandle);
00532         }
00533 
00534         win->create( name, width, height, colourDepth, fullScreen, 
00535                 left, top, depthBuffer, &mhInstance, mActiveD3DDriver, 
00536                 parentWindowHandle, mFSAAType, mFSAAQuality, mVSync );
00537 
00538         attachRenderTarget( *win );
00539 
00540         // If this is the first window, get the D3D device and create the texture manager
00541         if( firstWindow )
00542         {
00543             win->getCustomAttribute( "D3DDEVICE", &mpD3DDevice );
00544 
00545             // Create the texture manager for use by others
00546             mTextureManager = new D3D9TextureManager( mpD3DDevice );
00547             // Also create hardware buffer manager
00548             mHardwareBufferManager = new D3D9HardwareBufferManager(mpD3DDevice);
00549 
00550             // Create the GPU program manager
00551             mGpuProgramManager = new D3D9GpuProgramManager(mpD3DDevice);
00552             // create & register HLSL factory
00553             mHLSLProgramFactory = new D3D9HLSLProgramFactory();
00554             HighLevelGpuProgramManager::getSingleton().addFactory(mHLSLProgramFactory);
00555 
00556 
00557             // Initialise the capabilities structures
00558             initCapabilities();
00559 
00560 
00561             firstWindow = false;
00562             
00563         }
00564 
00565         OgreUnguardRet( win );
00566     }
00567     //---------------------------------------------------------------------
00568     void D3D9RenderSystem::initCapabilities(void)
00569     {
00570         // get caps
00571         mpD3D->GetDeviceCaps( mActiveD3DDriver->getAdapterNumber(), D3DDEVTYPE_HAL, &mCaps );
00572 
00573         // Check for hardware stencil support
00574         LPDIRECT3DSURFACE9 pSurf;
00575         D3DSURFACE_DESC surfDesc;
00576         mpD3DDevice->GetDepthStencilSurface(&pSurf);
00577         pSurf->GetDesc(&surfDesc);
00578 
00579         if (surfDesc.Format == D3DFMT_D24S8 || surfDesc.Format == D3DFMT_D24X8)
00580         {
00581             mCapabilities->setCapability(RSC_HWSTENCIL);
00582             // Actually, it's always 8-bit
00583             mCapabilities->setStencilBufferBitDepth(8);
00584 
00585         }
00586 
00587         // Set number of texture units
00588         mCapabilities->setNumTextureUnits(mCaps.MaxSimultaneousTextures);
00589         // Anisotropy?
00590         if (mCaps.MaxAnisotropy > 1)
00591             mCapabilities->setCapability(RSC_ANISOTROPY);
00592         // Automatic mipmap generation?
00593         if (mCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
00594             mCapabilities->setCapability(RSC_AUTOMIPMAP);
00595         // Blending between stages supported
00596         mCapabilities->setCapability(RSC_BLENDING);
00597         // Dot 3
00598         if (mCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
00599             mCapabilities->setCapability(RSC_DOT3);
00600         // Cube map
00601         if (mCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
00602             mCapabilities->setCapability(RSC_CUBEMAPPING);
00603 
00604         // We always support compression, D3DX will decompress if device does not support
00605         mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
00606         mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
00607 
00608         // We always support VBOs
00609         mCapabilities->setCapability(RSC_VBO);
00610 
00611         convertVertexShaderCaps();
00612         convertPixelShaderCaps();
00613 
00614         mCapabilities->log(LogManager::getSingleton().getDefaultLog());
00615     }
00616     //---------------------------------------------------------------------
00617     void D3D9RenderSystem::convertVertexShaderCaps(void)
00618     {
00619         ushort major, minor;
00620         major = static_cast<ushort>((mCaps.VertexShaderVersion & 0x0000FF00) >> 8);
00621         minor = static_cast<ushort>(mCaps.VertexShaderVersion & 0x000000FF);
00622 
00623         // Populate max version & params
00624         switch (major)
00625         {
00626         case 1:
00627             mCapabilities->setMaxVertexProgramVersion("vs_1_1");
00628             // No boolean params allowed
00629             mCapabilities->setVertexProgramConstantBoolCount(0);
00630             // No integer params allowed
00631             mCapabilities->setVertexProgramConstantIntCount(0);
00632             // float params, always 4D
00633             mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
00634            
00635             break;
00636         case 2:
00637             if (minor > 0)
00638             {
00639                 mCapabilities->setMaxVertexProgramVersion("vs_2_x");
00640             }
00641             else
00642             {
00643                 mCapabilities->setMaxVertexProgramVersion("vs_2_0");
00644             }
00645             // 16 boolean params allowed
00646             mCapabilities->setVertexProgramConstantBoolCount(16);
00647             // 16 integer params allowed, 4D
00648             mCapabilities->setVertexProgramConstantIntCount(16);
00649             // float params, always 4D
00650             mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
00651             break;
00652         case 3:
00653             mCapabilities->setMaxVertexProgramVersion("vs_3_0");
00654             // 16 boolean params allowed
00655             mCapabilities->setVertexProgramConstantBoolCount(16);
00656             // 16 integer params allowed, 4D
00657             mCapabilities->setVertexProgramConstantIntCount(16);
00658             // float params, always 4D
00659             mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
00660             break;
00661         default:
00662             mCapabilities->setMaxVertexProgramVersion("");
00663             break;
00664         }
00665 
00666         // populate syntax codes in program manager (no breaks in this one so it falls through)
00667         switch(major)
00668         {
00669         case 3:
00670             mGpuProgramManager->_pushSyntaxCode("vs_3_0");
00671         case 2:
00672             if (major > 2 || minor > 0)
00673                 mGpuProgramManager->_pushSyntaxCode("vs_2_x");
00674 
00675             mGpuProgramManager->_pushSyntaxCode("vs_2_0");
00676         case 1:
00677             mGpuProgramManager->_pushSyntaxCode("vs_1_1");
00678             mCapabilities->setCapability(RSC_VERTEX_PROGRAM);
00679         }
00680     }
00681     //---------------------------------------------------------------------
00682     void D3D9RenderSystem::convertPixelShaderCaps(void)
00683     {
00684         ushort major, minor;
00685         major = static_cast<ushort>((mCaps.PixelShaderVersion & 0x0000FF00) >> 8);
00686         minor = static_cast<ushort>(mCaps.PixelShaderVersion & 0x000000FF);
00687         switch (major)
00688         {
00689         case 1:
00690             switch(minor)
00691             {
00692             case 1:
00693                 mCapabilities->setMaxFragmentProgramVersion("ps_1_1");
00694                 break;
00695             case 2:
00696                 mCapabilities->setMaxFragmentProgramVersion("ps_1_2");
00697                 break;
00698             case 3:
00699                 mCapabilities->setMaxFragmentProgramVersion("ps_1_3");
00700                 break;
00701             case 4:
00702                 mCapabilities->setMaxFragmentProgramVersion("ps_1_4");
00703                 break;
00704             }
00705             break;
00706             // no boolean params allowed
00707             mCapabilities->setFragmentProgramConstantBoolCount(0);
00708             // no integer params allowed
00709             mCapabilities->setFragmentProgramConstantIntCount(0);
00710             // float params, always 4D
00711             // NB in ps_1_x these are actually stored as fixed point values,
00712             // but they are entered as floats
00713             mCapabilities->setFragmentProgramConstantFloatCount(8);
00714         case 2:
00715             if (minor > 0)
00716             {
00717                 mCapabilities->setMaxFragmentProgramVersion("ps_2_x");
00718                 // 16 boolean params allowed
00719                 mCapabilities->setFragmentProgramConstantBoolCount(16);
00720                 // 16 integer params allowed, 4D
00721                 mCapabilities->setFragmentProgramConstantIntCount(16);
00722                 // float params, always 4D
00723                 mCapabilities->setFragmentProgramConstantFloatCount(224);
00724             }
00725             else
00726             {
00727                 mCapabilities->setMaxFragmentProgramVersion("ps_2_0");
00728                 // no boolean params allowed
00729                 mCapabilities->setFragmentProgramConstantBoolCount(0);
00730                 // no integer params allowed
00731                 mCapabilities->setFragmentProgramConstantIntCount(0);
00732                 // float params, always 4D
00733                 mCapabilities->setFragmentProgramConstantFloatCount(32);
00734             }
00735             break;
00736         case 3:
00737             if (minor > 0)
00738             {
00739                 mCapabilities->setMaxFragmentProgramVersion("ps_3_x");
00740             }
00741             else
00742             {
00743                 mCapabilities->setMaxFragmentProgramVersion("ps_3_0");
00744             }
00745             // 16 boolean params allowed
00746             mCapabilities->setFragmentProgramConstantBoolCount(16);
00747             // 16 integer params allowed, 4D
00748             mCapabilities->setFragmentProgramConstantIntCount(16);
00749             // float params, always 4D
00750             mCapabilities->setFragmentProgramConstantFloatCount(224);
00751             break;
00752         default:
00753             mCapabilities->setMaxFragmentProgramVersion("");
00754             break;
00755         }
00756 
00757         // populate syntax codes in program manager (no breaks in this one so it falls through)
00758         switch(major)
00759         {
00760         case 3:
00761             if (minor > 0)
00762                 mGpuProgramManager->_pushSyntaxCode("ps_3_x");
00763 
00764             mGpuProgramManager->_pushSyntaxCode("ps_3_0");
00765         case 2:
00766             if (major > 2 || minor > 0)
00767                 mGpuProgramManager->_pushSyntaxCode("ps_2_x");
00768 
00769             mGpuProgramManager->_pushSyntaxCode("ps_2_0");
00770         case 1:
00771             if (major > 1 || minor >= 4)
00772                 mGpuProgramManager->_pushSyntaxCode("ps_1_4");
00773             if (major > 1 || minor >= 3)
00774                 mGpuProgramManager->_pushSyntaxCode("ps_1_3");
00775             if (major > 1 || minor >= 2)
00776                 mGpuProgramManager->_pushSyntaxCode("ps_1_2");
00777             
00778             mGpuProgramManager->_pushSyntaxCode("ps_1_1");
00779             mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
00780         }
00781     }
00782     //---------------------------------------------------------------------
00783     RenderTexture * D3D9RenderSystem::createRenderTexture( const String & name, unsigned int width, unsigned int height )
00784     {
00785         RenderTexture *rt = new D3D9RenderTexture( name, width, height );
00786         attachRenderTarget( *rt );
00787         return rt;
00788     }
00789     //---------------------------------------------------------------------
00790     void D3D9RenderSystem::destroyRenderWindow( RenderWindow* pWin )
00791     {
00792         // Find it to remove from list
00793         RenderTargetMap::iterator i = mRenderTargets.begin();
00794 
00795         while( i->second != pWin && i != mRenderTargets.end() )
00796         {
00797             if( i->second == pWin )
00798             {
00799                 mRenderTargets.erase(i);
00800                 delete pWin;
00801                 break;
00802             }
00803         }
00804     }
00805     //---------------------------------------------------------------------
00806     String D3D9RenderSystem::getErrorDescription( long errorNumber )
00807     {
00808         String errMsg = DXGetErrorDescription9( errorNumber );
00809         return errMsg;
00810     }
00811     //---------------------------------------------------------------------
00812     void D3D9RenderSystem::convertColourValue( const ColourValue& colour, unsigned long* pDest )
00813     {
00814         *pDest = colour.getAsLongARGB();
00815     }
00816     //---------------------------------------------------------------------
00817     void D3D9RenderSystem::_makeProjectionMatrix(Real fovy, Real aspect, Real nearPlane, 
00818         Real farPlane, Matrix4& dest, bool forGpuProgram)
00819     {
00820 
00821         D3DXMATRIX d3dMatrix;
00822         if (forGpuProgram)
00823         {
00824             D3DXMatrixPerspectiveFovRH(&d3dMatrix,
00825                 Math::AngleUnitsToRadians(fovy),
00826                 aspect,
00827                 nearPlane,
00828                 farPlane);
00829         }
00830         else
00831         {
00832             D3DXMatrixPerspectiveFovLH(&d3dMatrix,
00833                 Math::AngleUnitsToRadians(fovy),
00834                 aspect,
00835                 nearPlane,
00836                 farPlane);
00837         }
00838         dest = D3D9Mappings::convertD3DXMatrix(d3dMatrix);
00839 
00840 
00841         /*
00842         Real theta = Math::AngleUnitsToRadians(fovy * 0.5);
00843         Real h = 1 / Math::Tan(theta);
00844         Real w = h / aspect;
00845         Real Q = farPlane / ( farPlane - nearPlane );
00846 
00847         dest = Matrix4::ZERO;
00848         dest[0][0] = w;
00849         dest[1][1] = h;
00850         dest[2][2] = Q;
00851         dest[3][2] = 1.0f;
00852         dest[2][3] = -Q * nearPlane;
00853         */
00854     }
00855     //---------------------------------------------------------------------
00856     D3D9RenderSystem::ResizeRepositionWindow(HWND wich)
00857     {
00858         for (RenderTargetMap::iterator it = mRenderTargets.begin(); it != mRenderTargets.end(); ++it)
00859         {
00860             if (it->second->isActive())
00861             {
00862                 D3D9RenderWindow *pWin32Window = (D3D9RenderWindow *)it->second;
00863                 if (pWin32Window->getWindowHandle() == wich)
00864                 {
00865                     pWin32Window->WindowMovedOrResized();
00866                     break;
00867                 }
00868             }
00869         }
00870     }
00871     //---------------------------------------------------------------------
00872     void D3D9RenderSystem::setAmbientLight( float r, float g, float b )
00873     {
00874         HRESULT hr = __SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( r, g, b, 1.0f ) );
00875         if( FAILED( hr ) )
00876             Except( hr, "Failed to set render stat D3DRS_AMBIENT", "D3D9RenderSystem::setAmbientLight" );
00877     }
00878     //---------------------------------------------------------------------
00879     void D3D9RenderSystem::_useLights(const LightList& lights, unsigned short limit)
00880     {
00881         LightList::const_iterator i, iend;
00882         iend = lights.end();
00883         unsigned short num = 0;
00884         for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
00885         {
00886             setD3D9Light(num, *i);
00887         }
00888         // Disable extra lights
00889         for (; num < mCurrentLights; ++num)
00890         {
00891             setD3D9Light(num, NULL);
00892         }
00893         mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
00894 
00895     }
00896     //---------------------------------------------------------------------
00897     void D3D9RenderSystem::setShadingType( ShadeOptions so )
00898     {
00899         HRESULT hr = __SetRenderState( D3DRS_SHADEMODE, D3D9Mappings::get(so) );
00900         if( FAILED( hr ) )
00901             Except( hr, "Failed to set render stat D3DRS_SHADEMODE", "D3D9RenderSystem::setShadingType" );
00902     }
00903     //---------------------------------------------------------------------
00904     void D3D9RenderSystem::setLightingEnabled( bool enabled )
00905     {
00906         HRESULT hr;
00907         if( FAILED( hr = __SetRenderState( D3DRS_LIGHTING, enabled ) ) )
00908             Except( hr, "Failed to set render state D3DRS_LIGHTING", "D3D9RenderSystem::setLightingEnabled" );
00909     }
00910     //---------------------------------------------------------------------
00911     void D3D9RenderSystem::setD3D9Light( size_t index, Light* lt )
00912     {
00913         HRESULT hr;
00914 
00915         D3DLIGHT9 d3dLight;
00916         ZeroMemory( &d3dLight, sizeof(d3dLight) );
00917 
00918         if (!lt)
00919         {
00920             if( FAILED( hr = mpD3DDevice->LightEnable( index, FALSE) ) )
00921                 Except( hr, "Unable to disable light", "D3D9RenderSystem::setD3D9Light" );
00922         }
00923         else
00924         {
00925             switch( lt->getType() )
00926             {
00927             case Light::LT_POINT:
00928                 d3dLight.Type = D3DLIGHT_POINT;
00929                 break;
00930 
00931             case Light::LT_DIRECTIONAL:
00932                 d3dLight.Type = D3DLIGHT_DIRECTIONAL;
00933                 break;
00934 
00935             case Light::LT_SPOTLIGHT:
00936                 d3dLight.Type = D3DLIGHT_SPOT;
00937                 d3dLight.Falloff = lt->getSpotlightFalloff();
00938                 d3dLight.Theta = Math::AngleUnitsToRadians( lt->getSpotlightInnerAngle() );
00939                 d3dLight.Phi = Math::AngleUnitsToRadians( lt->getSpotlightOuterAngle() );
00940                 break;
00941             }
00942 
00943             ColourValue col;
00944             col = lt->getDiffuseColour();
00945             d3dLight.Diffuse = D3DXCOLOR( col.r, col.g, col.b, col.a );
00946 
00947             col = lt->getSpecularColour();
00948             d3dLight.Specular = D3DXCOLOR( col.r, col.g, col.b, col.a );
00949 
00950             Vector3 vec;
00951             if( lt->getType() != Light::LT_DIRECTIONAL )
00952             {
00953                 vec = lt->getDerivedPosition();
00954                 d3dLight.Position = D3DXVECTOR3( vec.x, vec.y, vec.z );
00955             }
00956             if( lt->getType() != Light::LT_POINT )
00957             {
00958                 vec = lt->getDerivedDirection();
00959                 d3dLight.Direction = D3DXVECTOR3( vec.x, vec.y, vec.z );
00960             }
00961 
00962             d3dLight.Range = lt->getAttenuationRange();
00963             d3dLight.Attenuation0 = lt->getAttenuationConstant();
00964             d3dLight.Attenuation1 = lt->getAttenuationLinear();
00965             d3dLight.Attenuation2 = lt->getAttenuationQuadric();
00966 
00967             if( FAILED( hr = mpD3DDevice->SetLight( index, &d3dLight ) ) )
00968                 Except( hr, "Unable to set light details", "D3D9RenderSystem::setD3D9Light" );
00969 
00970             if( FAILED( hr = mpD3DDevice->LightEnable( index, TRUE ) ) )
00971                 Except( hr, "Unable to enable light", "D3D9RenderSystem::setD3D9Light" );
00972         }
00973 
00974 
00975     }
00976     //---------------------------------------------------------------------
00977     void D3D9RenderSystem::_setViewMatrix( const Matrix4 &m )
00978     {
00979         D3DXMATRIX d3dmat = D3D9Mappings::makeD3DXMatrix( m );
00980         d3dmat.m[0][2] = -d3dmat.m[0][2];
00981         d3dmat.m[1][2] = -d3dmat.m[1][2];
00982         d3dmat.m[2][2] = -d3dmat.m[2][2];
00983         d3dmat.m[3][2] = -d3dmat.m[3][2];
00984 
00985         HRESULT hr;
00986         if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_VIEW, &d3dmat ) ) )
00987             Except( hr, "Cannot set D3D9 view matrix", "D3D9RenderSystem::_setViewMatrix" );
00988     }
00989     //---------------------------------------------------------------------
00990     void D3D9RenderSystem::_setProjectionMatrix( const Matrix4 &m )
00991     {
00992         D3DXMATRIX d3dMat = D3D9Mappings::makeD3DXMatrix( m );
00993 
00994         if( mActiveRenderTarget->requiresTextureFlipping() )
00995             d3dMat._22 = - d3dMat._22;
00996 
00997         HRESULT hr;
00998         if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_PROJECTION, &d3dMat ) ) )
00999             Except( hr, "Cannot set D3D9 projection matrix", "D3D9RenderSystem::_setProjectionMatrix" );
01000     }
01001     //---------------------------------------------------------------------
01002     void D3D9RenderSystem::_setWorldMatrix( const Matrix4 &m )
01003     {
01004         D3DXMATRIX d3dMat = D3D9Mappings::makeD3DXMatrix( m );
01005 
01006         HRESULT hr;
01007         if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_WORLD, &d3dMat ) ) )
01008             Except( hr, "Cannot set D3D9 world matrix", "D3D9RenderSystem::_setWorldMatrix" );
01009     }
01010     //---------------------------------------------------------------------
01011     void D3D9RenderSystem::_setSurfaceParams( const ColourValue &ambient, const ColourValue &diffuse,
01012         const ColourValue &specular, const ColourValue &emissive, Real shininess )
01013     {
01014         // Remember last call
01015         static ColourValue lastAmbient = ColourValue::Black;
01016         static ColourValue lastDiffuse = ColourValue::Black;
01017         static ColourValue lastSpecular = ColourValue::Black;
01018         static ColourValue lastEmissive = ColourValue::Black;
01019         static Real lastShininess = 0.0;
01020 
01021         // Only update if changed
01022         if( ambient != lastAmbient || diffuse != lastDiffuse ||
01023             specular != lastSpecular || emissive != lastEmissive ||
01024             shininess != lastShininess )
01025         {
01026             D3DMATERIAL9 material;
01027             material.Diffuse = D3DXCOLOR( diffuse.r, diffuse.g, diffuse.b, diffuse.a );
01028             material.Ambient = D3DXCOLOR( ambient.r, ambient.g, ambient.b, ambient.a );
01029             material.Specular = D3DXCOLOR( specular.r, specular.g, specular.b, specular.a );
01030             material.Emissive = D3DXCOLOR( emissive.r, emissive.g, emissive.b, emissive.a );
01031             material.Power = shininess;
01032 
01033             HRESULT hr = mpD3DDevice->SetMaterial( &material );
01034             if( FAILED( hr ) )
01035                 Except( hr, "Error setting D3D material", "D3D9RenderSystem::_setSurfaceParams" );
01036 
01037             // Remember the details
01038             lastAmbient = ambient;
01039             lastDiffuse = diffuse;
01040             lastSpecular = specular;
01041             lastEmissive = emissive;
01042             lastShininess = shininess;
01043         }
01044     }
01045     //---------------------------------------------------------------------
01046     void D3D9RenderSystem::_setTexture( size_t stage, bool enabled, const String &texname )
01047     {
01048         HRESULT hr;
01049         D3D9Texture *dt = (D3D9Texture *)TextureManager::getSingleton().getByName(texname);
01050         if (enabled && dt)
01051         {
01052             IDirect3DBaseTexture9 *pTex = dt->getTexture();
01053             if (mTexStageDesc[stage].pTex != pTex)
01054             {
01055                 hr = mpD3DDevice->SetTexture(stage, pTex);
01056                 if( hr != S_OK )
01057                 {
01058                     String str = "Unable to set texture '" + texname + "' in D3D9";
01059                     Except( hr, str, "D3D9RenderSystem::_setTexture" );
01060                 }
01061                 
01062                 // set stage desc.
01063                 mTexStageDesc[stage].pTex = pTex;
01064                 mTexStageDesc[stage].texType = D3D9Mappings::get(dt->getTextureType());
01065             }
01066         }
01067         else
01068         {
01069             if (mTexStageDesc[stage].pTex != 0)
01070             {
01071                 hr = mpD3DDevice->SetTexture(stage, 0);
01072                 if( hr != S_OK )
01073                 {
01074                     String str = "Unable to disable texture '" + texname + "' in D3D9";
01075                     Except( hr, str, "D3D9RenderSystem::_setTexture" );
01076                 }
01077             }
01078 
01079             hr = this->__SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE);
01080             if( hr != S_OK )
01081             {
01082                 String str = "Unable to disable texture '" + texname + "' in D3D9";
01083                 Except( hr, str, "D3D9RenderSystem::_setTexture" );
01084             }
01085 
01086             // set stage desc. to defaults
01087             mTexStageDesc[stage].pTex = 0;
01088             mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
01089             mTexStageDesc[stage].coordIndex = 0;
01090             mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
01091         }
01092     }
01093     //---------------------------------------------------------------------
01094     void D3D9RenderSystem::_setTextureCoordSet( size_t stage, size_t index )
01095     {
01096         HRESULT hr;
01097         hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, index );
01098         if( FAILED( hr ) )
01099             Except( hr, "Unable to set texture coord. set index", "D3D8RenderSystem::_setTextureCoordSet" );
01100         // Record settings
01101         mTexStageDesc[stage].coordIndex = index;
01102     }
01103     //---------------------------------------------------------------------
01104     void D3D9RenderSystem::_setTextureCoordCalculation( size_t stage, TexCoordCalcMethod m)
01105     {
01106         HRESULT hr = S_OK;
01107         // record the stage state
01108         mTexStageDesc[stage].autoTexCoordType = m;
01109 
01110         // choose normalization method
01111         if (m == TEXCALC_ENVIRONMENT_MAP_NORMAL || m == TEXCALC_ENVIRONMENT_MAP)
01112         {
01113             mForcedNormalisation = true;
01114             setNormaliseNormals(true);
01115         }
01116         else
01117         {
01118             mForcedNormalisation = false;
01119             setNormaliseNormals(false);
01120         }
01121         if (FAILED(hr))
01122             Except( hr, "Unable to set auto-normalisation", "D3D9RenderSystem::_setTextureCoordCalculation" );
01123 
01124         // set aut.tex.coord.gen.mode if present
01125         // if not present we'v already set it through D3D9RenderSystem::_setTextureCoordSet
01126         if (m != TEXCALC_NONE)
01127         {
01128             hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(m, mCaps));
01129             if(FAILED(hr))
01130                 Except( hr, "Unable to set texture auto tex.coord. generation mode", "D3D8RenderSystem::_setTextureCoordCalculation" );
01131         }
01132     }
01133     //---------------------------------------------------------------------
01134     void D3D9RenderSystem::_setTextureMatrix( size_t stage, const Matrix4& xForm )
01135     {
01136         HRESULT hr;
01137         D3DXMATRIX d3dMatId; // ident. matrix in D3DX format
01138         D3DXMATRIX d3dMat; // the matrix we'll maybe apply
01139         Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format
01140         // make the ident. matrix in D3D format
01141         D3DXMatrixIdentity(&d3dMatId);
01142 
01143         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP)
01144         {
01145             if (mCaps.VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP)
01146             {
01148                 Matrix4 ogreMatEnvMap = Matrix4::IDENTITY;
01149                 // set env_map values
01150                 ogreMatEnvMap[1][1] = -1.0f;
01151                 // concatenate with the xForm
01152                 newMat = newMat.concatenate(ogreMatEnvMap);
01153             }
01154             else
01155             {
01156                 /* If envmap is applied, but device doesn't support spheremap,
01157                 then we have to use texture transform to make the camera space normal
01158                 reference the envmap properly. This isn't exactly the same as spheremap
01159                 (it looks nasty on flat areas because the camera space normals are the same)
01160                 but it's the best approximation we have in the absence of a proper spheremap */
01161                 Matrix4 ogreMatEnvMap = Matrix4::IDENTITY;
01162                 // set env_map values
01163                 ogreMatEnvMap[0][0] = 0.5f;
01164                 ogreMatEnvMap[0][3] = 0.5f;
01165                 ogreMatEnvMap[1][1] = -0.5f;
01166                 ogreMatEnvMap[1][3] = 0.5f;
01167                 // concatenate with the xForm
01168                 newMat = newMat.concatenate(ogreMatEnvMap);
01169             }
01170         }
01171 
01172         // If this is a cubic reflection, we need to modify using the view matrix
01173         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION)
01174         {
01175             D3DXMATRIX viewMatrix; 
01176 
01177             // Get view matrix
01178             mpD3DDevice->GetTransform(D3DTS_VIEW, &viewMatrix);
01179             // Get transposed 3x3, ie since D3D is transposed just copy
01180             // We want to transpose since that will invert an orthonormal matrix ie rotation
01181             Matrix4 ogreViewTransposed;
01182             ogreViewTransposed[0][0] = viewMatrix.m[0][0];
01183             ogreViewTransposed[0][1] = viewMatrix.m[0][1];
01184             ogreViewTransposed[0][2] = viewMatrix.m[0][2];
01185             ogreViewTransposed[0][3] = 0.0f;
01186 
01187             ogreViewTransposed[1][0] = viewMatrix.m[1][0];
01188             ogreViewTransposed[1][1] = viewMatrix.m[1][1];
01189             ogreViewTransposed[1][2] = viewMatrix.m[1][2];
01190             ogreViewTransposed[1][3] = 0.0f;
01191 
01192             ogreViewTransposed[2][0] = viewMatrix.m[2][0];
01193             ogreViewTransposed[2][1] = viewMatrix.m[2][1];
01194             ogreViewTransposed[2][2] = viewMatrix.m[2][2];
01195             ogreViewTransposed[2][3] = 0.0f;
01196 
01197             ogreViewTransposed[3][0] = 0.0f;
01198             ogreViewTransposed[3][1] = 0.0f;
01199             ogreViewTransposed[3][2] = 0.0f;
01200             ogreViewTransposed[3][3] = 1.0f;
01201             
01202             newMat = newMat.concatenate(ogreViewTransposed);
01203         }
01204 
01205         // convert our matrix to D3D format
01206         d3dMat = D3D9Mappings::makeD3DXMatrix(newMat);
01207 
01208         // need this if texture is a cube map, to invert D3D's z coord
01209         if (mTexStageDesc[stage].autoTexCoordType != TEXCALC_NONE)
01210         {
01211             d3dMat._13 = -d3dMat._13;
01212             d3dMat._23 = -d3dMat._23;
01213             d3dMat._33 = -d3dMat._33;
01214             d3dMat._43 = -d3dMat._43;
01215         }
01216 
01217         // set the matrix if it's not the identity
01218         if (d3dMat != d3dMatId)
01219         {
01220             // tell D3D the dimension of tex. coord.
01221             int texCoordDim;
01222             switch (mTexStageDesc[stage].texType)
01223             {
01224             case D3D9Mappings::D3D_TEX_TYPE_NORMAL:
01225                 texCoordDim = 2;
01226                 break;
01227             case D3D9Mappings::D3D_TEX_TYPE_CUBE:
01228             case D3D9Mappings::D3D_TEX_TYPE_VOLUME:
01229                 texCoordDim = 3;
01230             }
01231 
01232             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim );
01233             if (FAILED(hr))
01234                 Except( hr, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" );
01235 
01236             hr = mpD3DDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
01237             if (FAILED(hr))
01238                 Except( hr, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
01239         }
01240         else
01241         {
01242             // disable all of this
01243             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
01244             if( FAILED( hr ) )
01245                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
01246 
01247             // set the identity matrix
01248             D3DXMatrixIdentity( &d3dMat );
01249             hr = mpD3DDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
01250             if( FAILED( hr ) )
01251                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
01252         }
01253     }
01254     //---------------------------------------------------------------------
01255     void D3D9RenderSystem::_setTextureAddressingMode( size_t stage, TextureUnitState::TextureAddressingMode tam )
01256     {
01257         HRESULT hr;
01258         if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSU, D3D9Mappings::get(tam) ) ) )
01259             Except( hr, "Failed to set texture addressing mode for U", "D3D9RenderSystem::_setTextureAddressingMode" );
01260         if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSV, D3D9Mappings::get(tam) ) ) )
01261             Except( hr, "Failed to set texture addressing mode for V", "D3D9RenderSystem::_setTextureAddressingMode" );
01262         if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSW, D3D9Mappings::get(tam) ) ) )
01263             Except( hr, "Failed to set texture addressing mode for W", "D3D9RenderSystem::_setTextureAddressingMode" );
01264     }
01265     //---------------------------------------------------------------------
01266     void D3D9RenderSystem::_setTextureBlendMode( size_t stage, const LayerBlendModeEx& bm )
01267     {
01268         HRESULT hr = S_OK;
01269         D3DTEXTURESTAGESTATETYPE tss;
01270         D3DCOLOR manualD3D;
01271 
01272         // choose type of blend.
01273         if( bm.blendType == LBT_COLOUR )
01274             tss = D3DTSS_COLOROP;
01275         else if( bm.blendType == LBT_ALPHA )
01276             tss = D3DTSS_ALPHAOP;
01277         // set manual factor if required by operation
01278         if (bm.operation == LBX_BLEND_MANUAL)
01279         {
01280             hr = __SetRenderState( D3DRS_TEXTUREFACTOR, D3DXCOLOR(0.0, 0.0, 0.0,  bm.factor) );
01281             if (FAILED(hr))
01282                 Except( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
01283         }
01284         // set operation
01285         hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.operation, mCaps) );
01286         if (FAILED(hr))
01287             Except( hr, "Failed to set operation", "D3D9RenderSystem::_setTextureBlendMode" );
01288 
01289         // choose source 1
01290         if( bm.blendType == LBT_COLOUR )
01291         {
01292             tss = D3DTSS_COLORARG1;
01293             manualD3D = D3DXCOLOR( bm.colourArg1.r, bm.colourArg1.g, bm.colourArg1.b, 1.0 );
01294         }
01295         else if( bm.blendType == LBT_ALPHA )
01296         {
01297             tss = D3DTSS_ALPHAARG1;
01298             manualD3D = D3DXCOLOR( 0.0, 0.0, 0.0, bm.alphaArg1 );
01299         }
01300         // Set manual factor if required
01301         if (bm.source1 == LBS_MANUAL)
01302         {
01303             hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
01304             if (FAILED(hr))
01305                 Except( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
01306         }
01307         // set source 1
01308         hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.source1) );
01309         if (FAILED(hr))
01310             Except( hr, "Failed to set source1", "D3D9RenderSystem::_setTextureBlendMode" );
01311         
01312         // choose source 2
01313         if( bm.blendType == LBT_COLOUR )
01314         {
01315             tss = D3DTSS_COLORARG2;
01316             manualD3D = D3DXCOLOR( bm.colourArg2.r, bm.colourArg2.g, bm.colourArg2.b, 1.0 );
01317         }
01318         else if( bm.blendType == LBT_ALPHA )
01319         {
01320             tss = D3DTSS_ALPHAARG2;
01321             manualD3D = D3DXCOLOR( 0.0, 0.0, 0.0, bm.alphaArg2 );
01322         }
01323         // Set manual factor if required
01324         if (bm.source2 == LBS_MANUAL)
01325         {
01326             hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
01327             if (FAILED(hr))
01328                 Except( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
01329         }
01330         // Now set source 2
01331         hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.source2) );
01332         if (FAILED(hr))
01333             Except( hr, "Failed to set source 2", "D3D9RenderSystem::_setTextureBlendMode" );
01334     }
01335     //---------------------------------------------------------------------
01336     void D3D9RenderSystem::_setSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor )
01337     {
01338         HRESULT hr;
01339         if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
01340             Except( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
01341         if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
01342             Except( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
01343     }
01344     //---------------------------------------------------------------------
01345     void D3D9RenderSystem::_setAlphaRejectSettings( CompareFunction func, unsigned char value )
01346     {
01347         HRESULT hr;
01348         if (func != CMPF_ALWAYS_PASS)
01349         {
01350             if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE ) ) )
01351                 Except( hr, "Failed to enable alpha testing", 
01352                 "D3D9RenderSystem::_setAlphaRejectSettings" );
01353         }
01354         else
01355         {
01356             if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  FALSE ) ) )
01357                 Except( hr, "Failed to disable alpha testing", 
01358                 "D3D9RenderSystem::_setAlphaRejectSettings" );
01359         }
01360         // Set always just be sure
01361         if( FAILED( hr = __SetRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
01362             Except( hr, "Failed to set alpha reject function", "D3D9RenderSystem::_setAlphaRejectSettings" );
01363         if( FAILED( hr = __SetRenderState( D3DRS_ALPHAREF, value ) ) )
01364             Except( hr, "Failed to set render state D3DRS_ALPHAREF", "D3D9RenderSystem::_setAlphaRejectSettings" );
01365     }
01366     //---------------------------------------------------------------------
01367     void D3D9RenderSystem::_setCullingMode( CullingMode mode )
01368     {
01369         HRESULT hr;
01370         bool flip = ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
01371                 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding));
01372 
01373         if( FAILED (hr = __SetRenderState(D3DRS_CULLMODE, 
01374             D3D9Mappings::get(mode, flip))) )
01375             Except( hr, "Failed to set culling mode", "D3D9RenderSystem::_setCullingMode" );
01376     }
01377     //---------------------------------------------------------------------
01378     void D3D9RenderSystem::_setDepthBufferParams( bool depthTest, bool depthWrite, CompareFunction depthFunction )
01379     {
01380         _setDepthBufferCheckEnabled( depthTest );
01381         _setDepthBufferWriteEnabled( depthWrite );
01382         _setDepthBufferFunction( depthFunction );
01383     }
01384     //---------------------------------------------------------------------
01385     void D3D9RenderSystem::_setDepthBufferCheckEnabled( bool enabled )
01386     {
01387         HRESULT hr;
01388 
01389         if( enabled )
01390         {
01391             // Use w-buffer if abialable
01392             if( mCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
01393                 hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
01394             else
01395                 hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
01396         }
01397         else
01398             hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
01399 
01400         if( FAILED( hr ) )
01401             Except( hr, "Error setting depth buffer test state", "D3D9RenderSystem::_setDepthBufferCheckEnabled" );
01402     }
01403     //---------------------------------------------------------------------
01404     void D3D9RenderSystem::_setDepthBufferWriteEnabled( bool enabled )
01405     {
01406         HRESULT hr;
01407 
01408         if( FAILED( hr = __SetRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
01409             Except( hr, "Error setting depth buffer write state", "D3D9RenderSystem::_setDepthBufferWriteEnabled" );
01410     }
01411     //---------------------------------------------------------------------
01412     void D3D9RenderSystem::_setDepthBufferFunction( CompareFunction func )
01413     {
01414         HRESULT hr;
01415         if( FAILED( hr = __SetRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
01416             Except( hr, "Error setting depth buffer test function", "D3D9RenderSystem::_setDepthBufferFunction" );
01417     }
01418     //---------------------------------------------------------------------
01419     void D3D9RenderSystem::_setDepthBias(ushort bias)
01420     {
01421         HRESULT hr = __SetRenderState(D3DRS_DEPTHBIAS, bias);
01422         if (FAILED(hr))
01423             Except(hr, "Error setting depth bias", "D3D9RenderSystem::_setDepthBias");
01424     }
01425     //---------------------------------------------------------------------
01426     void D3D9RenderSystem::_setColourBufferWriteEnabled(bool red, bool green, 
01427         bool blue, bool alpha)
01428     {
01429         DWORD val = 0;
01430         if (red) 
01431             val |= D3DCOLORWRITEENABLE_RED;
01432         if (green)
01433             val |= D3DCOLORWRITEENABLE_GREEN;
01434         if (blue)
01435             val |= D3DCOLORWRITEENABLE_BLUE;
01436         if (alpha)
01437             val |= D3DCOLORWRITEENABLE_ALPHA;
01438         HRESULT hr = __SetRenderState(D3DRS_COLORWRITEENABLE, val); 
01439         if (FAILED(hr))
01440             Except(hr, "Error setting colour write enable flags", 
01441             "D3D9RenderSystem::_setColourWriteEnabled");
01442     }
01443     //---------------------------------------------------------------------
01444     void D3D9RenderSystem::_setFog( FogMode mode, const ColourValue& colour, Real densitiy, Real start, Real end )
01445     {
01446         HRESULT hr;
01447 
01448         D3DRENDERSTATETYPE fogType, fogTypeNot;
01449 
01450         if (mCaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
01451         {
01452             fogType = D3DRS_FOGTABLEMODE;
01453             fogTypeNot = D3DRS_FOGVERTEXMODE;
01454         }
01455         else
01456         {
01457             fogType = D3DRS_FOGVERTEXMODE;
01458             fogTypeNot = D3DRS_FOGTABLEMODE;
01459         }
01460 
01461         if( mode == FOG_NONE)
01462         {
01463             // just disable
01464             hr = __SetRenderState(fogType, D3DFOG_NONE );
01465             hr = __SetRenderState(D3DRS_FOGENABLE, FALSE);
01466         }
01467         else
01468         {
01469             // Allow fog
01470             hr = __SetRenderState( D3DRS_FOGENABLE, TRUE );
01471             hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
01472             hr = __SetRenderState( fogType, D3D9Mappings::get(mode) );
01473 
01474             hr = __SetRenderState( D3DRS_FOGCOLOR, colour.getAsLongARGB() );
01475             hr = __SetRenderState( D3DRS_FOGSTART, *((LPDWORD)(&start)) );
01476             hr = __SetRenderState( D3DRS_FOGEND, *((LPDWORD)(&end)) );
01477             hr = __SetRenderState( D3DRS_FOGDENSITY, *((LPDWORD)(&densitiy)) );
01478         }
01479 
01480         if( FAILED( hr ) )
01481             Except( hr, "Error setting render state", "D3D9RenderSystem::_setFog" );
01482     }
01483     //---------------------------------------------------------------------
01484     void D3D9RenderSystem::_setRasterisationMode(SceneDetailLevel level)
01485     {
01486         HRESULT hr = __SetRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
01487         if (FAILED(hr))
01488             Except(hr, "Error setting rasterisation mode.", "D3D9RenderSystem::setRasterisationMode");
01489     }
01490     //---------------------------------------------------------------------
01491     void D3D9RenderSystem::setStencilCheckEnabled(bool enabled)
01492     {
01493         // Allow stencilling
01494         HRESULT hr = __SetRenderState(D3DRS_STENCILENABLE, enabled);
01495         if (FAILED(hr))
01496             Except(hr, "Error enabling / disabling stencilling.",
01497             "D3D9RenderSystem::setStencilCheckEnabled");
01498     }
01499     //---------------------------------------------------------------------
01500     void D3D9RenderSystem::setStencilBufferFunction(CompareFunction func)
01501     {
01502         HRESULT hr = __SetRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
01503         if (FAILED(hr))
01504             Except(hr, "Error setting stencil buffer test function.",
01505             "D3D9RenderSystem::_setStencilBufferFunction");
01506     }
01507     //---------------------------------------------------------------------
01508     void D3D9RenderSystem::setStencilBufferReferenceValue(ulong refValue)
01509     {
01510         HRESULT hr = __SetRenderState(D3DRS_STENCILREF, refValue);
01511         if (FAILED(hr))
01512             Except(hr, "Error setting stencil buffer reference value.",
01513             "D3D9RenderSystem::setStencilBufferReferenceValue");
01514     }
01515     //---------------------------------------------------------------------
01516     void D3D9RenderSystem::setStencilBufferMask(ulong mask)
01517     {
01518         HRESULT hr = __SetRenderState(D3DRS_STENCILMASK, mask);
01519         if (FAILED(hr))
01520             Except(hr, "Error setting stencil buffer mask.",
01521             "D3D9RenderSystem::setStencilBufferMask");
01522     }
01523     //---------------------------------------------------------------------
01524     void D3D9RenderSystem::setStencilBufferFailOperation(StencilOperation op)
01525     {
01526         HRESULT hr = __SetRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(op));
01527         if (FAILED(hr))
01528             Except(hr, "Error setting stencil fail operation.",
01529             "D3D9RenderSystem::setStencilBufferFailOperation");
01530     }
01531     //---------------------------------------------------------------------
01532     void D3D9RenderSystem::setStencilBufferDepthFailOperation(StencilOperation op)
01533     {
01534         HRESULT hr = __SetRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(op));
01535         if (FAILED(hr))
01536             Except(hr, "Error setting stencil depth fail operation.",
01537             "D3D9RenderSystem::setStencilBufferDepthFailOperation");
01538     }
01539     //---------------------------------------------------------------------
01540     void D3D9RenderSystem::setStencilBufferPassOperation(StencilOperation op)
01541     {
01542         HRESULT hr = __SetRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(op));
01543         if (FAILED(hr))
01544             Except(hr, "Error setting stencil pass operation.",
01545             "D3D9RenderSystem::setStencilBufferPassOperation");
01546     }
01547     //---------------------------------------------------------------------
01548     void D3D9RenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype, 
01549         FilterOptions filter)
01550     {
01551         HRESULT hr;
01552         D3D9Mappings::eD3DTexType texType = mTexStageDesc[unit].texType;
01553         hr = __SetSamplerState( unit, D3D9Mappings::get(ftype), 
01554             D3D9Mappings::get(ftype, filter, mCaps, texType));
01555         if (FAILED(hr))
01556             Except(hr, "Failed to set texture filter ", "D3D9RenderSystem::_setTextureUnitFiltering");
01557     }
01558     //---------------------------------------------------------------------
01559     DWORD D3D9RenderSystem::_getCurrentAnisotropy(size_t unit)
01560     {
01561         DWORD oldVal;
01562         mpD3DDevice->GetSamplerState(unit, D3DSAMP_MAXANISOTROPY, &oldVal);
01563             return oldVal;
01564     }
01565     //---------------------------------------------------------------------
01566     void D3D9RenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
01567     {
01568         if ((DWORD)maxAnisotropy > mCaps.MaxAnisotropy)
01569             maxAnisotropy = mCaps.MaxAnisotropy;
01570 
01571         if (_getCurrentAnisotropy(unit) != maxAnisotropy)
01572             __SetSamplerState( unit, D3DSAMP_MAXANISOTROPY, maxAnisotropy );
01573     }
01574     //---------------------------------------------------------------------
01575     HRESULT D3D9RenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
01576     {
01577         HRESULT hr;
01578         DWORD oldVal;
01579 
01580         if ( FAILED( hr = mpD3DDevice->GetRenderState(state, &oldVal) ) )
01581             return hr;
01582         if ( oldVal == value )
01583             return D3D_OK;
01584         else
01585             return mpD3DDevice->SetRenderState(state, value);
01586     }
01587     //---------------------------------------------------------------------
01588     HRESULT D3D9RenderSystem::__SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
01589     {
01590         HRESULT hr;
01591         DWORD oldVal;
01592 
01593         if ( FAILED( hr = mpD3DDevice->GetSamplerState(sampler, type, &oldVal) ) )
01594             return hr;
01595         if ( oldVal == value )
01596             return D3D_OK;
01597         else
01598             return mpD3DDevice->SetSamplerState(sampler, type, value);
01599     }
01600     //---------------------------------------------------------------------
01601     HRESULT D3D9RenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
01602     {
01603         HRESULT hr;
01604         DWORD oldVal;
01605         
01606         if ( FAILED( hr = mpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) )
01607             return hr;
01608         if ( oldVal == value )
01609             return D3D_OK;
01610         else
01611             return mpD3DDevice->SetTextureStageState(stage, type, value);
01612     }
01613     //---------------------------------------------------------------------
01614     void D3D9RenderSystem::_setViewport( Viewport *vp )
01615     {
01616         if( vp != mActiveViewport || vp->_isUpdated() )
01617         {
01618             mActiveViewport = vp;
01619             mActiveRenderTarget = vp->getTarget();
01620 
01621             // ok, it's different, time to set render target and viewport params
01622             D3DVIEWPORT9 d3dvp;
01623             HRESULT hr;
01624 
01625             // Set render target
01626             RenderTarget* target;
01627             target = vp->getTarget();
01628 
01629             LPDIRECT3DSURFACE9 pBack = NULL;
01630             target->getCustomAttribute( "DDBACKBUFFER", &pBack );
01631             if (!pBack)
01632                 return;
01633 
01634             LPDIRECT3DSURFACE9 pDepth = NULL;
01635             target->getCustomAttribute( "D3DZBUFFER", &pDepth );
01636             if (!pDepth)
01637                 return;
01638             
01639             hr = mpD3DDevice->SetRenderTarget(0, pBack);
01640             if (FAILED(hr))
01641             {
01642                 String msg = DXGetErrorDescription9(hr);
01643                 Except( hr, "Failed to setRenderTarget : " + msg, "D3D9RenderSystem::_setViewport" );
01644             }
01645             hr = mpD3DDevice->SetDepthStencilSurface(pDepth);
01646             if (FAILED(hr))
01647             {
01648                 String msg = DXGetErrorDescription9(hr);
01649                 Except( hr, "Failed to setDepthStencil : " + msg, "D3D9RenderSystem::_setViewport" );
01650             }
01651 
01652             _setCullingMode( mCullingMode );
01653 
01654             // set viewport dimensions
01655             d3dvp.X = vp->getActualLeft();
01656             d3dvp.Y = vp->getActualTop();
01657             d3dvp.Width = vp->getActualWidth();
01658             d3dvp.Height = vp->getActualHeight();
01659 
01660             // Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
01661             d3dvp.MinZ = 0.0f;
01662             d3dvp.MaxZ = 1.0f;
01663 
01664             if( FAILED( hr = mpD3DDevice->SetViewport( &d3dvp ) ) )
01665                 Except( hr, "Failed to set viewport.", "D3D9RenderSystem::_setViewport" );
01666 
01667             vp->_clearUpdatedFlag();
01668         }
01669     }
01670     //---------------------------------------------------------------------
01671     void D3D9RenderSystem::_beginFrame()
01672     {
01673         OgreGuard( "D3D9RenderSystem::_beginFrame" );
01674 
01675         HRESULT hr;
01676 
01677         if( !mActiveViewport )
01678             Except( Exception::ERR_INTERNAL_ERROR, "Cannot begin frame - no viewport selected.", "D3D9RenderSystem::_beginFrame" );
01679 
01680         // Clear the viewport if required
01681         if( mActiveViewport->getClearEveryFrame() )
01682         {
01683             if( FAILED( hr = mpD3DDevice->Clear( 
01684                 0, 
01685                 NULL, 
01686                 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
01687                 mActiveViewport->getBackgroundColour().getAsLongARGB(), 
01688                 1.0f, 0 ) ) )
01689             {
01690                 String msg = DXGetErrorDescription9(hr);
01691                 Except( hr, "Error clearing viewport : " + msg, "D3D9RenderSystem::_beginFrame" );
01692             }
01693         }
01694 
01695         if( FAILED( hr = mpD3DDevice->BeginScene() ) )
01696         {
01697             String msg = DXGetErrorDescription9(hr);
01698             Except( hr, "Error beginning frame :" + msg, "D3D9RenderSystem::_beginFrame" );
01699         }
01700 
01701         static bool firstTime = true;
01702         if( firstTime )
01703         {
01704             // First-time 
01705             // setup some defaults
01706             // Allow alpha blending
01707             hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
01708             if (FAILED(hr))
01709             {
01710                 String msg = DXGetErrorDescription9(hr);
01711                 Except(hr, "Error enabling alpha blending option : " + msg, "D3D9RenderSystem::_beginFrame");
01712             }
01713             // Allow specular
01714             hr = __SetRenderState(D3DRS_SPECULARENABLE, TRUE);
01715             if (FAILED(hr))
01716             {
01717                 String msg = DXGetErrorDescription9(hr);
01718                 Except(hr, "Error enabling alpha blending option : " + msg, "D3D9RenderSystem::_beginFrame");
01719             }
01720             firstTime = false;
01721         }
01722 
01723         OgreUnguard();
01724     }
01725     //---------------------------------------------------------------------
01726     void D3D9RenderSystem::_endFrame()
01727     {
01728         OgreGuard( "D3D9RenderSystem::_endFrame" );
01729 
01730         HRESULT hr;
01731         if( FAILED( hr = mpD3DDevice->EndScene() ) )
01732             Except( hr, "Error ending frame", "D3D9RenderSystem::_endFrame" );
01733 
01734         OgreUnguard();
01735     }
01736     //---------------------------------------------------------------------
01737     inline bool D3D9RenderSystem::compareDecls( D3DVERTEXELEMENT9* pDecl1, D3DVERTEXELEMENT9* pDecl2, size_t size )
01738     {
01739         for( size_t i=0; i < size; i++ )
01740         {
01741             if( pDecl1[i].Method != pDecl2[i].Method ||
01742                 pDecl1[i].Offset != pDecl2[i].Offset ||
01743                 pDecl1[i].Stream != pDecl2[i].Stream ||
01744                 pDecl1[i].Type != pDecl2[i].Type ||
01745                 pDecl1[i].Usage != pDecl2[i].Usage ||
01746                 pDecl1[i].UsageIndex != pDecl2[i].UsageIndex)
01747             {
01748                 return false;
01749             }
01750         }
01751 
01752         return true;
01753     }
01754     //---------------------------------------------------------------------
01755     void D3D9RenderSystem::setVertexDeclaration(VertexDeclaration* decl)
01756     {
01757         // Guard
01758         OgreGuard ("D3D9RenderSystem::setVertexDeclaration");
01759         HRESULT hr;
01760 
01761         D3D9VertexDeclaration* d3ddecl = 
01762             static_cast<D3D9VertexDeclaration*>(decl);
01763 
01764         static VertexDeclaration* lastDecl = 0;
01765 
01766         // attempt to detect duplicates
01767         if (!lastDecl || !(*lastDecl == *decl))
01768         {
01769 
01770             if (FAILED(hr = mpD3DDevice->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
01771             {
01772                 Except(hr, "Unable to set D3D9 vertex declaration", 
01773                     "D3D9RenderSystem::setVertexDeclaration");
01774             }
01775         }
01776 
01777         // UnGuard
01778         OgreUnguard();
01779     }
01780     //---------------------------------------------------------------------
01781     void D3D9RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
01782     {
01783         // Guard
01784         OgreGuard ("D3D9RenderSystem::setVertexBufferBinding");
01785 
01786         HRESULT hr;
01787 
01788         // TODO: attempt to detect duplicates
01789         const VertexBufferBinding::VertexBufferBindingMap& binds = binding->getBindings();
01790         VertexBufferBinding::VertexBufferBindingMap::const_iterator i, iend;
01791         iend = binds.end();
01792         for (i = binds.begin(); i != iend; ++i)
01793         {
01794             const D3D9HardwareVertexBuffer* d3d9buf = 
01795                 static_cast<const D3D9HardwareVertexBuffer*>(i->second.get());
01796             hr = mpD3DDevice->SetStreamSource(
01797                 static_cast<UINT>(i->first),
01798                 d3d9buf->getD3D9VertexBuffer(),
01799                 0, // no stream offset, this is handled in _render instead
01800                 static_cast<UINT>(d3d9buf->getVertexSize()) // stride
01801                 );
01802             if (FAILED(hr))
01803             {
01804                 Except(hr, "Unable to set D3D9 stream source for buffer binding", 
01805                     "D3D9RenderSystem::setVertexBufferBinding");
01806             }
01807 
01808 
01809         }
01810 
01811         // Unbind any unused sources
01812         for (size_t unused = binds.size(); unused < mLastVertexSourceCount; ++unused)
01813         {
01814             
01815             hr = mpD3DDevice->SetStreamSource(static_cast<UINT>(unused), NULL, 0, 0);
01816             if (FAILED(hr))
01817             {
01818                 Except(hr, "Unable to reset unused D3D9 stream source", 
01819                     "D3D9RenderSystem::setVertexBufferBinding");
01820             }
01821             
01822         }
01823         mLastVertexSourceCount = binds.size();
01824         
01825 
01826         
01827         // UnGuard
01828         OgreUnguard();
01829     }
01830     //---------------------------------------------------------------------
01831     void D3D9RenderSystem::_render(const RenderOperation& op)
01832     {
01833         // Guard
01834         OgreGuard ("D3D9RenderSystem::_render");
01835 
01836         // Exit immediately if there is nothing to render
01837         // This caused a problem on FireGL 8800
01838         if (op.vertexData->vertexCount == 0)
01839             return;
01840 
01841         // Call super class
01842         RenderSystem::_render(op);
01843 
01844         // To think about: possibly remove setVertexDeclaration and 
01845         // setVertexBufferBinding from RenderSystem since the sequence is
01846         // a bit too D3D9-specific?
01847         setVertexDeclaration(op.vertexData->vertexDeclaration);
01848         setVertexBufferBinding(op.vertexData->vertexBufferBinding);
01849 
01850         // Determine rendering operation
01851         D3DPRIMITIVETYPE primType;
01852         DWORD primCount = 0;
01853         switch( op.operationType )
01854         {
01855         case RenderOperation::OT_POINT_LIST:
01856             primType = D3DPT_POINTLIST;
01857             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
01858             break;
01859 
01860         case RenderOperation::OT_LINE_LIST:
01861             primType = D3DPT_LINELIST;
01862             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
01863             break;
01864 
01865         case RenderOperation::OT_LINE_STRIP:
01866             primType = D3DPT_LINESTRIP;
01867             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
01868             break;
01869 
01870         case RenderOperation::OT_TRIANGLE_LIST:
01871             primType = D3DPT_TRIANGLELIST;
01872             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
01873             break;
01874 
01875         case RenderOperation::OT_TRIANGLE_STRIP:
01876             primType = D3DPT_TRIANGLESTRIP;
01877             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
01878             break;
01879 
01880         case RenderOperation::OT_TRIANGLE_FAN:
01881             primType = D3DPT_TRIANGLEFAN;
01882             primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
01883             break;
01884         }
01885 
01886         if (!primCount)
01887             return;
01888 
01889         // Issue the op
01890         HRESULT hr;
01891         if( op.useIndexes )
01892         {
01893             D3D9HardwareIndexBuffer* d3dIdxBuf = 
01894                 static_cast<D3D9HardwareIndexBuffer*>(op.indexData->indexBuffer.get());
01895             hr = mpD3DDevice->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
01896             if (FAILED(hr))
01897             {
01898                 Except( hr, "Failed to set index buffer", "D3D9RenderSystem::_render" );
01899             }
01900 
01901             // do indexed draw operation
01902             hr = mpD3DDevice->DrawIndexedPrimitive(
01903                 primType, 
01904                 static_cast<INT>(op.vertexData->vertexStart), 
01905                 0, // Min vertex index - assume we can go right down to 0 
01906                 static_cast<UINT>(op.vertexData->vertexCount), 
01907                 static_cast<UINT>(op.indexData->indexStart), 
01908                 static_cast<UINT>(primCount)
01909                 );
01910         }
01911         else
01912         {
01913             // Unindexed, a little simpler!
01914             hr = mpD3DDevice->DrawPrimitive(
01915                 primType, 
01916                 static_cast<UINT>(op.vertexData->vertexStart), 
01917                 static_cast<UINT>(primCount)
01918                 ); 
01919         }
01920 
01921         if( FAILED( hr ) )
01922         {
01923             String msg = DXGetErrorDescription9(hr);
01924             Except( hr, "Failed to DrawPrimitive : " + msg, "D3D9RenderSystem::_render" );
01925         }
01926         
01927         // UnGuard
01928         OgreUnguard();
01929 
01930     }
01931     //---------------------------------------------------------------------
01932     void D3D9RenderSystem::setNormaliseNormals(bool normalise)
01933     {
01934         __SetRenderState(D3DRS_NORMALIZENORMALS, 
01935             (normalise || mForcedNormalisation) ? TRUE : FALSE);
01936     }
01937     //---------------------------------------------------------------------
01938     void D3D9RenderSystem::bindGpuProgram(GpuProgram* prg)
01939     {
01940         HRESULT hr;
01941         switch (prg->getType())
01942         {
01943         case GPT_VERTEX_PROGRAM:
01944             hr = mpD3DDevice->SetVertexShader(
01945                 static_cast<D3D9GpuVertexProgram*>(prg)->getVertexShader());
01946             if (FAILED(hr))
01947             {
01948                 Except(hr, "Error calling SetVertexShader", "D3D9RenderSystem::bindGpuProgram");
01949             }
01950             break;
01951         case GPT_FRAGMENT_PROGRAM:
01952             hr = mpD3DDevice->SetPixelShader(
01953                 static_cast<D3D9GpuFragmentProgram*>(prg)->getPixelShader());
01954             if (FAILED(hr))
01955             {
01956                 Except(hr, "Error calling SetPixelShader", "D3D9RenderSystem::bindGpuProgram");
01957             }
01958             break;
01959         };
01960 
01961     }
01962     //---------------------------------------------------------------------
01963     void D3D9RenderSystem::unbindGpuProgram(GpuProgramType gptype)
01964     {
01965         HRESULT hr;
01966         switch(gptype)
01967         {
01968         case GPT_VERTEX_PROGRAM:
01969             hr = mpD3DDevice->SetVertexShader(NULL);
01970             if (FAILED(hr))
01971             {
01972                 Except(hr, "Error resetting SetVertexShader to NULL", 
01973                     "D3D9RenderSystem::unbindGpuProgram");
01974             }
01975             break;
01976         case GPT_FRAGMENT_PROGRAM:
01977             hr = mpD3DDevice->SetPixelShader(NULL);
01978             if (FAILED(hr))
01979             {
01980                 Except(hr, "Error resetting SetPixelShader to NULL", 
01981                     "D3D9RenderSystem::unbindGpuProgram");
01982             }
01983             break;
01984         };
01985     }
01986     //---------------------------------------------------------------------
01987     void D3D9RenderSystem::bindGpuProgramParameters(GpuProgramType gptype, 
01988         GpuProgramParametersSharedPtr params)
01989     {
01990         HRESULT hr;
01991         unsigned int index;
01992         GpuProgramParameters::IntConstantIterator intIt = params->getIntConstantIterator();
01993         GpuProgramParameters::RealConstantIterator realIt = params->getRealConstantIterator();
01994 
01995         switch(gptype)
01996         {
01997         case GPT_VERTEX_PROGRAM:
01998             // Bind floats
01999             if (params->hasRealConstantParams())
02000             {
02001                 // Iterate over params and set the relevant ones
02002                 index = 0;
02003                 while (realIt.hasMoreElements())
02004                 {
02005                     GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
02006                     if (e->isSet)
02007                     {
02008                         if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantF(
02009                             index, e->val, 1)))
02010                         {
02011                             Except(hr, "Unable to upload shader float parameters", 
02012                                 "D3D9RenderSystem::bindGpuProgramParameters");
02013                         }
02014                     }
02015                     index++;
02016                     realIt.moveNext();
02017                 }
02018             }
02019             // Bind ints
02020             if (params->hasIntConstantParams())
02021             {
02022                 // Iterate over params and set the relevant ones
02023                 index = 0;
02024                 while (intIt.hasMoreElements())
02025                 {
02026                     GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
02027                     if (e->isSet)
02028                     {
02029                         if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantI(
02030                             index, e->val, 1)))
02031                         {
02032                             Except(hr, "Unable to upload shader float parameters", 
02033                                 "D3D9RenderSystem::bindGpuProgramParameters");
02034                         }
02035                     }
02036                     index++;
02037                     intIt.moveNext();
02038                 }
02039             }
02040             break;
02041         case GPT_FRAGMENT_PROGRAM:
02042             // Bind floats
02043             if (params->hasRealConstantParams())
02044             {
02045                 // Iterate over params and set the relevant ones
02046                 index = 0;
02047                 while (realIt.hasMoreElements())
02048                 {
02049                     GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
02050                     if (e->isSet)
02051                     {
02052                         /*
02053                         // TEST
02054                         LogManager::getSingleton().logMessage(
02055                             "  Set Constant " + StringConverter::toString(index) + " to float4(" +
02056                             StringConverter::toString(e->val[0]) + ", " + 
02057                             StringConverter::toString(e->val[1]) + ", " + 
02058                             StringConverter::toString(e->val[2]) + ", " + 
02059                             StringConverter::toString(e->val[3]) + ")"); 
02060                         */
02061 
02062                         if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantF(
02063                             index, e->val, 1)))
02064                         {
02065                             Except(hr, "Unable to upload shader float parameters", 
02066                                 "D3D9RenderSystem::bindGpuProgramParameters");
02067                         }
02068                     }
02069                     index++;
02070                     realIt.moveNext();
02071                 }
02072             }
02073             // Bind ints
02074             if (params->hasIntConstantParams())
02075             {
02076                 // Iterate over params and set the relevant ones
02077                 index = 0;
02078                 while (intIt.hasMoreElements())
02079                 {
02080                     GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
02081                     if (e->isSet)
02082                     {
02083                         if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantI(
02084                             index, e->val, 1)))
02085                         {
02086                             Except(hr, "Unable to upload shader float parameters", 
02087                                 "D3D9RenderSystem::bindGpuProgramParameters");
02088                         }
02089                     }
02090                     index++;
02091                     intIt.moveNext();
02092                 }
02093             }
02094             break;
02095         };
02096     }
02097 
02098 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:08 2004