source: OGRE/trunk/ogre_changes/Ogre1.2/RenderSystems/Direct3D9/src/OgreD3D9RenderSystem.cpp @ 1053

Revision 1053, 114.2 KB checked in by szirmay, 18 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://ogre.sourceforge.net/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreD3D9RenderSystem.h"
26#include "OgreD3D9Prerequisites.h"
27#include "OgreD3D9DriverList.h"
28#include "OgreD3D9Driver.h"
29#include "OgreD3D9VideoModeList.h"
30#include "OgreD3D9VideoMode.h"
31#include "OgreD3D9RenderWindow.h"
32#include "OgreD3D9TextureManager.h"
33#include "OgreD3D9Texture.h"
34#include "OgreLogManager.h"
35#include "OgreLight.h"
36#include "OgreMath.h"
37#include "OgreD3D9HardwareBufferManager.h"
38#include "OgreD3D9HardwareIndexBuffer.h"
39#include "OgreD3D9HardwareVertexBuffer.h"
40#include "OgreD3D9VertexDeclaration.h"
41#include "OgreD3D9GpuProgram.h"
42#include "OgreD3D9GpuProgramManager.h"
43//#include "OgreD3D9HLSLProgramFactory.h"
44#include "OgreHighLevelGpuProgramManager.h"
45#include "OgreD3D9HardwareOcclusionQuery.h"
46#include "OgreFrustum.h"
47#include "OgreD3D9MultiRenderTarget.h"
48
49
50namespace Ogre
51{
52
53        //---------------------------------------------------------------------
54        D3D9RenderSystem::D3D9RenderSystem( HINSTANCE hInstance )
55        {
56                OgreGuard( "D3D9RenderSystem::D3D9RenderSystem" );
57                LogManager::getSingleton().logMessage( "D3D9 : " + getName() + " created." );
58
59                // set the instance being passed
60                mhInstance = hInstance;
61
62                // set pointers to NULL
63                mpD3D = NULL;
64                mpD3DDevice = NULL;
65                mDriverList = NULL;
66                mActiveD3DDriver = NULL;
67        mTextureManager = NULL;
68        mHardwareBufferManager = NULL;
69                mGpuProgramManager = NULL;
70                mPrimaryWindow = NULL;
71                mDeviceLost = false;
72                mBasicStatesInitialised = false;
73                mUseNVPerfHUD = false;
74        //mHLSLProgramFactory = NULL;
75
76                // init lights
77                for(int i = 0; i < MAX_LIGHTS; i++ )
78                        mLights[i] = 0;
79
80                // Create our Direct3D object
81                if( NULL == (mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
82                        OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Failed to create Direct3D9 object", "D3D9RenderSystem::D3D9RenderSystem" );
83
84                // set config options defaults
85                initConfigOptions();
86
87                // fsaa options
88                mFSAAType = D3DMULTISAMPLE_NONE;
89                mFSAAQuality = 0;
90
91#ifdef GAMETOOLS_ILLUMINATION_MODULE
92                for (size_t n = 0; n < OGRE_MAX_TEXTURE_LAYERS + 4; n++)
93                {
94                        mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
95                        mTexStageDesc[n].coordIndex = 0;
96                        mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
97                        mTexStageDesc[n].pTex = 0;
98                }
99#else
100                // set stages desc. to defaults
101                for (size_t n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++)
102                {
103                        mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
104                        mTexStageDesc[n].coordIndex = 0;
105                        mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
106                        mTexStageDesc[n].pTex = 0;
107                }
108#endif
109
110                mLastVertexSourceCount = 0;
111
112        mCurrentLights = 0;
113
114                // Enumerate events
115                mEventNames.push_back("DeviceLost");
116                mEventNames.push_back("DeviceRestored");
117
118
119                OgreUnguard();
120        }
121        //---------------------------------------------------------------------
122        D3D9RenderSystem::~D3D9RenderSystem()
123        {
124                OgreGuard( "D3D9RenderSystem::~D3D9RenderSystem" );
125        shutdown();
126
127               
128               
129                SAFE_DELETE( mDriverList );
130                SAFE_DELETE( mTextureManager );
131        SAFE_DELETE(mHardwareBufferManager);
132        //SAFE_DELETE(mHLSLProgramFactory);
133                SAFE_DELETE(mGpuProgramManager);
134                SAFE_RELEASE( mpD3D );
135
136                LogManager::getSingleton().logMessage( "D3D9 : " + getName() + " destroyed." );
137                OgreUnguard();
138        }
139        //---------------------------------------------------------------------
140        const String& D3D9RenderSystem::getName() const
141        {
142                static String strName( "Direct3D9 Rendering Subsystem");
143                return strName;
144        }
145        //---------------------------------------------------------------------
146        D3D9DriverList* D3D9RenderSystem::getDirect3DDrivers()
147        {
148                if( !mDriverList )
149                        mDriverList = new D3D9DriverList( mpD3D );
150
151                return mDriverList;
152        }
153        //---------------------------------------------------------------------
154        bool D3D9RenderSystem::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
155        {
156                HRESULT hr;
157                hr = mpD3D->CheckDeviceMultiSampleType(
158                                adapterNum,
159                                deviceType,
160                                format,
161                                fullScreen,
162                                type,
163                                outQuality);
164
165                if (SUCCEEDED(hr))
166                        return true;
167                else
168                        return false;
169        }
170        //---------------------------------------------------------------------
171        void D3D9RenderSystem::initConfigOptions()
172        {
173                OgreGuard( "D3D9RenderSystem::initConfigOptions" );
174
175                D3D9DriverList* driverList;
176                D3D9Driver* driver;
177
178                ConfigOption optDevice;
179                ConfigOption optVideoMode;
180                ConfigOption optFullScreen;
181                ConfigOption optVSync;
182                ConfigOption optAA;
183                ConfigOption optFPUMode;
184                ConfigOption optNVPerfHUD;
185
186                driverList = this->getDirect3DDrivers();
187
188                optDevice.name = "Rendering Device";
189                optDevice.currentValue = "";
190                optDevice.possibleValues.clear();
191                optDevice.immutable = false;
192
193                optVideoMode.name = "Video Mode";
194                optVideoMode.currentValue = "800 x 600 @ 32-bit colour";
195                optVideoMode.immutable = false;
196
197                optFullScreen.name = "Full Screen";
198                optFullScreen.possibleValues.push_back( "Yes" );
199                optFullScreen.possibleValues.push_back( "No" );
200                optFullScreen.currentValue = "Yes";
201                optFullScreen.immutable = false;
202
203                for( unsigned j=0; j < driverList->count(); j++ )
204                {
205                        driver = driverList->item(j);
206                        optDevice.possibleValues.push_back( driver->DriverDescription() );
207                        // Make first one default
208                        if( j==0 )
209                                optDevice.currentValue = driver->DriverDescription();
210                }
211
212                optVSync.name = "VSync";
213                optVSync.immutable = false;
214                optVSync.possibleValues.push_back( "Yes" );
215                optVSync.possibleValues.push_back( "No" );
216                optVSync.currentValue = "No";
217
218                optAA.name = "Anti aliasing";
219                optAA.immutable = false;
220                optAA.possibleValues.push_back( "None" );
221                optAA.currentValue = "None";
222
223                optFPUMode.name = "Floating-point mode";
224#if OGRE_DOUBLE_PRECISION
225                optFPUMode.currentValue = "Consistent";
226#else
227                optFPUMode.currentValue = "Fastest";
228#endif
229                optFPUMode.possibleValues.clear();
230                optFPUMode.possibleValues.push_back("Fastest");
231                optFPUMode.possibleValues.push_back("Consistent");
232                optFPUMode.immutable = false;
233
234                optNVPerfHUD.currentValue = "No";
235                optNVPerfHUD.immutable = false;
236                optNVPerfHUD.name = "Allow NVPerfHUD";
237                optNVPerfHUD.possibleValues.push_back( "Yes" );
238                optNVPerfHUD.possibleValues.push_back( "No" );
239
240                mOptions[optDevice.name] = optDevice;
241                mOptions[optVideoMode.name] = optVideoMode;
242                mOptions[optFullScreen.name] = optFullScreen;
243                mOptions[optVSync.name] = optVSync;
244                mOptions[optAA.name] = optAA;
245                mOptions[optFPUMode.name] = optFPUMode;
246                mOptions[optNVPerfHUD.name] = optNVPerfHUD;
247
248                refreshD3DSettings();
249
250                OgreUnguard();
251        }
252        //---------------------------------------------------------------------
253        void D3D9RenderSystem::refreshD3DSettings()
254        {
255                OgreGuard( "D3D9RenderSystem::refreshD3DSettings" );
256
257                ConfigOption* optVideoMode;
258                D3D9Driver* driver = 0;
259                D3D9VideoMode* videoMode;
260
261                ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
262                if( opt != mOptions.end() )
263                {
264                        for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
265                        {
266                                driver = getDirect3DDrivers()->item(j);
267                                if( driver->DriverDescription() == opt->second.currentValue )
268                                        break;
269                        }
270
271                        if (driver)
272                        {
273                                opt = mOptions.find( "Video Mode" );
274                                optVideoMode = &opt->second;
275                                optVideoMode->possibleValues.clear();
276                                // get vide modes for this device
277                                for( unsigned k=0; k < driver->getVideoModeList()->count(); k++ )
278                                {
279                                        videoMode = driver->getVideoModeList()->item( k );
280                                        optVideoMode->possibleValues.push_back( videoMode->getDescription() );
281                                }
282                        }
283                }
284
285                OgreUnguard();
286        }
287        //---------------------------------------------------------------------
288        void D3D9RenderSystem::setConfigOption( const String &name, const String &value )
289        {
290                OgreGuard( "D3D9RenderSystem::setConfigOption" );
291
292        StringUtil::StrStreamType str;
293        str << "D3D9 : RenderSystem Option: " << name << " = " << value;
294                LogManager::getSingleton().logMessage(str.str());
295
296                // Find option
297                ConfigOptionMap::iterator it = mOptions.find( name );
298
299                // Update
300                if( it != mOptions.end() )
301                        it->second.currentValue = value;
302                else
303                {
304            str.str(StringUtil::BLANK);
305            str << "Option named '" << name << "' does not exist.";
306                        OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, str.str(), "D3D9RenderSystem::setConfigOption" );
307                }
308
309                // Refresh other options if D3DDriver changed
310                if( name == "Rendering Device" )
311                        refreshD3DSettings();
312
313                if( name == "Full Screen" )
314                {
315                        // Video mode is applicable
316                        it = mOptions.find( "Video Mode" );
317                        if (it->second.currentValue == "")
318                                it->second.currentValue = "800 x 600 @ 32-bit colour";
319                }
320
321                if( name == "Anti aliasing" )
322                {
323                        if (value == "None")
324                                _setFSAA(D3DMULTISAMPLE_NONE, 0);
325                        else
326                        {
327                                D3DMULTISAMPLE_TYPE fsaa = D3DMULTISAMPLE_NONE;
328                                DWORD level = 0;
329
330                                if (StringUtil::startsWith(value, "NonMaskable", false))
331                                {
332                                        fsaa = D3DMULTISAMPLE_NONMASKABLE;
333                                        size_t pos = value.find_last_of(" ");
334                                        String sNum = value.substr(pos + 1);
335                                        level = StringConverter::parseInt(sNum);
336                                        level -= 1;
337                                }
338                                else if (StringUtil::startsWith(value, "Level", false))
339                                {
340                                        size_t pos = value.find_last_of(" ");
341                                        String sNum = value.substr(pos + 1);
342                                        fsaa = (D3DMULTISAMPLE_TYPE)StringConverter::parseInt(sNum);
343                                }
344
345                                _setFSAA(fsaa, level);
346                        }
347                }
348
349                if( name == "VSync" )
350                {
351                        if (value == "Yes")
352                                mVSync = true;
353                        else
354                                mVSync = false;
355                }
356
357                if( name == "Allow NVPerfHUD" )
358                {
359                        if (value == "Yes")
360                                mUseNVPerfHUD = true;
361                        else
362                                mUseNVPerfHUD = false;
363                }
364
365                if( name == "Video Mode" )
366                {
367                        ConfigOption* optFSAA;
368                        it = mOptions.find( "Anti aliasing" );
369                        optFSAA = &it->second;
370                        optFSAA->possibleValues.clear();
371                        optFSAA->possibleValues.push_back("None");
372
373                        it = mOptions.find("Rendering Device");
374                        D3D9Driver *driver = getDirect3DDrivers()->item(it->second.currentValue);
375                        if (driver)
376                        {
377                                it = mOptions.find("Video Mode");
378                                D3D9VideoMode *videoMode = driver->getVideoModeList()->item(it->second.currentValue);
379                                if (videoMode)
380                                {
381                                        // get non maskable FSAA for this VMODE
382                                        DWORD numLevels = 0;
383                                        bool bOK = this->_checkMultiSampleQuality(
384                                                D3DMULTISAMPLE_NONMASKABLE,
385                                                &numLevels,
386                                                videoMode->getFormat(),
387                                                driver->getAdapterNumber(),
388                                                D3DDEVTYPE_HAL,
389                                                TRUE);
390                                        if (bOK && numLevels > 0)
391                                        {
392                                                for (DWORD n = 0; n < numLevels; n++)
393                                                        optFSAA->possibleValues.push_back("NonMaskable " + StringConverter::toString(n + 1));
394                                        }
395
396                                        // set maskable levels supported
397                                        for (unsigned int n = 2; n < 17; n++)
398                                        {
399                                                bOK = this->_checkMultiSampleQuality(
400                                                        (D3DMULTISAMPLE_TYPE)n,
401                                                        &numLevels,
402                                                        videoMode->getFormat(),
403                                                        driver->getAdapterNumber(),
404                                                        D3DDEVTYPE_HAL,
405                                                        TRUE);
406                                                if (bOK)
407                                                        optFSAA->possibleValues.push_back("Level " + StringConverter::toString(n));
408                                        }
409                                }
410                        }
411                }
412
413                OgreUnguard();
414        }
415        //---------------------------------------------------------------------
416        String D3D9RenderSystem::validateConfigOptions()
417        {
418                ConfigOptionMap::iterator it;
419               
420                // check if video mode is selected
421                it = mOptions.find( "Video Mode" );
422                if( it->second.currentValue == "" )
423                        return "A video mode must be selected.";
424
425                it = mOptions.find( "Rendering Device" );
426                bool foundDriver = false;
427                D3D9DriverList* driverList = getDirect3DDrivers();
428                for( ushort j=0; j < driverList->count(); j++ )
429                {
430                        if( driverList->item(j)->DriverDescription() == it->second.currentValue )
431                        {
432                                foundDriver = true;
433                                break;
434                        }
435                }
436
437                if (!foundDriver)
438                {
439                        // Just pick the first driver
440                        setConfigOption("Rendering Device", driverList->item(0)->DriverDescription());
441                        return "Your DirectX driver name has changed since the last time you ran OGRE; "
442                                "the 'Rendering Device' has been changed.";
443                }
444
445        it = mOptions.find( "VSync" );
446                if( it->second.currentValue == "Yes" )
447                        mVSync = true;
448                else
449                        mVSync = false;
450
451                return "";
452        }
453        //---------------------------------------------------------------------
454        ConfigOptionMap& D3D9RenderSystem::getConfigOptions()
455        {
456                // return a COPY of the current config options
457                return mOptions;
458        }
459        //---------------------------------------------------------------------
460        RenderWindow* D3D9RenderSystem::initialise( bool autoCreateWindow, const String& windowTitle )
461        {
462                RenderWindow* autoWindow = NULL;
463                LogManager::getSingleton().logMessage( "D3D9 : Subsystem Initialising" );
464
465                // Init using current settings
466                mActiveD3DDriver = NULL;
467                ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
468                for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
469                {
470                        if( getDirect3DDrivers()->item(j)->DriverDescription() == opt->second.currentValue )
471                        {
472                                mActiveD3DDriver = getDirect3DDrivers()->item(j);
473                                break;
474                        }
475                }
476
477                if( !mActiveD3DDriver )
478                        OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Problems finding requested Direct3D driver!", "D3D9RenderSystem::initialise" );
479
480                if( autoCreateWindow )
481                {
482                        bool fullScreen;
483                        opt = mOptions.find( "Full Screen" );
484                        if( opt == mOptions.end() )
485                                Exception( Exception::ERR_INTERNAL_ERROR, "Can't find full screen option!", "D3D9RenderSystem::initialise" );
486                        fullScreen = opt->second.currentValue == "Yes";
487
488                        D3D9VideoMode* videoMode = NULL;
489                        unsigned int width, height;
490                        String temp;
491
492                        opt = mOptions.find( "Video Mode" );
493                        if( opt == mOptions.end() )
494                                Exception( Exception::ERR_INTERNAL_ERROR, "Can't find Video Mode option!", "D3D9RenderSystem::initialise" );
495
496                        for( unsigned j=0; j < mActiveD3DDriver->getVideoModeList()->count(); j++ )
497                        {
498                                temp = mActiveD3DDriver->getVideoModeList()->item(j)->getDescription();
499                                if( temp == opt->second.currentValue )
500                                {
501                                        videoMode = mActiveD3DDriver->getVideoModeList()->item(j);
502                                        break;
503                                }
504                        }
505
506                        if( !videoMode )
507                                OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Can't find requested video mode.", "D3D9RenderSystem::initialise" );
508
509                        width = videoMode->getWidth();
510                        height = videoMode->getHeight();
511                       
512                        NameValuePairList miscParams;
513                        miscParams["colourDepth"] = StringConverter::toString(videoMode->getColourDepth());
514                        miscParams["FSAA"] = StringConverter::toString(mFSAAType);
515                        miscParams["FSAAQuality"] = StringConverter::toString(mFSAAQuality);
516                        miscParams["vsync"] = StringConverter::toString(mVSync);
517                        miscParams["useNVPerfHUD"] = StringConverter::toString(mUseNVPerfHUD);
518
519                        autoWindow = this->createRenderWindow( windowTitle, width, height,
520                                fullScreen, &miscParams );
521
522            // If we have 16bit depth buffer enable w-buffering.
523            assert( autoWindow );
524            if ( autoWindow->getColourDepth() == 16 )
525            {
526                mWBuffer = true;
527            }
528            else
529            {
530                mWBuffer = false;
531            }
532                }
533
534        LogManager::getSingleton().logMessage("***************************************");
535
536                LogManager::getSingleton().logMessage("*** D3D9 : Subsystem Initialised OK ***");
537        LogManager::getSingleton().logMessage("***************************************");
538
539                // call superclass method
540                RenderSystem::initialise( autoCreateWindow );
541
542
543                return autoWindow;
544        }
545        //---------------------------------------------------------------------
546        void D3D9RenderSystem::_setFSAA(D3DMULTISAMPLE_TYPE type, DWORD qualityLevel)
547        {
548                if (!mpD3DDevice)
549                {
550                        mFSAAType = type;
551                        mFSAAQuality = qualityLevel;
552                }
553        }
554        //---------------------------------------------------------------------
555        void D3D9RenderSystem::reinitialise()
556        {
557                LogManager::getSingleton().logMessage( "D3D9 : Reinitialising" );
558                this->shutdown();
559                this->initialise( true );
560        }
561        //---------------------------------------------------------------------
562        void D3D9RenderSystem::shutdown()
563        {
564                RenderSystem::shutdown();
565                freeDevice();
566                SAFE_DELETE( mDriverList );
567                mActiveD3DDriver = NULL;
568                mpD3DDevice = NULL;
569                mBasicStatesInitialised = false;
570                LogManager::getSingleton().logMessage("D3D9 : Shutting down cleanly.");
571        }
572        //---------------------------------------------------------------------
573        RenderWindow* D3D9RenderSystem::createRenderWindow(const String &name,
574                unsigned int width, unsigned int height, bool fullScreen,
575                const NameValuePairList *miscParams)
576        {
577
578                OgreGuard( "D3D9RenderSystem::createRenderWindow" );
579
580                // Check we're not creating a secondary window when the primary
581                // was fullscreen
582                if (mPrimaryWindow && mPrimaryWindow->isFullScreen())
583                {
584                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
585                                "Cannot create secondary windows when the primary is full screen",
586                                "D3D9RenderSystem::createRenderWindow");
587                }
588                if (mPrimaryWindow && fullScreen)
589                {
590                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
591                                "Cannot create full screen secondary windows",
592                                "D3D9RenderSystem::createRenderWindow");
593                }
594               
595                // Log a message
596                std::stringstream ss;
597                ss << "D3D9RenderSystem::createRenderWindow \"" << name << "\", " <<
598                        width << "x" << height << " ";
599                if(fullScreen)
600                        ss << "fullscreen ";
601                else
602                        ss << "windowed ";
603                if(miscParams)
604                {
605                        ss << " miscParams: ";
606                        NameValuePairList::const_iterator it;
607                        for(it=miscParams->begin(); it!=miscParams->end(); ++it)
608                        {
609                                ss << it->first << "=" << it->second << " ";
610                        }
611                        LogManager::getSingleton().logMessage(ss.str());
612                }
613               
614                String msg;
615
616                // Make sure we don't already have a render target of the
617                // sam name as the one supplied
618                if( mRenderTargets.find( name ) != mRenderTargets.end() )
619                {
620                        msg = "A render target of the same name '" + name + "' already "
621                                "exists.  You cannot create a new window with this name.";
622                        OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, msg, "D3D9RenderSystem::createRenderWindow" );
623                }
624
625                RenderWindow* win = new D3D9RenderWindow(mhInstance, mActiveD3DDriver,
626                        mPrimaryWindow ? mpD3DDevice : 0);
627
628                win->create( name, width, height, fullScreen, miscParams);
629
630                attachRenderTarget( *win );
631
632                // If this is the first window, get the D3D device and create the texture manager
633                if( !mPrimaryWindow )
634                {
635                        mPrimaryWindow = (D3D9RenderWindow *)win;
636                        win->getCustomAttribute( "D3DDEVICE", &mpD3DDevice );
637
638                        // Create the texture manager for use by others
639                        mTextureManager = new D3D9TextureManager( mpD3DDevice );
640            // Also create hardware buffer manager
641            mHardwareBufferManager = new D3D9HardwareBufferManager(mpD3DDevice);
642
643                        // Create the GPU program manager
644                        mGpuProgramManager = new D3D9GpuProgramManager(mpD3DDevice);
645            // create & register HLSL factory
646            //mHLSLProgramFactory = new D3D9HLSLProgramFactory();
647            //HighLevelGpuProgramManager::getSingleton().addFactory(mHLSLProgramFactory);
648            mGpuProgramManager->_pushSyntaxCode("hlsl");
649
650
651            // Initialise the capabilities structures
652            initCapabilities();
653
654                }
655                else
656                {
657                        mSecondaryWindows.push_back(static_cast<D3D9RenderWindow *>(win));
658                }
659
660                OgreUnguardRet( win );
661        }
662    //---------------------------------------------------------------------
663    void D3D9RenderSystem::initCapabilities(void)
664    {
665                // get caps
666                mpD3DDevice->GetDeviceCaps( &mCaps );
667
668        // Check for hardware stencil support
669                LPDIRECT3DSURFACE9 pSurf;
670                D3DSURFACE_DESC surfDesc;
671                mpD3DDevice->GetDepthStencilSurface(&pSurf);
672                pSurf->GetDesc(&surfDesc);
673                pSurf->Release();
674
675                if (surfDesc.Format == D3DFMT_D24S8 || surfDesc.Format == D3DFMT_D24X8)
676                {
677                        mCapabilities->setCapability(RSC_HWSTENCIL);
678                        // Actually, it's always 8-bit
679                        mCapabilities->setStencilBufferBitDepth(8);
680
681                }
682
683                // Set number of texture units
684                mCapabilities->setNumTextureUnits(mCaps.MaxSimultaneousTextures);
685        // Anisotropy?
686        if (mCaps.MaxAnisotropy > 1)
687            mCapabilities->setCapability(RSC_ANISOTROPY);
688        // Automatic mipmap generation?
689        if (mCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
690            mCapabilities->setCapability(RSC_AUTOMIPMAP);
691        // Blending between stages supported
692        mCapabilities->setCapability(RSC_BLENDING);
693        // Dot 3
694        if (mCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
695            mCapabilities->setCapability(RSC_DOT3);
696        // Cube map
697        if (mCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
698            mCapabilities->setCapability(RSC_CUBEMAPPING);
699
700        // We always support compression, D3DX will decompress if device does not support
701        mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION);
702        mCapabilities->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
703
704        // We always support VBOs
705        mCapabilities->setCapability(RSC_VBO);
706
707        // Scissor test
708        if (mCaps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST)
709            mCapabilities->setCapability(RSC_SCISSOR_TEST);
710
711        // Two-sided stencil
712        if (mCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)
713            mCapabilities->setCapability(RSC_TWO_SIDED_STENCIL);
714
715        // stencil wrap
716        if ((mCaps.StencilCaps & D3DSTENCILCAPS_INCR) &&
717            (mCaps.StencilCaps & D3DSTENCILCAPS_DECR))
718            mCapabilities->setCapability(RSC_STENCIL_WRAP);
719
720        // Check for hardware occlusion support
721        if ( ( mpD3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION,  NULL ) ) == D3D_OK )   
722        {
723            mCapabilities->setCapability(RSC_HWOCCLUSION);
724        }
725        convertVertexShaderCaps();
726        convertPixelShaderCaps();
727
728                // User clip planes
729        if (mCaps.MaxUserClipPlanes > 0)
730                {
731                        mCapabilities->setCapability(RSC_USER_CLIP_PLANES);
732                }
733
734                // UBYTE4 type?
735                if (mCaps.DeclTypes & D3DDTCAPS_UBYTE4)
736                {
737                        mCapabilities->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
738                }
739
740                // Infinite projection?
741                // We have no capability for this, so we have to base this on our
742                // experience and reports from users
743                // Non-vertex program capable hardware does not appear to support it
744                if (mCapabilities->hasCapability(RSC_VERTEX_PROGRAM))
745                {
746                        // GeForce4 Ti (and presumably GeForce3) does not
747                        // render infinite projection properly, even though it does in GL
748            // So exclude all cards prior to the FX range from doing infinite
749            const D3DADAPTER_IDENTIFIER9& adapterID = mActiveD3DDriver->getAdapterIdentifier();
750                        if (adapterID.VendorId != 0x10DE || // not nVidia
751                                !((adapterID.DeviceId >= 0x200 && adapterID.DeviceId <= 0x20F) || //gf3
752                                  (adapterID.DeviceId >= 0x250 && adapterID.DeviceId <= 0x25F) || //gf4ti
753                                  (adapterID.DeviceId >= 0x280 && adapterID.DeviceId <= 0x28F) || //gf4ti
754                                  (adapterID.DeviceId >= 0x170 && adapterID.DeviceId <= 0x18F) || //gf4 go
755                                  (adapterID.DeviceId >= 0x280 && adapterID.DeviceId <= 0x28F)))  //gf4ti go
756                        {
757                                mCapabilities->setCapability(RSC_INFINITE_FAR_PLANE);
758                        }
759                       
760                }
761               
762                // 3D textures?
763                if (mCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
764                {
765                        mCapabilities->setCapability(RSC_TEXTURE_3D);
766                }
767               
768        // non-power-of-two texturs always supported
769        mCapabilities->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
770
771                // We always support rendertextures bigger than the frame buffer
772        mCapabilities->setCapability(RSC_HWRENDER_TO_TEXTURE);
773
774                // Determine if any floating point texture format is supported
775                D3DFORMAT floatFormats[6] = {D3DFMT_R16F, D3DFMT_G16R16F,
776                        D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F,
777                        D3DFMT_A32B32G32R32F};
778                LPDIRECT3DSURFACE9 bbSurf;
779                mPrimaryWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
780                D3DSURFACE_DESC bbSurfDesc;
781                bbSurf->GetDesc(&bbSurfDesc);
782               
783                for (int i = 0; i < 6; ++i)
784                {
785                        if (SUCCEEDED(mpD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,
786                                D3DDEVTYPE_HAL, bbSurfDesc.Format,
787                                0, D3DRTYPE_TEXTURE, floatFormats[i])))
788                        {
789                                mCapabilities->setCapability(RSC_TEXTURE_FLOAT);
790                                break;
791                        }
792                       
793                }
794               
795                // Number of render targets
796                mCapabilities->setNumMultiRenderTargets(std::min((ushort)mCaps.NumSimultaneousRTs, (ushort)OGRE_MAX_MULTIPLE_RENDER_TARGETS));
797
798                //
799                if(mCaps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS)
800                {
801                        LogManager::getSingleton().logMessage("Multiple render targets with independent bit depths supported");
802                }
803
804                // Point size
805                mCapabilities->setMaxPointSize(mCaps.MaxPointSize);
806               
807
808                Log* defaultLog = LogManager::getSingleton().getDefaultLog();
809                if (defaultLog)
810                {
811                        mCapabilities->log(defaultLog);
812                }
813    }
814    //---------------------------------------------------------------------
815    void D3D9RenderSystem::convertVertexShaderCaps(void)
816    {
817        ushort major, minor;
818        major = static_cast<ushort>((mCaps.VertexShaderVersion & 0x0000FF00) >> 8);
819        minor = static_cast<ushort>(mCaps.VertexShaderVersion & 0x000000FF);
820
821        bool vs2x = false;
822        bool vs2a = false;
823
824        // Special case detection for vs_2_x/a support
825        if (major >= 2)
826        {
827            if ((mCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
828                (mCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
829                (mCaps.VS20Caps.NumTemps >= 12))
830            {
831                vs2x = true;
832            }
833
834            if ((mCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
835                (mCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
836                (mCaps.VS20Caps.NumTemps >= 13))
837            {
838                vs2a = true;
839            }
840        }
841
842        // Populate max version & params
843        switch (major)
844        {
845        case 1:
846            mCapabilities->setMaxVertexProgramVersion("vs_1_1");
847            // No boolean params allowed
848            mCapabilities->setVertexProgramConstantBoolCount(0);
849            // No integer params allowed
850            mCapabilities->setVertexProgramConstantIntCount(0);
851            // float params, always 4D
852            mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
853           
854            break;
855        case 2:
856            if (vs2a)
857            {
858                mCapabilities->setMaxVertexProgramVersion("vs_2_a");
859            }
860            else if (vs2x)
861            {
862                mCapabilities->setMaxVertexProgramVersion("vs_2_x");
863            }
864            else
865            {
866                mCapabilities->setMaxVertexProgramVersion("vs_2_0");
867            }
868            // 16 boolean params allowed
869            mCapabilities->setVertexProgramConstantBoolCount(16);
870            // 16 integer params allowed, 4D
871            mCapabilities->setVertexProgramConstantIntCount(16);
872            // float params, always 4D
873            mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
874            break;
875        case 3:
876            mCapabilities->setMaxVertexProgramVersion("vs_3_0");
877            // 16 boolean params allowed
878            mCapabilities->setVertexProgramConstantBoolCount(16);
879            // 16 integer params allowed, 4D
880            mCapabilities->setVertexProgramConstantIntCount(16);
881            // float params, always 4D
882            mCapabilities->setVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
883            break;
884        default:
885            mCapabilities->setMaxVertexProgramVersion("");
886            break;
887        }
888
889        // populate syntax codes in program manager (no breaks in this one so it falls through)
890        switch(major)
891        {
892        case 3:
893            mGpuProgramManager->_pushSyntaxCode("vs_3_0");
894        case 2:
895            if (vs2x)
896                mGpuProgramManager->_pushSyntaxCode("vs_2_x");
897            if (vs2a)
898                mGpuProgramManager->_pushSyntaxCode("vs_2_a");
899
900            mGpuProgramManager->_pushSyntaxCode("vs_2_0");
901        case 1:
902            mGpuProgramManager->_pushSyntaxCode("vs_1_1");
903            mCapabilities->setCapability(RSC_VERTEX_PROGRAM);
904        }
905    }
906    //---------------------------------------------------------------------
907    void D3D9RenderSystem::convertPixelShaderCaps(void)
908    {
909        ushort major, minor;
910        major = static_cast<ushort>((mCaps.PixelShaderVersion & 0x0000FF00) >> 8);
911        minor = static_cast<ushort>(mCaps.PixelShaderVersion & 0x000000FF);
912
913                bool ps2a = false;
914        bool ps2b = false;
915        bool ps2x = false;
916
917        // Special case detection for ps_2_x/a/b support
918        if (major >= 2)
919        {
920                        if ((mCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
921                (mCaps.PS20Caps.NumTemps >= 32))
922            {
923                ps2b = true;
924            }
925
926                if ((mCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
927                (mCaps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
928                (mCaps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
929                                (mCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
930                                (mCaps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION) &&
931                (mCaps.PS20Caps.NumTemps >= 22))
932                {
933                ps2a = true;
934                        }
935
936            // Does this enough?
937            if (ps2a || ps2b)
938            {
939                ps2x = true;
940            }
941        }
942
943        switch (major)
944        {
945        case 1:
946            switch(minor)
947            {
948            case 1:
949                mCapabilities->setMaxFragmentProgramVersion("ps_1_1");
950                break;
951            case 2:
952                mCapabilities->setMaxFragmentProgramVersion("ps_1_2");
953                break;
954            case 3:
955                mCapabilities->setMaxFragmentProgramVersion("ps_1_3");
956                break;
957            case 4:
958                mCapabilities->setMaxFragmentProgramVersion("ps_1_4");
959                break;
960            }
961            // no boolean params allowed
962            mCapabilities->setFragmentProgramConstantBoolCount(0);
963            // no integer params allowed
964            mCapabilities->setFragmentProgramConstantIntCount(0);
965            // float params, always 4D
966            // NB in ps_1_x these are actually stored as fixed point values,
967            // but they are entered as floats
968            mCapabilities->setFragmentProgramConstantFloatCount(8);
969            break;
970        case 2:
971                        if (ps2a)
972            {
973                mCapabilities->setMaxFragmentProgramVersion("ps_2_a");
974            }
975                        else if (ps2b)
976            {
977                mCapabilities->setMaxFragmentProgramVersion("ps_2_b");
978            }
979                        else if (ps2x)
980            {
981                mCapabilities->setMaxFragmentProgramVersion("ps_2_x");
982            }
983            else
984            {
985                mCapabilities->setMaxFragmentProgramVersion("ps_2_0");
986            }
987            // 16 boolean params allowed
988            mCapabilities->setFragmentProgramConstantBoolCount(16);
989            // 16 integer params allowed, 4D
990            mCapabilities->setFragmentProgramConstantIntCount(16);
991            // float params, always 4D
992            mCapabilities->setFragmentProgramConstantFloatCount(32);
993            break;
994        case 3:
995            if (minor > 0)
996            {
997                mCapabilities->setMaxFragmentProgramVersion("ps_3_x");
998            }
999            else
1000            {
1001                mCapabilities->setMaxFragmentProgramVersion("ps_3_0");
1002            }
1003            // 16 boolean params allowed
1004            mCapabilities->setFragmentProgramConstantBoolCount(16);
1005            // 16 integer params allowed, 4D
1006            mCapabilities->setFragmentProgramConstantIntCount(16);
1007            // float params, always 4D
1008            mCapabilities->setFragmentProgramConstantFloatCount(224);
1009            break;
1010        default:
1011            mCapabilities->setMaxFragmentProgramVersion("");
1012            break;
1013        }
1014
1015        // populate syntax codes in program manager (no breaks in this one so it falls through)
1016        switch(major)
1017        {
1018        case 3:
1019            if (minor > 0)
1020                mGpuProgramManager->_pushSyntaxCode("ps_3_x");
1021
1022            mGpuProgramManager->_pushSyntaxCode("ps_3_0");
1023        case 2:
1024            if (ps2x)
1025                mGpuProgramManager->_pushSyntaxCode("ps_2_x");
1026            if (ps2a)
1027                mGpuProgramManager->_pushSyntaxCode("ps_2_a");
1028            if (ps2b)
1029                mGpuProgramManager->_pushSyntaxCode("ps_2_b");
1030
1031            mGpuProgramManager->_pushSyntaxCode("ps_2_0");
1032        case 1:
1033            if (major > 1 || minor >= 4)
1034                mGpuProgramManager->_pushSyntaxCode("ps_1_4");
1035            if (major > 1 || minor >= 3)
1036                mGpuProgramManager->_pushSyntaxCode("ps_1_3");
1037            if (major > 1 || minor >= 2)
1038                mGpuProgramManager->_pushSyntaxCode("ps_1_2");
1039           
1040            mGpuProgramManager->_pushSyntaxCode("ps_1_1");
1041            mCapabilities->setCapability(RSC_FRAGMENT_PROGRAM);
1042        }
1043    }
1044        //-----------------------------------------------------------------------
1045        MultiRenderTarget * D3D9RenderSystem::createMultiRenderTarget(const String & name)
1046        {
1047                MultiRenderTarget *retval;
1048                retval = new D3D9MultiRenderTarget(name);
1049                attachRenderTarget(*retval);
1050
1051                return retval;
1052        }
1053        //---------------------------------------------------------------------
1054        void D3D9RenderSystem::destroyRenderTarget(const String& name)
1055        {
1056                // Check in specialised lists
1057                if (mPrimaryWindow->getName() == name)
1058                {
1059                        // We're destroying the primary window, so reset device and window
1060                        mPrimaryWindow = 0;
1061                }
1062                else
1063                {
1064                        // Check secondary windows
1065                        SecondaryWindowList::iterator sw;
1066                        for (sw = mSecondaryWindows.begin(); sw != mSecondaryWindows.end(); ++sw)
1067                        {
1068                                if ((*sw)->getName() == name)
1069                                {
1070                                        mSecondaryWindows.erase(sw);
1071                                        break;
1072                                }
1073                        }
1074                }
1075                // Do the real removal
1076                RenderSystem::destroyRenderTarget(name);
1077
1078                // Did we destroy the primary?
1079                if (!mPrimaryWindow)
1080                {
1081                        // device is no longer valid, so free it all up
1082                        freeDevice();
1083                }
1084
1085        }
1086        //-----------------------------------------------------------------------
1087        void D3D9RenderSystem::freeDevice(void)
1088        {
1089                if (mpD3DDevice)
1090                {
1091                        // Set all texture units to nothing to release texture surfaces
1092                        _disableTextureUnitsFrom(0);
1093                        // Unbind any vertex streams to avoid memory leaks
1094                        for (unsigned int i = 0; i < mLastVertexSourceCount; ++i)
1095                        {
1096                                HRESULT hr = mpD3DDevice->SetStreamSource(i, NULL, 0, 0);
1097                        }
1098                        // Clean up depth stencil surfaces
1099                        _cleanupDepthStencils();
1100                        SAFE_RELEASE(mpD3DDevice);
1101                        mActiveD3DDriver->setD3DDevice(NULL);
1102                        mpD3DDevice = 0;
1103
1104                }
1105
1106
1107        }
1108        //---------------------------------------------------------------------
1109        String D3D9RenderSystem::getErrorDescription( long errorNumber ) const
1110        {
1111                const String errMsg = DXGetErrorDescription9( errorNumber );
1112                return errMsg;
1113        }
1114    //---------------------------------------------------------------------
1115        VertexElementType D3D9RenderSystem::getColourVertexElementType(void) const
1116        {
1117                return VET_COLOUR_ARGB;
1118        }
1119        //---------------------------------------------------------------------
1120        void D3D9RenderSystem::_convertProjectionMatrix(const Matrix4& matrix,
1121        Matrix4& dest, bool forGpuProgram)
1122    {
1123        dest = matrix;
1124
1125        // Convert depth range from [-1,+1] to [0,1]
1126        dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
1127        dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
1128        dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
1129        dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
1130
1131        if (!forGpuProgram)
1132        {
1133            // Convert right-handed to left-handed
1134            dest[0][2] = -dest[0][2];
1135            dest[1][2] = -dest[1][2];
1136            dest[2][2] = -dest[2][2];
1137            dest[3][2] = -dest[3][2];
1138        }
1139    }
1140        //---------------------------------------------------------------------
1141        void D3D9RenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane,
1142        Real farPlane, Matrix4& dest, bool forGpuProgram)
1143        {
1144        Radian theta ( fovy * 0.5 );
1145                Real h = 1 / Math::Tan(theta);
1146                Real w = h / aspect;
1147                Real q, qn;
1148        if (farPlane == 0)
1149        {
1150            q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
1151            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
1152        }
1153        else
1154        {
1155            q = farPlane / ( farPlane - nearPlane );
1156            qn = -q * nearPlane;
1157        }
1158
1159                dest = Matrix4::ZERO;
1160                dest[0][0] = w;
1161                dest[1][1] = h;
1162
1163        if (forGpuProgram)
1164        {
1165            dest[2][2] = -q;
1166                    dest[3][2] = -1.0f;
1167        }
1168        else
1169        {
1170            dest[2][2] = q;
1171            dest[3][2] = 1.0f;
1172        }
1173
1174        dest[2][3] = qn;
1175        }
1176        //---------------------------------------------------------------------
1177        void D3D9RenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, Real farPlane,
1178                Matrix4& dest, bool forGpuProgram )
1179        {
1180        Radian thetaY (fovy / 2.0f);
1181        Real tanThetaY = Math::Tan(thetaY);
1182
1183        //Real thetaX = thetaY * aspect;
1184        Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
1185        Real half_w = tanThetaX * nearPlane;
1186        Real half_h = tanThetaY * nearPlane;
1187        Real iw = 1.0 / half_w;
1188        Real ih = 1.0 / half_h;
1189        Real q;
1190        if (farPlane == 0)
1191        {
1192            q = 0;
1193        }
1194        else
1195        {
1196            q = 1.0 / (farPlane - nearPlane);
1197        }
1198
1199        dest = Matrix4::ZERO;
1200        dest[0][0] = iw;
1201        dest[1][1] = ih;
1202        dest[2][2] = q;
1203        dest[2][3] = -nearPlane / (farPlane - nearPlane);
1204        dest[3][3] = 1;
1205
1206        if (forGpuProgram)
1207        {
1208            dest[2][2] = -dest[2][2];
1209        }
1210        }
1211        //---------------------------------------------------------------------
1212        void D3D9RenderSystem::setAmbientLight( float r, float g, float b )
1213        {
1214                HRESULT hr = __SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( r, g, b, 1.0f ) );
1215                if( FAILED( hr ) )
1216                        OGRE_EXCEPT( hr, "Failed to set render stat D3DRS_AMBIENT", "D3D9RenderSystem::setAmbientLight" );
1217        }
1218        //---------------------------------------------------------------------
1219    void D3D9RenderSystem::_useLights(const LightList& lights, unsigned short limit)
1220    {
1221        LightList::const_iterator i, iend;
1222        iend = lights.end();
1223        unsigned short num = 0;
1224        for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
1225        {
1226            setD3D9Light(num, *i);
1227        }
1228        // Disable extra lights
1229        for (; num < mCurrentLights; ++num)
1230        {
1231            setD3D9Light(num, NULL);
1232        }
1233        mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
1234
1235    }
1236        //---------------------------------------------------------------------
1237        void D3D9RenderSystem::setShadingType( ShadeOptions so )
1238        {
1239                HRESULT hr = __SetRenderState( D3DRS_SHADEMODE, D3D9Mappings::get(so) );
1240                if( FAILED( hr ) )
1241                        OGRE_EXCEPT( hr, "Failed to set render stat D3DRS_SHADEMODE", "D3D9RenderSystem::setShadingType" );
1242        }
1243        //---------------------------------------------------------------------
1244        void D3D9RenderSystem::setLightingEnabled( bool enabled )
1245        {
1246                HRESULT hr;
1247                if( FAILED( hr = __SetRenderState( D3DRS_LIGHTING, enabled ) ) )
1248                        OGRE_EXCEPT( hr, "Failed to set render state D3DRS_LIGHTING", "D3D9RenderSystem::setLightingEnabled" );
1249        }
1250        //---------------------------------------------------------------------
1251        void D3D9RenderSystem::setD3D9Light( size_t index, Light* lt )
1252        {
1253                HRESULT hr;
1254
1255                D3DLIGHT9 d3dLight;
1256                ZeroMemory( &d3dLight, sizeof(d3dLight) );
1257
1258        if (!lt)
1259        {
1260            if( FAILED( hr = mpD3DDevice->LightEnable( index, FALSE) ) )
1261                            OGRE_EXCEPT( hr, "Unable to disable light", "D3D9RenderSystem::setD3D9Light" );
1262        }
1263        else
1264        {
1265                        switch( lt->getType() )
1266                        {
1267                        case Light::LT_POINT:
1268                                d3dLight.Type = D3DLIGHT_POINT;
1269                                break;
1270
1271                        case Light::LT_DIRECTIONAL:
1272                                d3dLight.Type = D3DLIGHT_DIRECTIONAL;
1273                                break;
1274
1275                        case Light::LT_SPOTLIGHT:
1276                                d3dLight.Type = D3DLIGHT_SPOT;
1277                                d3dLight.Falloff = lt->getSpotlightFalloff();
1278                                d3dLight.Theta = lt->getSpotlightInnerAngle().valueRadians();
1279                                d3dLight.Phi = lt->getSpotlightOuterAngle().valueRadians();
1280                                break;
1281                        }
1282
1283                        ColourValue col;
1284                        col = lt->getDiffuseColour();
1285                        d3dLight.Diffuse = D3DXCOLOR( col.r, col.g, col.b, col.a );
1286
1287                        col = lt->getSpecularColour();
1288                        d3dLight.Specular = D3DXCOLOR( col.r, col.g, col.b, col.a );
1289
1290                        Vector3 vec;
1291                        if( lt->getType() != Light::LT_DIRECTIONAL )
1292                        {
1293                                vec = lt->getDerivedPosition();
1294                                d3dLight.Position = D3DXVECTOR3( vec.x, vec.y, vec.z );
1295                        }
1296                        if( lt->getType() != Light::LT_POINT )
1297                        {
1298                                vec = lt->getDerivedDirection();
1299                                d3dLight.Direction = D3DXVECTOR3( vec.x, vec.y, vec.z );
1300                        }
1301
1302                        d3dLight.Range = lt->getAttenuationRange();
1303                        d3dLight.Attenuation0 = lt->getAttenuationConstant();
1304                        d3dLight.Attenuation1 = lt->getAttenuationLinear();
1305                        d3dLight.Attenuation2 = lt->getAttenuationQuadric();
1306
1307                        if( FAILED( hr = mpD3DDevice->SetLight( index, &d3dLight ) ) )
1308                                OGRE_EXCEPT( hr, "Unable to set light details", "D3D9RenderSystem::setD3D9Light" );
1309
1310            if( FAILED( hr = mpD3DDevice->LightEnable( index, TRUE ) ) )
1311                            OGRE_EXCEPT( hr, "Unable to enable light", "D3D9RenderSystem::setD3D9Light" );
1312        }
1313
1314
1315        }
1316        //---------------------------------------------------------------------
1317        void D3D9RenderSystem::_setViewMatrix( const Matrix4 &m )
1318        {
1319        // save latest view matrix
1320        mViewMatrix = m;
1321        mViewMatrix[2][0] = -mViewMatrix[2][0];
1322        mViewMatrix[2][1] = -mViewMatrix[2][1];
1323        mViewMatrix[2][2] = -mViewMatrix[2][2];
1324        mViewMatrix[2][3] = -mViewMatrix[2][3];
1325
1326        D3DXMATRIX d3dmat = D3D9Mappings::makeD3DXMatrix( mViewMatrix );
1327
1328                HRESULT hr;
1329                if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_VIEW, &d3dmat ) ) )
1330                        OGRE_EXCEPT( hr, "Cannot set D3D9 view matrix", "D3D9RenderSystem::_setViewMatrix" );
1331        }
1332        //---------------------------------------------------------------------
1333        void D3D9RenderSystem::_setProjectionMatrix( const Matrix4 &m )
1334        {
1335                D3DXMATRIX d3dMat = D3D9Mappings::makeD3DXMatrix( m );
1336
1337                if( mActiveRenderTarget->requiresTextureFlipping() )
1338        {
1339            // Invert transformed y
1340            d3dMat._12 = - d3dMat._12;
1341                        d3dMat._22 = - d3dMat._22;
1342            d3dMat._32 = - d3dMat._32;
1343            d3dMat._42 = - d3dMat._42;
1344        }
1345
1346                HRESULT hr;
1347                if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_PROJECTION, &d3dMat ) ) )
1348                        OGRE_EXCEPT( hr, "Cannot set D3D9 projection matrix", "D3D9RenderSystem::_setProjectionMatrix" );
1349        }
1350        //---------------------------------------------------------------------
1351        void D3D9RenderSystem::_setWorldMatrix( const Matrix4 &m )
1352        {
1353                D3DXMATRIX d3dMat = D3D9Mappings::makeD3DXMatrix( m );
1354
1355                HRESULT hr;
1356                if( FAILED( hr = mpD3DDevice->SetTransform( D3DTS_WORLD, &d3dMat ) ) )
1357                        OGRE_EXCEPT( hr, "Cannot set D3D9 world matrix", "D3D9RenderSystem::_setWorldMatrix" );
1358        }
1359        //---------------------------------------------------------------------
1360        void D3D9RenderSystem::_setSurfaceParams( const ColourValue &ambient, const ColourValue &diffuse,
1361                const ColourValue &specular, const ColourValue &emissive, Real shininess,
1362        TrackVertexColourType tracking )
1363        {
1364               
1365                D3DMATERIAL9 material;
1366                material.Diffuse = D3DXCOLOR( diffuse.r, diffuse.g, diffuse.b, diffuse.a );
1367                material.Ambient = D3DXCOLOR( ambient.r, ambient.g, ambient.b, ambient.a );
1368                material.Specular = D3DXCOLOR( specular.r, specular.g, specular.b, specular.a );
1369                material.Emissive = D3DXCOLOR( emissive.r, emissive.g, emissive.b, emissive.a );
1370                material.Power = shininess;
1371
1372                HRESULT hr = mpD3DDevice->SetMaterial( &material );
1373                if( FAILED( hr ) )
1374                        OGRE_EXCEPT( hr, "Error setting D3D material", "D3D9RenderSystem::_setSurfaceParams" );
1375
1376
1377                if(tracking != TVC_NONE)
1378        {
1379            __SetRenderState(D3DRS_COLORVERTEX, TRUE);
1380            __SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, (tracking&TVC_AMBIENT)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
1381            __SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, (tracking&TVC_DIFFUSE)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
1382            __SetRenderState(D3DRS_SPECULARMATERIALSOURCE, (tracking&TVC_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
1383            __SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, (tracking&TVC_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
1384        }
1385        else
1386        {
1387            __SetRenderState(D3DRS_COLORVERTEX, FALSE);               
1388        }
1389       
1390        }
1391        //---------------------------------------------------------------------
1392        void D3D9RenderSystem::_setPointParameters(Real size,
1393                bool attenuationEnabled, Real constant, Real linear, Real quadratic,
1394                Real minSize, Real maxSize)
1395    {
1396                if(attenuationEnabled)
1397                {
1398                        // scaling required
1399                        __SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
1400                        __SetFloatRenderState(D3DRS_POINTSCALE_A, constant);
1401                        __SetFloatRenderState(D3DRS_POINTSCALE_B, linear);
1402                        __SetFloatRenderState(D3DRS_POINTSCALE_C, quadratic);
1403                }
1404                else
1405                {
1406                        // no scaling required
1407                        __SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
1408                }
1409                __SetFloatRenderState(D3DRS_POINTSIZE, size);
1410                __SetFloatRenderState(D3DRS_POINTSIZE_MIN, minSize);
1411                if (maxSize == 0.0f)
1412                        maxSize = mCapabilities->getMaxPointSize();
1413                __SetFloatRenderState(D3DRS_POINTSIZE_MAX, maxSize);
1414
1415
1416    }
1417        //---------------------------------------------------------------------
1418        void D3D9RenderSystem::_setPointSpritesEnabled(bool enabled)
1419        {
1420                if (enabled)
1421                {
1422                        __SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
1423                }
1424                else
1425                {
1426                        __SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
1427                }
1428        }
1429
1430       
1431#ifdef GAMETOOLS_ILLUMINATION_MODULE
1432        void D3D9RenderSystem::_setTexture( size_t stage, bool enabled, const String &texname )
1433        {
1434                int newstage = stage;
1435                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1436                {
1437                        stage -= OGRE_MAX_TEXTURE_LAYERS;               
1438                        newstage = stage + 1 + D3DDMAPSAMPLER;         
1439                }
1440
1441               
1442                HRESULT hr;
1443                D3D9TexturePtr dt = TextureManager::getSingleton().getByName(texname);
1444                if (enabled && !dt.isNull())
1445                {
1446            // note used
1447            dt->touch();
1448
1449                        IDirect3DBaseTexture9 *pTex = dt->getTexture();
1450                        if (mTexStageDesc[stage].pTex != pTex)
1451                        {
1452                                hr = mpD3DDevice->SetTexture(newstage, pTex);
1453                                if( hr != S_OK )
1454                                {
1455                                        String str = "Unable to set texture '" + texname + "' in D3D9";
1456                                        OGRE_EXCEPT( hr, str, "D3D9RenderSystem::_setTexture" );
1457                                }
1458                               
1459                                // set stage desc.
1460                                mTexStageDesc[stage].pTex = pTex;
1461                                mTexStageDesc[stage].texType = D3D9Mappings::get(dt->getTextureType());
1462                        }
1463                }
1464                else
1465                {
1466                        if (mTexStageDesc[stage].pTex != 0)
1467                        {
1468                                hr = mpD3DDevice->SetTexture(stage, 0);
1469                                if( hr != S_OK )
1470                                {
1471                                        String str = "Unable to disable texture '" + texname + "' in D3D9";
1472                                        OGRE_EXCEPT( hr, str, "D3D9RenderSystem::_setTexture" );
1473                                }
1474                        }
1475
1476                        hr = this->__SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE);
1477                        if( hr != S_OK )
1478                        {
1479                                String str = "Unable to disable texture '" + texname + "' in D3D9";
1480                                OGRE_EXCEPT( hr, str, "D3D9RenderSystem::_setTexture" );
1481                        }
1482
1483                        // set stage desc. to defaults
1484                        mTexStageDesc[stage].pTex = 0;
1485                        mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
1486                        mTexStageDesc[stage].coordIndex = 0;
1487                        mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
1488                }
1489        }
1490#else
1491        void D3D9RenderSystem::_setTexture( size_t stage, bool enabled, const String &texname )
1492        {
1493                HRESULT hr;
1494                D3D9TexturePtr dt = TextureManager::getSingleton().getByName(texname);
1495                if (enabled && !dt.isNull())
1496                {
1497            // note used
1498            dt->touch();
1499
1500                        IDirect3DBaseTexture9 *pTex = dt->getTexture();
1501                        if (mTexStageDesc[stage].pTex != pTex)
1502                        {
1503                                hr = mpD3DDevice->SetTexture(stage, pTex);
1504                                if( hr != S_OK )
1505                                {
1506                                        String str = "Unable to set texture '" + texname + "' in D3D9";
1507                                        OGRE_EXCEPT( hr, str, "D3D9RenderSystem::_setTexture" );
1508                                }
1509                               
1510                                // set stage desc.
1511                                mTexStageDesc[stage].pTex = pTex;
1512                                mTexStageDesc[stage].texType = D3D9Mappings::get(dt->getTextureType());
1513                        }
1514                }
1515                else
1516                {
1517                        if (mTexStageDesc[stage].pTex != 0)
1518                        {
1519                                hr = mpD3DDevice->SetTexture(stage, 0);
1520                                if( hr != S_OK )
1521                                {
1522                                        String str = "Unable to disable texture '" + texname + "' in D3D9";
1523                                        OGRE_EXCEPT( hr, str, "D3D9RenderSystem::_setTexture" );
1524                                }
1525                        }
1526
1527                        hr = this->__SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE);
1528                        if( hr != S_OK )
1529                        {
1530                                String str = "Unable to disable texture '" + texname + "' in D3D9";
1531                                OGRE_EXCEPT( hr, str, "D3D9RenderSystem::_setTexture" );
1532                        }
1533
1534                        // set stage desc. to defaults
1535                        mTexStageDesc[stage].pTex = 0;
1536                        mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
1537                        mTexStageDesc[stage].coordIndex = 0;
1538                        mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
1539                }
1540        }
1541#endif
1542
1543        //---------------------------------------------------------------------
1544        void D3D9RenderSystem::_setTextureCoordSet( size_t stage, size_t index )
1545        {
1546                #ifdef GAMETOOLS_ILLUMINATION_MODULE
1547                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1548                        stage -= OGRE_MAX_TEXTURE_LAYERS;
1549                #endif
1550
1551                HRESULT hr;
1552        // Record settings
1553        mTexStageDesc[stage].coordIndex = index;
1554
1555                hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(mTexStageDesc[stage].autoTexCoordType, mCaps) | index );
1556                if( FAILED( hr ) )
1557                        OGRE_EXCEPT( hr, "Unable to set texture coord. set index", "D3D8RenderSystem::_setTextureCoordSet" );
1558        }
1559        //---------------------------------------------------------------------
1560        void D3D9RenderSystem::_setTextureCoordCalculation( size_t stage, TexCoordCalcMethod m,
1561        const Frustum* frustum)
1562        {
1563                #ifdef GAMETOOLS_ILLUMINATION_MODULE
1564                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1565                        stage -= OGRE_MAX_TEXTURE_LAYERS;
1566                #endif
1567
1568                HRESULT hr;
1569                // record the stage state
1570                mTexStageDesc[stage].autoTexCoordType = m;
1571        mTexStageDesc[stage].frustum = frustum;
1572
1573                hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(m, mCaps) | mTexStageDesc[stage].coordIndex );
1574                if(FAILED(hr))
1575                        OGRE_EXCEPT( hr, "Unable to set texture auto tex.coord. generation mode", "D3D8RenderSystem::_setTextureCoordCalculation" );
1576        }
1577    //---------------------------------------------------------------------
1578        void D3D9RenderSystem::_setTextureMatrix( size_t stage, const Matrix4& xForm )
1579        {       
1580                #ifdef GAMETOOLS_ILLUMINATION_MODULE
1581                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1582                        stage -= OGRE_MAX_TEXTURE_LAYERS;
1583                #endif
1584
1585                HRESULT hr;
1586                D3DXMATRIX d3dMat; // the matrix we'll maybe apply
1587                Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format
1588                // Cache texcoord calc method to register
1589                TexCoordCalcMethod autoTexCoordType = mTexStageDesc[stage].autoTexCoordType;
1590
1591                if (autoTexCoordType == TEXCALC_ENVIRONMENT_MAP)
1592        {
1593            if (mCaps.VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP)
1594            {
1595                /** Invert the texture for the spheremap */
1596                Matrix4 ogreMatEnvMap = Matrix4::IDENTITY;
1597                            // set env_map values
1598                            ogreMatEnvMap[1][1] = -1.0f;
1599                            // concatenate with the xForm
1600                            newMat = newMat.concatenate(ogreMatEnvMap);
1601            }
1602            else
1603            {
1604                        /* If envmap is applied, but device doesn't support spheremap,
1605                        then we have to use texture transform to make the camera space normal
1606                        reference the envmap properly. This isn't exactly the same as spheremap
1607                        (it looks nasty on flat areas because the camera space normals are the same)
1608                        but it's the best approximation we have in the absence of a proper spheremap */
1609                            // concatenate with the xForm
1610                newMat = newMat.concatenate(Matrix4::CLIPSPACE2DTOIMAGESPACE);
1611            }
1612                }
1613
1614        // If this is a cubic reflection, we need to modify using the view matrix
1615        if (autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION)
1616        {
1617            // Get transposed 3x3
1618            // We want to transpose since that will invert an orthonormal matrix ie rotation
1619            Matrix4 ogreViewTransposed;
1620            ogreViewTransposed[0][0] = mViewMatrix[0][0];
1621            ogreViewTransposed[0][1] = mViewMatrix[1][0];
1622            ogreViewTransposed[0][2] = mViewMatrix[2][0];
1623            ogreViewTransposed[0][3] = 0.0f;
1624
1625            ogreViewTransposed[1][0] = mViewMatrix[0][1];
1626            ogreViewTransposed[1][1] = mViewMatrix[1][1];
1627            ogreViewTransposed[1][2] = mViewMatrix[2][1];
1628            ogreViewTransposed[1][3] = 0.0f;
1629
1630            ogreViewTransposed[2][0] = mViewMatrix[0][2];
1631            ogreViewTransposed[2][1] = mViewMatrix[1][2];
1632            ogreViewTransposed[2][2] = mViewMatrix[2][2];
1633            ogreViewTransposed[2][3] = 0.0f;
1634
1635            ogreViewTransposed[3][0] = 0.0f;
1636            ogreViewTransposed[3][1] = 0.0f;
1637            ogreViewTransposed[3][2] = 0.0f;
1638            ogreViewTransposed[3][3] = 1.0f;
1639           
1640            newMat = newMat.concatenate(ogreViewTransposed);
1641        }
1642
1643        if (autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
1644        {
1645            // Derive camera space to projector space transform
1646            // To do this, we need to undo the camera view matrix, then
1647            // apply the projector view & projection matrices
1648            newMat = mViewMatrix.inverse();
1649            newMat = mTexStageDesc[stage].frustum->getViewMatrix() * newMat;
1650            newMat = mTexStageDesc[stage].frustum->getProjectionMatrix() * newMat;
1651            newMat = Matrix4::CLIPSPACE2DTOIMAGESPACE * newMat;
1652            newMat = xForm * newMat;
1653        }
1654
1655                // need this if texture is a cube map, to invert D3D's z coord
1656                if (autoTexCoordType != TEXCALC_NONE &&
1657            autoTexCoordType != TEXCALC_PROJECTIVE_TEXTURE)
1658                {
1659            newMat[2][0] = -newMat[2][0];
1660            newMat[2][1] = -newMat[2][1];
1661            newMat[2][2] = -newMat[2][2];
1662            newMat[2][3] = -newMat[2][3];
1663                }
1664
1665        // convert our matrix to D3D format
1666                d3dMat = D3D9Mappings::makeD3DXMatrix(newMat);
1667
1668                // set the matrix if it's not the identity
1669                if (!D3DXMatrixIsIdentity(&d3dMat))
1670                {
1671            /* It's seems D3D automatically add a texture coordinate with value 1,
1672            and fill up the remaining texture coordinates with 0 for the input
1673            texture coordinates before pass to texture coordinate transformation.
1674
1675               NOTE: It's difference with D3DDECLTYPE enumerated type expand in
1676            DirectX SDK documentation!
1677
1678               So we should prepare the texcoord transform, make the transformation
1679            just like standardized vector expand, thus, fill w with value 1 and
1680            others with 0.
1681            */
1682            if (autoTexCoordType == TEXCALC_NONE)
1683            {
1684                /* FIXME: The actually input texture coordinate dimensions should
1685                be determine by texture coordinate vertex element. Now, just trust
1686                user supplied texture type matchs texture coordinate vertex element.
1687                */
1688                if (mTexStageDesc[stage].texType == D3D9Mappings::D3D_TEX_TYPE_NORMAL)
1689                {
1690                    /* It's 2D input texture coordinate:
1691
1692                      texcoord in vertex buffer     D3D expanded to     We are adjusted to
1693                                                -->                 -->
1694                                (u, v)               (u, v, 1, 0)          (u, v, 0, 1)
1695                    */
1696                    std::swap(d3dMat._31, d3dMat._41);
1697                    std::swap(d3dMat._32, d3dMat._42);
1698                    std::swap(d3dMat._33, d3dMat._43);
1699                    std::swap(d3dMat._34, d3dMat._44);
1700                }
1701            }
1702            else
1703            {
1704                // All texgen generate 3D input texture coordinates.
1705            }
1706
1707                        // tell D3D the dimension of tex. coord.
1708                        int texCoordDim = D3DTTFF_COUNT2;
1709            if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
1710            {
1711                /* We want texcoords (u, v, w, q) always get divided by q, but D3D
1712                projected texcoords is divided by the last element (in the case of
1713                2D texcoord, is w). So we tweak the transform matrix, transform the
1714                texcoords with w and q swapped: (u, v, q, w), and then D3D will
1715                divide u, v by q. The w and q just ignored as it wasn't used by
1716                rasterizer.
1717                */
1718                            switch (mTexStageDesc[stage].texType)
1719                            {
1720                            case D3D9Mappings::D3D_TEX_TYPE_NORMAL:
1721                    std::swap(d3dMat._13, d3dMat._14);
1722                    std::swap(d3dMat._23, d3dMat._24);
1723                    std::swap(d3dMat._33, d3dMat._34);
1724                    std::swap(d3dMat._43, d3dMat._44);
1725
1726                    texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT3;
1727                    break;
1728
1729                            case D3D9Mappings::D3D_TEX_TYPE_CUBE:
1730                            case D3D9Mappings::D3D_TEX_TYPE_VOLUME:
1731                    // Yes, we support 3D projective texture.
1732                                    texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT4;
1733                    break;
1734                }
1735            }
1736            else
1737            {
1738                            switch (mTexStageDesc[stage].texType)
1739                            {
1740                            case D3D9Mappings::D3D_TEX_TYPE_NORMAL:
1741                                    texCoordDim = D3DTTFF_COUNT2;
1742                                    break;
1743                            case D3D9Mappings::D3D_TEX_TYPE_CUBE:
1744                            case D3D9Mappings::D3D_TEX_TYPE_VOLUME:
1745                                    texCoordDim = D3DTTFF_COUNT3;
1746                    break;
1747                            }
1748            }
1749
1750                        hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim );
1751                        if (FAILED(hr))
1752                                OGRE_EXCEPT( hr, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" );
1753
1754                        hr = mpD3DDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
1755                        if (FAILED(hr))
1756                                OGRE_EXCEPT( hr, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
1757                }
1758                else
1759                {
1760                        // disable all of this
1761                        hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
1762                        if( FAILED( hr ) )
1763                                OGRE_EXCEPT( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
1764
1765                        // set the identity matrix
1766                        hr = mpD3DDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
1767                        if( FAILED( hr ) )
1768                                OGRE_EXCEPT( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
1769                }
1770        }
1771        //---------------------------------------------------------------------
1772        void D3D9RenderSystem::_setTextureAddressingMode( size_t stage,
1773                const TextureUnitState::UVWAddressingMode& uvw )
1774        {
1775                #ifdef GAMETOOLS_ILLUMINATION_MODULE
1776                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1777                        stage -= OGRE_MAX_TEXTURE_LAYERS;
1778                #endif
1779
1780                HRESULT hr;
1781                if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSU, D3D9Mappings::get(uvw.u) ) ) )
1782                        OGRE_EXCEPT( hr, "Failed to set texture addressing mode for U", "D3D9RenderSystem::_setTextureAddressingMode" );
1783                if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSV, D3D9Mappings::get(uvw.v) ) ) )
1784                        OGRE_EXCEPT( hr, "Failed to set texture addressing mode for V", "D3D9RenderSystem::_setTextureAddressingMode" );
1785                if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_ADDRESSW, D3D9Mappings::get(uvw.w) ) ) )
1786                        OGRE_EXCEPT( hr, "Failed to set texture addressing mode for W", "D3D9RenderSystem::_setTextureAddressingMode" );
1787        }
1788    //-----------------------------------------------------------------------------
1789    void D3D9RenderSystem::_setTextureBorderColour(size_t stage,
1790        const ColourValue& colour)
1791    {
1792                #ifdef GAMETOOLS_ILLUMINATION_MODULE
1793                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1794                        stage -= OGRE_MAX_TEXTURE_LAYERS;
1795                #endif
1796
1797                HRESULT hr;
1798                if( FAILED( hr = __SetSamplerState( stage, D3DSAMP_BORDERCOLOR, colour.getAsARGB()) ) )
1799                        OGRE_EXCEPT( hr, "Failed to set texture border colour", "D3D9RenderSystem::_setTextureBorderColour" );
1800    }
1801        //---------------------------------------------------------------------
1802        void D3D9RenderSystem::_setTextureBlendMode( size_t stage, const LayerBlendModeEx& bm )
1803        {
1804                #ifdef GAMETOOLS_ILLUMINATION_MODULE
1805                if(stage >= OGRE_MAX_TEXTURE_LAYERS)
1806                        stage -= OGRE_MAX_TEXTURE_LAYERS;
1807                #endif
1808
1809                HRESULT hr = S_OK;
1810                D3DTEXTURESTAGESTATETYPE tss;
1811                D3DCOLOR manualD3D;
1812
1813
1814                // choose type of blend.
1815                if( bm.blendType == LBT_COLOUR )
1816                        tss = D3DTSS_COLOROP;
1817                else if( bm.blendType == LBT_ALPHA )
1818                        tss = D3DTSS_ALPHAOP;
1819                else
1820                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1821                        "Invalid blend type", "D3D9RenderSystem::_setTextureBlendMode");
1822
1823                // set manual factor if required by operation
1824                if (bm.operation == LBX_BLEND_MANUAL)
1825                {
1826                        hr = __SetRenderState( D3DRS_TEXTUREFACTOR, D3DXCOLOR(0.0, 0.0, 0.0,  bm.factor) );
1827                        if (FAILED(hr))
1828                                OGRE_EXCEPT( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
1829                }
1830                // set operation
1831                hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.operation, mCaps) );
1832                if (FAILED(hr))
1833                        OGRE_EXCEPT( hr, "Failed to set operation", "D3D9RenderSystem::_setTextureBlendMode" );
1834
1835                // choose source 1
1836                if( bm.blendType == LBT_COLOUR )
1837                {
1838                        tss = D3DTSS_COLORARG1;
1839                        manualD3D = D3DXCOLOR( bm.colourArg1.r, bm.colourArg1.g, bm.colourArg1.b, bm.colourArg1.a );
1840                        mManualBlendColours[stage][0] = bm.colourArg1;
1841                }
1842                else if( bm.blendType == LBT_ALPHA )
1843                {
1844                        tss = D3DTSS_ALPHAARG1;
1845                        manualD3D = D3DXCOLOR( mManualBlendColours[stage][0].r,
1846                                mManualBlendColours[stage][0].g,
1847                                mManualBlendColours[stage][0].b, bm.alphaArg1 );
1848                }
1849                else
1850                {
1851                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1852                                "Invalid blend type", "D3D9RenderSystem::_setTextureBlendMode");
1853                }
1854                // Set manual factor if required
1855                if (bm.source1 == LBS_MANUAL)
1856                {
1857                        hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
1858                        if (FAILED(hr))
1859                                OGRE_EXCEPT( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
1860                }
1861                // set source 1
1862                hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.source1) );
1863                if (FAILED(hr))
1864                        OGRE_EXCEPT( hr, "Failed to set source1", "D3D9RenderSystem::_setTextureBlendMode" );
1865               
1866                // choose source 2
1867                if( bm.blendType == LBT_COLOUR )
1868                {
1869                        tss = D3DTSS_COLORARG2;
1870                        manualD3D = D3DXCOLOR( bm.colourArg2.r, bm.colourArg2.g, bm.colourArg2.b, bm.colourArg2.a );
1871                        mManualBlendColours[stage][1] = bm.colourArg1;
1872                }
1873                else if( bm.blendType == LBT_ALPHA )
1874                {
1875                        tss = D3DTSS_ALPHAARG2;
1876                        manualD3D = D3DXCOLOR( mManualBlendColours[stage][1].r,
1877                                mManualBlendColours[stage][1].g,
1878                                mManualBlendColours[stage][1].b,
1879                                bm.alphaArg2 );
1880                }
1881                // Set manual factor if required
1882                if (bm.source2 == LBS_MANUAL)
1883                {
1884                        hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
1885                        if (FAILED(hr))
1886                                OGRE_EXCEPT( hr, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
1887                }
1888                // Now set source 2
1889                hr = __SetTextureStageState( stage, tss, D3D9Mappings::get(bm.source2) );
1890                if (FAILED(hr))
1891                        OGRE_EXCEPT( hr, "Failed to set source 2", "D3D9RenderSystem::_setTextureBlendMode" );
1892
1893                // Set interpolation factor if lerping
1894                if (bm.operation == LBX_BLEND_DIFFUSE_COLOUR &&
1895                        mCaps.TextureOpCaps & D3DTEXOPCAPS_LERP)
1896                {
1897                        // choose source 0 (lerp factor)
1898                        if( bm.blendType == LBT_COLOUR )
1899                        {
1900                                tss = D3DTSS_COLORARG0;
1901                        }
1902                        else if( bm.blendType == LBT_ALPHA )
1903                        {
1904                                tss = D3DTSS_ALPHAARG0;
1905                        }
1906                        hr = __SetTextureStageState(stage, tss, D3DTA_DIFFUSE);
1907
1908                        if (FAILED(hr))
1909                                OGRE_EXCEPT( hr, "Failed to set lerp source 0",
1910                                        "D3D9RenderSystem::_setTextureBlendMode" );
1911
1912                }
1913        }
1914       
1915#ifdef GAMETOOLS_ILLUMINATION_MODULE
1916
1917        void D3D9RenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor,
1918                                                                                SceneBlendFactor destFactor,
1919                                                                                SceneBlendOperation blendOp,
1920                                                                                bool separateAlpha,
1921                                                                                SceneBlendFactor sourceFactorAlpha,
1922                                                                                SceneBlendFactor destFactorAlpha,
1923                                                                                SceneBlendOperation blendOpAlpha)
1924        {
1925                HRESULT hr;
1926                if( sourceFactor == SBF_ONE && destFactor == SBF_ZERO &&
1927                        sourceFactorAlpha == SBF_ONE && destFactorAlpha == SBF_ZERO)
1928                {
1929                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
1930                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1931                }
1932                else
1933                {
1934                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
1935                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1936                                       
1937                        if(separateAlpha)
1938                        {
1939                                if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE)))
1940                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1941                               
1942                                if (FAILED(hr = __SetRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(blendOp))))
1943                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1944
1945                                if( FAILED( hr = __SetRenderState( D3DRS_SRCBLENDALPHA, D3D9Mappings::get(sourceFactor) ) ) )
1946                                        OGRE_EXCEPT( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
1947                                if( FAILED( hr = __SetRenderState( D3DRS_DESTBLENDALPHA, D3D9Mappings::get(destFactor) ) ) )
1948                                        OGRE_EXCEPT( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
1949               
1950                        }
1951                        else
1952                        {
1953                                if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE)))
1954                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1955                        }
1956                       
1957                        if (FAILED(hr = __SetRenderState(D3DRS_BLENDOP, D3D9Mappings::get(blendOpAlpha))))
1958                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1959                        if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
1960                                OGRE_EXCEPT( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
1961                        if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
1962                                OGRE_EXCEPT( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );                   
1963                }
1964        }
1965#else
1966        //---------------------------------------------------------------------
1967        void D3D9RenderSystem::_setSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor )
1968        {
1969                HRESULT hr;
1970                if( sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
1971                {
1972                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
1973                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1974                }
1975                else
1976                {
1977                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
1978                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1979                        if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
1980                                OGRE_EXCEPT( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
1981                        if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
1982                                OGRE_EXCEPT( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
1983                }
1984        }
1985#endif
1986        //---------------------------------------------------------------------
1987        void D3D9RenderSystem::_setAlphaRejectSettings( CompareFunction func, unsigned char value )
1988        {
1989                HRESULT hr;
1990        if (func != CMPF_ALWAYS_PASS)
1991        {
1992            if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE ) ) )
1993                        OGRE_EXCEPT( hr, "Failed to enable alpha testing",
1994                "D3D9RenderSystem::_setAlphaRejectSettings" );
1995        }
1996        else
1997        {
1998            if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  FALSE ) ) )
1999                        OGRE_EXCEPT( hr, "Failed to disable alpha testing",
2000                "D3D9RenderSystem::_setAlphaRejectSettings" );
2001        }
2002        // Set always just be sure
2003                if( FAILED( hr = __SetRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
2004                        OGRE_EXCEPT( hr, "Failed to set alpha reject function", "D3D9RenderSystem::_setAlphaRejectSettings" );
2005                if( FAILED( hr = __SetRenderState( D3DRS_ALPHAREF, value ) ) )
2006                        OGRE_EXCEPT( hr, "Failed to set render state D3DRS_ALPHAREF", "D3D9RenderSystem::_setAlphaRejectSettings" );
2007        }
2008        //---------------------------------------------------------------------
2009        void D3D9RenderSystem::_setCullingMode( CullingMode mode )
2010        {
2011                HRESULT hr;
2012        bool flip = ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
2013                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding));
2014
2015                if( FAILED (hr = __SetRenderState(D3DRS_CULLMODE,
2016            D3D9Mappings::get(mode, flip))) )
2017                        OGRE_EXCEPT( hr, "Failed to set culling mode", "D3D9RenderSystem::_setCullingMode" );
2018        }
2019        //---------------------------------------------------------------------
2020        void D3D9RenderSystem::_setDepthBufferParams( bool depthTest, bool depthWrite, CompareFunction depthFunction )
2021        {
2022                _setDepthBufferCheckEnabled( depthTest );
2023                _setDepthBufferWriteEnabled( depthWrite );
2024                _setDepthBufferFunction( depthFunction );
2025        }
2026        //---------------------------------------------------------------------
2027        void D3D9RenderSystem::_setDepthBufferCheckEnabled( bool enabled )
2028        {
2029                HRESULT hr;
2030
2031                if( enabled )
2032                {
2033                        // Use w-buffer if available and enabled
2034                        if( mWBuffer && mCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
2035                                hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
2036                        else
2037                                hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
2038                }
2039                else
2040                        hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
2041
2042                if( FAILED( hr ) )
2043                        OGRE_EXCEPT( hr, "Error setting depth buffer test state", "D3D9RenderSystem::_setDepthBufferCheckEnabled" );
2044        }
2045        //---------------------------------------------------------------------
2046        void D3D9RenderSystem::_setDepthBufferWriteEnabled( bool enabled )
2047        {
2048                HRESULT hr;
2049
2050                if( FAILED( hr = __SetRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
2051                        OGRE_EXCEPT( hr, "Error setting depth buffer write state", "D3D9RenderSystem::_setDepthBufferWriteEnabled" );
2052        }
2053        //---------------------------------------------------------------------
2054        void D3D9RenderSystem::_setDepthBufferFunction( CompareFunction func )
2055        {
2056                HRESULT hr;
2057                if( FAILED( hr = __SetRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
2058                        OGRE_EXCEPT( hr, "Error setting depth buffer test function", "D3D9RenderSystem::_setDepthBufferFunction" );
2059        }
2060        //---------------------------------------------------------------------
2061        void D3D9RenderSystem::_setDepthBias(ushort bias)
2062        {
2063                float bias_float = static_cast<float>(-bias);
2064                // scale down - certainly needed for nVidia
2065                bias_float /= 250000.0f;
2066                HRESULT hr = __SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&bias_float);
2067                if (FAILED(hr))
2068                        OGRE_EXCEPT(hr, "Error setting depth bias", "D3D9RenderSystem::_setDepthBias");
2069        }
2070        //---------------------------------------------------------------------
2071        void D3D9RenderSystem::_setColourBufferWriteEnabled(bool red, bool green,
2072                bool blue, bool alpha)
2073        {
2074                DWORD val = 0;
2075                if (red)
2076                        val |= D3DCOLORWRITEENABLE_RED;
2077                if (green)
2078                        val |= D3DCOLORWRITEENABLE_GREEN;
2079                if (blue)
2080                        val |= D3DCOLORWRITEENABLE_BLUE;
2081                if (alpha)
2082                        val |= D3DCOLORWRITEENABLE_ALPHA;
2083                HRESULT hr = __SetRenderState(D3DRS_COLORWRITEENABLE, val);
2084                if (FAILED(hr))
2085                        OGRE_EXCEPT(hr, "Error setting colour write enable flags",
2086                        "D3D9RenderSystem::_setColourBufferWriteEnabled");
2087        }
2088        //---------------------------------------------------------------------
2089        void D3D9RenderSystem::_setFog( FogMode mode, const ColourValue& colour, Real densitiy, Real start, Real end )
2090        {
2091                HRESULT hr;
2092
2093                D3DRENDERSTATETYPE fogType, fogTypeNot;
2094
2095                if (mCaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
2096                {
2097                        fogType = D3DRS_FOGTABLEMODE;
2098                        fogTypeNot = D3DRS_FOGVERTEXMODE;
2099                }
2100                else
2101                {
2102                        fogType = D3DRS_FOGVERTEXMODE;
2103                        fogTypeNot = D3DRS_FOGTABLEMODE;
2104                }
2105
2106                if( mode == FOG_NONE)
2107                {
2108                        // just disable
2109                        hr = __SetRenderState(fogType, D3DFOG_NONE );
2110                        hr = __SetRenderState(D3DRS_FOGENABLE, FALSE);
2111                }
2112                else
2113                {
2114                        // Allow fog
2115                        hr = __SetRenderState( D3DRS_FOGENABLE, TRUE );
2116                        hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
2117                        hr = __SetRenderState( fogType, D3D9Mappings::get(mode) );
2118
2119                        hr = __SetRenderState( D3DRS_FOGCOLOR, colour.getAsARGB() );
2120                        hr = __SetFloatRenderState( D3DRS_FOGSTART, start );
2121                        hr = __SetFloatRenderState( D3DRS_FOGEND, end );
2122                        hr = __SetFloatRenderState( D3DRS_FOGDENSITY, densitiy );
2123                }
2124
2125                if( FAILED( hr ) )
2126                        OGRE_EXCEPT( hr, "Error setting render state", "D3D9RenderSystem::_setFog" );
2127        }
2128        //---------------------------------------------------------------------
2129        void D3D9RenderSystem::_setPolygonMode(PolygonMode level)
2130        {
2131                HRESULT hr = __SetRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
2132                if (FAILED(hr))
2133                        OGRE_EXCEPT(hr, "Error setting polygon mode.", "D3D9RenderSystem::setPolygonMode");
2134        }
2135        //---------------------------------------------------------------------
2136        void D3D9RenderSystem::setStencilCheckEnabled(bool enabled)
2137        {
2138                // Allow stencilling
2139                HRESULT hr = __SetRenderState(D3DRS_STENCILENABLE, enabled);
2140                if (FAILED(hr))
2141                        OGRE_EXCEPT(hr, "Error enabling / disabling stencilling.",
2142                        "D3D9RenderSystem::setStencilCheckEnabled");
2143        }
2144    //---------------------------------------------------------------------
2145    void D3D9RenderSystem::setStencilBufferParams(CompareFunction func,
2146        uint32 refValue, uint32 mask, StencilOperation stencilFailOp,
2147        StencilOperation depthFailOp, StencilOperation passOp,
2148        bool twoSidedOperation)
2149    {
2150        HRESULT hr;
2151        bool flip;
2152
2153        // 2-sided operation
2154        if (twoSidedOperation)
2155        {
2156            if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
2157                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
2158                    "D3D9RenderSystem::setStencilBufferParams");
2159            hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
2160                    if (FAILED(hr))
2161                            OGRE_EXCEPT(hr, "Error setting 2-sided stencil mode.",
2162                            "D3D9RenderSystem::setStencilBufferParams");
2163            // NB: We should always treat CCW as front face for consistent with default
2164            // culling mode. Therefore, we must take care with two-sided stencil settings.
2165            flip = (mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping()) ||
2166                   (!mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping());
2167
2168            // Set alternative versions of ops
2169            // fail op
2170            hr = __SetRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp, !flip));
2171            if (FAILED(hr))
2172                OGRE_EXCEPT(hr, "Error setting stencil fail operation (2-sided).",
2173                "D3D9RenderSystem::setStencilBufferParams");
2174
2175            // depth fail op
2176            hr = __SetRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp, !flip));
2177            if (FAILED(hr))
2178                OGRE_EXCEPT(hr, "Error setting stencil depth fail operation (2-sided).",
2179                "D3D9RenderSystem::setStencilBufferParams");
2180
2181            // pass op
2182            hr = __SetRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp, !flip));
2183            if (FAILED(hr))
2184                OGRE_EXCEPT(hr, "Error setting stencil pass operation (2-sided).",
2185                "D3D9RenderSystem::setStencilBufferParams");
2186        }
2187        else
2188        {
2189            hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2190                    if (FAILED(hr))
2191                            OGRE_EXCEPT(hr, "Error setting 1-sided stencil mode.",
2192                            "D3D9RenderSystem::setStencilBufferParams");
2193            flip = false;
2194        }
2195
2196        // func
2197        hr = __SetRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
2198                if (FAILED(hr))
2199                        OGRE_EXCEPT(hr, "Error setting stencil buffer test function.",
2200                        "D3D9RenderSystem::setStencilBufferParams");
2201
2202        // reference value
2203        hr = __SetRenderState(D3DRS_STENCILREF, refValue);
2204                if (FAILED(hr))
2205                        OGRE_EXCEPT(hr, "Error setting stencil buffer reference value.",
2206                        "D3D9RenderSystem::setStencilBufferParams");
2207
2208        // mask
2209        hr = __SetRenderState(D3DRS_STENCILMASK, mask);
2210                if (FAILED(hr))
2211                        OGRE_EXCEPT(hr, "Error setting stencil buffer mask.",
2212                        "D3D9RenderSystem::setStencilBufferParams");
2213
2214                // fail op
2215        hr = __SetRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp, flip));
2216                if (FAILED(hr))
2217                        OGRE_EXCEPT(hr, "Error setting stencil fail operation.",
2218                        "D3D9RenderSystem::setStencilBufferParams");
2219
2220        // depth fail op
2221        hr = __SetRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp, flip));
2222                if (FAILED(hr))
2223                        OGRE_EXCEPT(hr, "Error setting stencil depth fail operation.",
2224                        "D3D9RenderSystem::setStencilBufferParams");
2225
2226        // pass op
2227        hr = __SetRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp, flip));
2228                if (FAILED(hr))
2229                        OGRE_EXCEPT(hr, "Error setting stencil pass operation.",
2230                        "D3D9RenderSystem::setStencilBufferParams");
2231        }
2232        //---------------------------------------------------------------------
2233    void D3D9RenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype,
2234        FilterOptions filter)
2235        {               
2236                #ifdef GAMETOOLS_ILLUMINATION_MODULE
2237                if(unit >= OGRE_MAX_TEXTURE_LAYERS)
2238                        unit -= OGRE_MAX_TEXTURE_LAYERS;
2239                #endif
2240
2241                HRESULT hr;
2242                D3D9Mappings::eD3DTexType texType = mTexStageDesc[unit].texType;
2243        hr = __SetSamplerState( unit, D3D9Mappings::get(ftype),
2244            D3D9Mappings::get(ftype, filter, mCaps, texType));
2245                if (FAILED(hr))
2246                        OGRE_EXCEPT(hr, "Failed to set texture filter ", "D3D9RenderSystem::_setTextureUnitFiltering");
2247        }
2248    //---------------------------------------------------------------------
2249        DWORD D3D9RenderSystem::_getCurrentAnisotropy(size_t unit)
2250        {
2251                DWORD oldVal;
2252                mpD3DDevice->GetSamplerState(unit, D3DSAMP_MAXANISOTROPY, &oldVal);
2253                        return oldVal;
2254        }
2255        //---------------------------------------------------------------------
2256        void D3D9RenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
2257        {
2258                #ifdef GAMETOOLS_ILLUMINATION_MODULE
2259                if(unit >= OGRE_MAX_TEXTURE_LAYERS)
2260                        unit -= OGRE_MAX_TEXTURE_LAYERS;
2261                #endif
2262
2263                if ((DWORD)maxAnisotropy > mCaps.MaxAnisotropy)
2264                        maxAnisotropy = mCaps.MaxAnisotropy;
2265
2266                if (_getCurrentAnisotropy(unit) != maxAnisotropy)
2267                        __SetSamplerState( unit, D3DSAMP_MAXANISOTROPY, maxAnisotropy );
2268        }
2269        //---------------------------------------------------------------------
2270        HRESULT D3D9RenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
2271        {
2272                HRESULT hr;
2273                DWORD oldVal;
2274
2275                if ( FAILED( hr = mpD3DDevice->GetRenderState(state, &oldVal) ) )
2276                        return hr;
2277                if ( oldVal == value )
2278                        return D3D_OK;
2279                else
2280                        return mpD3DDevice->SetRenderState(state, value);
2281        }
2282        //---------------------------------------------------------------------
2283        HRESULT D3D9RenderSystem::__SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
2284        {
2285                HRESULT hr;
2286                DWORD oldVal;
2287
2288                if ( FAILED( hr = mpD3DDevice->GetSamplerState(sampler, type, &oldVal) ) )
2289                        return hr;
2290                if ( oldVal == value )
2291                        return D3D_OK;
2292                else
2293                        return mpD3DDevice->SetSamplerState(sampler, type, value);
2294        }
2295        //---------------------------------------------------------------------
2296        HRESULT D3D9RenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
2297        {
2298                HRESULT hr;
2299                DWORD oldVal;
2300               
2301                if ( FAILED( hr = mpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) )
2302                        return hr;
2303                if ( oldVal == value )
2304                        return D3D_OK;
2305                else
2306                        return mpD3DDevice->SetTextureStageState(stage, type, value);
2307        }
2308        //---------------------------------------------------------------------
2309        void D3D9RenderSystem::_setViewport( Viewport *vp )
2310        {
2311                if( vp != mActiveViewport || vp->_isUpdated() )
2312                {
2313                        mActiveViewport = vp;
2314                        mActiveRenderTarget = vp->getTarget();
2315
2316                        // ok, it's different, time to set render target and viewport params
2317                        D3DVIEWPORT9 d3dvp;
2318                        HRESULT hr;
2319
2320                        // Set render target
2321                        RenderTarget* target;
2322                        target = vp->getTarget();
2323
2324                        // Retrieve render surfaces (up to OGRE_MAX_MULTIPLE_RENDER_TARGETS)
2325                        LPDIRECT3DSURFACE9 pBack[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
2326                        memset(pBack, 0, sizeof(pBack));
2327                        target->getCustomAttribute( "DDBACKBUFFER", &pBack );
2328                        if (!pBack[0])
2329                                return;
2330
2331                        LPDIRECT3DSURFACE9 pDepth = NULL;
2332                        target->getCustomAttribute( "D3DZBUFFER", &pDepth );
2333                        if (!pDepth)
2334                        {
2335                                /// No depth buffer provided, use our own
2336                                /// Request a depth stencil that is compatible with the format, multisample type and
2337                                /// dimensions of the render target.
2338                                D3DSURFACE_DESC srfDesc;
2339                                if(FAILED(pBack[0]->GetDesc(&srfDesc)))
2340                                        return; // ?
2341                                pDepth = _getDepthStencilFor(srfDesc.Format, srfDesc.MultiSampleType, srfDesc.Width, srfDesc.Height);
2342                        }
2343                        // Bind render targets
2344                        uint count = mCapabilities->numMultiRenderTargets();
2345                        for(uint x=0; x<count; ++x)
2346                        {
2347                                hr = mpD3DDevice->SetRenderTarget(x, pBack[x]);
2348                                if (FAILED(hr))
2349                                {
2350                                        String msg = DXGetErrorDescription9(hr);
2351                                        OGRE_EXCEPT( hr, "Failed to setRenderTarget : " + msg, "D3D9RenderSystem::_setViewport" );
2352                                }
2353                        }
2354                        hr = mpD3DDevice->SetDepthStencilSurface(pDepth);
2355                        if (FAILED(hr))
2356                        {
2357                                String msg = DXGetErrorDescription9(hr);
2358                                OGRE_EXCEPT( hr, "Failed to setDepthStencil : " + msg, "D3D9RenderSystem::_setViewport" );
2359                        }
2360
2361                        _setCullingMode( mCullingMode );
2362
2363                        // set viewport dimensions
2364                        d3dvp.X = vp->getActualLeft();
2365                        d3dvp.Y = vp->getActualTop();
2366                        d3dvp.Width = vp->getActualWidth();
2367                        d3dvp.Height = vp->getActualHeight();
2368            if (target->requiresTextureFlipping())
2369            {
2370                // Convert "top-left" to "bottom-left"
2371                d3dvp.Y = target->getHeight() - d3dvp.Height - d3dvp.Y;
2372            }
2373
2374                        // Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
2375                        d3dvp.MinZ = 0.0f;
2376                        d3dvp.MaxZ = 1.0f;
2377
2378                        if( FAILED( hr = mpD3DDevice->SetViewport( &d3dvp ) ) )
2379                                OGRE_EXCEPT( hr, "Failed to set viewport.", "D3D9RenderSystem::_setViewport" );
2380
2381                        vp->_clearUpdatedFlag();
2382                }
2383        }
2384        //---------------------------------------------------------------------
2385        void D3D9RenderSystem::_beginFrame()
2386        {
2387                OgreGuard( "D3D9RenderSystem::_beginFrame" );
2388
2389                HRESULT hr;
2390
2391                if( !mActiveViewport )
2392                        OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Cannot begin frame - no viewport selected.", "D3D9RenderSystem::_beginFrame" );
2393
2394                // Clear the viewport if required
2395                if( mActiveViewport->getClearEveryFrame() )
2396                {
2397            clearFrameBuffer(mActiveViewport->getClearBuffers(),
2398                mActiveViewport->getBackgroundColour());
2399                }
2400
2401                if( FAILED( hr = mpD3DDevice->BeginScene() ) )
2402                {
2403                        String msg = DXGetErrorDescription9(hr);
2404                        OGRE_EXCEPT( hr, "Error beginning frame :" + msg, "D3D9RenderSystem::_beginFrame" );
2405                }
2406
2407                if(!mBasicStatesInitialised)
2408                {
2409                        // First-time
2410                        // setup some defaults
2411                        // Allow specular
2412                        hr = __SetRenderState(D3DRS_SPECULARENABLE, TRUE);
2413                        if (FAILED(hr))
2414                        {
2415                                String msg = DXGetErrorDescription9(hr);
2416                                OGRE_EXCEPT(hr, "Error enabling alpha blending option : " + msg, "D3D9RenderSystem::_beginFrame");
2417                        }
2418                        mBasicStatesInitialised = true;
2419                }
2420
2421                OgreUnguard();
2422        }
2423        //---------------------------------------------------------------------
2424        void D3D9RenderSystem::_endFrame()
2425        {
2426                OgreGuard( "D3D9RenderSystem::_endFrame" );
2427
2428                HRESULT hr;
2429                if( FAILED( hr = mpD3DDevice->EndScene() ) )
2430                        OGRE_EXCEPT( hr, "Error ending frame", "D3D9RenderSystem::_endFrame" );
2431
2432                OgreUnguard();
2433        }
2434        //---------------------------------------------------------------------
2435        inline bool D3D9RenderSystem::compareDecls( D3DVERTEXELEMENT9* pDecl1, D3DVERTEXELEMENT9* pDecl2, size_t size )
2436        {
2437                for( size_t i=0; i < size; i++ )
2438                {
2439                        if( pDecl1[i].Method != pDecl2[i].Method ||
2440                                pDecl1[i].Offset != pDecl2[i].Offset ||
2441                                pDecl1[i].Stream != pDecl2[i].Stream ||
2442                                pDecl1[i].Type != pDecl2[i].Type ||
2443                                pDecl1[i].Usage != pDecl2[i].Usage ||
2444                                pDecl1[i].UsageIndex != pDecl2[i].UsageIndex)
2445                        {
2446                                return false;
2447                        }
2448                }
2449
2450                return true;
2451        }
2452    //---------------------------------------------------------------------
2453        void D3D9RenderSystem::setVertexDeclaration(VertexDeclaration* decl)
2454        {
2455                // Guard
2456                OgreGuard ("D3D9RenderSystem::setVertexDeclaration");
2457        HRESULT hr;
2458
2459        D3D9VertexDeclaration* d3ddecl =
2460            static_cast<D3D9VertexDeclaration*>(decl);
2461
2462        if (FAILED(hr = mpD3DDevice->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
2463        {
2464            OGRE_EXCEPT(hr, "Unable to set D3D9 vertex declaration",
2465                "D3D9RenderSystem::setVertexDeclaration");
2466        }
2467
2468        // UnGuard
2469                OgreUnguard();
2470        }
2471    //---------------------------------------------------------------------
2472        void D3D9RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
2473        {
2474                // Guard
2475                OgreGuard ("D3D9RenderSystem::setVertexBufferBinding");
2476
2477        HRESULT hr;
2478
2479        // TODO: attempt to detect duplicates
2480        const VertexBufferBinding::VertexBufferBindingMap& binds = binding->getBindings();
2481        VertexBufferBinding::VertexBufferBindingMap::const_iterator i, iend;
2482        iend = binds.end();
2483        for (i = binds.begin(); i != iend; ++i)
2484        {
2485            const D3D9HardwareVertexBuffer* d3d9buf =
2486                static_cast<const D3D9HardwareVertexBuffer*>(i->second.get());
2487            hr = mpD3DDevice->SetStreamSource(
2488                static_cast<UINT>(i->first),
2489                d3d9buf->getD3D9VertexBuffer(),
2490                0, // no stream offset, this is handled in _render instead
2491                static_cast<UINT>(d3d9buf->getVertexSize()) // stride
2492                );
2493            if (FAILED(hr))
2494            {
2495                OGRE_EXCEPT(hr, "Unable to set D3D9 stream source for buffer binding",
2496                    "D3D9RenderSystem::setVertexBufferBinding");
2497            }
2498
2499
2500        }
2501
2502                // Unbind any unused sources
2503                for (size_t unused = binds.size(); unused < mLastVertexSourceCount; ++unused)
2504                {
2505                       
2506            hr = mpD3DDevice->SetStreamSource(static_cast<UINT>(unused), NULL, 0, 0);
2507            if (FAILED(hr))
2508            {
2509                OGRE_EXCEPT(hr, "Unable to reset unused D3D9 stream source",
2510                    "D3D9RenderSystem::setVertexBufferBinding");
2511            }
2512                       
2513                }
2514                mLastVertexSourceCount = binds.size();
2515               
2516
2517               
2518        // UnGuard
2519                OgreUnguard();
2520        }
2521    //---------------------------------------------------------------------
2522    void D3D9RenderSystem::_render(const RenderOperation& op)
2523        {
2524                // Guard
2525                OgreGuard ("D3D9RenderSystem::_render");
2526
2527        // Exit immediately if there is nothing to render
2528        // This caused a problem on FireGL 8800
2529        if (op.vertexData->vertexCount == 0)
2530            return;
2531
2532        // Call super class
2533                RenderSystem::_render(op);
2534
2535        // To think about: possibly remove setVertexDeclaration and
2536        // setVertexBufferBinding from RenderSystem since the sequence is
2537        // a bit too D3D9-specific?
2538                setVertexDeclaration(op.vertexData->vertexDeclaration);
2539        setVertexBufferBinding(op.vertexData->vertexBufferBinding);
2540
2541                // Determine rendering operation
2542                D3DPRIMITIVETYPE primType = D3DPT_TRIANGLELIST;
2543                DWORD primCount = 0;
2544        switch( op.operationType )
2545                {
2546        case RenderOperation::OT_POINT_LIST:
2547                        primType = D3DPT_POINTLIST;
2548                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
2549                        break;
2550
2551                case RenderOperation::OT_LINE_LIST:
2552                        primType = D3DPT_LINELIST;
2553                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
2554                        break;
2555
2556                case RenderOperation::OT_LINE_STRIP:
2557                        primType = D3DPT_LINESTRIP;
2558                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
2559                        break;
2560
2561                case RenderOperation::OT_TRIANGLE_LIST:
2562                        primType = D3DPT_TRIANGLELIST;
2563                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
2564                        break;
2565
2566                case RenderOperation::OT_TRIANGLE_STRIP:
2567                        primType = D3DPT_TRIANGLESTRIP;
2568                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
2569                        break;
2570
2571                case RenderOperation::OT_TRIANGLE_FAN:
2572                        primType = D3DPT_TRIANGLEFAN;
2573                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
2574                        break;
2575                }
2576
2577        if (!primCount)
2578                        return;
2579
2580                // Issue the op
2581        HRESULT hr;
2582                if( op.useIndexes )
2583                {
2584            D3D9HardwareIndexBuffer* d3dIdxBuf =
2585                static_cast<D3D9HardwareIndexBuffer*>(op.indexData->indexBuffer.get());
2586                        hr = mpD3DDevice->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
2587                        if (FAILED(hr))
2588            {
2589                                OGRE_EXCEPT( hr, "Failed to set index buffer", "D3D9RenderSystem::_render" );
2590            }
2591
2592            do
2593            {
2594                // do indexed draw operation
2595                            hr = mpD3DDevice->DrawIndexedPrimitive(
2596                    primType,
2597                    static_cast<INT>(op.vertexData->vertexStart),
2598                    0, // Min vertex index - assume we can go right down to 0
2599                    static_cast<UINT>(op.vertexData->vertexCount),
2600                    static_cast<UINT>(op.indexData->indexStart),
2601                    static_cast<UINT>(primCount)
2602                    );
2603
2604            } while (updatePassIterationRenderState());
2605                }
2606                else
2607        {
2608            // nfz: gpu_iterate
2609            do
2610            {
2611                // Unindexed, a little simpler!
2612                            hr = mpD3DDevice->DrawPrimitive(
2613                    primType,
2614                    static_cast<UINT>(op.vertexData->vertexStart),
2615                    static_cast<UINT>(primCount)
2616                    );
2617
2618            } while (updatePassIterationRenderState());
2619        }
2620
2621                if( FAILED( hr ) )
2622                {
2623                        String msg = DXGetErrorDescription9(hr);
2624                        OGRE_EXCEPT( hr, "Failed to DrawPrimitive : " + msg, "D3D9RenderSystem::_render" );
2625                }
2626       
2627        // UnGuard
2628                OgreUnguard();
2629
2630        }
2631    //---------------------------------------------------------------------
2632    void D3D9RenderSystem::setNormaliseNormals(bool normalise)
2633    {
2634        __SetRenderState(D3DRS_NORMALIZENORMALS,
2635            normalise ? TRUE : FALSE);
2636    }
2637        //---------------------------------------------------------------------
2638    void D3D9RenderSystem::bindGpuProgram(GpuProgram* prg)
2639    {
2640        HRESULT hr;
2641        switch (prg->getType())
2642        {
2643        case GPT_VERTEX_PROGRAM:
2644            hr = mpD3DDevice->SetVertexShader(
2645                static_cast<D3D9GpuVertexProgram*>(prg)->getVertexShader());
2646            if (FAILED(hr))
2647            {
2648                OGRE_EXCEPT(hr, "Error calling SetVertexShader", "D3D9RenderSystem::bindGpuProgram");
2649            }
2650            break;
2651        case GPT_FRAGMENT_PROGRAM:
2652            hr = mpD3DDevice->SetPixelShader(
2653                static_cast<D3D9GpuFragmentProgram*>(prg)->getPixelShader());
2654            if (FAILED(hr))
2655            {
2656                OGRE_EXCEPT(hr, "Error calling SetPixelShader", "D3D9RenderSystem::bindGpuProgram");
2657            }
2658            break;
2659        };
2660       
2661        RenderSystem::bindGpuProgram(prg);
2662
2663    }
2664        //---------------------------------------------------------------------
2665    void D3D9RenderSystem::unbindGpuProgram(GpuProgramType gptype)
2666    {
2667        HRESULT hr;
2668        switch(gptype)
2669        {
2670        case GPT_VERTEX_PROGRAM:
2671            mActiveVertexGpuProgramParameters.setNull();
2672            hr = mpD3DDevice->SetVertexShader(NULL);
2673            if (FAILED(hr))
2674            {
2675                OGRE_EXCEPT(hr, "Error resetting SetVertexShader to NULL",
2676                    "D3D9RenderSystem::unbindGpuProgram");
2677            }
2678            break;
2679        case GPT_FRAGMENT_PROGRAM:
2680            mActiveFragmentGpuProgramParameters.setNull();
2681            hr = mpD3DDevice->SetPixelShader(NULL);
2682            if (FAILED(hr))
2683            {
2684                OGRE_EXCEPT(hr, "Error resetting SetPixelShader to NULL",
2685                    "D3D9RenderSystem::unbindGpuProgram");
2686            }
2687            break;
2688        };
2689        RenderSystem::unbindGpuProgram(gptype);
2690    }
2691        //---------------------------------------------------------------------
2692    void D3D9RenderSystem::bindGpuProgramParameters(GpuProgramType gptype,
2693        GpuProgramParametersSharedPtr params)
2694    {
2695        HRESULT hr;
2696        unsigned int index;
2697        GpuProgramParameters::IntConstantIterator intIt = params->getIntConstantIterator();
2698        GpuProgramParameters::RealConstantIterator realIt = params->getRealConstantIterator();
2699
2700        switch(gptype)
2701        {
2702        case GPT_VERTEX_PROGRAM:
2703            mActiveVertexGpuProgramParameters = params;
2704            // Bind floats
2705            if (params->hasRealConstantParams())
2706            {
2707                // Iterate over params and set the relevant ones
2708                index = 0;
2709                while (realIt.hasMoreElements())
2710                {
2711                    const GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
2712                    if (e->isSet)
2713                    {
2714                        if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantF(
2715                            index, e->val, 1)))
2716                        {
2717                            OGRE_EXCEPT(hr, "Unable to upload vertex shader float parameters",
2718                                "D3D9RenderSystem::bindGpuProgramParameters");
2719                        }
2720                    }
2721                    index++;
2722                    realIt.moveNext();
2723                }
2724            }
2725            // Bind ints
2726            if (params->hasIntConstantParams())
2727            {
2728                // Iterate over params and set the relevant ones
2729                index = 0;
2730                while (intIt.hasMoreElements())
2731                {
2732                    const GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
2733                    if (e->isSet)
2734                    {
2735                        if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantI(
2736                            index, e->val, 1)))
2737                        {
2738                            OGRE_EXCEPT(hr, "Unable to upload vertex shader float parameters",
2739                                "D3D9RenderSystem::bindGpuProgramParameters");
2740                        }
2741                    }
2742                    index++;
2743                    intIt.moveNext();
2744                }
2745            }
2746            break;
2747        case GPT_FRAGMENT_PROGRAM:
2748            mActiveFragmentGpuProgramParameters = params;
2749            // Bind floats
2750            if (params->hasRealConstantParams())
2751            {
2752                // Iterate over params and set the relevant ones
2753                index = 0;
2754                while (realIt.hasMoreElements())
2755                {
2756                    const GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
2757                    if (e->isSet)
2758                    {
2759                        /*
2760                        // TEST
2761                        LogManager::getSingleton().logMessage(
2762                            "  Set Constant " + StringConverter::toString(index) + " to float4(" +
2763                            StringConverter::toString(e->val[0]) + ", " +
2764                            StringConverter::toString(e->val[1]) + ", " +
2765                            StringConverter::toString(e->val[2]) + ", " +
2766                            StringConverter::toString(e->val[3]) + ")");
2767                        */
2768
2769                        if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantF(
2770                            index, e->val, 1)))
2771                        {
2772                            OGRE_EXCEPT(hr, "Unable to upload pixel shader float parameters",
2773                                "D3D9RenderSystem::bindGpuProgramParameters");
2774                        }
2775                    }
2776                    index++;
2777                    realIt.moveNext();
2778                }
2779            }
2780            // Bind ints
2781            if (params->hasIntConstantParams())
2782            {
2783                // Iterate over params and set the relevant ones
2784                index = 0;
2785                while (intIt.hasMoreElements())
2786                {
2787                    const GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
2788                    if (e->isSet)
2789                    {
2790                        if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantI(
2791                            index, e->val, 1)))
2792                        {
2793                            OGRE_EXCEPT(hr, "Unable to upload pixel shader float parameters",
2794                                "D3D9RenderSystem::bindGpuProgramParameters");
2795                        }
2796                    }
2797                    index++;
2798                    intIt.moveNext();
2799                }
2800            }
2801            break;
2802        };
2803    }
2804        //---------------------------------------------------------------------
2805    void D3D9RenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype)
2806    {
2807
2808        HRESULT hr;
2809        GpuProgramParameters::RealConstantEntry* realEntry;
2810
2811        switch(gptype)
2812        {
2813        case GPT_VERTEX_PROGRAM:
2814            realEntry = mActiveVertexGpuProgramParameters->getPassIterationEntry();
2815            if (realEntry)
2816            {
2817                if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantF(
2818                        mActiveVertexGpuProgramParameters->getPassIterationEntryIndex(), realEntry->val, 1)))
2819                {
2820                    OGRE_EXCEPT(hr, "Unable to upload vertex shader multi pass parameters",
2821                    "D3D9RenderSystem::bindGpuProgramMultiPassParameters");
2822                }
2823            }
2824            break;
2825
2826        case GPT_FRAGMENT_PROGRAM:
2827            realEntry = mActiveFragmentGpuProgramParameters->getPassIterationEntry();
2828            if (realEntry)
2829            {
2830                if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantF(
2831                        mActiveFragmentGpuProgramParameters->getPassIterationEntryIndex(), realEntry->val, 1)))
2832                {
2833                    OGRE_EXCEPT(hr, "Unable to upload pixel shader multi pass parameters",
2834                    "D3D9RenderSystem::bindGpuProgramMultiPassParameters");
2835                }
2836            }
2837            break;
2838
2839        }
2840    }
2841    //---------------------------------------------------------------------
2842    void D3D9RenderSystem::setClipPlanes(const PlaneList& clipPlanes)
2843    {
2844        size_t i;
2845        size_t numClipPlanes;
2846        float dx9ClipPlane[4];
2847        DWORD mask = 0;
2848        HRESULT hr;
2849
2850        numClipPlanes = clipPlanes.size();
2851        for (i = 0; i < numClipPlanes; ++i)
2852        {
2853            const Plane& plane = clipPlanes[i];
2854
2855            dx9ClipPlane[0] = plane.normal.x;
2856            dx9ClipPlane[1] = plane.normal.y;
2857            dx9ClipPlane[2] = plane.normal.z;
2858            dx9ClipPlane[3] = plane.d;
2859
2860            hr = mpD3DDevice->SetClipPlane(i, dx9ClipPlane);
2861            if (FAILED(hr))
2862            {
2863                OGRE_EXCEPT(hr, "Unable to set clip plane",
2864                    "D3D9RenderSystem::setClipPlanes");
2865            }
2866
2867            mask |= (1 << i);
2868        }
2869
2870        hr = __SetRenderState(D3DRS_CLIPPLANEENABLE, mask);
2871        if (FAILED(hr))
2872        {
2873            OGRE_EXCEPT(hr, "Unable to set render state for clip planes",
2874                "D3D9RenderSystem::setClipPlanes");
2875        }
2876    }
2877        //---------------------------------------------------------------------
2878    void D3D9RenderSystem::setScissorTest(bool enabled, size_t left, size_t top, size_t right,
2879        size_t bottom)
2880    {
2881        HRESULT hr;
2882        if (enabled)
2883        {
2884            if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
2885            {
2886                OGRE_EXCEPT(hr, "Unable to enable scissor rendering state; " + getErrorDescription(hr),
2887                    "D3D9RenderSystem::setScissorTest");
2888            }
2889            RECT rect;
2890            rect.left = left;
2891            rect.top = top;
2892            rect.bottom = bottom;
2893            rect.right = right;
2894            if (FAILED(hr = mpD3DDevice->SetScissorRect(&rect)))
2895            {
2896                OGRE_EXCEPT(hr, "Unable to set scissor rectangle; " + getErrorDescription(hr),
2897                    "D3D9RenderSystem::setScissorTest");
2898            }
2899        }
2900        else
2901        {
2902            if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
2903            {
2904                OGRE_EXCEPT(hr, "Unable to disable scissor rendering state; " + getErrorDescription(hr),
2905                    "D3D9RenderSystem::setScissorTest");
2906            }
2907        }
2908    }
2909    //---------------------------------------------------------------------
2910    void D3D9RenderSystem::clearFrameBuffer(unsigned int buffers,
2911        const ColourValue& colour, Real depth, unsigned short stencil)
2912    {
2913        DWORD flags = 0;
2914        if (buffers & FBT_COLOUR)
2915        {
2916            flags |= D3DCLEAR_TARGET;
2917        }
2918        if (buffers & FBT_DEPTH)
2919        {
2920            flags |= D3DCLEAR_ZBUFFER;
2921        }
2922        // Only try to clear the stencil buffer if supported
2923        if (buffers & FBT_STENCIL && mCapabilities->hasCapability(RSC_HWSTENCIL))
2924        {
2925            flags |= D3DCLEAR_STENCIL;
2926        }
2927        HRESULT hr;
2928        if( FAILED( hr = mpD3DDevice->Clear(
2929            0,
2930            NULL,
2931            flags,
2932            colour.getAsARGB(),
2933            depth,
2934            stencil ) ) )
2935        {
2936            String msg = DXGetErrorDescription9(hr);
2937            OGRE_EXCEPT( hr, "Error clearing frame buffer : "
2938                + msg, "D3D9RenderSystem::clearFrameBuffer" );
2939        }
2940    }
2941    //---------------------------------------------------------------------
2942    void D3D9RenderSystem::_makeProjectionMatrix(Real left, Real right,
2943        Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
2944        bool forGpuProgram)
2945    {
2946        // Correct position for off-axis projection matrix
2947        if (!forGpuProgram)
2948        {
2949            Real offsetX = left + right;
2950            Real offsetY = top + bottom;
2951
2952            left -= offsetX;
2953            right -= offsetX;
2954            top -= offsetY;
2955            bottom -= offsetY;
2956        }
2957
2958        Real width = right - left;
2959        Real height = top - bottom;
2960        Real q, qn;
2961        if (farPlane == 0)
2962        {
2963            q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
2964            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
2965        }
2966        else
2967        {
2968            q = farPlane / ( farPlane - nearPlane );
2969            qn = -q * nearPlane;
2970        }
2971        dest = Matrix4::ZERO;
2972        dest[0][0] = 2 * nearPlane / width;
2973        dest[0][2] = (right+left) / width;
2974        dest[1][1] = 2 * nearPlane / height;
2975        dest[1][2] = (top+bottom) / height;
2976        if (forGpuProgram)
2977        {
2978            dest[2][2] = -q;
2979            dest[3][2] = -1.0f;
2980        }
2981        else
2982        {
2983            dest[2][2] = q;
2984            dest[3][2] = 1.0f;
2985        }
2986        dest[2][3] = qn;
2987    }
2988
2989    // ------------------------------------------------------------------
2990    void D3D9RenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
2991    {
2992        float plane[4] = { A, B, C, D };
2993        mpD3DDevice->SetClipPlane (index, plane);
2994    }
2995
2996    // ------------------------------------------------------------------
2997    void D3D9RenderSystem::enableClipPlane (ushort index, bool enable)
2998    {
2999        DWORD prev;
3000        mpD3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
3001        __SetRenderState(D3DRS_CLIPPLANEENABLE, prev | (1 << index));
3002    }
3003    //---------------------------------------------------------------------
3004    HardwareOcclusionQuery* D3D9RenderSystem::createHardwareOcclusionQuery(void)
3005    {
3006                D3D9HardwareOcclusionQuery* ret = new D3D9HardwareOcclusionQuery (mpD3DDevice);
3007                mHwOcclusionQueries.push_back(ret);
3008                return ret;
3009    }
3010    //---------------------------------------------------------------------
3011    Real D3D9RenderSystem::getHorizontalTexelOffset(void)
3012    {
3013        // D3D considers the origin to be in the center of a pixel
3014        return -0.5f;
3015    }
3016    //---------------------------------------------------------------------
3017    Real D3D9RenderSystem::getVerticalTexelOffset(void)
3018    {
3019        // D3D considers the origin to be in the center of a pixel
3020        return -0.5f;
3021    }
3022    //---------------------------------------------------------------------
3023    void D3D9RenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane,
3024        bool forGpuProgram)
3025    {
3026        // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
3027
3028        // Calculate the clip-space corner point opposite the clipping plane
3029        // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
3030        // transform it into camera space by multiplying it
3031        // by the inverse of the projection matrix
3032
3033        /* generalised version
3034        Vector4 q = matrix.inverse() *
3035            Vector4(Math::Sign(plane.normal.x), Math::Sign(plane.normal.y), 1.0f, 1.0f);
3036        */
3037        Vector4 q;
3038        q.x = Math::Sign(plane.normal.x) / matrix[0][0];
3039        q.y = Math::Sign(plane.normal.y) / matrix[1][1];
3040        q.z = 1.0F;
3041        // flip the next bit from Lengyel since we're right-handed
3042        if (forGpuProgram)
3043        {
3044            q.w = (1.0F - matrix[2][2]) / matrix[2][3];
3045        }
3046        else
3047        {
3048            q.w = (1.0F + matrix[2][2]) / matrix[2][3];
3049        }
3050
3051        // Calculate the scaled plane vector
3052        Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
3053        Vector4 c = clipPlane4d * (1.0F / (clipPlane4d.dotProduct(q)));
3054
3055        // Replace the third row of the projection matrix
3056        matrix[2][0] = c.x;
3057        matrix[2][1] = c.y;
3058        // flip the next bit from Lengyel since we're right-handed
3059        if (forGpuProgram)
3060        {
3061            matrix[2][2] = c.z;
3062        }
3063        else
3064        {
3065            matrix[2][2] = -c.z;
3066        }
3067        matrix[2][3] = c.w;       
3068    }
3069    //---------------------------------------------------------------------
3070    Real D3D9RenderSystem::getMinimumDepthInputValue(void)
3071    {
3072        // Range [0.0f, 1.0f]
3073        return 0.0f;
3074    }
3075    //---------------------------------------------------------------------
3076    Real D3D9RenderSystem::getMaximumDepthInputValue(void)
3077    {
3078        // Range [0.0f, 1.0f]
3079        // D3D inverts even identity view matrices, so maximum INPUT is -1.0
3080        return -1.0f;
3081    }
3082        //---------------------------------------------------------------------
3083        void D3D9RenderSystem::restoreLostDevice(void)
3084        {
3085                // Release all non-managed resources
3086
3087                // Cleanup depth stencils
3088                _cleanupDepthStencils();
3089
3090                // Set all texture units to nothing
3091                _disableTextureUnitsFrom(0);
3092
3093                // Unbind any vertex streams
3094                for (size_t i = 0; i < mLastVertexSourceCount; ++i)
3095                {
3096                        mpD3DDevice->SetStreamSource(i, NULL, 0, 0);
3097                }
3098        mLastVertexSourceCount = 0;
3099
3100        // Release all automatic temporary buffers and free unused
3101        // temporary buffers, so we doesn't need to recreate them,
3102        // and they will reallocate on demand. This save a lot of
3103        // release/recreate of non-managed vertex buffers which
3104        // wasn't need at all.
3105        mHardwareBufferManager->_releaseBufferCopies(true);
3106
3107                // We have to deal with non-managed textures and vertex buffers
3108                // GPU programs don't have to be restored
3109                static_cast<D3D9TextureManager*>(mTextureManager)->releaseDefaultPoolResources();
3110                static_cast<D3D9HardwareBufferManager*>(mHardwareBufferManager)
3111                        ->releaseDefaultPoolResources();
3112
3113                // release additional swap chains (secondary windows)
3114                SecondaryWindowList::iterator sw;
3115                for (sw = mSecondaryWindows.begin(); sw != mSecondaryWindows.end(); ++sw)
3116                {
3117                        (*sw)->destroyD3DResources();
3118                }
3119
3120                // Reset the device, using the primary window presentation params
3121                HRESULT hr = mpD3DDevice->Reset(
3122                        mPrimaryWindow->getPresentationParameters());
3123
3124                if (hr == D3DERR_DEVICELOST)
3125                {
3126                        // Don't continue
3127                        return;
3128                }
3129                else if (FAILED(hr))
3130                {
3131                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
3132                                "Cannot reset device! " + getErrorDescription(hr),
3133                                "D3D9RenderWindow::restoreLostDevice" );
3134                }
3135
3136                // will have lost basic states
3137                mBasicStatesInitialised = false;
3138        mVertexProgramBound = false;
3139        mFragmentProgramBound = false;
3140
3141
3142                // recreate additional swap chains
3143                for (sw = mSecondaryWindows.begin(); sw != mSecondaryWindows.end(); ++sw)
3144                {
3145                        (*sw)->createD3DResources();
3146                }
3147
3148                // Recreate all non-managed resources
3149                static_cast<D3D9TextureManager*>(mTextureManager)
3150                        ->recreateDefaultPoolResources();
3151                static_cast<D3D9HardwareBufferManager*>(mHardwareBufferManager)
3152                        ->recreateDefaultPoolResources();
3153                       
3154                LogManager::getSingleton().logMessage("!!! Direct3D Device successfully restored.");
3155
3156                mDeviceLost = false;
3157
3158                fireEvent("DeviceRestored");
3159
3160        }
3161        //---------------------------------------------------------------------
3162        bool D3D9RenderSystem::isDeviceLost(void)
3163        {
3164                return mDeviceLost;
3165        }
3166        //---------------------------------------------------------------------
3167        void D3D9RenderSystem::_notifyDeviceLost(void)
3168        {
3169                LogManager::getSingleton().logMessage("!!! Direct3D Device Lost!");
3170                mDeviceLost = true;
3171                // will have lost basic states
3172                mBasicStatesInitialised = false;
3173
3174                fireEvent("DeviceLost");
3175        }
3176
3177        //---------------------------------------------------------------------
3178        // Formats to try, in decreasing order of preference
3179        D3DFORMAT ddDepthStencilFormats[]={
3180                D3DFMT_D24FS8,
3181                D3DFMT_D24S8,
3182                D3DFMT_D24X4S4,
3183                D3DFMT_D24X8,
3184                D3DFMT_D15S1,
3185                D3DFMT_D16,
3186                D3DFMT_D32
3187        };
3188#define NDSFORMATS (sizeof(ddDepthStencilFormats)/sizeof(D3DFORMAT))
3189       
3190        D3DFORMAT D3D9RenderSystem::_getDepthStencilFormatFor(D3DFORMAT fmt)
3191        {
3192                /// Check if result is cached
3193                DepthStencilHash::iterator i = mDepthStencilHash.find((unsigned int)fmt);
3194                if(i != mDepthStencilHash.end())
3195                        return i->second;
3196                /// If not, probe with CheckDepthStencilMatch
3197                D3DFORMAT dsfmt = D3DFMT_UNKNOWN;
3198
3199                /// Get description of primary render target
3200                LPDIRECT3DSURFACE9 mSurface = mPrimaryWindow->getRenderSurface();
3201                D3DSURFACE_DESC srfDesc;
3202
3203                if(!FAILED(mSurface->GetDesc(&srfDesc)))
3204                {
3205                        /// Probe all depth stencil formats
3206                        /// Break on first one that matches
3207                        for(size_t x=0; x<NDSFORMATS; ++x)
3208                        {
3209                // Verify that the depth format exists
3210                if (mpD3D->CheckDeviceFormat(
3211                    mActiveD3DDriver->getAdapterNumber(),
3212                    D3DDEVTYPE_HAL,
3213                    srfDesc.Format,
3214                    D3DUSAGE_DEPTHSTENCIL,
3215                    D3DRTYPE_SURFACE,
3216                    ddDepthStencilFormats[x]) != D3D_OK)
3217                {
3218                    continue;
3219                }
3220                // Verify that the depth format is compatible
3221                                if(mpD3D->CheckDepthStencilMatch(
3222                                        mActiveD3DDriver->getAdapterNumber(),
3223                                        D3DDEVTYPE_HAL, srfDesc.Format,
3224                                        fmt, ddDepthStencilFormats[x]) == D3D_OK)
3225                                {
3226                                        dsfmt = ddDepthStencilFormats[x];
3227                                        break;
3228                                }
3229                        }
3230                }
3231                /// Cache result
3232                mDepthStencilHash[(unsigned int)fmt] = dsfmt;
3233                return dsfmt;
3234        }
3235        IDirect3DSurface9* D3D9RenderSystem::_getDepthStencilFor(D3DFORMAT fmt, D3DMULTISAMPLE_TYPE multisample, size_t width, size_t height)
3236        {
3237                D3DFORMAT dsfmt = _getDepthStencilFormatFor(fmt);
3238                if(dsfmt == D3DFMT_UNKNOWN)
3239                        return 0;
3240                IDirect3DSurface9 *surface = 0;
3241
3242                /// Check if result is cached
3243                ZBufferFormat zbfmt(dsfmt, multisample);
3244                ZBufferHash::iterator i = mZBufferHash.find(zbfmt);
3245                if(i != mZBufferHash.end())
3246                {
3247                        /// Check if size is larger or equal
3248                        if(i->second.width >= width && i->second.height >= height)
3249                        {
3250                                surface = i->second.surface;
3251                        }
3252                        else
3253                        {
3254                                /// If not, destroy current buffer
3255                                i->second.surface->Release();
3256                                mZBufferHash.erase(i);
3257                        }
3258                }
3259                if(!surface)
3260                {
3261                        /// If not, create the depthstencil surface
3262                        HRESULT hr = mpD3DDevice->CreateDepthStencilSurface(
3263                                width,
3264                                height,
3265                                dsfmt,
3266                                multisample,
3267                                NULL,
3268                                TRUE,  // discard true or false?
3269                                &surface,
3270                                NULL);
3271                        if(FAILED(hr))
3272                        {
3273                                String msg = DXGetErrorDescription9(hr);
3274                                OGRE_EXCEPT( hr, "Error CreateDepthStencilSurface : " + msg, "D3D9RenderSystem::_getDepthStencilFor" );
3275                        }
3276                        /// And cache it
3277                        ZBufferRef zb;
3278                        zb.surface = surface;
3279                        zb.width = width;
3280                        zb.height = height;
3281                        mZBufferHash[zbfmt] = zb;
3282                }
3283                return surface;
3284        }
3285        void D3D9RenderSystem::_cleanupDepthStencils()
3286        {
3287                for(ZBufferHash::iterator i = mZBufferHash.begin(); i != mZBufferHash.end(); ++i)
3288                {
3289                        /// Release buffer
3290                        i->second.surface->Release();
3291                }
3292                mZBufferHash.clear();
3293        }
3294
3295       
3296        #ifdef GAMETOOLS_ILLUMINATION_MODULE
3297                void D3D9RenderSystem::_setTextureUnitSettings(size_t texUnit, TextureUnitState& tl)
3298                {
3299                        int newUnit = texUnit;
3300                        if(tl.isVertexTexture())
3301                                newUnit = OGRE_MAX_TEXTURE_LAYERS + texUnit;
3302
3303                        RenderSystem::_setTextureUnitSettings(newUnit, tl);
3304                }
3305        #endif
3306}
Note: See TracBrowser for help on using the repository browser.