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

Revision 1354, 114.3 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                        blendOp == SBOP_ADD && blendOpAlpha == SBOP_ADD)
1929                {
1930                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
1931                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1932                }
1933                else
1934                {
1935                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
1936                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1937                                       
1938                        if(separateAlpha)
1939                        {
1940                                if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE)))
1941                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1942                               
1943                                if (FAILED(hr = __SetRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(blendOpAlpha))))
1944                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1945
1946                                if( FAILED( hr = __SetRenderState( D3DRS_SRCBLENDALPHA, D3D9Mappings::get(sourceFactorAlpha) ) ) )
1947                                        OGRE_EXCEPT( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
1948                                if( FAILED( hr = __SetRenderState( D3DRS_DESTBLENDALPHA, D3D9Mappings::get(destFactorAlpha) ) ) )
1949                                        OGRE_EXCEPT( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
1950               
1951                        }
1952                        else
1953                        {
1954                                if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE)))
1955                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1956                        }
1957                       
1958                        if (FAILED(hr = __SetRenderState(D3DRS_BLENDOP, D3D9Mappings::get(blendOp))))
1959                                        OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1960                        if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
1961                                OGRE_EXCEPT( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
1962                        if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
1963                                OGRE_EXCEPT( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );                   
1964                }
1965        }
1966#else
1967        //---------------------------------------------------------------------
1968        void D3D9RenderSystem::_setSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor )
1969        {
1970                HRESULT hr;
1971                if( sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
1972                {
1973                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
1974                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1975                }
1976                else
1977                {
1978                        if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
1979                                OGRE_EXCEPT( hr, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
1980                        if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
1981                                OGRE_EXCEPT( hr, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
1982                        if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
1983                                OGRE_EXCEPT( hr, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
1984                }
1985        }
1986#endif
1987        //---------------------------------------------------------------------
1988        void D3D9RenderSystem::_setAlphaRejectSettings( CompareFunction func, unsigned char value )
1989        {
1990                HRESULT hr;
1991        if (func != CMPF_ALWAYS_PASS)
1992        {
1993            if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE ) ) )
1994                        OGRE_EXCEPT( hr, "Failed to enable alpha testing",
1995                "D3D9RenderSystem::_setAlphaRejectSettings" );
1996        }
1997        else
1998        {
1999            if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE,  FALSE ) ) )
2000                        OGRE_EXCEPT( hr, "Failed to disable alpha testing",
2001                "D3D9RenderSystem::_setAlphaRejectSettings" );
2002        }
2003        // Set always just be sure
2004                if( FAILED( hr = __SetRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
2005                        OGRE_EXCEPT( hr, "Failed to set alpha reject function", "D3D9RenderSystem::_setAlphaRejectSettings" );
2006                if( FAILED( hr = __SetRenderState( D3DRS_ALPHAREF, value ) ) )
2007                        OGRE_EXCEPT( hr, "Failed to set render state D3DRS_ALPHAREF", "D3D9RenderSystem::_setAlphaRejectSettings" );
2008        }
2009        //---------------------------------------------------------------------
2010        void D3D9RenderSystem::_setCullingMode( CullingMode mode )
2011        {
2012                HRESULT hr;
2013        bool flip = ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
2014                (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding));
2015
2016                if( FAILED (hr = __SetRenderState(D3DRS_CULLMODE,
2017            D3D9Mappings::get(mode, flip))) )
2018                        OGRE_EXCEPT( hr, "Failed to set culling mode", "D3D9RenderSystem::_setCullingMode" );
2019        }
2020        //---------------------------------------------------------------------
2021        void D3D9RenderSystem::_setDepthBufferParams( bool depthTest, bool depthWrite, CompareFunction depthFunction )
2022        {
2023                _setDepthBufferCheckEnabled( depthTest );
2024                _setDepthBufferWriteEnabled( depthWrite );
2025                _setDepthBufferFunction( depthFunction );
2026        }
2027        //---------------------------------------------------------------------
2028        void D3D9RenderSystem::_setDepthBufferCheckEnabled( bool enabled )
2029        {
2030                HRESULT hr;
2031
2032                if( enabled )
2033                {
2034                        // Use w-buffer if available and enabled
2035                        if( mWBuffer && mCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
2036                                hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
2037                        else
2038                                hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
2039                }
2040                else
2041                        hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
2042
2043                if( FAILED( hr ) )
2044                        OGRE_EXCEPT( hr, "Error setting depth buffer test state", "D3D9RenderSystem::_setDepthBufferCheckEnabled" );
2045        }
2046        //---------------------------------------------------------------------
2047        void D3D9RenderSystem::_setDepthBufferWriteEnabled( bool enabled )
2048        {
2049                HRESULT hr;
2050
2051                if( FAILED( hr = __SetRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
2052                        OGRE_EXCEPT( hr, "Error setting depth buffer write state", "D3D9RenderSystem::_setDepthBufferWriteEnabled" );
2053        }
2054        //---------------------------------------------------------------------
2055        void D3D9RenderSystem::_setDepthBufferFunction( CompareFunction func )
2056        {
2057                HRESULT hr;
2058                if( FAILED( hr = __SetRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
2059                        OGRE_EXCEPT( hr, "Error setting depth buffer test function", "D3D9RenderSystem::_setDepthBufferFunction" );
2060        }
2061        //---------------------------------------------------------------------
2062        void D3D9RenderSystem::_setDepthBias(ushort bias)
2063        {
2064                float bias_float = static_cast<float>(-bias);
2065                // scale down - certainly needed for nVidia
2066                bias_float /= 250000.0f;
2067                HRESULT hr = __SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&bias_float);
2068                if (FAILED(hr))
2069                        OGRE_EXCEPT(hr, "Error setting depth bias", "D3D9RenderSystem::_setDepthBias");
2070        }
2071        //---------------------------------------------------------------------
2072        void D3D9RenderSystem::_setColourBufferWriteEnabled(bool red, bool green,
2073                bool blue, bool alpha)
2074        {
2075                DWORD val = 0;
2076                if (red)
2077                        val |= D3DCOLORWRITEENABLE_RED;
2078                if (green)
2079                        val |= D3DCOLORWRITEENABLE_GREEN;
2080                if (blue)
2081                        val |= D3DCOLORWRITEENABLE_BLUE;
2082                if (alpha)
2083                        val |= D3DCOLORWRITEENABLE_ALPHA;
2084                HRESULT hr = __SetRenderState(D3DRS_COLORWRITEENABLE, val);
2085                if (FAILED(hr))
2086                        OGRE_EXCEPT(hr, "Error setting colour write enable flags",
2087                        "D3D9RenderSystem::_setColourBufferWriteEnabled");
2088        }
2089        //---------------------------------------------------------------------
2090        void D3D9RenderSystem::_setFog( FogMode mode, const ColourValue& colour, Real densitiy, Real start, Real end )
2091        {
2092                HRESULT hr;
2093
2094                D3DRENDERSTATETYPE fogType, fogTypeNot;
2095
2096                if (mCaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
2097                {
2098                        fogType = D3DRS_FOGTABLEMODE;
2099                        fogTypeNot = D3DRS_FOGVERTEXMODE;
2100                }
2101                else
2102                {
2103                        fogType = D3DRS_FOGVERTEXMODE;
2104                        fogTypeNot = D3DRS_FOGTABLEMODE;
2105                }
2106
2107                if( mode == FOG_NONE)
2108                {
2109                        // just disable
2110                        hr = __SetRenderState(fogType, D3DFOG_NONE );
2111                        hr = __SetRenderState(D3DRS_FOGENABLE, FALSE);
2112                }
2113                else
2114                {
2115                        // Allow fog
2116                        hr = __SetRenderState( D3DRS_FOGENABLE, TRUE );
2117                        hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
2118                        hr = __SetRenderState( fogType, D3D9Mappings::get(mode) );
2119
2120                        hr = __SetRenderState( D3DRS_FOGCOLOR, colour.getAsARGB() );
2121                        hr = __SetFloatRenderState( D3DRS_FOGSTART, start );
2122                        hr = __SetFloatRenderState( D3DRS_FOGEND, end );
2123                        hr = __SetFloatRenderState( D3DRS_FOGDENSITY, densitiy );
2124                }
2125
2126                if( FAILED( hr ) )
2127                        OGRE_EXCEPT( hr, "Error setting render state", "D3D9RenderSystem::_setFog" );
2128        }
2129        //---------------------------------------------------------------------
2130        void D3D9RenderSystem::_setPolygonMode(PolygonMode level)
2131        {
2132                HRESULT hr = __SetRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
2133                if (FAILED(hr))
2134                        OGRE_EXCEPT(hr, "Error setting polygon mode.", "D3D9RenderSystem::setPolygonMode");
2135        }
2136        //---------------------------------------------------------------------
2137        void D3D9RenderSystem::setStencilCheckEnabled(bool enabled)
2138        {
2139                // Allow stencilling
2140                HRESULT hr = __SetRenderState(D3DRS_STENCILENABLE, enabled);
2141                if (FAILED(hr))
2142                        OGRE_EXCEPT(hr, "Error enabling / disabling stencilling.",
2143                        "D3D9RenderSystem::setStencilCheckEnabled");
2144        }
2145    //---------------------------------------------------------------------
2146    void D3D9RenderSystem::setStencilBufferParams(CompareFunction func,
2147        uint32 refValue, uint32 mask, StencilOperation stencilFailOp,
2148        StencilOperation depthFailOp, StencilOperation passOp,
2149        bool twoSidedOperation)
2150    {
2151        HRESULT hr;
2152        bool flip;
2153
2154        // 2-sided operation
2155        if (twoSidedOperation)
2156        {
2157            if (!mCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
2158                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
2159                    "D3D9RenderSystem::setStencilBufferParams");
2160            hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
2161                    if (FAILED(hr))
2162                            OGRE_EXCEPT(hr, "Error setting 2-sided stencil mode.",
2163                            "D3D9RenderSystem::setStencilBufferParams");
2164            // NB: We should always treat CCW as front face for consistent with default
2165            // culling mode. Therefore, we must take care with two-sided stencil settings.
2166            flip = (mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping()) ||
2167                   (!mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping());
2168
2169            // Set alternative versions of ops
2170            // fail op
2171            hr = __SetRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp, !flip));
2172            if (FAILED(hr))
2173                OGRE_EXCEPT(hr, "Error setting stencil fail operation (2-sided).",
2174                "D3D9RenderSystem::setStencilBufferParams");
2175
2176            // depth fail op
2177            hr = __SetRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp, !flip));
2178            if (FAILED(hr))
2179                OGRE_EXCEPT(hr, "Error setting stencil depth fail operation (2-sided).",
2180                "D3D9RenderSystem::setStencilBufferParams");
2181
2182            // pass op
2183            hr = __SetRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp, !flip));
2184            if (FAILED(hr))
2185                OGRE_EXCEPT(hr, "Error setting stencil pass operation (2-sided).",
2186                "D3D9RenderSystem::setStencilBufferParams");
2187        }
2188        else
2189        {
2190            hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2191                    if (FAILED(hr))
2192                            OGRE_EXCEPT(hr, "Error setting 1-sided stencil mode.",
2193                            "D3D9RenderSystem::setStencilBufferParams");
2194            flip = false;
2195        }
2196
2197        // func
2198        hr = __SetRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
2199                if (FAILED(hr))
2200                        OGRE_EXCEPT(hr, "Error setting stencil buffer test function.",
2201                        "D3D9RenderSystem::setStencilBufferParams");
2202
2203        // reference value
2204        hr = __SetRenderState(D3DRS_STENCILREF, refValue);
2205                if (FAILED(hr))
2206                        OGRE_EXCEPT(hr, "Error setting stencil buffer reference value.",
2207                        "D3D9RenderSystem::setStencilBufferParams");
2208
2209        // mask
2210        hr = __SetRenderState(D3DRS_STENCILMASK, mask);
2211                if (FAILED(hr))
2212                        OGRE_EXCEPT(hr, "Error setting stencil buffer mask.",
2213                        "D3D9RenderSystem::setStencilBufferParams");
2214
2215                // fail op
2216        hr = __SetRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp, flip));
2217                if (FAILED(hr))
2218                        OGRE_EXCEPT(hr, "Error setting stencil fail operation.",
2219                        "D3D9RenderSystem::setStencilBufferParams");
2220
2221        // depth fail op
2222        hr = __SetRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp, flip));
2223                if (FAILED(hr))
2224                        OGRE_EXCEPT(hr, "Error setting stencil depth fail operation.",
2225                        "D3D9RenderSystem::setStencilBufferParams");
2226
2227        // pass op
2228        hr = __SetRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp, flip));
2229                if (FAILED(hr))
2230                        OGRE_EXCEPT(hr, "Error setting stencil pass operation.",
2231                        "D3D9RenderSystem::setStencilBufferParams");
2232        }
2233        //---------------------------------------------------------------------
2234    void D3D9RenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype,
2235        FilterOptions filter)
2236        {               
2237                #ifdef GAMETOOLS_ILLUMINATION_MODULE
2238                if(unit >= OGRE_MAX_TEXTURE_LAYERS)
2239                        unit -= OGRE_MAX_TEXTURE_LAYERS;
2240                #endif
2241
2242                HRESULT hr;
2243                D3D9Mappings::eD3DTexType texType = mTexStageDesc[unit].texType;
2244        hr = __SetSamplerState( unit, D3D9Mappings::get(ftype),
2245            D3D9Mappings::get(ftype, filter, mCaps, texType));
2246                if (FAILED(hr))
2247                        OGRE_EXCEPT(hr, "Failed to set texture filter ", "D3D9RenderSystem::_setTextureUnitFiltering");
2248        }
2249    //---------------------------------------------------------------------
2250        DWORD D3D9RenderSystem::_getCurrentAnisotropy(size_t unit)
2251        {
2252                DWORD oldVal;
2253                mpD3DDevice->GetSamplerState(unit, D3DSAMP_MAXANISOTROPY, &oldVal);
2254                        return oldVal;
2255        }
2256        //---------------------------------------------------------------------
2257        void D3D9RenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
2258        {
2259                #ifdef GAMETOOLS_ILLUMINATION_MODULE
2260                if(unit >= OGRE_MAX_TEXTURE_LAYERS)
2261                        unit -= OGRE_MAX_TEXTURE_LAYERS;
2262                #endif
2263
2264                if ((DWORD)maxAnisotropy > mCaps.MaxAnisotropy)
2265                        maxAnisotropy = mCaps.MaxAnisotropy;
2266
2267                if (_getCurrentAnisotropy(unit) != maxAnisotropy)
2268                        __SetSamplerState( unit, D3DSAMP_MAXANISOTROPY, maxAnisotropy );
2269        }
2270        //---------------------------------------------------------------------
2271        HRESULT D3D9RenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
2272        {
2273                HRESULT hr;
2274                DWORD oldVal;
2275
2276                if ( FAILED( hr = mpD3DDevice->GetRenderState(state, &oldVal) ) )
2277                        return hr;
2278                if ( oldVal == value )
2279                        return D3D_OK;
2280                else
2281                        return mpD3DDevice->SetRenderState(state, value);
2282        }
2283        //---------------------------------------------------------------------
2284        HRESULT D3D9RenderSystem::__SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
2285        {
2286                HRESULT hr;
2287                DWORD oldVal;
2288
2289                if ( FAILED( hr = mpD3DDevice->GetSamplerState(sampler, type, &oldVal) ) )
2290                        return hr;
2291                if ( oldVal == value )
2292                        return D3D_OK;
2293                else
2294                        return mpD3DDevice->SetSamplerState(sampler, type, value);
2295        }
2296        //---------------------------------------------------------------------
2297        HRESULT D3D9RenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
2298        {
2299                HRESULT hr;
2300                DWORD oldVal;
2301               
2302                if ( FAILED( hr = mpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) )
2303                        return hr;
2304                if ( oldVal == value )
2305                        return D3D_OK;
2306                else
2307                        return mpD3DDevice->SetTextureStageState(stage, type, value);
2308        }
2309        //---------------------------------------------------------------------
2310        void D3D9RenderSystem::_setViewport( Viewport *vp )
2311        {
2312                if( vp != mActiveViewport || vp->_isUpdated() )
2313                {
2314                        mActiveViewport = vp;
2315                        mActiveRenderTarget = vp->getTarget();
2316
2317                        // ok, it's different, time to set render target and viewport params
2318                        D3DVIEWPORT9 d3dvp;
2319                        HRESULT hr;
2320
2321                        // Set render target
2322                        RenderTarget* target;
2323                        target = vp->getTarget();
2324
2325                        // Retrieve render surfaces (up to OGRE_MAX_MULTIPLE_RENDER_TARGETS)
2326                        LPDIRECT3DSURFACE9 pBack[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
2327                        memset(pBack, 0, sizeof(pBack));
2328                        target->getCustomAttribute( "DDBACKBUFFER", &pBack );
2329                        if (!pBack[0])
2330                                return;
2331
2332                        LPDIRECT3DSURFACE9 pDepth = NULL;
2333                        target->getCustomAttribute( "D3DZBUFFER", &pDepth );
2334                        if (!pDepth)
2335                        {
2336                                /// No depth buffer provided, use our own
2337                                /// Request a depth stencil that is compatible with the format, multisample type and
2338                                /// dimensions of the render target.
2339                                D3DSURFACE_DESC srfDesc;
2340                                if(FAILED(pBack[0]->GetDesc(&srfDesc)))
2341                                        return; // ?
2342                                pDepth = _getDepthStencilFor(srfDesc.Format, srfDesc.MultiSampleType, srfDesc.Width, srfDesc.Height);
2343                        }
2344                        // Bind render targets
2345                        uint count = mCapabilities->numMultiRenderTargets();
2346                        for(uint x=0; x<count; ++x)
2347                        {
2348                                hr = mpD3DDevice->SetRenderTarget(x, pBack[x]);
2349                                if (FAILED(hr))
2350                                {
2351                                        String msg = DXGetErrorDescription9(hr);
2352                                        OGRE_EXCEPT( hr, "Failed to setRenderTarget : " + msg, "D3D9RenderSystem::_setViewport" );
2353                                }
2354                        }
2355                        hr = mpD3DDevice->SetDepthStencilSurface(pDepth);
2356                        if (FAILED(hr))
2357                        {
2358                                String msg = DXGetErrorDescription9(hr);
2359                                OGRE_EXCEPT( hr, "Failed to setDepthStencil : " + msg, "D3D9RenderSystem::_setViewport" );
2360                        }
2361
2362                        _setCullingMode( mCullingMode );
2363
2364                        // set viewport dimensions
2365                        d3dvp.X = vp->getActualLeft();
2366                        d3dvp.Y = vp->getActualTop();
2367                        d3dvp.Width = vp->getActualWidth();
2368                        d3dvp.Height = vp->getActualHeight();
2369            if (target->requiresTextureFlipping())
2370            {
2371                // Convert "top-left" to "bottom-left"
2372                d3dvp.Y = target->getHeight() - d3dvp.Height - d3dvp.Y;
2373            }
2374
2375                        // Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
2376                        d3dvp.MinZ = 0.0f;
2377                        d3dvp.MaxZ = 1.0f;
2378
2379                        if( FAILED( hr = mpD3DDevice->SetViewport( &d3dvp ) ) )
2380                                OGRE_EXCEPT( hr, "Failed to set viewport.", "D3D9RenderSystem::_setViewport" );
2381
2382                        vp->_clearUpdatedFlag();
2383                }
2384        }
2385        //---------------------------------------------------------------------
2386        void D3D9RenderSystem::_beginFrame()
2387        {
2388                OgreGuard( "D3D9RenderSystem::_beginFrame" );
2389
2390                HRESULT hr;
2391
2392                if( !mActiveViewport )
2393                        OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Cannot begin frame - no viewport selected.", "D3D9RenderSystem::_beginFrame" );
2394
2395                // Clear the viewport if required
2396                if( mActiveViewport->getClearEveryFrame() )
2397                {
2398            clearFrameBuffer(mActiveViewport->getClearBuffers(),
2399                mActiveViewport->getBackgroundColour());
2400                }
2401
2402                if( FAILED( hr = mpD3DDevice->BeginScene() ) )
2403                {
2404                        String msg = DXGetErrorDescription9(hr);
2405                        OGRE_EXCEPT( hr, "Error beginning frame :" + msg, "D3D9RenderSystem::_beginFrame" );
2406                }
2407
2408                if(!mBasicStatesInitialised)
2409                {
2410                        // First-time
2411                        // setup some defaults
2412                        // Allow specular
2413                        hr = __SetRenderState(D3DRS_SPECULARENABLE, TRUE);
2414                        if (FAILED(hr))
2415                        {
2416                                String msg = DXGetErrorDescription9(hr);
2417                                OGRE_EXCEPT(hr, "Error enabling alpha blending option : " + msg, "D3D9RenderSystem::_beginFrame");
2418                        }
2419                        mBasicStatesInitialised = true;
2420                }
2421
2422                OgreUnguard();
2423        }
2424        //---------------------------------------------------------------------
2425        void D3D9RenderSystem::_endFrame()
2426        {
2427                OgreGuard( "D3D9RenderSystem::_endFrame" );
2428
2429                HRESULT hr;
2430                if( FAILED( hr = mpD3DDevice->EndScene() ) )
2431                        OGRE_EXCEPT( hr, "Error ending frame", "D3D9RenderSystem::_endFrame" );
2432
2433                OgreUnguard();
2434        }
2435        //---------------------------------------------------------------------
2436        inline bool D3D9RenderSystem::compareDecls( D3DVERTEXELEMENT9* pDecl1, D3DVERTEXELEMENT9* pDecl2, size_t size )
2437        {
2438                for( size_t i=0; i < size; i++ )
2439                {
2440                        if( pDecl1[i].Method != pDecl2[i].Method ||
2441                                pDecl1[i].Offset != pDecl2[i].Offset ||
2442                                pDecl1[i].Stream != pDecl2[i].Stream ||
2443                                pDecl1[i].Type != pDecl2[i].Type ||
2444                                pDecl1[i].Usage != pDecl2[i].Usage ||
2445                                pDecl1[i].UsageIndex != pDecl2[i].UsageIndex)
2446                        {
2447                                return false;
2448                        }
2449                }
2450
2451                return true;
2452        }
2453    //---------------------------------------------------------------------
2454        void D3D9RenderSystem::setVertexDeclaration(VertexDeclaration* decl)
2455        {
2456                // Guard
2457                OgreGuard ("D3D9RenderSystem::setVertexDeclaration");
2458        HRESULT hr;
2459
2460        D3D9VertexDeclaration* d3ddecl =
2461            static_cast<D3D9VertexDeclaration*>(decl);
2462
2463        if (FAILED(hr = mpD3DDevice->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
2464        {
2465            OGRE_EXCEPT(hr, "Unable to set D3D9 vertex declaration",
2466                "D3D9RenderSystem::setVertexDeclaration");
2467        }
2468
2469        // UnGuard
2470                OgreUnguard();
2471        }
2472    //---------------------------------------------------------------------
2473        void D3D9RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
2474        {
2475                // Guard
2476                OgreGuard ("D3D9RenderSystem::setVertexBufferBinding");
2477
2478        HRESULT hr;
2479
2480        // TODO: attempt to detect duplicates
2481        const VertexBufferBinding::VertexBufferBindingMap& binds = binding->getBindings();
2482        VertexBufferBinding::VertexBufferBindingMap::const_iterator i, iend;
2483        iend = binds.end();
2484        for (i = binds.begin(); i != iend; ++i)
2485        {
2486            const D3D9HardwareVertexBuffer* d3d9buf =
2487                static_cast<const D3D9HardwareVertexBuffer*>(i->second.get());
2488            hr = mpD3DDevice->SetStreamSource(
2489                static_cast<UINT>(i->first),
2490                d3d9buf->getD3D9VertexBuffer(),
2491                0, // no stream offset, this is handled in _render instead
2492                static_cast<UINT>(d3d9buf->getVertexSize()) // stride
2493                );
2494            if (FAILED(hr))
2495            {
2496                OGRE_EXCEPT(hr, "Unable to set D3D9 stream source for buffer binding",
2497                    "D3D9RenderSystem::setVertexBufferBinding");
2498            }
2499
2500
2501        }
2502
2503                // Unbind any unused sources
2504                for (size_t unused = binds.size(); unused < mLastVertexSourceCount; ++unused)
2505                {
2506                       
2507            hr = mpD3DDevice->SetStreamSource(static_cast<UINT>(unused), NULL, 0, 0);
2508            if (FAILED(hr))
2509            {
2510                OGRE_EXCEPT(hr, "Unable to reset unused D3D9 stream source",
2511                    "D3D9RenderSystem::setVertexBufferBinding");
2512            }
2513                       
2514                }
2515                mLastVertexSourceCount = binds.size();
2516               
2517
2518               
2519        // UnGuard
2520                OgreUnguard();
2521        }
2522    //---------------------------------------------------------------------
2523    void D3D9RenderSystem::_render(const RenderOperation& op)
2524        {
2525                // Guard
2526                OgreGuard ("D3D9RenderSystem::_render");
2527
2528        // Exit immediately if there is nothing to render
2529        // This caused a problem on FireGL 8800
2530        if (op.vertexData->vertexCount == 0)
2531            return;
2532
2533        // Call super class
2534                RenderSystem::_render(op);
2535
2536        // To think about: possibly remove setVertexDeclaration and
2537        // setVertexBufferBinding from RenderSystem since the sequence is
2538        // a bit too D3D9-specific?
2539                setVertexDeclaration(op.vertexData->vertexDeclaration);
2540        setVertexBufferBinding(op.vertexData->vertexBufferBinding);
2541
2542                // Determine rendering operation
2543                D3DPRIMITIVETYPE primType = D3DPT_TRIANGLELIST;
2544                DWORD primCount = 0;
2545        switch( op.operationType )
2546                {
2547        case RenderOperation::OT_POINT_LIST:
2548                        primType = D3DPT_POINTLIST;
2549                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
2550                        break;
2551
2552                case RenderOperation::OT_LINE_LIST:
2553                        primType = D3DPT_LINELIST;
2554                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
2555                        break;
2556
2557                case RenderOperation::OT_LINE_STRIP:
2558                        primType = D3DPT_LINESTRIP;
2559                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
2560                        break;
2561
2562                case RenderOperation::OT_TRIANGLE_LIST:
2563                        primType = D3DPT_TRIANGLELIST;
2564                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
2565                        break;
2566
2567                case RenderOperation::OT_TRIANGLE_STRIP:
2568                        primType = D3DPT_TRIANGLESTRIP;
2569                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
2570                        break;
2571
2572                case RenderOperation::OT_TRIANGLE_FAN:
2573                        primType = D3DPT_TRIANGLEFAN;
2574                        primCount = (DWORD)(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
2575                        break;
2576                }
2577
2578        if (!primCount)
2579                        return;
2580
2581                // Issue the op
2582        HRESULT hr;
2583                if( op.useIndexes )
2584                {
2585            D3D9HardwareIndexBuffer* d3dIdxBuf =
2586                static_cast<D3D9HardwareIndexBuffer*>(op.indexData->indexBuffer.get());
2587                        hr = mpD3DDevice->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
2588                        if (FAILED(hr))
2589            {
2590                                OGRE_EXCEPT( hr, "Failed to set index buffer", "D3D9RenderSystem::_render" );
2591            }
2592
2593            do
2594            {
2595                // do indexed draw operation
2596                            hr = mpD3DDevice->DrawIndexedPrimitive(
2597                    primType,
2598                    static_cast<INT>(op.vertexData->vertexStart),
2599                    0, // Min vertex index - assume we can go right down to 0
2600                    static_cast<UINT>(op.vertexData->vertexCount),
2601                    static_cast<UINT>(op.indexData->indexStart),
2602                    static_cast<UINT>(primCount)
2603                    );
2604
2605            } while (updatePassIterationRenderState());
2606                }
2607                else
2608        {
2609            // nfz: gpu_iterate
2610            do
2611            {
2612                // Unindexed, a little simpler!
2613                            hr = mpD3DDevice->DrawPrimitive(
2614                    primType,
2615                    static_cast<UINT>(op.vertexData->vertexStart),
2616                    static_cast<UINT>(primCount)
2617                    );
2618
2619            } while (updatePassIterationRenderState());
2620        }
2621
2622                if( FAILED( hr ) )
2623                {
2624                        String msg = DXGetErrorDescription9(hr);
2625                        OGRE_EXCEPT( hr, "Failed to DrawPrimitive : " + msg, "D3D9RenderSystem::_render" );
2626                }
2627       
2628        // UnGuard
2629                OgreUnguard();
2630
2631        }
2632    //---------------------------------------------------------------------
2633    void D3D9RenderSystem::setNormaliseNormals(bool normalise)
2634    {
2635        __SetRenderState(D3DRS_NORMALIZENORMALS,
2636            normalise ? TRUE : FALSE);
2637    }
2638        //---------------------------------------------------------------------
2639    void D3D9RenderSystem::bindGpuProgram(GpuProgram* prg)
2640    {
2641        HRESULT hr;
2642        switch (prg->getType())
2643        {
2644        case GPT_VERTEX_PROGRAM:
2645            hr = mpD3DDevice->SetVertexShader(
2646                static_cast<D3D9GpuVertexProgram*>(prg)->getVertexShader());
2647            if (FAILED(hr))
2648            {
2649                OGRE_EXCEPT(hr, "Error calling SetVertexShader", "D3D9RenderSystem::bindGpuProgram");
2650            }
2651            break;
2652        case GPT_FRAGMENT_PROGRAM:
2653            hr = mpD3DDevice->SetPixelShader(
2654                static_cast<D3D9GpuFragmentProgram*>(prg)->getPixelShader());
2655            if (FAILED(hr))
2656            {
2657                OGRE_EXCEPT(hr, "Error calling SetPixelShader", "D3D9RenderSystem::bindGpuProgram");
2658            }
2659            break;
2660        };
2661       
2662        RenderSystem::bindGpuProgram(prg);
2663
2664    }
2665        //---------------------------------------------------------------------
2666    void D3D9RenderSystem::unbindGpuProgram(GpuProgramType gptype)
2667    {
2668        HRESULT hr;
2669        switch(gptype)
2670        {
2671        case GPT_VERTEX_PROGRAM:
2672            mActiveVertexGpuProgramParameters.setNull();
2673            hr = mpD3DDevice->SetVertexShader(NULL);
2674            if (FAILED(hr))
2675            {
2676                OGRE_EXCEPT(hr, "Error resetting SetVertexShader to NULL",
2677                    "D3D9RenderSystem::unbindGpuProgram");
2678            }
2679            break;
2680        case GPT_FRAGMENT_PROGRAM:
2681            mActiveFragmentGpuProgramParameters.setNull();
2682            hr = mpD3DDevice->SetPixelShader(NULL);
2683            if (FAILED(hr))
2684            {
2685                OGRE_EXCEPT(hr, "Error resetting SetPixelShader to NULL",
2686                    "D3D9RenderSystem::unbindGpuProgram");
2687            }
2688            break;
2689        };
2690        RenderSystem::unbindGpuProgram(gptype);
2691    }
2692        //---------------------------------------------------------------------
2693    void D3D9RenderSystem::bindGpuProgramParameters(GpuProgramType gptype,
2694        GpuProgramParametersSharedPtr params)
2695    {
2696        HRESULT hr;
2697        unsigned int index;
2698        GpuProgramParameters::IntConstantIterator intIt = params->getIntConstantIterator();
2699        GpuProgramParameters::RealConstantIterator realIt = params->getRealConstantIterator();
2700
2701        switch(gptype)
2702        {
2703        case GPT_VERTEX_PROGRAM:
2704            mActiveVertexGpuProgramParameters = params;
2705            // Bind floats
2706            if (params->hasRealConstantParams())
2707            {
2708                // Iterate over params and set the relevant ones
2709                index = 0;
2710                while (realIt.hasMoreElements())
2711                {
2712                    const GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
2713                    if (e->isSet)
2714                    {
2715                        if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantF(
2716                            index, e->val, 1)))
2717                        {
2718                            OGRE_EXCEPT(hr, "Unable to upload vertex shader float parameters",
2719                                "D3D9RenderSystem::bindGpuProgramParameters");
2720                        }
2721                    }
2722                    index++;
2723                    realIt.moveNext();
2724                }
2725            }
2726            // Bind ints
2727            if (params->hasIntConstantParams())
2728            {
2729                // Iterate over params and set the relevant ones
2730                index = 0;
2731                while (intIt.hasMoreElements())
2732                {
2733                    const GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
2734                    if (e->isSet)
2735                    {
2736                        if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantI(
2737                            index, e->val, 1)))
2738                        {
2739                            OGRE_EXCEPT(hr, "Unable to upload vertex shader float parameters",
2740                                "D3D9RenderSystem::bindGpuProgramParameters");
2741                        }
2742                    }
2743                    index++;
2744                    intIt.moveNext();
2745                }
2746            }
2747            break;
2748        case GPT_FRAGMENT_PROGRAM:
2749            mActiveFragmentGpuProgramParameters = params;
2750            // Bind floats
2751            if (params->hasRealConstantParams())
2752            {
2753                // Iterate over params and set the relevant ones
2754                index = 0;
2755                while (realIt.hasMoreElements())
2756                {
2757                    const GpuProgramParameters::RealConstantEntry* e = realIt.peekNextPtr();
2758                    if (e->isSet)
2759                    {
2760                        /*
2761                        // TEST
2762                        LogManager::getSingleton().logMessage(
2763                            "  Set Constant " + StringConverter::toString(index) + " to float4(" +
2764                            StringConverter::toString(e->val[0]) + ", " +
2765                            StringConverter::toString(e->val[1]) + ", " +
2766                            StringConverter::toString(e->val[2]) + ", " +
2767                            StringConverter::toString(e->val[3]) + ")");
2768                        */
2769
2770                        if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantF(
2771                            index, e->val, 1)))
2772                        {
2773                            OGRE_EXCEPT(hr, "Unable to upload pixel shader float parameters",
2774                                "D3D9RenderSystem::bindGpuProgramParameters");
2775                        }
2776                    }
2777                    index++;
2778                    realIt.moveNext();
2779                }
2780            }
2781            // Bind ints
2782            if (params->hasIntConstantParams())
2783            {
2784                // Iterate over params and set the relevant ones
2785                index = 0;
2786                while (intIt.hasMoreElements())
2787                {
2788                    const GpuProgramParameters::IntConstantEntry* e = intIt.peekNextPtr();
2789                    if (e->isSet)
2790                    {
2791                        if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantI(
2792                            index, e->val, 1)))
2793                        {
2794                            OGRE_EXCEPT(hr, "Unable to upload pixel shader float parameters",
2795                                "D3D9RenderSystem::bindGpuProgramParameters");
2796                        }
2797                    }
2798                    index++;
2799                    intIt.moveNext();
2800                }
2801            }
2802            break;
2803        };
2804    }
2805        //---------------------------------------------------------------------
2806    void D3D9RenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype)
2807    {
2808
2809        HRESULT hr;
2810        GpuProgramParameters::RealConstantEntry* realEntry;
2811
2812        switch(gptype)
2813        {
2814        case GPT_VERTEX_PROGRAM:
2815            realEntry = mActiveVertexGpuProgramParameters->getPassIterationEntry();
2816            if (realEntry)
2817            {
2818                if (FAILED(hr = mpD3DDevice->SetVertexShaderConstantF(
2819                        mActiveVertexGpuProgramParameters->getPassIterationEntryIndex(), realEntry->val, 1)))
2820                {
2821                    OGRE_EXCEPT(hr, "Unable to upload vertex shader multi pass parameters",
2822                    "D3D9RenderSystem::bindGpuProgramMultiPassParameters");
2823                }
2824            }
2825            break;
2826
2827        case GPT_FRAGMENT_PROGRAM:
2828            realEntry = mActiveFragmentGpuProgramParameters->getPassIterationEntry();
2829            if (realEntry)
2830            {
2831                if (FAILED(hr = mpD3DDevice->SetPixelShaderConstantF(
2832                        mActiveFragmentGpuProgramParameters->getPassIterationEntryIndex(), realEntry->val, 1)))
2833                {
2834                    OGRE_EXCEPT(hr, "Unable to upload pixel shader multi pass parameters",
2835                    "D3D9RenderSystem::bindGpuProgramMultiPassParameters");
2836                }
2837            }
2838            break;
2839
2840        }
2841    }
2842    //---------------------------------------------------------------------
2843    void D3D9RenderSystem::setClipPlanes(const PlaneList& clipPlanes)
2844    {
2845        size_t i;
2846        size_t numClipPlanes;
2847        float dx9ClipPlane[4];
2848        DWORD mask = 0;
2849        HRESULT hr;
2850
2851        numClipPlanes = clipPlanes.size();
2852        for (i = 0; i < numClipPlanes; ++i)
2853        {
2854            const Plane& plane = clipPlanes[i];
2855
2856            dx9ClipPlane[0] = plane.normal.x;
2857            dx9ClipPlane[1] = plane.normal.y;
2858            dx9ClipPlane[2] = plane.normal.z;
2859            dx9ClipPlane[3] = plane.d;
2860
2861            hr = mpD3DDevice->SetClipPlane(i, dx9ClipPlane);
2862            if (FAILED(hr))
2863            {
2864                OGRE_EXCEPT(hr, "Unable to set clip plane",
2865                    "D3D9RenderSystem::setClipPlanes");
2866            }
2867
2868            mask |= (1 << i);
2869        }
2870
2871        hr = __SetRenderState(D3DRS_CLIPPLANEENABLE, mask);
2872        if (FAILED(hr))
2873        {
2874            OGRE_EXCEPT(hr, "Unable to set render state for clip planes",
2875                "D3D9RenderSystem::setClipPlanes");
2876        }
2877    }
2878        //---------------------------------------------------------------------
2879    void D3D9RenderSystem::setScissorTest(bool enabled, size_t left, size_t top, size_t right,
2880        size_t bottom)
2881    {
2882        HRESULT hr;
2883        if (enabled)
2884        {
2885            if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
2886            {
2887                OGRE_EXCEPT(hr, "Unable to enable scissor rendering state; " + getErrorDescription(hr),
2888                    "D3D9RenderSystem::setScissorTest");
2889            }
2890            RECT rect;
2891            rect.left = left;
2892            rect.top = top;
2893            rect.bottom = bottom;
2894            rect.right = right;
2895            if (FAILED(hr = mpD3DDevice->SetScissorRect(&rect)))
2896            {
2897                OGRE_EXCEPT(hr, "Unable to set scissor rectangle; " + getErrorDescription(hr),
2898                    "D3D9RenderSystem::setScissorTest");
2899            }
2900        }
2901        else
2902        {
2903            if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
2904            {
2905                OGRE_EXCEPT(hr, "Unable to disable scissor rendering state; " + getErrorDescription(hr),
2906                    "D3D9RenderSystem::setScissorTest");
2907            }
2908        }
2909    }
2910    //---------------------------------------------------------------------
2911    void D3D9RenderSystem::clearFrameBuffer(unsigned int buffers,
2912        const ColourValue& colour, Real depth, unsigned short stencil)
2913    {
2914        DWORD flags = 0;
2915        if (buffers & FBT_COLOUR)
2916        {
2917            flags |= D3DCLEAR_TARGET;
2918        }
2919        if (buffers & FBT_DEPTH)
2920        {
2921            flags |= D3DCLEAR_ZBUFFER;
2922        }
2923        // Only try to clear the stencil buffer if supported
2924        if (buffers & FBT_STENCIL && mCapabilities->hasCapability(RSC_HWSTENCIL))
2925        {
2926            flags |= D3DCLEAR_STENCIL;
2927        }
2928        HRESULT hr;
2929        if( FAILED( hr = mpD3DDevice->Clear(
2930            0,
2931            NULL,
2932            flags,
2933            colour.getAsARGB(),
2934            depth,
2935            stencil ) ) )
2936        {
2937            String msg = DXGetErrorDescription9(hr);
2938            OGRE_EXCEPT( hr, "Error clearing frame buffer : "
2939                + msg, "D3D9RenderSystem::clearFrameBuffer" );
2940        }
2941    }
2942    //---------------------------------------------------------------------
2943    void D3D9RenderSystem::_makeProjectionMatrix(Real left, Real right,
2944        Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
2945        bool forGpuProgram)
2946    {
2947        // Correct position for off-axis projection matrix
2948        if (!forGpuProgram)
2949        {
2950            Real offsetX = left + right;
2951            Real offsetY = top + bottom;
2952
2953            left -= offsetX;
2954            right -= offsetX;
2955            top -= offsetY;
2956            bottom -= offsetY;
2957        }
2958
2959        Real width = right - left;
2960        Real height = top - bottom;
2961        Real q, qn;
2962        if (farPlane == 0)
2963        {
2964            q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
2965            qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
2966        }
2967        else
2968        {
2969            q = farPlane / ( farPlane - nearPlane );
2970            qn = -q * nearPlane;
2971        }
2972        dest = Matrix4::ZERO;
2973        dest[0][0] = 2 * nearPlane / width;
2974        dest[0][2] = (right+left) / width;
2975        dest[1][1] = 2 * nearPlane / height;
2976        dest[1][2] = (top+bottom) / height;
2977        if (forGpuProgram)
2978        {
2979            dest[2][2] = -q;
2980            dest[3][2] = -1.0f;
2981        }
2982        else
2983        {
2984            dest[2][2] = q;
2985            dest[3][2] = 1.0f;
2986        }
2987        dest[2][3] = qn;
2988    }
2989
2990    // ------------------------------------------------------------------
2991    void D3D9RenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
2992    {
2993        float plane[4] = { A, B, C, D };
2994        mpD3DDevice->SetClipPlane (index, plane);
2995    }
2996
2997    // ------------------------------------------------------------------
2998    void D3D9RenderSystem::enableClipPlane (ushort index, bool enable)
2999    {
3000        DWORD prev;
3001        mpD3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
3002        __SetRenderState(D3DRS_CLIPPLANEENABLE, prev | (1 << index));
3003    }
3004    //---------------------------------------------------------------------
3005    HardwareOcclusionQuery* D3D9RenderSystem::createHardwareOcclusionQuery(void)
3006    {
3007                D3D9HardwareOcclusionQuery* ret = new D3D9HardwareOcclusionQuery (mpD3DDevice);
3008                mHwOcclusionQueries.push_back(ret);
3009                return ret;
3010    }
3011    //---------------------------------------------------------------------
3012    Real D3D9RenderSystem::getHorizontalTexelOffset(void)
3013    {
3014        // D3D considers the origin to be in the center of a pixel
3015        return -0.5f;
3016    }
3017    //---------------------------------------------------------------------
3018    Real D3D9RenderSystem::getVerticalTexelOffset(void)
3019    {
3020        // D3D considers the origin to be in the center of a pixel
3021        return -0.5f;
3022    }
3023    //---------------------------------------------------------------------
3024    void D3D9RenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane,
3025        bool forGpuProgram)
3026    {
3027        // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
3028
3029        // Calculate the clip-space corner point opposite the clipping plane
3030        // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
3031        // transform it into camera space by multiplying it
3032        // by the inverse of the projection matrix
3033
3034        /* generalised version
3035        Vector4 q = matrix.inverse() *
3036            Vector4(Math::Sign(plane.normal.x), Math::Sign(plane.normal.y), 1.0f, 1.0f);
3037        */
3038        Vector4 q;
3039        q.x = Math::Sign(plane.normal.x) / matrix[0][0];
3040        q.y = Math::Sign(plane.normal.y) / matrix[1][1];
3041        q.z = 1.0F;
3042        // flip the next bit from Lengyel since we're right-handed
3043        if (forGpuProgram)
3044        {
3045            q.w = (1.0F - matrix[2][2]) / matrix[2][3];
3046        }
3047        else
3048        {
3049            q.w = (1.0F + matrix[2][2]) / matrix[2][3];
3050        }
3051
3052        // Calculate the scaled plane vector
3053        Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
3054        Vector4 c = clipPlane4d * (1.0F / (clipPlane4d.dotProduct(q)));
3055
3056        // Replace the third row of the projection matrix
3057        matrix[2][0] = c.x;
3058        matrix[2][1] = c.y;
3059        // flip the next bit from Lengyel since we're right-handed
3060        if (forGpuProgram)
3061        {
3062            matrix[2][2] = c.z;
3063        }
3064        else
3065        {
3066            matrix[2][2] = -c.z;
3067        }
3068        matrix[2][3] = c.w;       
3069    }
3070    //---------------------------------------------------------------------
3071    Real D3D9RenderSystem::getMinimumDepthInputValue(void)
3072    {
3073        // Range [0.0f, 1.0f]
3074        return 0.0f;
3075    }
3076    //---------------------------------------------------------------------
3077    Real D3D9RenderSystem::getMaximumDepthInputValue(void)
3078    {
3079        // Range [0.0f, 1.0f]
3080        // D3D inverts even identity view matrices, so maximum INPUT is -1.0
3081        return -1.0f;
3082    }
3083        //---------------------------------------------------------------------
3084        void D3D9RenderSystem::restoreLostDevice(void)
3085        {
3086                // Release all non-managed resources
3087
3088                // Cleanup depth stencils
3089                _cleanupDepthStencils();
3090
3091                // Set all texture units to nothing
3092                _disableTextureUnitsFrom(0);
3093
3094                // Unbind any vertex streams
3095                for (size_t i = 0; i < mLastVertexSourceCount; ++i)
3096                {
3097                        mpD3DDevice->SetStreamSource(i, NULL, 0, 0);
3098                }
3099        mLastVertexSourceCount = 0;
3100
3101        // Release all automatic temporary buffers and free unused
3102        // temporary buffers, so we doesn't need to recreate them,
3103        // and they will reallocate on demand. This save a lot of
3104        // release/recreate of non-managed vertex buffers which
3105        // wasn't need at all.
3106        mHardwareBufferManager->_releaseBufferCopies(true);
3107
3108                // We have to deal with non-managed textures and vertex buffers
3109                // GPU programs don't have to be restored
3110                static_cast<D3D9TextureManager*>(mTextureManager)->releaseDefaultPoolResources();
3111                static_cast<D3D9HardwareBufferManager*>(mHardwareBufferManager)
3112                        ->releaseDefaultPoolResources();
3113
3114                // release additional swap chains (secondary windows)
3115                SecondaryWindowList::iterator sw;
3116                for (sw = mSecondaryWindows.begin(); sw != mSecondaryWindows.end(); ++sw)
3117                {
3118                        (*sw)->destroyD3DResources();
3119                }
3120
3121                // Reset the device, using the primary window presentation params
3122                HRESULT hr = mpD3DDevice->Reset(
3123                        mPrimaryWindow->getPresentationParameters());
3124
3125                if (hr == D3DERR_DEVICELOST)
3126                {
3127                        // Don't continue
3128                        return;
3129                }
3130                else if (FAILED(hr))
3131                {
3132                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
3133                                "Cannot reset device! " + getErrorDescription(hr),
3134                                "D3D9RenderWindow::restoreLostDevice" );
3135                }
3136
3137                // will have lost basic states
3138                mBasicStatesInitialised = false;
3139        mVertexProgramBound = false;
3140        mFragmentProgramBound = false;
3141
3142
3143                // recreate additional swap chains
3144                for (sw = mSecondaryWindows.begin(); sw != mSecondaryWindows.end(); ++sw)
3145                {
3146                        (*sw)->createD3DResources();
3147                }
3148
3149                // Recreate all non-managed resources
3150                static_cast<D3D9TextureManager*>(mTextureManager)
3151                        ->recreateDefaultPoolResources();
3152                static_cast<D3D9HardwareBufferManager*>(mHardwareBufferManager)
3153                        ->recreateDefaultPoolResources();
3154                       
3155                LogManager::getSingleton().logMessage("!!! Direct3D Device successfully restored.");
3156
3157                mDeviceLost = false;
3158
3159                fireEvent("DeviceRestored");
3160
3161        }
3162        //---------------------------------------------------------------------
3163        bool D3D9RenderSystem::isDeviceLost(void)
3164        {
3165                return mDeviceLost;
3166        }
3167        //---------------------------------------------------------------------
3168        void D3D9RenderSystem::_notifyDeviceLost(void)
3169        {
3170                LogManager::getSingleton().logMessage("!!! Direct3D Device Lost!");
3171                mDeviceLost = true;
3172                // will have lost basic states
3173                mBasicStatesInitialised = false;
3174
3175                fireEvent("DeviceLost");
3176        }
3177
3178        //---------------------------------------------------------------------
3179        // Formats to try, in decreasing order of preference
3180        D3DFORMAT ddDepthStencilFormats[]={
3181                D3DFMT_D24FS8,
3182                D3DFMT_D24S8,
3183                D3DFMT_D24X4S4,
3184                D3DFMT_D24X8,
3185                D3DFMT_D15S1,
3186                D3DFMT_D16,
3187                D3DFMT_D32
3188        };
3189#define NDSFORMATS (sizeof(ddDepthStencilFormats)/sizeof(D3DFORMAT))
3190       
3191        D3DFORMAT D3D9RenderSystem::_getDepthStencilFormatFor(D3DFORMAT fmt)
3192        {
3193                /// Check if result is cached
3194                DepthStencilHash::iterator i = mDepthStencilHash.find((unsigned int)fmt);
3195                if(i != mDepthStencilHash.end())
3196                        return i->second;
3197                /// If not, probe with CheckDepthStencilMatch
3198                D3DFORMAT dsfmt = D3DFMT_UNKNOWN;
3199
3200                /// Get description of primary render target
3201                LPDIRECT3DSURFACE9 mSurface = mPrimaryWindow->getRenderSurface();
3202                D3DSURFACE_DESC srfDesc;
3203
3204                if(!FAILED(mSurface->GetDesc(&srfDesc)))
3205                {
3206                        /// Probe all depth stencil formats
3207                        /// Break on first one that matches
3208                        for(size_t x=0; x<NDSFORMATS; ++x)
3209                        {
3210                // Verify that the depth format exists
3211                if (mpD3D->CheckDeviceFormat(
3212                    mActiveD3DDriver->getAdapterNumber(),
3213                    D3DDEVTYPE_HAL,
3214                    srfDesc.Format,
3215                    D3DUSAGE_DEPTHSTENCIL,
3216                    D3DRTYPE_SURFACE,
3217                    ddDepthStencilFormats[x]) != D3D_OK)
3218                {
3219                    continue;
3220                }
3221                // Verify that the depth format is compatible
3222                                if(mpD3D->CheckDepthStencilMatch(
3223                                        mActiveD3DDriver->getAdapterNumber(),
3224                                        D3DDEVTYPE_HAL, srfDesc.Format,
3225                                        fmt, ddDepthStencilFormats[x]) == D3D_OK)
3226                                {
3227                                        dsfmt = ddDepthStencilFormats[x];
3228                                        break;
3229                                }
3230                        }
3231                }
3232                /// Cache result
3233                mDepthStencilHash[(unsigned int)fmt] = dsfmt;
3234                return dsfmt;
3235        }
3236        IDirect3DSurface9* D3D9RenderSystem::_getDepthStencilFor(D3DFORMAT fmt, D3DMULTISAMPLE_TYPE multisample, size_t width, size_t height)
3237        {
3238                D3DFORMAT dsfmt = _getDepthStencilFormatFor(fmt);
3239                if(dsfmt == D3DFMT_UNKNOWN)
3240                        return 0;
3241                IDirect3DSurface9 *surface = 0;
3242
3243                /// Check if result is cached
3244                ZBufferFormat zbfmt(dsfmt, multisample);
3245                ZBufferHash::iterator i = mZBufferHash.find(zbfmt);
3246                if(i != mZBufferHash.end())
3247                {
3248                        /// Check if size is larger or equal
3249                        if(i->second.width >= width && i->second.height >= height)
3250                        {
3251                                surface = i->second.surface;
3252                        }
3253                        else
3254                        {
3255                                /// If not, destroy current buffer
3256                                i->second.surface->Release();
3257                                mZBufferHash.erase(i);
3258                        }
3259                }
3260                if(!surface)
3261                {
3262                        /// If not, create the depthstencil surface
3263                        HRESULT hr = mpD3DDevice->CreateDepthStencilSurface(
3264                                width,
3265                                height,
3266                                dsfmt,
3267                                multisample,
3268                                NULL,
3269                                TRUE,  // discard true or false?
3270                                &surface,
3271                                NULL);
3272                        if(FAILED(hr))
3273                        {
3274                                String msg = DXGetErrorDescription9(hr);
3275                                OGRE_EXCEPT( hr, "Error CreateDepthStencilSurface : " + msg, "D3D9RenderSystem::_getDepthStencilFor" );
3276                        }
3277                        /// And cache it
3278                        ZBufferRef zb;
3279                        zb.surface = surface;
3280                        zb.width = width;
3281                        zb.height = height;
3282                        mZBufferHash[zbfmt] = zb;
3283                }
3284                return surface;
3285        }
3286        void D3D9RenderSystem::_cleanupDepthStencils()
3287        {
3288                for(ZBufferHash::iterator i = mZBufferHash.begin(); i != mZBufferHash.end(); ++i)
3289                {
3290                        /// Release buffer
3291                        i->second.surface->Release();
3292                }
3293                mZBufferHash.clear();
3294        }
3295
3296       
3297        #ifdef GAMETOOLS_ILLUMINATION_MODULE
3298                void D3D9RenderSystem::_setTextureUnitSettings(size_t texUnit, TextureUnitState& tl)
3299                {
3300                        int newUnit = texUnit;
3301                        if(tl.isVertexTexture())
3302                                newUnit = OGRE_MAX_TEXTURE_LAYERS + texUnit;
3303
3304                        RenderSystem::_setTextureUnitSettings(newUnit, tl);
3305                }
3306        #endif
3307}
Note: See TracBrowser for help on using the repository browser.