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

OgreD3D7RenderSystem.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004 (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://ogre.sourceforge.net/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include <malloc.h>
00026 #include "OgreD3D7RenderSystem.h"
00027 #include "OgreDDDriver.h"
00028 #include "OgreD3D7Device.h"
00029 #include "OgreD3D7DeviceList.h"
00030 #include "OgreDDDriverList.h"
00031 #include "OgreDDVideoModeList.h"
00032 #include "OgreDDVideoMode.h"
00033 #include "OgreRenderWindow.h"
00034 #include "OgreLogManager.h"
00035 #include "OgreRenderSystem.h"
00036 #include "OgreException.h"
00037 #include "OgreSceneManager.h"
00038 #include "OgreD3D7TextureManager.h"
00039 #include "OgreViewport.h"
00040 #include "OgreLight.h"
00041 #include "OgreMatrix4.h"
00042 #include "OgreMath.h"
00043 #include "OgreD3D7RenderWindow.h"
00044 #include "OgreFrustum.h"
00045 #include "OgreD3D7GpuProgramManager.h"
00046 
00047 
00048 namespace Ogre {
00049     const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(
00050         0.5,    0,  0, -0.5, 
00051         0, -0.5,  0, -0.5, 
00052         0,    0,  0,   1,
00053         0,    0,  0,   1);
00054 
00055     const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO(
00056         -0.5,    0,  0, -0.5, 
00057         0, 0.5,  0, -0.5, 
00058         0,    0,  0,   1,
00059         0,    0,  0,   1);
00060 
00061     //-----------------------------------------------------------------------
00062     D3DRenderSystem::D3DRenderSystem(HINSTANCE hInstance)
00063     {
00064         OgreGuard( "D3DRenderSystem::D3DRenderSystem" );
00065 
00066         LogManager::getSingleton().logMessage(getName() + " created.");
00067 
00068         mlpD3DDevice = NULL;
00069         // Reset driver list
00070         mDriverList = NULL;
00071         mActiveDDDriver = NULL;
00072         mhInstance = hInstance;
00073         mHardwareBufferManager = NULL;
00074         mGpuProgramManager = NULL;
00075 
00076         initConfigOptions();
00077 
00078         // Initialise D3DX library
00079         D3DXInitialize();
00080 
00081         // set stages desc. to defaults
00082         for (int n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++)
00083         {
00084             mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
00085             mTexStageDesc[n].coordIndex = 0;
00086             mTexStageDesc[n].texType = D3D_TEX_TYPE_NORMAL;
00087             mTexStageDesc[n].pTex = NULL;
00088         }
00089 
00090         mCurrentLights = 0;
00091 
00092         OgreUnguard();
00093     }
00094 
00095     //-----------------------------------------------------------------------
00096     D3DRenderSystem::~D3DRenderSystem()
00097     {
00098         OgreGuard( "D3DRenderSystem::~D3DRenderSystem" );
00099 
00100         SAFE_DELETE(mTextureManager);
00101         SAFE_DELETE(mDriverList);
00102         SAFE_DELETE(mCapabilities);
00103         SAFE_DELETE(mHardwareBufferManager);
00104         SAFE_DELETE(mGpuProgramManager);
00105 
00106         D3DXUninitialize();
00107         LogManager::getSingleton().logMessage(getName() + " destroyed.");
00108 
00109         OgreUnguard();
00110     }
00111 
00112     //-----------------------------------------------------------------------
00113     const String& D3DRenderSystem::getName(void) const
00114     {
00115         static String strName("Direct3D7 Rendering Subsystem");
00116         return strName;
00117     }
00118 
00119     //-----------------------------------------------------------------------
00120     void D3DRenderSystem::initConfigOptions(void)
00121     {
00122         OgreGuard( "D3DRenderSystem::initConfigOptions" );
00123 
00124         DDDriverList* ddList;
00125         DDDriver* dd;
00126 
00127         ConfigOption optDevice;
00128         ConfigOption optVideoMode;
00129         ConfigOption optFullScreen;
00130         ConfigOption optVSync;
00131 
00132         ddList = this->getDirectDrawDrivers();
00133 
00134         // Create option for devices
00135         optDevice.name = "Rendering Device";
00136         optDevice.currentValue = "";
00137         optDevice.possibleValues.clear();
00138         optDevice.immutable = false;
00139 
00140         // Option for video modes
00141         optVideoMode.name = "Video Mode";
00142         optVideoMode.currentValue = "";
00143         optVideoMode.immutable = false;
00144 
00145         // Option for full screen
00146         optFullScreen.name = "Full Screen";
00147         optFullScreen.possibleValues.push_back("Yes");
00148         optFullScreen.possibleValues.push_back("No");
00149         optFullScreen.currentValue = "Yes";
00150 
00151 
00152         unsigned k = ddList->count();
00153         // First, get DirectDraw driver options
00154         for( unsigned j = 0; j < ddList->count(); j++ )
00155         {
00156             dd = ddList->item(j);
00157             // Add to device option list
00158             optDevice.possibleValues.push_back( dd->DriverDescription() );
00159 
00160             // Make first one default
00161             if( j==0 )
00162             {
00163                 optDevice.currentValue = dd->DriverDescription();
00164 
00165             }
00166 
00167 
00168         }
00169 
00170         // VSync option
00171         optVSync.name = "VSync";
00172         optVSync.immutable = false;
00173         optVSync.possibleValues.push_back("Yes");
00174         optVSync.possibleValues.push_back("No");
00175         optVSync.currentValue = "Yes";
00176 
00177 
00178         mOptions[optDevice.name] = optDevice;
00179         mOptions[optVideoMode.name] = optVideoMode;
00180         mOptions[optFullScreen.name] = optFullScreen;
00181         mOptions[optVSync.name] = optVSync;
00182 
00183         // Set default-based settings
00184         refreshDDSettings();
00185 
00186         OgreUnguard();
00187     }
00188 
00189     //-----------------------------------------------------------------------
00190     void D3DRenderSystem::refreshDDSettings(void)
00191     {
00192         OgreGuard( "D3DRenderSystem::refreshDDSettings" );
00193 
00194         DDVideoMode* vid;
00195         ConfigOption* optVideoMode;
00196         ConfigOption* optFullScreen;
00197         DDDriver* dd;
00198 
00199         // Stuffs DD-Driver specific settings
00200 
00201         // Find DD Driver selected in options
00202         ConfigOptionMap::iterator opt = mOptions.find("Rendering Device");
00203 
00204         if( opt != mOptions.end() )
00205         {
00206             for( unsigned j = 0; j < getDirectDrawDrivers()->count(); j++ )
00207             {
00208                 dd = getDirectDrawDrivers()->item(j);
00209                 if( dd->DriverDescription() == opt->second.currentValue )
00210                     break;
00211             }
00212 
00213             // Get fullScreen and Video mode options
00214             opt = mOptions.find("Video Mode");
00215             optVideoMode = &opt->second;
00216             opt = mOptions.find("Full Screen");
00217             optFullScreen = &opt->second;
00218 
00219             // Full screen forced?
00220             if (!(dd->CanRenderWindowed()))
00221             {
00222                 setConfigOption("Full Screen", "Yes");
00223                 optFullScreen->immutable = true;
00224             }
00225             else
00226                 optFullScreen->immutable = false;
00227 
00228             // Get video modes for this device
00229             optVideoMode->possibleValues.clear();
00230 
00231             for( unsigned k = 0; k<dd->getVideoModeList()->count(); k++ )
00232             {
00233                 vid = dd->getVideoModeList()->item(k);
00234                 optVideoMode->possibleValues.push_back(vid->Description());
00235             }
00236         }
00237 
00238         OgreUnguard();
00239     }
00240 
00241 
00242     //-----------------------------------------------------------------------
00243     ConfigOptionMap& D3DRenderSystem::getConfigOptions(void)
00244     {
00245         // Return a COPY of the current config options
00246         return mOptions;
00247 
00248     }
00249 
00250     //-----------------------------------------------------------------------
00251     void D3DRenderSystem::setConfigOption(const String &name, const String &value)
00252     {
00253         OgreGuard( "D3DRenderSystem::setConfigOption" );
00254 
00255         char msg[128];
00256 
00257         sprintf(msg, "RenderSystem Option: %s = %s", name.c_str(), value.c_str());
00258         LogManager::getSingleton().logMessage(msg);
00259 
00260         // Find option
00261         ConfigOptionMap::iterator it = mOptions.find(name);
00262 
00263         // Update
00264         if( it != mOptions.end())
00265             it->second.currentValue = value;
00266         else
00267         {
00268             sprintf(msg, "Option named %s does not exist.", name.c_str());
00269             Except(Exception::ERR_INVALIDPARAMS,
00270                 msg, "D3DRenderSystem::setConfigOption");
00271         }
00272 
00273         // Refresh other options if DD Driver changed
00274         if (name == "Rendering Device")
00275             refreshDDSettings();
00276 
00277         if (name == "Full Screen")
00278         {
00279             if (value == "No")
00280             {
00281                 // Video mode is not applicable
00282                 it = mOptions.find("Video Mode");
00283                 it->second.currentValue = "N/A";
00284                 it->second.immutable = true;
00285             }
00286             else
00287             {
00288                 // Video mode is applicable
00289                 it = mOptions.find("Video Mode");
00290                 // default to 640 x 480 x 16
00291                 it->second.currentValue = "640 x 480 @ 16-bit colour";
00292                 it->second.immutable = false;
00293             }
00294         }
00295 
00296         OgreUnguard();
00297     }
00298     //-----------------------------------------------------------------------
00299     String D3DRenderSystem::validateConfigOptions(void)
00300     {
00301         // Check video mode specified in full screen mode
00302         ConfigOptionMap::iterator o = mOptions.find("Full Screen");
00303         if (o->second.currentValue == "Yes")
00304         {
00305             // Check video mode
00306             o = mOptions.find("Video Mode");
00307             if (o->second.currentValue == "")
00308             {
00309                 return "A video mode must be selected for running in full-screen mode.";
00310             }
00311         }
00312 
00313         o = mOptions.find( "Rendering Device" );
00314         bool foundDriver = false;
00315         DDDriverList* driverList = getDirectDrawDrivers();
00316         for( ushort j=0; j < driverList->count(); j++ )
00317         {
00318             if( driverList->item(j)->DriverDescription() == o->second.currentValue )
00319             {
00320                 foundDriver = true;
00321                 break;
00322             }
00323         }
00324         if (!foundDriver)
00325         {
00326             // Just pick the first driver
00327             setConfigOption("Rendering Device", driverList->item(0)->DriverDescription());
00328             return "Your DirectX driver name has changed since the last time you ran OGRE; "
00329                 "the 'Rendering Device' has been changed.";
00330         }
00331         return "";
00332 
00333     }
00334     //-----------------------------------------------------------------------
00335     RenderWindow* D3DRenderSystem::initialise(bool autoCreateWindow, const String& windowTitle)
00336     {
00337         RenderWindow* autoWindow = 0;
00338 
00339 
00340         LogManager::getSingleton().logMessage(
00341             "***************************************\n"
00342             "*** Direct3D Subsystem Initialising ***\n"
00343             "***************************************" );
00344 
00345         // ---------------------------
00346         // Init using current settings
00347         // ---------------------------
00348 
00349         // DirectDraw driver
00350         mActiveDDDriver = 0;
00351         ConfigOptionMap::iterator opt = mOptions.find("Rendering Device");
00352         for( unsigned j = 0; j<getDirectDrawDrivers()->count(); j++ )
00353         {
00354             if (getDirectDrawDrivers()->item(j)->DriverDescription() == opt->second.currentValue)
00355             {
00356                 mActiveDDDriver = getDirectDrawDrivers()->item(j);
00357                 break;
00358             }
00359         }
00360 
00361         if (!mActiveDDDriver)
00362             Except(Exception::ERR_INVALIDPARAMS, "Problems finding requested DirectDraw driver!",
00363             "D3DRenderSystem::initialise");
00364 
00365 
00366         // Sort out the creation of a new window if required
00367         if (autoCreateWindow)
00368         {
00369             // Full screen?
00370             bool fullScreen;
00371             opt = mOptions.find("Full Screen");
00372             if( opt == mOptions.end() )
00373                 Except(999, "Can't find full screen option!",
00374                 "D3DRenderSystem::initialise");
00375             if (opt->second.currentValue == "Yes")
00376                 fullScreen = true;
00377             else
00378                 fullScreen = false;
00379 
00380             // Get video mode
00381             DDVideoMode* vid;
00382             unsigned int height, width, colourDepth;
00383 
00384             vid = 0;
00385             String temp;
00386             if (fullScreen)
00387             {
00388                 opt = mOptions.find("Video Mode");
00389 
00390                 for( unsigned j=0; j<mActiveDDDriver->getVideoModeList()->count(); j++ )
00391                 {
00392                     temp = mActiveDDDriver->getVideoModeList()->item(j)->Description();
00393                     if (temp == opt->second.currentValue)
00394                     {
00395                         vid = mActiveDDDriver->getVideoModeList()->item(j);
00396                         break;
00397                     }
00398                 }
00399 
00400                 if (!vid)
00401                     Except(9999, "Can't find requested video mode.",
00402                     "D3DRenderSystem::initilise");
00403                 width = vid->mWidth;
00404                 height = vid->mHeight;
00405                 colourDepth = vid->mColourDepth;
00406 
00407             }
00408             else
00409             {
00410                 // Notional height / width
00411                 width = 800;
00412                 height = 600;
00413                 colourDepth = 0; // colour depth based on desktop
00414             }
00415 
00416             // Create myself a window
00417             autoWindow = this->createRenderWindow(windowTitle, width, height, colourDepth, fullScreen);
00418 
00419 
00420 
00421         }
00422 
00423         opt = mOptions.find("VSync");
00424         if (opt!=mOptions.end())
00425         {
00426             if (opt->second.currentValue == "Yes")
00427             {
00428                 setWaitForVerticalBlank(true);
00429             }
00430             else
00431             {
00432                 setWaitForVerticalBlank(false);
00433             }
00434         }
00435 
00436 
00437         LogManager::getSingleton().logMessage("*****************************************");
00438         LogManager::getSingleton().logMessage("*** Direct3D Subsystem Initialised Ok ***");
00439         LogManager::getSingleton().logMessage("*****************************************");
00440 
00441         // call superclass method
00442         RenderSystem::initialise(autoCreateWindow);
00443 
00444         // Create buffer manager
00445         mHardwareBufferManager = new D3D7HardwareBufferManager();
00446         // Create dummy gpu manager
00447         mGpuProgramManager = new D3D7GpuProgramManager();
00448 
00449 
00450         return autoWindow;
00451 
00452     }
00453 
00454     //-----------------------------------------------------------------------
00455     void D3DRenderSystem::reinitialise(void)
00456     {
00457         this->shutdown();
00458         this->initialise(true);
00459     }
00460 
00461 
00462     //-----------------------------------------------------------------------
00463     void D3DRenderSystem::shutdown(void)
00464     {
00465         RenderSystem::shutdown();
00466 
00467         // Cleanup
00468         // Release all DirectX resources
00469         //D3DTextr_InvalidateAllTextures();
00470         if (mActiveDDDriver)
00471         {
00472             mActiveDDDriver->Cleanup();
00473         }
00474 
00475         // Delete system objects
00476         SAFE_DELETE(mDriverList);
00477 
00478         mActiveDDDriver = NULL;
00479 
00480 
00481 
00482         // Write termination message
00483         LogManager::getSingleton().logMessage("*-*-* Direct3D Subsystem shutting down cleanly.");
00484 
00485 
00486     }
00487 
00488     //-----------------------------------------------------------------------
00489     void D3DRenderSystem::setAmbientLight(float r, float g, float b)
00490     {
00491         // Call D3D
00492         D3DCOLOR col = D3DRGB(r,g,b);
00493 
00494         HRESULT hr = __SetRenderState(D3DRENDERSTATE_AMBIENT, col);
00495         if (FAILED(hr))
00496             Except(hr, "Error setting ambient light.", "D3DRenderSystem::setAmbientLight");
00497     }
00498 
00499     //-----------------------------------------------------------------------
00500     void D3DRenderSystem::setShadingType(ShadeOptions so)
00501     {
00502         D3DSHADEMODE d3dMode;
00503         switch(so)
00504         {
00505         case SO_FLAT:
00506             d3dMode = D3DSHADE_FLAT;
00507             break;
00508         case SO_GOURAUD:
00509             d3dMode = D3DSHADE_GOURAUD;
00510             break;
00511         case SO_PHONG:
00512             d3dMode = D3DSHADE_PHONG;
00513             break;
00514 
00515         }
00516 
00517         HRESULT hr = __SetRenderState(D3DRENDERSTATE_SHADEMODE, d3dMode);
00518         if (FAILED(hr))
00519             Except(hr, "Error setting shading mode.", "D3DRenderSystem::setShadingType");
00520 
00521     }
00522 
00523 
00524     //-----------------------------------------------------------------------
00525     RenderWindow* D3DRenderSystem::createRenderWindow(const String &name, unsigned int width, unsigned int height, unsigned int colourDepth,
00526         bool fullScreen, int left, int top, bool depthBuffer, RenderWindow* parentWindowHandle)
00527     {
00528         static bool firstWindow = true;
00529         OgreGuard( "D3DRenderSystem::createRenderWindow" );
00530 
00531         String msg;
00532 
00533         // Make sure we don't already have a render target of the
00534         // same name as the one supplied
00535         if( mRenderTargets.find( name ) != mRenderTargets.end() )
00536         {
00537             msg = msg + "A render target of the same name (" + name + ") already "
00538                 "exists. You cannot create a new window with this name.";
00539             Except(999,msg,"D3DRenderSystem::createRenderWindow");
00540         }
00541 
00542         RenderWindow* win = new D3D7RenderWindow();
00543         // Create window, supplying DD interface & hInstance
00544         win->create(name, width, height, colourDepth, fullScreen,
00545             left, top, depthBuffer, &mhInstance, mActiveDDDriver, parentWindowHandle);
00546 
00547         attachRenderTarget( *win );
00548 
00549         // If this is the first window, get the D3D device
00550         //  and create the texture manager, setup caps
00551         if (firstWindow)
00552         {
00553             win->getCustomAttribute("D3DDEVICE", &mlpD3DDevice);
00554             // Get caps
00555             mlpD3DDevice->GetCaps(&mD3DDeviceDesc);
00556             // Create my texture manager for use by others
00557             // Note this is a Singleton; pointer is held static by superclass
00558             mTextureManager = new D3DTextureManager(mlpD3DDevice);
00559 
00560             // Check for hardware stencil support
00561             // Get render target, then depth buffer and check format
00562             LPDIRECTDRAWSURFACE7 lpTarget;
00563             win->getCustomAttribute("DDBACKBUFFER", &lpTarget);
00564             DDSCAPS2 ddscaps;
00565             ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
00566             ddscaps.dwCaps = DDSCAPS_ZBUFFER;
00567             lpTarget->GetAttachedSurface(&ddscaps, &lpTarget);
00568             lpTarget->Release();
00569             DDSURFACEDESC2 ddsd;
00570             ddsd.dwSize = sizeof(DDSURFACEDESC2);
00571             lpTarget->GetSurfaceDesc(&ddsd);
00572             DWORD stencil =  ddsd.ddpfPixelFormat.dwStencilBitDepth;
00573             if(stencil > 0)
00574             {
00575                 mCapabilities->setCapability(RSC_HWSTENCIL);
00576                 mCapabilities->setStencilBufferBitDepth(stencil);
00577                 if ((mD3DDeviceDesc.dwStencilCaps & D3DSTENCILCAPS_INCR) && 
00578                     (mD3DDeviceDesc.dwStencilCaps & D3DSTENCILCAPS_DECR))
00579                     mCapabilities->setCapability(RSC_STENCIL_WRAP);
00580             }
00581 
00582             // Anisotropy?
00583             if (mD3DDeviceDesc.dwMaxAnisotropy > 1)
00584                 mCapabilities->setCapability(RSC_ANISOTROPY);
00585             // Blending between stages supported
00586             mCapabilities->setCapability(RSC_BLENDING);
00587             // Cubemapping
00588             if (mD3DDeviceDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP)
00589                 mCapabilities->setCapability(RSC_CUBEMAPPING);
00590 
00591             // DOT3
00592             if (mD3DDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
00593                 mCapabilities->setCapability(RSC_DOT3);
00594 
00595             // Set the number of texture units based on details from current device
00596             mCapabilities->setNumTextureUnits(mD3DDeviceDesc.wMaxSimultaneousTextures);
00597 
00598             mCapabilities->log(LogManager::getSingleton().getDefaultLog());
00599 
00600             firstWindow = false;
00601         }
00602 
00603         OgreUnguardRet( win );
00604     }
00605 
00606     RenderTexture * D3DRenderSystem::createRenderTexture( const String & name, unsigned int width, unsigned int height )
00607     {
00608         RenderTexture * rt = new D3D7RenderTexture( name, width, height );
00609         attachRenderTarget( *rt );
00610         return rt;
00611     }
00612 
00613     //-----------------------------------------------------------------------
00614     // Low-level overridden members
00615     //-----------------------------------------------------------------------
00616     //---------------------------------------------------------------------
00617     void D3DRenderSystem::_useLights(const LightList& lights, unsigned short limit)
00618     {
00619         LightList::const_iterator i, iend;
00620         iend = lights.end();
00621         unsigned short num = 0;
00622         for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
00623         {
00624             setD3DLight(num, *i);
00625         }
00626         // Disable extra lights
00627         for (; num < mCurrentLights; ++num)
00628         {
00629             setD3DLight(num, NULL);
00630         }
00631         mCurrentLights = std::min(limit, static_cast<unsigned short>(lights.size()));
00632 
00633     }
00634     //-----------------------------------------------------------------------
00635     void D3DRenderSystem::setD3DLight(size_t index, Light* lt)
00636     {
00637         // Add to D3D
00638         HRESULT hr;
00639         D3DLIGHT7 d3dLight;
00640 
00641         if (!lt)
00642         {
00643             hr = mlpD3DDevice->LightEnable(index, FALSE);
00644             if (FAILED(hr))
00645                 Except(hr, "Unable to disable light.", "D3DRenderSystem::setD3DLight");
00646         }
00647         else
00648         {
00649             switch (lt->getType())
00650             {
00651             case Light::LT_POINT:
00652                 d3dLight.dltType = D3DLIGHT_POINT;
00653                 break;
00654             case Light::LT_DIRECTIONAL:
00655                 d3dLight.dltType = D3DLIGHT_DIRECTIONAL;
00656                 break;
00657             case Light::LT_SPOTLIGHT:
00658                 d3dLight.dltType = D3DLIGHT_SPOT;
00659                 d3dLight.dvFalloff = lt->getSpotlightFalloff();
00660                 d3dLight.dvTheta = Math::AngleUnitsToRadians(lt->getSpotlightInnerAngle());
00661                 d3dLight.dvPhi = Math::AngleUnitsToRadians(lt->getSpotlightOuterAngle());
00662                 break;
00663             }
00664 
00665             // Colours
00666             ColourValue col;
00667             col = lt->getDiffuseColour();
00668             d3dLight.dcvDiffuse.r = col.r;
00669             d3dLight.dcvDiffuse.g = col.g;
00670             d3dLight.dcvDiffuse.b = col.b;
00671             d3dLight.dcvDiffuse.a = col.a;
00672 
00673             col = lt->getSpecularColour();
00674             d3dLight.dcvSpecular.r = col.r;
00675             d3dLight.dcvSpecular.g = col.g;
00676             d3dLight.dcvSpecular.b = col.b;
00677             d3dLight.dcvSpecular.a = col.a;
00678 
00679             // Never use ambient for a movable light
00680             d3dLight.dcvAmbient.r = 0.0;
00681             d3dLight.dcvAmbient.g = 0.0;
00682             d3dLight.dcvAmbient.b = 0.0;
00683             d3dLight.dcvAmbient.a = 0.0;
00684 
00685             // Position (Irrelevant for directional)
00686             Vector3 vec;
00687             if (lt->getType() != Light::LT_DIRECTIONAL)
00688             {
00689                 vec = lt->getDerivedPosition();
00690 
00691                 d3dLight.dvPosition.x = vec.x;
00692                 d3dLight.dvPosition.y = vec.y;
00693                 d3dLight.dvPosition.z = vec.z;
00694             }
00695             // Direction (Irrelevant for point lights)
00696             if (lt->getType() != Light::LT_POINT)
00697             {
00698                 vec = lt->getDerivedDirection();
00699                 d3dLight.dvDirection.x = vec.x;
00700                 d3dLight.dvDirection.y = vec.y;
00701                 d3dLight.dvDirection.z = vec.z;
00702             }
00703             // Attenuation parameters
00704             d3dLight.dvRange = lt->getAttenuationRange();
00705             d3dLight.dvAttenuation0 = lt->getAttenuationConstant();
00706             d3dLight.dvAttenuation1 = lt->getAttenuationLinear();
00707             d3dLight.dvAttenuation2 = lt->getAttenuationQuadric();
00708 
00709 
00710 
00711             // Set light state
00712             hr = mlpD3DDevice->SetLight(index, &d3dLight);
00713 
00714             if (FAILED(hr))
00715                 Except(hr, "Unable to set light details", "D3DRenderSystem::setD3DLight");
00716 
00717             hr = mlpD3DDevice->LightEnable(index, TRUE);
00718             if (FAILED(hr))
00719                 Except(hr, "Unable to enable light.", "D3DRenderSystem::setD3DLight");
00720         }
00721 
00722 
00723     }
00724     //-----------------------------------------------------------------------
00725     D3DMATRIX D3DRenderSystem::makeD3DMatrix(const Matrix4& mat)
00726     {
00727         // Transpose matrix
00728         // D3D uses row vectors i.e. V*M
00729         // Ogre, OpenGL and everything else uses coloumn vectors i.e. M*V
00730         D3DMATRIX d3dMat;
00731 
00732         d3dMat.m[0][0] = mat[0][0];
00733         d3dMat.m[0][1] = mat[1][0];
00734         d3dMat.m[0][2] = mat[2][0];
00735         d3dMat.m[0][3] = mat[3][0];
00736 
00737         d3dMat.m[1][0] = mat[0][1];
00738         d3dMat.m[1][1] = mat[1][1];
00739         d3dMat.m[1][2] = mat[2][1];
00740         d3dMat.m[1][3] = mat[3][1];
00741 
00742         d3dMat.m[2][0] = mat[0][2];
00743         d3dMat.m[2][1] = mat[1][2];
00744         d3dMat.m[2][2] = mat[2][2];
00745         d3dMat.m[2][3] = mat[3][2];
00746 
00747         d3dMat.m[3][0] = mat[0][3];
00748         d3dMat.m[3][1] = mat[1][3];
00749         d3dMat.m[3][2] = mat[2][3];
00750         d3dMat.m[3][3] = mat[3][3];
00751 
00752         return d3dMat;
00753     }
00754 
00755     Matrix4 D3DRenderSystem::convertD3DMatrix(const D3DMATRIX& d3dmat)
00756     {
00757         // The reverse of makeD3DMatrix
00758         // Transpose matrix
00759         // D3D uses row vectors i.e. V*M
00760         // Ogre, OpenGL and everything else uses coloumn vectors i.e. M*V
00761         Matrix4 mat;
00762         for (unsigned row = 0; row < 4; ++row)
00763             for (unsigned col = 0; col < 4; ++col)
00764                 mat[col][row] = d3dmat.m[row][col];
00765 
00766         return mat;
00767 
00768 
00769     }
00770     //-----------------------------------------------------------------------
00771     void D3DRenderSystem::_setWorldMatrix(const Matrix4 &m)
00772     {
00773         D3DMATRIX d3dmat;
00774 
00775         d3dmat = makeD3DMatrix(m);
00776 
00777         HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &d3dmat);
00778 
00779         if (FAILED(hr))
00780             Except(hr, "Cannot set D3D world matrix",
00781             "D3DRenderSystem::_setWorldMatrix");
00782     }
00783 
00784     //-----------------------------------------------------------------------
00785     void D3DRenderSystem::_setViewMatrix(const Matrix4 &m)
00786     {
00787         // save latest view matrix
00788         mViewMatrix = m;
00789         mViewMatrix[2][0] = -mViewMatrix[2][0];
00790         mViewMatrix[2][1] = -mViewMatrix[2][1];
00791         mViewMatrix[2][2] = -mViewMatrix[2][2];
00792         mViewMatrix[2][3] = -mViewMatrix[2][3];
00793 
00794         D3DMATRIX d3dmat = makeD3DMatrix(mViewMatrix);
00795 
00796         HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &d3dmat);
00797 
00798         if (FAILED(hr))
00799             Except(hr, "Cannot set D3D view matrix",
00800             "D3DRenderSystem::_setViewMatrix");
00801 
00802     }
00803     //-----------------------------------------------------------------------
00804     void D3DRenderSystem::_setProjectionMatrix(const Matrix4 &m)
00805     {
00806         D3DMATRIX d3dmat = makeD3DMatrix(m);
00807 
00808         if( mActiveRenderTarget->requiresTextureFlipping() )
00809         {
00810             d3dmat._22 = - d3dmat._22;
00811         }
00812 
00813         HRESULT hr = mlpD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &d3dmat);
00814 
00815         if (FAILED(hr))
00816             Except(hr, "Cannot set D3D projection matrix",
00817             "D3DRenderSystem::_setProjectionMatrix");
00818     }
00819 
00820 
00821     //-----------------------------------------------------------------------
00822     void D3DRenderSystem::_setSurfaceParams(const ColourValue &ambient,
00823         const ColourValue &diffuse, const ColourValue &specular,
00824         const ColourValue &emissive, const Real shininess)
00825     {
00826         // Remember last call
00827         static ColourValue lastAmbient = ColourValue::Black;
00828         static ColourValue lastDiffuse = ColourValue::Black;
00829         static ColourValue lastSpecular = ColourValue::Black;
00830         static ColourValue lastEmissive = ColourValue::Black;
00831         static Real lastShininess = 0.0;
00832 
00833         // Only update if changed
00834         if (ambient != lastAmbient || diffuse != lastDiffuse ||
00835             specular != lastSpecular || emissive != lastEmissive ||
00836             shininess != lastShininess)
00837         {
00838 
00839             // Convert to D3D
00840             D3DMATERIAL7 d3dMat;
00841 
00842             d3dMat.dcvDiffuse.r = diffuse.r;
00843             d3dMat.dcvDiffuse.g = diffuse.g;
00844             d3dMat.dcvDiffuse.b = diffuse.b;
00845             d3dMat.dcvDiffuse.a = diffuse.a;
00846 
00847             d3dMat.dcvAmbient.r = ambient.r;
00848             d3dMat.dcvAmbient.g = ambient.g;
00849             d3dMat.dcvAmbient.b = ambient.b;
00850             d3dMat.dcvAmbient.a = ambient.a;
00851 
00852             d3dMat.dcvSpecular.r = specular.r;
00853             d3dMat.dcvSpecular.g = specular.g;
00854             d3dMat.dcvSpecular.b = specular.b;
00855             d3dMat.dcvSpecular.a = specular.a;
00856 
00857             d3dMat.dcvEmissive.r = emissive.r;
00858             d3dMat.dcvEmissive.g = emissive.g;
00859             d3dMat.dcvEmissive.b = emissive.b;
00860             d3dMat.dcvEmissive.a = emissive.a;
00861 
00862             d3dMat.dvPower = shininess;
00863 
00864             HRESULT hr = mlpD3DDevice->SetMaterial(&d3dMat);
00865             if (FAILED(hr))
00866                 Except(hr, "Error setting D3D material.", "D3DRenderSystem::_setSurfaceParams");
00867 
00868         }
00869     }
00870     //-----------------------------------------------------------------------
00871     void D3DRenderSystem::_setTexture(size_t stage, bool enabled, const String &texname)
00872     {
00873         HRESULT hr;
00874         D3DTexture* dt = static_cast< D3DTexture* >(TextureManager::getSingleton().getByName(texname));
00875         if (enabled && dt)
00876         {
00877             LPDIRECTDRAWSURFACE7 pTex = dt->getDDSurface();
00878             if (pTex != mTexStageDesc[stage].pTex)
00879             {
00880                 hr = mlpD3DDevice->SetTexture(stage, pTex );
00881                 if (FAILED(hr))
00882                     Except(hr, "Unable to set texture in D3D.", "D3DRenderSystem::_setTexture");
00883 
00884                 // set stage desc.
00885                 mTexStageDesc[stage].texType = _ogreTexTypeToD3DTexType(dt->getTextureType());
00886                 mTexStageDesc[stage].pTex = pTex;
00887             }
00888         }
00889         else
00890         {
00891             hr = mlpD3DDevice->SetTexture(stage, 0);
00892             if (FAILED(hr))
00893                 Except(hr, "Unable to disable texture in D3D.", "D3DRenderSystem::_setTexture");
00894             hr = __SetTextureStageState( stage, D3DTSS_COLOROP, D3DTOP_DISABLE );
00895             if (FAILED(hr))
00896                 Except(hr, "Unable to disable texture in D3D.", "D3DRenderSystem::_setTexture");
00897 
00898             // set stage desc. to defaults
00899             mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
00900             mTexStageDesc[stage].coordIndex = 0;
00901             mTexStageDesc[stage].texType = D3D_TEX_TYPE_NORMAL;
00902             mTexStageDesc[stage].pTex = NULL;
00903         }
00904     }
00905     //-----------------------------------------------------------------------
00906     void D3DRenderSystem::_setTextureCoordCalculation(size_t stage, TexCoordCalcMethod m, 
00907         const Frustum* frustum)
00908     {
00909         HRESULT hr = S_OK;
00910         // record the stage state
00911         mTexStageDesc[stage].autoTexCoordType = m;
00912         mTexStageDesc[stage].frustum = frustum;
00913 
00914         switch( m )
00915         {
00916         case TEXCALC_NONE:
00917             // if no calc we've already set index through D3D9RenderSystem::_setTextureCoordSet
00918             break;
00919         case TEXCALC_ENVIRONMENT_MAP: 
00920             // D3D7 does not support spherical reflection
00921             hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
00922             break;
00923         case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
00924             hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR );
00925             break;
00926         case TEXCALC_ENVIRONMENT_MAP_PLANAR:
00927         case TEXCALC_PROJECTIVE_TEXTURE:
00928             hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION );
00929             break;
00930         case TEXCALC_ENVIRONMENT_MAP_NORMAL:
00931             hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
00932             break;
00933         }
00934         if( FAILED( hr ) )
00935             Except( hr, "Error setting texture coord calculation", "D3DRenderSystem::_setTextureCoordCalculation" );
00936 
00937     }
00938     //-----------------------------------------------------------------------
00939     void D3DRenderSystem::_setTextureMatrix(size_t stage, const Matrix4& xForm)
00940     {
00941         HRESULT hr;
00942         D3DMATRIX d3dMat; // the matrix we'll maybe apply
00943         Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format
00944         
00945 
00946         /* If envmap is applied, since D3D7 doesn't support spheremap,
00947         then we have to use texture transform to make the camera space normal
00948         reference the envmap properly. This isn't exactly the same as spheremap
00949         (it looks nasty on flat areas because the camera space normals are the same)
00950         but it's the best approximation we have in the absence of a proper spheremap */
00951         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP)
00952         {
00953             // concatenate with the xForm
00954             newMat = newMat.concatenate(Matrix4::CLIPSPACE2DTOIMAGESPACE);
00955         }
00956 
00957         // If this is a cubic reflection, we need to modify using the view matrix
00958         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION)
00959         {
00960             D3DMATRIX viewMatrix; 
00961 
00962             // Get view matrix
00963             mlpD3DDevice->GetTransform(D3DTRANSFORMSTATE_VIEW, &viewMatrix);
00964             // Get transposed 3x3, ie since D3D is transposed just copy
00965             // We want to transpose since that will invert an orthonormal matrix ie rotation
00966             Matrix4 ogreViewTransposed;
00967             ogreViewTransposed[0][0] = viewMatrix.m[0][0];
00968             ogreViewTransposed[0][1] = viewMatrix.m[0][1];
00969             ogreViewTransposed[0][2] = viewMatrix.m[0][2];
00970             ogreViewTransposed[0][3] = 0.0f;
00971 
00972             ogreViewTransposed[1][0] = viewMatrix.m[1][0];
00973             ogreViewTransposed[1][1] = viewMatrix.m[1][1];
00974             ogreViewTransposed[1][2] = viewMatrix.m[1][2];
00975             ogreViewTransposed[1][3] = 0.0f;
00976 
00977             ogreViewTransposed[2][0] = viewMatrix.m[2][0];
00978             ogreViewTransposed[2][1] = viewMatrix.m[2][1];
00979             ogreViewTransposed[2][2] = viewMatrix.m[2][2];
00980             ogreViewTransposed[2][3] = 0.0f;
00981 
00982             ogreViewTransposed[3][0] = 0.0f;
00983             ogreViewTransposed[3][1] = 0.0f;
00984             ogreViewTransposed[3][2] = 0.0f;
00985             ogreViewTransposed[3][3] = 1.0f;
00986             
00987             newMat = newMat.concatenate(ogreViewTransposed);
00988         }
00989 
00990         if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
00991         {
00992             // Derive camera space to projector space transform
00993             // To do this, we need to undo the camera view matrix, then 
00994             // apply the projector view & projection matrices
00995             newMat = mViewMatrix.inverse() * newMat;
00996             newMat = mTexStageDesc[stage].frustum->getViewMatrix() * newMat;
00997             newMat = mTexStageDesc[stage].frustum->getProjectionMatrix() * newMat;
00998             if (mTexStageDesc[stage].frustum->getProjectionType() == PT_PERSPECTIVE)
00999             {
01000                 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * newMat;
01001             }
01002             else
01003             {
01004                 newMat = PROJECTIONCLIPSPACE2DTOIMAGESPACE_ORTHO * newMat;
01005             }
01006 
01007         }
01008 
01009         // convert our matrix to D3D format
01010         d3dMat = makeD3DMatrix(newMat);
01011 
01012         // need this if texture is a cube map, to invert D3D's z coord
01013         if (mTexStageDesc[stage].autoTexCoordType != TEXCALC_NONE)
01014         {
01015             d3dMat._13 = -d3dMat._13;
01016             d3dMat._23 = -d3dMat._23;
01017             d3dMat._33 = -d3dMat._33;
01018             d3dMat._43 = -d3dMat._43;
01019         }
01020 
01021         // set the matrix if it's not the identity
01022         if (!(newMat == Matrix4::IDENTITY))
01023         {
01024             // tell D3D the dimension of tex. coord.
01025             int texCoordDim;
01026             if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
01027             {
01028                 texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT3;
01029             }
01030             else
01031             {
01032                 switch (mTexStageDesc[stage].texType)
01033                 {
01034                 case D3D_TEX_TYPE_NORMAL:
01035                     texCoordDim = D3DTTFF_COUNT2;
01036                     break;
01037                 case D3D_TEX_TYPE_CUBE:
01038                 case D3D_TEX_TYPE_VOLUME:
01039                     texCoordDim = D3DTTFF_COUNT3;
01040                 }
01041             }
01042 
01043             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim );
01044             if (FAILED(hr))
01045                 Except( hr, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" );
01046 
01047             hr = mlpD3DDevice->SetTransform( 
01048                 (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + stage), &d3dMat );
01049             if (FAILED(hr))
01050                 Except( hr, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
01051         }
01052         else
01053         {
01054             // disable all of this
01055             hr = __SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
01056             if( FAILED( hr ) )
01057                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
01058 
01059             // set the identity matrix
01060             D3DUtil_SetIdentityMatrix( d3dMat );
01061             hr = mlpD3DDevice->SetTransform( 
01062                 (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + stage), &d3dMat );
01063             if( FAILED( hr ) )
01064                 Except( hr, "Error setting texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
01065         }
01066     }
01067     //---------------------------------------------------------------------
01068     void D3DRenderSystem::_setTextureCoordSet( size_t stage, size_t index )
01069     {
01070         HRESULT hr;
01071         hr = __SetTextureStageState( stage, D3DTSS_TEXCOORDINDEX, index );
01072         if( FAILED( hr ) )
01073             Except( hr, "Unable to set texture coord. set index", "D3DRenderSystem::_setTextureCoordSet" );
01074         // Record settings
01075         mTexStageDesc[stage].coordIndex = index;
01076     }
01077     //-----------------------------------------------------------------------
01078     void D3DRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm)
01079     {
01080         HRESULT hr;
01081         D3DTEXTURESTAGESTATETYPE tss;
01082         DWORD value;
01083 
01084         if (bm.blendType == LBT_COLOUR)
01085         {
01086             tss = D3DTSS_COLOROP;
01087         }
01088         else if (bm.blendType == LBT_ALPHA)
01089         {
01090             tss= D3DTSS_ALPHAOP;
01091         }
01092 
01093         switch (bm.operation)
01094         {
01095         case LBX_SOURCE1:
01096             value = D3DTOP_SELECTARG1;
01097             break;
01098         case LBX_SOURCE2:
01099             value = D3DTOP_SELECTARG2;
01100             break;
01101         case LBX_MODULATE:
01102             value = D3DTOP_MODULATE;
01103             break;
01104         case LBX_MODULATE_X2:
01105             value = D3DTOP_MODULATE2X;
01106             break;
01107         case LBX_MODULATE_X4:
01108             value = D3DTOP_MODULATE4X;
01109             break;
01110         case LBX_ADD:
01111             value = D3DTOP_ADD;
01112             break;
01113         case LBX_ADD_SIGNED:
01114             value = D3DTOP_ADDSIGNED;
01115             break;
01116         case LBX_ADD_SMOOTH:
01117             value = D3DTOP_ADDSMOOTH;
01118             break;
01119         case LBX_SUBTRACT:
01120             value = D3DTOP_SUBTRACT;
01121             break;
01122         case LBX_BLEND_DIFFUSE_ALPHA:
01123             value = D3DTOP_BLENDDIFFUSEALPHA;
01124             break;
01125         case LBX_BLEND_TEXTURE_ALPHA:
01126             value = D3DTOP_BLENDTEXTUREALPHA;
01127             break;
01128         case LBX_BLEND_CURRENT_ALPHA:
01129             value = D3DTOP_BLENDCURRENTALPHA;
01130             break;
01131         case LBX_BLEND_MANUAL:
01132             value = D3DTOP_BLENDFACTORALPHA;
01133             // Set factor in render state
01134             hr = __SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR,
01135                 D3DRGBA(0,0,0,bm.factor));
01136             break;
01137         case LBX_DOTPRODUCT:
01138             if (mD3DDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
01139                 value = D3DTOP_DOTPRODUCT3;
01140             else
01141                 value = D3DTOP_MODULATE;
01142             break;
01143         }
01144 
01145         // Make call to set operation
01146         hr = __SetTextureStageState(stage, tss, value);
01147 
01148         // Now set up sources
01149         D3DCOLOR manualD3D;
01150         if (bm.blendType == LBT_COLOUR)
01151         {
01152             tss = D3DTSS_COLORARG1;
01153             manualD3D = D3DRGBA(bm.colourArg1.r,bm.colourArg1.g,bm.colourArg1.b,1.0);
01154         }
01155         else if (bm.blendType == LBT_ALPHA)
01156         {
01157             tss = D3DTSS_ALPHAARG1;
01158             manualD3D = D3DRGBA(0,0,0,bm.alphaArg1);
01159         }
01160         LayerBlendSource bs = bm.source1;
01161         for (int i = 0; i < 2; ++i)
01162         {
01163             switch (bs)
01164             {
01165             case LBS_CURRENT:
01166                 value = D3DTA_CURRENT;
01167                 break;
01168             case LBS_TEXTURE:
01169                 value = D3DTA_TEXTURE;
01170                 break;
01171             case LBS_DIFFUSE:
01172                 value = D3DTA_DIFFUSE;
01173                 break;
01174             case LBS_SPECULAR:
01175                 value = D3DTA_SPECULAR;
01176                 break;
01177             case LBS_MANUAL:
01178                 value = D3DTA_TFACTOR;
01179                 // Set factor in render state
01180                 hr = __SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR,    manualD3D);
01181                 break;
01182             }
01183 
01184             // Set source
01185             hr = __SetTextureStageState(stage, tss, value);
01186 
01187             // Source2
01188             bs = bm.source2;
01189             if (bm.blendType == LBT_COLOUR)
01190             {
01191                 tss = D3DTSS_COLORARG2;
01192                 manualD3D = D3DRGBA(bm.colourArg2.r,bm.colourArg2.g,bm.colourArg2.b,1.0);
01193             }
01194             else if (bm.blendType == LBT_ALPHA)
01195             {
01196                 tss = D3DTSS_ALPHAARG2;
01197                 manualD3D = D3DRGBA(0,0,0,bm.alphaArg2);
01198             }
01199         }
01200     }
01201     //-----------------------------------------------------------------------
01202     void D3DRenderSystem::_setTextureAddressingMode(size_t stage, TextureUnitState::TextureAddressingMode tam)
01203     {
01204         HRESULT hr;
01205         D3DTEXTUREADDRESS d3dType;
01206 
01207         switch(tam)
01208         {
01209         case TextureUnitState::TAM_WRAP:
01210             d3dType = D3DTADDRESS_WRAP;
01211             break;
01212         case TextureUnitState::TAM_MIRROR:
01213             d3dType = D3DTADDRESS_MIRROR;
01214             break;
01215         case TextureUnitState::TAM_CLAMP:
01216             d3dType = D3DTADDRESS_CLAMP;
01217             break;
01218         }
01219 
01220 
01221         hr = __SetTextureStageState(stage, D3DTSS_ADDRESS, d3dType);
01222     }
01223     //-----------------------------------------------------------------------
01224     void D3DRenderSystem::_setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
01225     {
01226         HRESULT hr;
01227         D3DBLEND d3dSrcBlend, d3dDestBlend;
01228 
01229         D3DBLEND* pBlend = &d3dSrcBlend;
01230         SceneBlendFactor ogreBlend = sourceFactor;
01231 
01232         for (int i = 0 ; i < 2; ++i)
01233         {
01234             switch(ogreBlend)
01235             {
01236             case SBF_ONE:
01237                 *pBlend = D3DBLEND_ONE;
01238                 break;
01239             case SBF_ZERO:
01240                 *pBlend = D3DBLEND_ZERO;
01241                 break;
01242             case SBF_DEST_COLOUR:
01243                 *pBlend = D3DBLEND_DESTCOLOR;
01244                 break;
01245             case SBF_SOURCE_COLOUR:
01246                 *pBlend = D3DBLEND_SRCCOLOR;
01247                 break;
01248             case SBF_ONE_MINUS_DEST_COLOUR:
01249                 *pBlend = D3DBLEND_INVDESTCOLOR;
01250                 break;
01251             case SBF_ONE_MINUS_SOURCE_COLOUR:
01252                 *pBlend = D3DBLEND_INVSRCCOLOR;
01253                 break;
01254             case SBF_DEST_ALPHA:
01255                 *pBlend = D3DBLEND_DESTALPHA;
01256                 break;
01257             case SBF_SOURCE_ALPHA:
01258                 *pBlend = D3DBLEND_SRCALPHA;
01259                 break;
01260             case SBF_ONE_MINUS_DEST_ALPHA:
01261                 *pBlend = D3DBLEND_INVDESTALPHA;
01262                 break;
01263             case SBF_ONE_MINUS_SOURCE_ALPHA:
01264                 *pBlend = D3DBLEND_INVSRCALPHA;
01265                 break;
01266             }
01267             ogreBlend = destFactor;
01268             pBlend = &d3dDestBlend;
01269 
01270         }
01271 
01272         hr = __SetRenderState(D3DRENDERSTATE_SRCBLEND, d3dSrcBlend);
01273 
01274         hr = __SetRenderState(D3DRENDERSTATE_DESTBLEND, d3dDestBlend);
01275 
01276         // Save last scene blend, because colour write off is simulated 
01277         // through scene blend
01278         mSavedDestFactor = destFactor;
01279         mSavedSrcFactor = sourceFactor;
01280 
01281 
01282     }
01283     //-----------------------------------------------------------------------
01284     void D3DRenderSystem::_setAlphaRejectSettings(CompareFunction func, unsigned char value)
01285     {
01286         HRESULT hr;
01287         if (func != CMPF_ALWAYS_PASS)
01288         {
01289             if( FAILED( hr = __SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE,  TRUE ) ) )
01290                 Except( hr, "Failed to enable alpha testing", 
01291                 "D3DRenderSystem::_setAlphaRejectSettings" );
01292         }
01293         else
01294         {
01295             if( FAILED( hr = __SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE,  FALSE ) ) )
01296                 Except( hr, "Failed to disable alpha testing", 
01297                 "D3DRenderSystem::_setAlphaRejectSettings" );
01298         }
01299 
01300         // Set always just be sure
01301         hr = __SetRenderState(D3DRENDERSTATE_ALPHAFUNC, 
01302             convertCompareFunction(func));
01303 
01304         hr = __SetRenderState(D3DRENDERSTATE_ALPHAREF, value);    
01305     }
01306     //-----------------------------------------------------------------------
01307     void D3DRenderSystem::_setViewport(Viewport *vp)
01308     {
01309         // Check if viewport is different
01310         if (vp != mActiveViewport || vp->_isUpdated())
01311         {
01312             mActiveViewport = vp;
01313             mActiveRenderTarget = vp->getTarget();
01314             // Ok, it's different. Time to set render target (maybe)
01315             //  and viewport params.
01316             D3DVIEWPORT7 d3dvp;
01317             HRESULT hr;
01318 
01319             // Set render target
01320             // TODO - maybe only set when required?
01321             RenderTarget* target;
01322             target = vp->getTarget();
01323             // Get DD Back buffer
01324             LPDIRECTDRAWSURFACE7 pBack;
01325             target->getCustomAttribute("DDBACKBUFFER", &pBack);
01326 
01327             hr = mlpD3DDevice->SetRenderTarget( pBack, 0 );
01328 
01329             _setCullingMode( mCullingMode );
01330 
01331             // Set viewport dimensions
01332             d3dvp.dwX = vp->getActualLeft();
01333             d3dvp.dwY = vp->getActualTop();
01334             d3dvp.dwWidth = vp->getActualWidth();
01335             d3dvp.dwHeight = vp->getActualHeight();
01336 
01337             // Z-values from 0.0 to 1.0 (TODO - standardise with OpenGL?)
01338             d3dvp.dvMinZ = 0.0f;
01339             d3dvp.dvMaxZ = 1.0f;
01340 
01341             hr = mlpD3DDevice->SetViewport(&d3dvp);
01342 
01343             if (FAILED(hr))
01344                 Except(hr, "Error setting D3D viewport.",
01345                 "D3DRenderSystem::_setViewport");
01346 
01347             vp->_clearUpdatedFlag();
01348 
01349         }
01350     }
01351 
01352     //-----------------------------------------------------------------------
01353     void D3DRenderSystem::_beginFrame(void)
01354     {
01355         OgreGuard( "D3DRenderSystem::_beginFrame" );
01356 
01357         HRESULT hr;
01358 
01359         if (!mActiveViewport)
01360             Except(999, "Cannot begin frame - no viewport selected.",
01361             "D3DRenderSystem::_beginFrame");
01362 
01363         // Clear the viewport if required
01364         if (mActiveViewport->getClearEveryFrame())
01365         {
01366             clearFrameBuffer(FBT_COLOUR | FBT_DEPTH, 
01367                 mActiveViewport->getBackgroundColour());
01368         }
01369 
01370         hr = mlpD3DDevice->BeginScene();
01371         if (FAILED(hr))
01372             Except(hr, "Error beginning frame.",
01373             "D3DRenderSystem::_beginFrame");
01374 
01375         // Moved here from _render, no point checking every rendering call
01376         static bool firstTime = true;
01377         if (firstTime)
01378         {
01379             // First-time setup
01380             // Set up some defaults
01381 
01382             // Allow alpha blending
01383             hr = __SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
01384             if (FAILED(hr))
01385                 Except(hr, "Error enabling alpha blending option.",
01386                 "D3DRenderSystem::_beginFrame");
01387 
01388             // Allow specular effects
01389             hr = __SetRenderState(D3DRENDERSTATE_SPECULARENABLE, TRUE);
01390             if (FAILED(hr))
01391                 Except(hr, "Error enabling specular option.",
01392                 "D3DRenderSystem::_beginFrame");
01393 
01394             firstTime = false;
01395         }
01396 
01397         OgreUnguard();
01398     }
01399 
01400     //-----------------------------------------------------------------------
01401     void D3DRenderSystem::_render(const RenderOperation& op)
01402     {
01403         OgreGuard( "D3DRenderSystem::_render" );
01404         HRESULT hr;
01405 
01406         // Exit immediately if there is nothing to render
01407         // This caused a problem on FireGL 8800
01408         if (op.vertexData->vertexCount == 0)
01409             return;
01410 
01411         // call superclass
01412         RenderSystem::_render(op);
01413         // Set up vertex flags
01414         DWORD d3dVertexFormat = 0;
01415         unsigned int numTexCoords = 0;
01416 
01417         // Assume no more than 10 buffers!
01418         static unsigned char* pBufPtrs[10];
01419 
01420         // Lock all the buffers first
01421         // They're system memory buffers anyway
01422         const VertexBufferBinding::VertexBufferBindingMap binds = 
01423             op.vertexData->vertexBufferBinding->getBindings();
01424         VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi, bindend;
01425         bindend = binds.end();
01426         for (bindi = binds.begin(); bindi != bindend; ++bindi)
01427         {
01428             // lock from vertex start only
01429             pBufPtrs[bindi->first] = static_cast<unsigned char*>(
01430                 bindi->second->lock(
01431                     op.vertexData->vertexStart * bindi->second->getVertexSize(),
01432                     op.vertexData->vertexCount * bindi->second->getVertexSize(),
01433                     HardwareBuffer::HBL_READ_ONLY)
01434                     );
01435 
01436         }
01437 
01438         // Determine vertex format
01439 
01440         // Struct for data pointers
01441         D3DDRAWPRIMITIVESTRIDEDDATA strideData;
01442 
01443         // Iterate over elements
01444         VertexDeclaration::VertexElementList::const_iterator elemi, elemend;
01445         const VertexDeclaration::VertexElementList elems = 
01446             op.vertexData->vertexDeclaration->getElements();
01447         elemend = elems.end();
01448         for (elemi = elems.begin(); elemi != elemend; ++elemi)
01449         {
01450             // Get a few basic details
01451             const VertexElement& elem = *elemi;
01452             unsigned short source = elem.getSource();
01453             size_t vertexSize = op.vertexData->vertexDeclaration->getVertexSize(source);
01454             size_t offset = elem.getOffset();
01455             // semantic-specific stuff
01456             switch (elem.getSemantic())
01457             {
01458             case VES_POSITION:
01459                 d3dVertexFormat |= D3DFVF_XYZ; // Untransformed  
01460                 strideData.position.lpvData = pBufPtrs[source] + offset;
01461                 strideData.position.dwStride = static_cast<DWORD>(vertexSize);
01462                 // Set up pointer
01463                 break;
01464             case VES_NORMAL:
01465                 d3dVertexFormat |= D3DFVF_NORMAL; 
01466                 strideData.normal.lpvData = pBufPtrs[source] + offset;
01467                 strideData.normal.dwStride = static_cast<DWORD>(vertexSize);
01468                 break;
01469             case VES_DIFFUSE:
01470                 d3dVertexFormat |= D3DFVF_DIFFUSE; 
01471                 strideData.diffuse.lpvData = pBufPtrs[source] + offset;
01472                 strideData.diffuse.dwStride = static_cast<DWORD>(vertexSize);
01473                 break;
01474             case VES_SPECULAR:
01475                 d3dVertexFormat |= D3DFVF_SPECULAR; 
01476                 strideData.specular.lpvData = pBufPtrs[source] + offset;
01477                 strideData.specular.dwStride = static_cast<DWORD>(vertexSize);
01478                 break;
01479             case VES_TEXTURE_COORDINATES:
01480                 // texcoords must go in order
01481                 if (elem.getIndex() != numTexCoords)
01482                 {
01483                     Except(Exception::ERR_INVALIDPARAMS, "Invalid vertex format, texture coordinates"
01484                         " must be in order wih no gaps.", "D3DRenderSystem::_render");
01485                 }
01486                 // Don't add D3DFVF_TEXn flag here, wait until we know how many total
01487                 // However, specify size
01488                 switch (elem.getType())
01489                 {
01490                 case VET_FLOAT1:
01491                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE1(numTexCoords);
01492                     break;
01493                 case VET_FLOAT2:
01494                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE2(numTexCoords);
01495                     break;
01496                 case VET_FLOAT3:
01497                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE3(numTexCoords);
01498                     break;
01499                 case VET_FLOAT4:
01500                     d3dVertexFormat |= D3DFVF_TEXCOORDSIZE4(numTexCoords);
01501                     break;
01502                 }
01503 
01504                 strideData.textureCoords[numTexCoords].lpvData = pBufPtrs[source] + offset;
01505                 strideData.textureCoords[numTexCoords].dwStride = static_cast<DWORD>(vertexSize);
01506 
01507                 // Increment number of coords
01508                 ++numTexCoords;
01509             }
01510 
01511         }
01512         // Add combined texture flag
01513         switch(numTexCoords)
01514         {
01515             case 0: 
01516                 // do nothing
01517                 break;
01518             case 1:
01519                 d3dVertexFormat |= D3DFVF_TEX1;
01520                 break;
01521             case 2:
01522                 d3dVertexFormat |= D3DFVF_TEX2;
01523                 break;
01524             case 3:
01525                 d3dVertexFormat |= D3DFVF_TEX3;
01526                 break;
01527             case 4:
01528                 d3dVertexFormat |= D3DFVF_TEX4;
01529                 break;
01530             case 5:
01531                 d3dVertexFormat |= D3DFVF_TEX5;
01532                 break;
01533             case 6:
01534                 d3dVertexFormat |= D3DFVF_TEX6;
01535                 break;
01536             case 7:
01537                 d3dVertexFormat |= D3DFVF_TEX7;
01538                 break;
01539             case 8:
01540                 d3dVertexFormat |= D3DFVF_TEX8;
01541                 break;
01542         }
01543 
01544         // Determine rendering operation
01545         D3DPRIMITIVETYPE primType;
01546         switch (op.operationType)
01547         {
01548         case RenderOperation::OT_POINT_LIST:
01549             primType = D3DPT_POINTLIST;
01550             break;
01551         case RenderOperation::OT_LINE_LIST:
01552             primType = D3DPT_LINELIST;
01553             break;
01554         case RenderOperation::OT_LINE_STRIP:
01555             primType = D3DPT_LINESTRIP;
01556             break;
01557         case RenderOperation::OT_TRIANGLE_LIST:
01558             primType = D3DPT_TRIANGLELIST;
01559             break;
01560         case RenderOperation::OT_TRIANGLE_STRIP:
01561             primType = D3DPT_TRIANGLESTRIP;
01562             break;
01563         case RenderOperation::OT_TRIANGLE_FAN:
01564             primType = D3DPT_TRIANGLEFAN;
01565             break;
01566         }
01567 
01568 
01569         if (op.useIndexes)
01570         {
01571             // Get pointer to index buffer
01572             // D3D7 only allows 16-bit indexes, this is enforced in buffer manager
01573             unsigned short* pIdx = static_cast<unsigned short*>(
01574                 op.indexData->indexBuffer->lock(
01575                     op.indexData->indexStart,
01576                     op.indexData->indexCount * sizeof(unsigned short),
01577                     HardwareBuffer::HBL_READ_ONLY) );
01578 
01579             hr = mlpD3DDevice->DrawIndexedPrimitiveStrided(primType,
01580                 d3dVertexFormat, 
01581                 &strideData, 
01582                 static_cast<DWORD>(op.vertexData->vertexCount),
01583                 pIdx, 
01584                 static_cast<DWORD>(op.indexData->indexCount)
01585                 , 0);
01586         }
01587         else
01588         {
01589             hr = mlpD3DDevice->DrawPrimitiveStrided(primType,
01590                 d3dVertexFormat, 
01591                 &strideData, 
01592                 static_cast<DWORD>(op.vertexData->vertexCount),
01593                 0);
01594         }
01595 
01596         // unlock buffers
01597         for (bindi = binds.begin(); bindi != bindend; ++bindi)
01598         {
01599             bindi->second->unlock();
01600         }
01601 
01602         if (FAILED(hr))
01603         {
01604             char szBuffer[512];
01605             D3DXGetErrorString( hr, 512, szBuffer );
01606             Except( hr, szBuffer, "D3DRenderSystem::_render");
01607         }
01608 
01609 
01610 
01611 
01612         OgreUnguard();
01613     }
01614 
01615     //-----------------------------------------------------------------------
01616     void D3DRenderSystem::_endFrame(void)
01617     {
01618         OgreGuard( "D3DRenderSystem::_endFrame" );
01619 
01620         HRESULT hr;
01621         hr = mlpD3DDevice->EndScene();
01622 
01623         if (FAILED(hr))
01624             Except(hr, "Error ending frame.",
01625             "D3DRenderSystem::_endFrame");
01626 
01627         OgreUnguard();
01628     }
01629 
01630     //-----------------------------------------------------------------------
01631     void D3DRenderSystem::_setCullingMode(CullingMode mode)
01632     {
01633         HRESULT hr;
01634         DWORD d3dMode;
01635 
01636         mCullingMode = mode;
01637 
01638         if (mode == CULL_NONE)
01639         {
01640             d3dMode = D3DCULL_NONE;
01641         }
01642         else if( mode == CULL_CLOCKWISE )
01643         {
01644             if( (mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
01645                 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding))
01646                 d3dMode = D3DCULL_CCW;
01647             else
01648                 d3dMode = D3DCULL_CW;
01649         }
01650         else if (mode == CULL_ANTICLOCKWISE)
01651         {
01652             if( (mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
01653                 (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding))
01654                 d3dMode = D3DCULL_CW;
01655             else
01656                 d3dMode = D3DCULL_CCW;
01657         }
01658 
01659         hr = __SetRenderState(D3DRENDERSTATE_CULLMODE, d3dMode);
01660         if (FAILED(hr))
01661             Except(hr, "Unable to set D3D culling mode.",
01662             "D3DRenderSystem::_setCullingMode");
01663 
01664     }
01665 
01666     //-----------------------------------------------------------------------
01667     void D3DRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
01668     {
01669         _setDepthBufferCheckEnabled(depthTest);
01670         _setDepthBufferWriteEnabled(depthWrite);
01671         _setDepthBufferFunction(depthFunction);
01672 
01673     }
01674     //-----------------------------------------------------------------------
01675     void D3DRenderSystem::_setDepthBufferCheckEnabled(bool enabled)
01676     {
01677         HRESULT hr;
01678 
01679         if (enabled)
01680         {
01681             // Use w-buffer if available
01682             if (mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_WBUFFER)
01683                 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_USEW);
01684             else
01685                 hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
01686             if (FAILED(hr))
01687                 Except(hr, "Error setting depth buffer test state.",
01688                 "D3DRenderSystem::_setDepthBufferCheckEnabled");
01689         }
01690         else
01691         {
01692             hr = __SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
01693             if (FAILED(hr))
01694                 Except(hr, "Error setting depth buffer test state.",
01695                 "D3DRenderSystem::_setDepthBufferCheckEnabled");
01696         }
01697     }
01698     //-----------------------------------------------------------------------
01699     void D3DRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
01700     {
01701         HRESULT hr;
01702 
01703         hr = __SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, enabled);
01704         if (FAILED(hr))
01705             Except(hr, "Error setting depth buffer write state.",
01706             "D3DRenderSystem::_setDepthBufferWriteEnabled");
01707     }
01708     //-----------------------------------------------------------------------
01709     void D3DRenderSystem::_setDepthBufferFunction(CompareFunction func)
01710     {
01711         HRESULT hr = __SetRenderState(D3DRENDERSTATE_ZFUNC, 
01712             convertCompareFunction(func));
01713         if (FAILED(hr))
01714             Except(hr, "Error setting depth buffer test function.",
01715             "D3DRenderSystem::_setDepthBufferFunction");
01716     }
01717     //-----------------------------------------------------------------------
01718     void D3DRenderSystem::_setDepthBias(ushort bias)
01719     {
01720         HRESULT hr = __SetRenderState(D3DRENDERSTATE_ZBIAS, 
01721             bias);
01722         if (FAILED(hr))
01723             Except(hr, "Error setting depth bias.",
01724             "D3DRenderSystem::_setDepthBias");
01725     }
01726     //-----------------------------------------------------------------------
01727     String D3DRenderSystem::getErrorDescription(long errCode) const
01728     {
01729         char* errDesc;
01730         DWORD i;
01731 
01732         errDesc = new char[255];
01733         // Try windows errors first
01734         i = FormatMessage(
01735             FORMAT_MESSAGE_FROM_HMODULE |
01736             FORMAT_MESSAGE_FROM_SYSTEM |
01737             FORMAT_MESSAGE_IGNORE_INSERTS,
01738             NULL,
01739             DDERR_SURFACELOST,
01740             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
01741             (LPTSTR) errDesc,
01742             255,
01743             NULL
01744             );
01745 
01746 
01747         if (i == 0)
01748         {
01749             // Not found in windows message descriptions
01750             switch (errCode)
01751             {
01752             case DD_OK:
01753                 strcpy(errDesc, "DD_OK: The request completed successfully.");
01754                 break;
01755             case DDERR_ALREADYINITIALIZED:
01756                 strcpy(errDesc, "DDERR_ALREADYINITIALIZED: The object has already been initialized.");
01757                 break;
01758             case DDERR_BLTFASTCANTCLIP :
01759                 strcpy(errDesc, "DDERR_BLTFASTCANTCLIP: A DirectDrawClipper object is attached to a source surface that has passed into a call to the IDirectDrawSurface7::BltFast method.");
01760                 break;
01761             case DDERR_CANNOTATTACHSURFACE:
01762                 strcpy(errDesc, "DDERR_CANNOTATTACHSURFACE: A surface cannot be attached to another requested surface.");
01763                 break;
01764             case DDERR_CANNOTDETACHSURFACE:
01765                 strcpy(errDesc, "DDERR_CANNOTATTACHSURFACE: A surface cannot be detached from another requested surface.");
01766                 break;
01767             case DDERR_CANTCREATEDC:
01768                 strcpy(errDesc, "DDERR_CANTCREATEDC: Windows can not create any more device contexts (DCs), or a DC was requested for a palette-indexed surface when the surface had no palette and the display mode was not palette-indexed.");
01769                 break;
01770             case DDERR_CANTDUPLICATE:
01771                 strcpy(errDesc, "DDERR_CANTDUPLICATE: Primary and 3-D surfaces, or surfaces that are implicitly created, cannot be duplicated.");
01772                 break;
01773             case DDERR_CANTLOCKSURFACE:
01774                 strcpy(errDesc, "DDERR_CANTLOCKSURFACE: Access to this surface is refused because an attempt was made to lock the primary surface without DCI support.");
01775                 break;
01776             case DDERR_CANTPAGELOCK:
01777                 strcpy(errDesc, "DDERR_CANTPAGELOCK: An attempt to page lock a surface failed. Page lock will not work on a display-memory surface or an emulated primary surface.");
01778                 break;
01779             case DDERR_CANTPAGEUNLOCK:
01780                 strcpy(errDesc, "DDERR_CANTPAGEUNLOCK: An attempt to page unlock a surface failed. Page unlock will not work on a display-memory surface or an emulated primary surface.");
01781                 break;
01782             case DDERR_CLIPPERISUSINGHWND:
01783                 strcpy(errDesc, "DDERR_CLIPPERISUSINGHWND: An attempt was made to set a clip list for a DirectDrawClipper object that is already monitoring a window handle.");
01784                 break;
01785             case DDERR_COLORKEYNOTSET:
01786                 strcpy(errDesc, "DDERR_COLORKEYNOTSET: No source color key is specified for this operation.");
01787                 break;
01788             case DDERR_CURRENTLYNOTAVAIL:
01789                 strcpy(errDesc, "DDERR_CURRENTLYNOTAVAIL: No support is currently available.");
01790                 break;
01791             case DDERR_DCALREADYCREATED:
01792                 strcpy(errDesc, "DDERR_DCALREADYCREATED: A device context (DC) has already been returned for this surface. Only one DC can be retrieved for each surface.");
01793                 break;
01794             case DDERR_DEVICEDOESNTOWNSURFACE:
01795                 strcpy(errDesc, "DDERR_DEVICEDOESNTOWNSURFACE: Surfaces created by one DirectDraw device cannot be used directly by another DirectDraw device.");
01796                 break;
01797             case DDERR_DIRECTDRAWALREADYCREATED:
01798                 strcpy(errDesc, "DDERR_DIRECTDRAWALREADYCREATED: A DirectDraw object representing this driver has already been created for this process.");
01799                 break;
01800             case DDERR_EXCEPTION:
01801                 strcpy(errDesc, "DDERR_EXCEPTION: An exception was encountered while performing the requested operation.");
01802                 break;
01803             case DDERR_EXCLUSIVEMODEALREADYSET:
01804                 strcpy(errDesc, "DDERR_EXCLUSIVEMODEALREADYSET: An attempt was made to set the cooperative level when it was already set to exclusive.");
01805                 break;
01806             case DDERR_EXPIRED:
01807                 strcpy(errDesc, "DDERR_EXPIRED: The data has expired and is therefore no longer valid.");
01808                 break;
01809             case DDERR_GENERIC:
01810                 strcpy(errDesc, "DDERR_GENERIC: There is an undefined error condition.");
01811                 break;
01812             case DDERR_HEIGHTALIGN:
01813                 strcpy(errDesc, "DDERR_HEIGHTALIGN: The height of the provided rectangle is not a multiple of the required alignment.");
01814                 break;
01815             case DDERR_HWNDALREADYSET:
01816                 strcpy(errDesc, "DDERR_HWNDALREADYSET: The DirectDraw cooperative level window handle has already been set. It cannot be reset while the process has surfaces or palettes created.");
01817                 break;
01818             case DDERR_HWNDSUBCLASSED:
01819                 strcpy(errDesc, "DDERR_HWNDSUBCLASSED: DirectDraw is prevented from restoring state because the DirectDraw cooperative level window handle has been subclassed.");
01820                 break;
01821             case DDERR_IMPLICITLYCREATED:
01822                 strcpy(errDesc, "DDERR_IMPLICITLYCREATED: The surface cannot be restored because it is an implicitly created surface.");
01823                 break;
01824             case DDERR_INCOMPATIBLEPRIMARY:
01825                 strcpy(errDesc, "DDERR_INCOMPATIBLEPRIMARY: The primary surface creation request does not match with the existing primary surface.");
01826                 break;
01827             case DDERR_INVALIDCAPS:
01828                 strcpy(errDesc, "DDERR_INVALIDCAPS: One or more of the capability bits passed to the callback function are incorrect.");
01829                 break;
01830             case DDERR_INVALIDCLIPLIST:
01831                 strcpy(errDesc, "DDERR_INVALIDCLIPLIST: DirectDraw does not support the provided clip list.");
01832                 break;
01833             case DDERR_INVALIDDIRECTDRAWGUID:
01834                 strcpy(errDesc, "DDERR_INVALIDDIRECTDRAWGUID: The globally unique identifier (GUID) passed to the DirectDrawCreate function is not a valid DirectDraw driver identifier.");
01835                 break;
01836             case DDERR_INVALIDMODE:
01837                 strcpy(errDesc, "DDERR_INVALIDMODE: DirectDraw does not support the requested mode.");
01838                 break;
01839             case DDERR_INVALIDOBJECT:
01840                 strcpy(errDesc, "DDERR_INVALIDOBJECT: DirectDraw received a pointer that was an invalid DirectDraw object.");
01841                 break;
01842             case DDERR_INVALIDPARAMS:
01843                 strcpy(errDesc, "DDERR_INVALIDPARAMS: One or more of the parameters passed to the method are incorrect.");
01844                 break;
01845             case DDERR_INVALIDPIXELFORMAT:
01846                 strcpy(errDesc, "DDERR_INVALIDPIXELFORMAT: The pixel format was invalid as specified.");
01847                 break;
01848             case DDERR_INVALIDPOSITION:
01849                 strcpy(errDesc, "DDERR_INVALIDPOSITION: The position of the overlay on the destination is no longer legal.");
01850                 break;
01851             case DDERR_INVALIDRECT:
01852                 strcpy(errDesc, "DDERR_INVALIDRECT: The provided rectangle was invalid.");
01853                 break;
01854             case DDERR_INVALIDSTREAM:
01855                 strcpy(errDesc, "DDERR_INVALIDSTREAM: The specified stream contains invalid data.");
01856                 break;
01857             case DDERR_INVALIDSURFACETYPE:
01858                 strcpy(errDesc, "DDERR_INVALIDSURFACETYPE: The requested operation could not be performed because the surface was of the wrong type.");
01859                 break;
01860             case DDERR_LOCKEDSURFACES:
01861                 strcpy(errDesc, "DDERR_LOCKEDSURFACES: One or more surfaces are locked, causing the failure of the requested operation.");
01862                 break;
01863             case DDERR_MOREDATA:
01864                 strcpy(errDesc, "DDERR_MOREDATA: There is more data available than the specified buffer size can hold.");
01865                 break;
01866             case DDERR_NO3D:
01867                 strcpy(errDesc, "DDERR_NO3D: No 3-D hardware or emulation is present.");
01868                 break;
01869             case DDERR_NOALPHAHW:
01870                 strcpy(errDesc, "DDERR_NOALPHAHW: No alpha acceleration hardware is present or available, causing the failure of the requested operation.");
01871                 break;
01872             case DDERR_NOBLTHW:
01873                 strcpy(errDesc, "DDERR_NOBLTHW: No blitter hardware is present.");
01874                 break;
01875             case DDERR_NOCLIPLIST:
01876                 strcpy(errDesc, "DDERR_NOCLIPLIST: No clip list is available.");
01877                 break;
01878             case DDERR_NOCLIPPERATTACHED:
01879                 strcpy(errDesc, "DDERR_NOCLIPPERATTACHED: No DirectDrawClipper object is attached to the surface object.");
01880                 break;
01881             case DDERR_NOCOLORCONVHW:
01882                 strcpy(errDesc, "DDERR_NOCOLORCONVHW: The operation cannot be carried out because no color-conversion hardware is present or available.");
01883                 break;
01884             case DDERR_NOCOLORKEY:
01885                 strcpy(errDesc, "DDERR_NOCOLORKEY: The surface does not currently have a color key.");
01886                 break;
01887             case DDERR_NOCOLORKEYHW:
01888                 strcpy(errDesc, "DDERR_NOCOLORKEYHW: The operation cannot be carried out because there is no hardware support for the destination color key.");
01889                 break;
01890             case DDERR_NOCOOPERATIVELEVELSET:
01891                 strcpy(errDesc, "DDERR_NOCOOPERATIVELEVELSET: A create function is called without the IDirectDraw7::SetCooperativeLevel method being called.");
01892                 break;
01893             case DDERR_NODC:
01894                 strcpy(errDesc, "DDERR_NODC: No DC has ever been created for this surface.");
01895                 break;
01896             case DDERR_NODDROPSHW:
01897                 strcpy(errDesc, "DDERR_NODDROPSHW: No DirectDraw raster operation (ROP) hardware is available.");
01898                 break;
01899             case DDERR_NODIRECTDRAWHW:
01900                 strcpy(errDesc, "DDERR_NODIRECTDRAWHW: Hardware-only DirectDraw object creation is not possible; the driver does not support any hardware.");
01901                 break;
01902             case DDERR_NODIRECTDRAWSUPPORT:
01903                 strcpy(errDesc, "DDERR_NODIRECTDRAWSUPPORT: DirectDraw support is not possible with the current display driver.");
01904                 break;
01905             case DDERR_NOEMULATION:
01906                 strcpy(errDesc, "DDERR_NOEMULATION: Software emulation is not available.");
01907                 break;
01908             case DDERR_NOEXCLUSIVEMODE:
01909                 strcpy(errDesc, "DDERR_NOEXCLUSIVEMODE: The operation requires the application to have exclusive mode, but the application does not have exclusive mode.");
01910                 break;
01911             case DDERR_NOFLIPHW:
01912                 strcpy(errDesc, "DDERR_NOFLIPHW: Flipping visible surfaces is not supported.");
01913                 break;
01914             case DDERR_NOFOCUSWINDOW:
01915                 strcpy(errDesc, "DDERR_NOFOCUSWINDOW: An attempt was made to create or set a device window without first setting the focus window.");
01916                 break;
01917             case DDERR_NOGDI:
01918                 strcpy(errDesc, "DDERR_NOGDI: No GDI is present.");
01919                 break;
01920             case DDERR_NOHWND:
01921                 strcpy(errDesc, "DDERR_NOHWND: Clipper notification requires a window handle, or no window handle has been previously set as the cooperative level window handle.");
01922                 break;
01923             case DDERR_NOMIPMAPHW:
01924                 strcpy(errDesc, "DDERR_NOMIPMAPHW: The operation cannot be carried out because no mipmap capable texture mapping hardware is present or available.");
01925                 break;
01926             case DDERR_NOMIRRORHW:
01927                 strcpy(errDesc, "DDERR_NOMIRRORHW: The operation cannot be carried out because no mirroring hardware is present or available.");
01928                 break;
01929             case DDERR_NONONLOCALVIDMEM:
01930                 strcpy(errDesc, "DDERR_NONONLOCALVIDMEM: An attempt was made to allocate non-local video memory from a device that does not support non-local video memory.");
01931                 break;
01932             case DDERR_NOOPTIMIZEHW:
01933                 strcpy(errDesc, "DDERR_NOOPTIMIZEHW: The device does not support optimized surfaces.");
01934                 break;
01935             case DDERR_NOOVERLAYDEST:
01936                 strcpy(errDesc, "DDERR_NOOVERLAYDEST: The IDirectDrawSurface4::GetOverlayPosition method is called on an overlay that the IDirectDrawSurface7::UpdateOverlay method has not been called on to establish a destination.");
01937                 break;
01938             case DDERR_NOOVERLAYHW:
01939                 strcpy(errDesc, "DDERR_NOOVERLAYHW: The operation cannot be carried out because no overlay hardware is present or available.");
01940                 break;
01941             case DDERR_NOPALETTEATTACHED:
01942                 strcpy(errDesc, "DDERR_NOPALETTEATTACHED: No palette object is attached to this surface.");
01943                 break;
01944             case DDERR_NOPALETTEHW:
01945                 strcpy(errDesc, "DDERR_NOPALETTEHW: There is no hardware support for 16- or 256-color palettes.");
01946                 break;
01947             case DDERR_NORASTEROPHW:
01948                 strcpy(errDesc, "DDERR_NORASTEROPHW: The operation cannot be carried out because no appropriate raster operation hardware is present or available.");
01949                 break;
01950             case DDERR_NOROTATIONHW:
01951                 strcpy(errDesc, "DDERR_NOROTATIONHW: The operation cannot be carried out because no rotation hardware is present or available.");
01952                 break;
01953             case DDERR_NOSTRETCHHW:
01954                 strcpy(errDesc, "DDERR_NOSTRETCHHW: The operation cannot be carried out because there is no hardware support for stretching.");
01955                 break;
01956             case DDERR_NOT4BITCOLOR:
01957                 strcpy(errDesc, "DDERR_NOT4BITCOLOR: The DirectDrawSurface object is not using a 4-bit color palette and the requested operation requires a 4-bit color palette.");
01958                 break;
01959             case DDERR_NOT4BITCOLORINDEX:
01960                 strcpy(errDesc, "DDERR_NOT4BITCOLORINDEX: The DirectDrawSurface object is not using a 4-bit color index palette and the requested operation requires a 4-bit color index palette.");
01961                 break;
01962             case DDERR_NOT8BITCOLOR:
01963                 strcpy(errDesc, "DDERR_NOT8BITCOLOR: The DirectDrawSurface object is not using an 8-bit color palette and the requested operation requires an 8-bit color palette.");
01964                 break;
01965             case DDERR_NOTAOVERLAYSURFACE:
01966                 strcpy(errDesc, "DDERR_NOTAOVERLAYSURFACE: An overlay component is called for a non-overlay surface.");
01967                 break;
01968             case DDERR_NOTEXTUREHW:
01969                 strcpy(errDesc, "DDERR_NOTEXTUREHW: The operation cannot be carried out because no texture-mapping hardware is present or available.");
01970                 break;
01971             case DDERR_NOTFLIPPABLE:
01972                 strcpy(errDesc, "DDERR_NOTFLIPPABLE: An attempt has been made to flip a surface that cannot be flipped.");
01973                 break;
01974             case DDERR_NOTFOUND:
01975                 strcpy(errDesc, "DDERR_NOTFOUND: The requested item was not found.");
01976                 break;
01977             case DDERR_NOTINITIALIZED:
01978                 strcpy(errDesc, "DDERR_NOTINITIALIZED: An attempt was made to call an interface method of a DirectDraw object created by CoCreateInstance before the object was initialized.");
01979                 break;
01980             case DDERR_NOTLOADED:
01981                 strcpy(errDesc, "DDERR_NOTLOADED: The surface is an optimized surface, but it has not yet been allocated any memory.");
01982                 break;
01983             case DDERR_NOTLOCKED:
01984                 strcpy(errDesc, "DDERR_NOTLOCKED: An attempt is made to unlock a surface that was not locked.");
01985                 break;
01986             case DDERR_NOTPAGELOCKED:
01987                 strcpy(errDesc, "DDERR_NOTPAGELOCKED: An attempt is made to page unlock a surface with no outstanding page locks.");
01988                 break;
01989             case DDERR_NOTPALETTIZED:
01990                 strcpy(errDesc, "DDERR_NOTPALETTIZED: The surface being used is not a palette-based surface.");
01991                 break;
01992             case DDERR_NOVSYNCHW:
01993                 strcpy(errDesc, "DDERR_NOVSYNCHW: The operation cannot be carried out because there is no hardware support for vertical blank synchronized operations.");
01994                 break;
01995             case DDERR_NOZBUFFERHW:
01996                 strcpy(errDesc, "DDERR_NOZBUFFERHW: The operation to create a z-buffer in display memory or to perform a blit using a z-buffer cannot be carried out because there is no hardware support for z-buffers.");
01997                 break;
01998             case DDERR_NOZOVERLAYHW:
01999                 strcpy(errDesc, "DDERR_NOZOVERLAYHW: The overlay surfaces cannot be z-layered based on the z-order because the hardware does not support z-ordering of overlays.");
02000                 break;
02001             case DDERR_OUTOFCAPS:
02002                 strcpy(errDesc, "DDERR_OUTOFCAPS: The hardware needed for the requested operation has already been allocated.");
02003                 break;
02004             case DDERR_OUTOFMEMORY:
02005                 strcpy(errDesc, "DDERR_OUTOFMEMORY: DirectDraw does not have enough memory to perform the operation.");
02006                 break;
02007             case DDERR_OUTOFVIDEOMEMORY:
02008                 strcpy(errDesc, "DDERR_OUTOFVIDEOMEMORY: DirectDraw does not have enough display memory to perform the operation.");
02009                 break;
02010             case DDERR_OVERLAPPINGRECTS:
02011                 strcpy(errDesc, "DDERR_OVERLAPPINGRECTS: Operation could not be carried out because the source and destination rectangles are on the same surface and overlap each other.");
02012                 break;
02013             case DDERR_OVERLAYCANTCLIP:
02014                 strcpy(errDesc, "DDERR_OVERLAYCANTCLIP: The hardware does not support clipped overlays.");
02015                 break;
02016             case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
02017                 strcpy(errDesc, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE: An attempt was made to have more than one color key active on an overlay.");
02018                 break;
02019             case DDERR_OVERLAYNOTVISIBLE:
02020                 strcpy(errDesc, "DDERR_OVERLAYNOTVISIBLE: The IDirectDrawSurface7::GetOverlayPosition method is called on a hidden overlay.");
02021                 break;
02022             case DDERR_PALETTEBUSY:
02023                 strcpy(errDesc, "DDERR_PALETTEBUSY: Access to this palette is refused because the palette is locked by another thread.");
02024                 break;
02025             case DDERR_PRIMARYSURFACEALREADYEXISTS:
02026                 strcpy(errDesc, "DDERR_PRIMARYSURFACEALREADYEXISTS: This process has already created a primary surface.");
02027                 break;
02028             case DDERR_REGIONTOOSMALL:
02029                 strcpy(errDesc, "DDERR_REGIONTOOSMALL: The region passed to the IDirectDrawClipper::GetClipList method is too small.");
02030                 break;
02031             case DDERR_SURFACEALREADYATTACHED:
02032                 strcpy(errDesc, "DDERR_SURFACEALREADYATTACHED: An attempt was made to attach a surface to another surface to which it is already attached.");
02033                 break;
02034             case DDERR_SURFACEALREADYDEPENDENT:
02035                 strcpy(errDesc, "DDERR_SURFACEALREADYDEPENDENT: An attempt was made to make a surface a dependency of another surface to which it is already dependent.");
02036                 break;
02037             case DDERR_SURFACEBUSY:
02038                 strcpy(errDesc, "DDERR_SURFACEBUSY: Access to the surface is refused because the surface is locked by another thread.");
02039                 break;
02040             case DDERR_SURFACEISOBSCURED:
02041                 strcpy(errDesc, "DDERR_SURFACEISOBSCURED: Access to the surface is refused because the surface is obscured.");
02042                 break;
02043             case DDERR_SURFACELOST:
02044                 strcpy(errDesc, "DDERR_SURFACELOST: Access to the surface is refused because the surface memory is gone. Call the IDirectDrawSurface7::Restore method on this surface to restore the memory associated with it.");
02045                 break;
02046             case DDERR_SURFACENOTATTACHED:
02047                 strcpy(errDesc, "DDERR_SURFACENOTATTACHED: The requested surface is not attached.");
02048                 break;
02049             case DDERR_TOOBIGHEIGHT:
02050                 strcpy(errDesc, "DDERR_TOOBIGHEIGHT: The height requested by DirectDraw is too large.");
02051                 break;
02052             case DDERR_TOOBIGSIZE:
02053                 strcpy(errDesc, "DDERR_TOOBIGSIZE: The size requested by DirectDraw is too large. However, the individual height and width are valid sizes.");
02054                 break;
02055             case DDERR_TOOBIGWIDTH:
02056                 strcpy(errDesc, "DDERR_TOOBIGWIDTH: The width requested by DirectDraw is too large.");
02057                 break;
02058             case DDERR_UNSUPPORTED:
02059                 strcpy(errDesc, "DDERR_UNSUPPORTED: The operation is not supported.");
02060                 break;
02061             case DDERR_UNSUPPORTEDFORMAT:
02062                 strcpy(errDesc, "DDERR_UNSUPPORTEDFORMAT: The FourCC format requested is not supported by DirectDraw.");
02063                 break;
02064             case DDERR_UNSUPPORTEDMASK:
02065                 strcpy(errDesc, "DDERR_UNSUPPORTEDMASK: The bitmask in the pixel format requested is not supported by DirectDraw.");
02066                 break;
02067             case DDERR_UNSUPPORTEDMODE:
02068                 strcpy(errDesc, "DDERR_UNSUPPORTEDMODE: The display is currently in an unsupported mode.");
02069                 break;
02070             case DDERR_VERTICALBLANKINPROGRESS:
02071                 strcpy(errDesc, "DDERR_VERTICALBLANKINPROGRESS: A vertical blank is in progress.");
02072                 break;
02073             case DDERR_VIDEONOTACTIVE:
02074                 strcpy(errDesc, "DDERR_VIDEONOTACTIVE: The video port is not active.");
02075                 break;
02076             case DDERR_WASSTILLDRAWING:
02077                 strcpy(errDesc, "DDERR_WASSTILLDRAWING: The previous blit operation that is transferring information to or from this surface is incomplete.");
02078                 break;
02079             case DDERR_WRONGMODE:
02080                 strcpy(errDesc, "DDERR_WRONGMODE: This surface cannot be restored because it was created in a different mode.");
02081                 break;
02082             case DDERR_XALIGN:
02083                 strcpy(errDesc, "DDERR_XALIGN: The provided rectangle was not horizontally aligned on a required boundary.");
02084                 break;
02085             default:
02086                 strcpy(errDesc, "Unknown error code.");
02087             }
02088         }
02089         return errDesc;
02090     }
02091 
02092     /*
02093     D3D_OK
02094     D3DERR_BADMAJORVERSION
02095     D3DERR_BADMINORVERSION
02096     D3DERR_COLORKEYATTACHED
02097     D3DERR_CONFLICTINGTEXTUREFILTER
02098     D3DERR_CONFLICTINGTEXTUREPALETTE
02099     D3DERR_CONFLICTINGRENDERSTATE
02100     D3DERR_DEVICEAGGREGATED (new for DirectX 5.0)
02101     D3DERR_EXECUTE_CLIPPED_FAILED
02102     D3DERR_EXECUTE_CREATE_FAILED
02103     D3DERR_EXECUTE_DESTROY_FAILED
02104     D3DERR_EXECUTE_FAILED
02105     D3DERR_EXECUTE_LOCK_FAILED
02106     D3DERR_EXECUTE_LOCKED
02107     D3DERR_EXECUTE_NOT_LOCKED
02108     D3DERR_EXECUTE_UNLOCK_FAILED
02109     D3DERR_INITFAILED (new for DirectX 5.0)
02110     D3DERR_INBEGIN (new for DirectX 5.0)
02111     D3DERR_INVALID_DEVICE (new for DirectX 5.0)
02112     D3DERR_INVALIDCURRENTVIEWPORT (new for DirectX 5.0)
02113     D3DERR_INVALIDMATRIX
02114     D3DERR_INVALIDPALETTE(new for DirectX 5.0)
02115     D3DERR_INVALIDPRIMITIVETYPE (new for DirectX 5.0)
02116     D3DERR_INVALIDRAMPTEXTURE (new for DirectX 5.0)
02117     D3DERR_INVALIDVERTEXFORMAT (new for DirectX 6.0)
02118     D3DERR_INVALIDVERTEXTYPE (new for DirectX 5.0)
02119     D3DERR_LIGHT_SET_FAILED
02120     D3DERR_LIGHTHASVIEWPORT (new for DirectX 5.0)
02121     D3DERR_LIGHTNOTINTHISVIEWPORT (new for DirectX 5.0)
02122     D3DERR_MATERIAL_CREATE_FAILED
02123     D3DERR_MATERIAL_DESTROY_FAILED
02124     D3DERR_MATERIAL_GETDATA_FAILED
02125     D3DERR_MATERIAL_SETDATA_FAILED
02126     D3DERR_MATRIX_CREATE_FAILED
02127     D3DERR_MATRIX_DESTROY_FAILED
02128     D3DERR_MATRIX_GETDATA_FAILED
02129     D3DERR_MATRIX_SETDATA_FAILED
02130     D3DERR_NOCURRENTVIEWPORT (new for DirectX 5.0)
02131     D3DERR_NOTINBEGIN (new for DirectX 5.0)
02132     D3DERR_NOVIEWPORTS (new for DirectX 5.0)
02133     D3DERR_SCENE_BEGIN_FAILED
02134     D3DERR_SCENE_END_FAILED
02135     D3DERR_SCENE_IN_SCENE
02136     D3DERR_SCENE_NOT_IN_SCENE
02137     D3DERR_SETVIEWPORTDATA_FAILED
02138     D3DERR_STENCILBUFFER_NOTPRESENT
02139     D3DERR_SURFACENOTINVIDMEM (new for DirectX 5.0)
02140     D3DERR_TEXTURE_BADSIZE (new for DirectX 5.0)
02141     D3DERR_TEXTURE_CREATE_FAILED
02142     D3DERR_TEXTURE_DESTROY_FAILED
02143     D3DERR_TEXTURE_GETSURF_FAILED
02144     D3DERR_TEXTURE_LOAD_FAILED
02145     D3DERR_TEXTURE_LOCK_FAILED
02146     D3DERR_TEXTURE_LOCKED
02147     D3DERR_TEXTURE_NO_SUPPORT
02148     D3DERR_TEXTURE_NOT_LOCKED
02149     D3DERR_TEXTURE_SWAP_FAILED
02150     D3DERR_TEXTURE_UNLOCK_FAILED
02151     D3DERR_TOOMANYOPERATIONS
02152     D3DERR_TOOMANYPRIMITIVES
02153     D3DERR_UNSUPPORTEDALPHAARG
02154     D3DERR_UNSUPPORTEDALPHAOPERATION
02155     D3DERR_UNSUPPORTEDCOLORARG
02156     D3DERR_UNSUPPORTEDCOLOROPERATION
02157     D3DERR_UNSUPPORTEDFACTORVALUE
02158     D3DERR_UNSUPPORTEDTEXTUREFILTER
02159     D3DERR_VBUF_CREATE_FAILED
02160     D3DERR_VERTEXBUFFERLOCKED
02161     D3DERR_VERTEXBUFFEROPTIMIZED
02162     D3DERR_VIEWPORTDATANOTSET (new for DirectX 5.0)
02163     D3DERR_VIEWPORTHASNODEVICE (new for DirectX 5.0)
02164     D3DERR_WRONGTEXTUREFORMAT
02165     D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY (new for DirectX 5.0)
02166     D3DERR_ZBUFF_NEEDS_VIDEOMEMORY (new for DirectX 5.0)
02167     D3DERR_ZBUFFER_NOTPRESENT
02168     */
02169 
02170     //-----------------------------------------------------------------------
02171     DDDriverList* D3DRenderSystem::getDirectDrawDrivers(void)
02172     {
02173         if (!mDriverList)
02174         {
02175             mDriverList = new DDDriverList;
02176         }
02177 
02178         return mDriverList;
02179     }
02180     //-----------------------------------------------------------------------
02181     void D3DRenderSystem::setLightingEnabled(bool enabled)
02182     {
02183         // Call D3D
02184         HRESULT hr = __SetRenderState(D3DRENDERSTATE_LIGHTING, enabled);
02185         if (FAILED(hr))
02186             Except(hr, "Error lighting status.", "D3DRenderSystem::setLightingEnabled");
02187     }
02188     //-----------------------------------------------------------------------
02189     void D3DRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
02190     {
02191         HRESULT hr;
02192 
02193         D3DRENDERSTATETYPE fogType, fogTypeNot;
02194 
02195         if (mD3DDeviceDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)
02196         {
02197             fogType = D3DRENDERSTATE_FOGTABLEMODE;
02198             fogTypeNot = D3DRENDERSTATE_FOGVERTEXMODE;
02199         }
02200         else
02201         {
02202             fogType = D3DRENDERSTATE_FOGVERTEXMODE;
02203             fogTypeNot = D3DRENDERSTATE_FOGTABLEMODE;
02204         }
02205 
02206         if( mode == FOG_NONE)
02207         {
02208             // just disable
02209             hr = __SetRenderState(fogType, D3DFOG_NONE );
02210             hr = __SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE);
02211         }
02212         else
02213         {
02214             // Allow fog
02215             hr = __SetRenderState( D3DRENDERSTATE_FOGENABLE, TRUE );
02216             hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
02217             switch(mode)
02218             {
02219             case FOG_EXP:
02220                 hr = __SetRenderState( fogType, D3DFOG_EXP);
02221                 break;
02222             case FOG_EXP2:
02223                 hr = __SetRenderState( fogType, D3DFOG_EXP2);
02224                 break;
02225             case FOG_LINEAR:
02226                 hr = __SetRenderState( fogType, D3DFOG_LINEAR);
02227                 break;
02228 
02229             }
02230 
02231             hr = __SetRenderState( D3DRENDERSTATE_FOGCOLOR, colour.getAsLongARGB() );
02232             hr = __SetRenderState( D3DRENDERSTATE_FOGSTART, *((LPDWORD)(&start)) );
02233             hr = __SetRenderState( D3DRENDERSTATE_FOGEND, *((LPDWORD)(&end)) );
02234             hr = __SetRenderState( D3DRENDERSTATE_FOGDENSITY, *((LPDWORD)(&density)) );
02235         }
02236 
02237 
02238     }
02239 
02240     //---------------------------------------------------------------------
02241     void D3DRenderSystem::convertColourValue(const ColourValue& colour, unsigned long* pDest)
02242     {
02243         *pDest = colour.getAsLongARGB();
02244     }
02245     //---------------------------------------------------------------------
02246     void D3DRenderSystem::_makeProjectionMatrix(Real fovy, Real aspect, 
02247         Real nearPlane, Real farPlane, Matrix4& dest, bool forGpuProgram)
02248     {
02249         Real theta = Math::AngleUnitsToRadians(fovy * 0.5);
02250         Real h = 1 / Math::Tan(theta);
02251         Real w = h / aspect;
02252         Real q, qn;
02253         if (farPlane == 0)
02254         {
02255             q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
02256             qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
02257         }
02258         else
02259         {
02260             q = farPlane / ( farPlane - nearPlane );
02261             qn = -q * nearPlane;
02262         }
02263 
02264         dest = Matrix4::ZERO;
02265         dest[0][0] = w;
02266         dest[1][1] = h;
02267         dest[2][2] = q;
02268         dest[3][2] = 1.0f;
02269         dest[2][3] = qn;
02270 
02271     }
02272     //---------------------------------------------------------------------
02273     void D3DRenderSystem::_makeOrthoMatrix(Real fovy, Real aspect, Real nearPlane, Real farPlane, 
02274         Matrix4& dest, bool forGpuProgram )
02275     {
02276         Real thetaY = Math::AngleUnitsToRadians(fovy / 2.0f);
02277         Real sinThetaY = Math::Sin(thetaY);
02278         Real thetaX = thetaY * aspect;
02279         Real sinThetaX = Math::Sin(thetaX);
02280         Real w = 1.0 / (sinThetaX * nearPlane);
02281         Real h = 1.0 / (sinThetaY * nearPlane);
02282         Real q;
02283         if (farPlane == 0)
02284         {
02285             q = 0;
02286         }
02287         else
02288         {
02289             q = 1.0 / (farPlane - nearPlane);
02290         }
02291 
02292 
02293         dest = Matrix4::ZERO;
02294         dest[0][0] = w;
02295         dest[1][1] = h;
02296         dest[2][2] = q;
02297         dest[3][3] = 1; 
02298     }
02299     //---------------------------------------------------------------------
02300     void D3DRenderSystem::_setRasterisationMode(SceneDetailLevel level)
02301     {
02302         D3DFILLMODE d3dmode;
02303 
02304         switch(level)
02305         {
02306         case SDL_POINTS:
02307             d3dmode = D3DFILL_POINT;
02308             break;
02309         case SDL_WIREFRAME:
02310             d3dmode = D3DFILL_WIREFRAME;
02311             break;
02312         case SDL_SOLID:
02313             d3dmode = D3DFILL_SOLID;
02314             break;
02315 
02316         }
02317 
02318         HRESULT hr = __SetRenderState(D3DRENDERSTATE_FILLMODE, d3dmode);
02319         if (FAILED(hr))
02320         {
02321             Except(hr, "Error setting rasterisation mode.", 
02322                 "D3DRenderSystem::setRasterisationMode");
02323         }
02324 
02325 
02326     }
02327     //---------------------------------------------------------------------
02328     void D3DRenderSystem::setStencilCheckEnabled(bool enabled)
02329     {
02330         // Allow stencilling
02331         HRESULT hr = __SetRenderState(D3DRENDERSTATE_STENCILENABLE, enabled);
02332         if (FAILED(hr))
02333             Except(hr, "Error enabling / disabling stencilling.",
02334             "D3DRenderSystem::setStencilCheckEnabled");
02335 
02336     }
02337     //---------------------------------------------------------------------
02338     void D3DRenderSystem::setStencilBufferParams(CompareFunction func, ulong refValue, 
02339         ulong mask, StencilOperation stencilFailOp, 
02340         StencilOperation depthFailOp, StencilOperation passOp, 
02341         bool twoSidedOperation)
02342     {
02343         HRESULT hr;
02344 
02345         // D3D7 does not support 2-sided stencil operations
02346         if (twoSidedOperation)
02347             Except(Exception::ERR_INVALIDPARAMS, "Direct3D7 does not support 2-sided stencil ops",
02348                "D3DRenderSystem::setStencilBufferParams");
02349 
02350         // Function
02351         hr = __SetRenderState(D3DRENDERSTATE_STENCILFUNC, 
02352             convertCompareFunction(func));
02353 
02354         if (FAILED(hr))
02355             Except(hr, "Error setting stencil buffer test function.",
02356             "D3DRenderSystem::setStencilBufferParams");
02357 
02358         // reference value
02359         hr = __SetRenderState(D3DRENDERSTATE_STENCILREF, refValue);
02360         if (FAILED(hr))
02361             Except(hr, "Error setting stencil buffer reference value.",
02362             "D3DRenderSystem::setStencilBufferParams");
02363 
02364         // mask
02365         hr = __SetRenderState(D3DRENDERSTATE_STENCILMASK, mask);
02366         if (FAILED(hr))
02367             Except(hr, "Error setting stencil buffer mask.",
02368             "D3DRenderSystem::setStencilBufferParams");
02369 
02370         // fail op
02371         hr = __SetRenderState(D3DRENDERSTATE_STENCILFAIL, 
02372             convertStencilOp(stencilFailOp));
02373         if (FAILED(hr))
02374             Except(hr, "Error setting stencil fail operation.",
02375             "D3DRenderSystem::setStencilBufferParams");
02376 
02377         // depth fail op
02378         hr = __SetRenderState(D3DRENDERSTATE_STENCILZFAIL, 
02379             convertStencilOp(depthFailOp));
02380         if (FAILED(hr))
02381             Except(hr, "Error setting stencil depth fail operation.",
02382             "D3DRenderSystem::setStencilBufferParams");
02383 
02384         // pass op
02385         hr = __SetRenderState(D3DRENDERSTATE_STENCILPASS, 
02386             convertStencilOp(passOp));
02387         if (FAILED(hr))
02388             Except(hr, "Error setting stencil pass operation.",
02389             "D3DRenderSystem::setStencilBufferParams");
02390     }
02391     //---------------------------------------------------------------------
02392     D3DCMPFUNC D3DRenderSystem::convertCompareFunction(CompareFunction func)
02393     {
02394         switch(func)
02395         {
02396         case CMPF_ALWAYS_FAIL:
02397             return D3DCMP_NEVER;
02398         case CMPF_ALWAYS_PASS:
02399             return D3DCMP_ALWAYS;
02400         case CMPF_LESS:
02401             return D3DCMP_LESS;
02402         case CMPF_LESS_EQUAL:
02403             return D3DCMP_LESSEQUAL;
02404         case CMPF_EQUAL:
02405             return D3DCMP_EQUAL;
02406         case CMPF_NOT_EQUAL:
02407             return D3DCMP_NOTEQUAL;
02408         case CMPF_GREATER_EQUAL:
02409             return D3DCMP_GREATEREQUAL;
02410         case CMPF_GREATER:
02411             return D3DCMP_GREATER;
02412         };
02413         // to shut the compiler up
02414         return D3DCMP_ALWAYS;
02415     }
02416     //---------------------------------------------------------------------
02417     D3DSTENCILOP D3DRenderSystem::convertStencilOp(StencilOperation op)
02418     {
02419         switch(op)
02420         {
02421         case SOP_KEEP:
02422             return D3DSTENCILOP_KEEP;
02423         case SOP_ZERO:
02424             return D3DSTENCILOP_ZERO;
02425         case SOP_REPLACE:
02426             return D3DSTENCILOP_REPLACE;
02427         case SOP_INCREMENT:
02428             return D3DSTENCILOP_INCRSAT;
02429         case SOP_DECREMENT:
02430             return D3DSTENCILOP_DECRSAT;
02431         case SOP_INCREMENT_WRAP:
02432             return D3DSTENCILOP_INCR;
02433         case SOP_DECREMENT_WRAP:
02434             return D3DSTENCILOP_DECR;
02435         case SOP_INVERT:
02436             return D3DSTENCILOP_INVERT;
02437         };
02438         // To shut the compiler up
02439         return D3DSTENCILOP_KEEP;
02440     }
02441 
02442     DWORD D3DRenderSystem::_getCurrentAnisotropy(size_t unit)
02443     {
02444         DWORD oldVal;
02445         mlpD3DDevice->GetTextureStageState(unit, D3DTSS_MAXANISOTROPY, &oldVal);
02446         return oldVal;
02447     }
02448 
02449     
02450     void D3DRenderSystem::_setTextureUnitFiltering(size_t unit, 
02451         FilterType ftype, FilterOptions filter)
02452     {
02453         __SetTextureStageState(unit, _getFilterCode(ftype), _getFilter(ftype, filter));
02454     }
02455 
02456     void D3DRenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
02457     {
02458         if ((DWORD)maxAnisotropy > mD3DDeviceDesc.dwMaxAnisotropy)
02459             maxAnisotropy = mD3DDeviceDesc.dwMaxAnisotropy;
02460 
02461         if (_getCurrentAnisotropy(unit) != maxAnisotropy)
02462             __SetTextureStageState( unit, D3DTSS_MAXANISOTROPY, maxAnisotropy );
02463     }
02464 
02465     void D3DRenderSystem::setVertexDeclaration(VertexDeclaration* decl)
02466     {
02467         // TODO
02468     }
02469 
02470     void D3DRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
02471     {
02472         // TODO
02473     }
02474     //-----------------------------------------------------------------------
02475     D3DTEXTURESTAGESTATETYPE D3DRenderSystem::_getFilterCode(FilterType ft) const
02476     {
02477         switch (ft)
02478         {
02479         case FT_MIN:
02480             return D3DTSS_MINFILTER;
02481             break;
02482         case FT_MAG:
02483             return D3DTSS_MAGFILTER;
02484             break;
02485         case FT_MIP:
02486             return D3DTSS_MIPFILTER;
02487             break;
02488         }
02489 
02490         // to keep compiler happy
02491         return D3DTSS_MINFILTER;
02492     }
02493     //-----------------------------------------------------------------------
02494     DWORD D3DRenderSystem::_getFilter(FilterType ft, FilterOptions fo) const
02495     {
02496         switch (ft)
02497         {
02498         case FT_MIN:
02499             switch( fo )
02500             {
02501                 // NOTE: Fall through if device doesn't support requested type
02502             case FO_ANISOTROPIC:
02503                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC )
02504                 {
02505                     return D3DTFN_ANISOTROPIC;
02506                     break;
02507                 }
02508             case FO_LINEAR:
02509                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR )
02510                 {
02511                     return D3DTFN_LINEAR;
02512                     break;
02513                 }
02514             case FO_POINT:
02515             case TFO_NONE:
02516                 return D3DTFN_POINT;
02517                 break;
02518             }
02519             break;
02520         case FT_MAG:
02521             switch( fo )
02522             {
02523             // NOTE: Fall through if device doesn't support requested type
02524             case FO_ANISOTROPIC:
02525                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC )
02526                 {
02527                     return D3DTFG_ANISOTROPIC;
02528                     break;
02529                 }
02530             case FO_LINEAR:
02531                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR )
02532                 {
02533                     return D3DTFG_LINEAR;
02534                     break;
02535                 }
02536             case FO_POINT:
02537             case FO_NONE:
02538                 return D3DTFG_POINT;
02539                 break;
02540             }
02541             break;
02542         case FT_MIP:
02543             switch( fo )
02544             {
02545             case FO_ANISOTROPIC:
02546             case FO_LINEAR:
02547                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR )
02548                 {
02549                     return D3DTFP_LINEAR;
02550                     break;
02551                 }
02552             case FO_POINT:
02553                 if( mD3DDeviceDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR )
02554                 {
02555                     return D3DTFP_POINT;
02556                     break;
02557                 }
02558             case TFO_NONE:
02559                 return D3DTFP_NONE;
02560                 break;
02561             }
02562             break;
02563         }
02564 
02565         // should never get here
02566         return 0;
02567     }
02568     //---------------------------------------------------------------------
02569     void D3DRenderSystem::setNormaliseNormals(bool normalise)
02570     {
02571         __SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, 
02572             normalise ? TRUE : FALSE);
02573     }
02574     //---------------------------------------------------------------------
02575     HRESULT D3DRenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
02576     {
02577         HRESULT hr;
02578         DWORD oldVal;
02579 
02580         if ( FAILED( hr = mlpD3DDevice->GetRenderState(state, &oldVal) ) )
02581             return hr;
02582         if ( oldVal == value )
02583             return D3D_OK;
02584         else
02585             return mlpD3DDevice->SetRenderState(state, value);
02586     }
02587     //---------------------------------------------------------------------
02588     HRESULT D3DRenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
02589     {
02590         HRESULT hr;
02591         DWORD oldVal;
02592 
02593         if ( FAILED( hr = mlpD3DDevice->GetTextureStageState(stage, type, &oldVal) ) )
02594             return hr;
02595         if ( oldVal == value )
02596             return D3D_OK;
02597         else
02598             return mlpD3DDevice->SetTextureStageState(stage, type, value);
02599     }
02600 
02601     //---------------------------------------------------------------------
02602     void D3DRenderSystem::clearFrameBuffer(unsigned int buffers, 
02603         const ColourValue& colour, Real depth, unsigned short stencil)
02604     {
02605         DWORD flags = 0;
02606         if (buffers & FBT_COLOUR)
02607         {
02608             flags |= D3DCLEAR_TARGET;
02609         }
02610         if (buffers & FBT_DEPTH)
02611         {
02612             flags |= D3DCLEAR_ZBUFFER;
02613         }
02614         // Only try to clear the stencil if supported, otherwise it will fail
02615         if (buffers & FBT_STENCIL && mCapabilities->hasCapability(RSC_HWSTENCIL))
02616         {
02617             flags |= D3DCLEAR_STENCIL;
02618         }
02619         HRESULT hr;
02620         if( FAILED( hr = mlpD3DDevice->Clear( 
02621             0, 
02622             NULL, 
02623             flags,
02624             colour.getAsLongARGB(), 
02625             depth, 
02626             stencil ) ) )
02627         {
02628             String msg = getErrorDescription(hr);
02629             Except( hr, "Error clearing frame buffer : " 
02630                 + msg, "D3DRenderSystem::clearFrameBuffer" );
02631         }
02632     }
02633     //---------------------------------------------------------------------
02634     void D3DRenderSystem::_makeProjectionMatrix(Real left, Real right, 
02635         Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
02636         bool forGpuProgram)
02637     {
02638         Real width = right - left;
02639         Real height = top - bottom;
02640         Real q, qn;
02641         if (farPlane == 0)
02642         {
02643             q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
02644             qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
02645         }
02646         else
02647         {
02648             q = farPlane / ( farPlane - nearPlane );
02649             qn = -q * nearPlane;
02650         }
02651         dest = Matrix4::ZERO;
02652         dest[0][0] = 2 * nearPlane / width;
02653         dest[0][2] = (right+left) / width;
02654         dest[1][1] = 2 * nearPlane / height;
02655         dest[1][2] = (top+bottom) / height;
02656         dest[2][2] = q;
02657         dest[3][2] = 1.0f;
02658         dest[2][3] = qn;
02659     }
02660 
02661     //---------------------------------------------------------------------
02662     void D3DRenderSystem::setClipPlanes(const PlaneList& clipPlanes)
02663     {
02664         size_t i;
02665         size_t numClipPlanes;
02666         D3DVALUE dx7ClipPlane[4];
02667         DWORD mask = 0;
02668         HRESULT hr;
02669         numClipPlanes = clipPlanes.size();
02670 
02671         for (i = 0; i < numClipPlanes; ++i)
02672         {
02673             const Plane& plane = clipPlanes[i];
02674 
02675             dx7ClipPlane[0] = plane.normal.x;
02676             dx7ClipPlane[1] = plane.normal.y;
02677             dx7ClipPlane[2] = plane.normal.z;
02678             dx7ClipPlane[3] = -plane.d;
02679 
02680             hr = mlpD3DDevice->SetClipPlane(i, dx7ClipPlane);
02681             if (FAILED(hr))
02682             {
02683                 Except(hr, "Unable to set clip plane", 
02684                     "D3D7RenderSystem::setClipPlanes");
02685             }
02686 
02687             mask |= (1 << i);
02688         }
02689 
02690         hr = mlpD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, mask);
02691         if (FAILED(hr))
02692         {
02693             Except(hr, "Unable to set render state for clip planes", 
02694                 "D3D7RenderSystem::setClipPlanes");
02695         }
02696     }
02697 
02698     // ------------------------------------------------------------------
02699     void D3DRenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
02700     {
02701         float plane[4] = { A, B, C, D };
02702         mlpD3DDevice->SetClipPlane (index, plane);
02703     }
02704 
02705     // ------------------------------------------------------------------
02706     void D3DRenderSystem::enableClipPlane (ushort index, bool enable)
02707     {
02708         DWORD prev;
02709         mlpD3DDevice->GetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, &prev);
02710         __SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE, prev | (1 << index));
02711     }
02712     //---------------------------------------------------------------------
02713     HardwareOcclusionQuery* D3DRenderSystem::createHardwareOcclusionQuery(void)
02714     {
02715         return (HardwareOcclusionQuery*) 0; // Hardware occlusion is not supported when DirectX7 is used
02716     }
02717     //-----------------------------------------------------------------------
02718     void D3DRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
02719     {
02720         // D3D7 does not have a colour write mask setting, so emulate it using
02721         // scene blending, on the assumption that setSceneBlend will be called
02722         // before this
02723         if (red || green || blue || alpha)
02724         {
02725             // restore saved scene blend
02726             _setSceneBlending(mSavedSrcFactor, mSavedDestFactor);
02727         }
02728         else
02729         {
02730             _setSceneBlending(SBF_ZERO, SBF_ONE);
02731         }
02732     }
02733 
02734 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:00 2004