Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

# KeosD3D9RenderSystem.cpp

Go to the documentation of this file.

    00001 /*
    00002  * This source file is part of KEOS (Free 3D Engine)
    00003  * For the latest info, see http://www.keosengine.org/
    00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
    00005  *
    00006  * This program is free software; you can redistribute it and/or modify it under
    00007  * the terms of the GNU Lesser General Public License as published by the Free Software
    00008  * Foundation; either version 2 of the License, or (at your option) any later
    00009  * version.
    00010  *
    00011  * This program is distributed in the hope that it will be useful, but WITHOUT
    00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00014  *
    00015  * You should have received a copy of the GNU Lesser General Public License along with
    00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00018  * http://www.gnu.org/copyleft/lesser.txt.
    00019  *
    00020  */
    00021 #include "KeosD3D9RenderSystem.h"
    00022 #include "KeosD3D9Window.h"
    00023 #include "KeosD3D9Enum.h"
    00024 #include "KeosD3D9Exception.h"
    00025 #include "KeosD3D9Buffer.h"
    00026 #include "KeosD3D9Declaration.h"
    00027 #include "KeosD3D9Texture.h"
    00028 #include "KeosLogger.h"
    00029 #include "KeosMatrix4.h"
    00030 #include "KeosColor.h"
    00031 #include "KeosRenderSystemCapabilities.h"
    00032 #include "KeosPixelUtils.h"
    00033 #include "KeosString.h"
    00034 #include "KeosD3D9Shader.h"
    00035 #include "Cg/cgD3D9.h"
    00036
    00037 namespace Keos
    00038 {
    00039     //=======================================================================
    00040     // CD3D9RenderSystem implementation
    00041     //=======================================================================
    00042
    00043     //-----------------------------------------------------------------------
    00044     CD3D9RenderSystem::CD3D9RenderSystem()
    00045     {
    00046                 m_pD3D9 = new CD3D9();
    00047
    00048         m_nMinVertex = 0;
    00049         m_nVertexCount = 0;
    00050                 m_bDeviceLost = false;
    00051
    00052         // Create our Direct3D object
    00053                 if( NULL == (m_pD3D9->pD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
    00054                         D3D9_EXCEPT("Failed to create Direct3D9 object", "CD3D9RenderSystem::CD3D9RenderSystem");
    00055
    00056                 // Create Matrices
    00057                 for (int i = 0; i < 6; ++i)
    00058                         m_Matrices[i].push_back(CMatrix4());
    00059
    00060     }
    00061
    00062     //-----------------------------------------------------------------------
    00063     CD3D9RenderSystem::~CD3D9RenderSystem()
    00064     {
    00065                 Shutdown();
    00066         cgD3D9SetDevice(NULL);
    00067                 delete m_pD3D9;
    00068     }
    00069
    00070         //-----------------------------------------------------------------------
    00071         const String& CD3D9RenderSystem::GetName(void) const
    00072     {
    00073         static String strName("Direct3D9");
    00074         return strName;
    00075     }
    00076
    00077     //-----------------------------------------------------------------------
    00078     IRenderWindow* CD3D9RenderSystem::Initialise(bool bAutoCreateWindow, const String& strWindowTitle)
    00079     {
    00080         ILogger::Log("--> Starting Direct3D9 Subsystem");
    00081
    00082         ConfigOptionMap::iterator opt = m_Options.find("Video Mode");
    00083         if (opt == m_Options.end())
    00084             D3D9_EXCEPT("Can't find \"Video Mode\" option", "CD3D9RenderSystem::Initialise");
    00085         String val = opt->second.currentValue;
    00086         String::size_type pos = val.find('x');
    00087         if (pos == String::npos)
    00088             D3D9_EXCEPT("Invalid Video Mode provided", "COGLRenderSystem::Initialise");
    00089             uint w = CStringConverter::ParseUnsignedInt(val.substr(0, pos));
    00090         uint h = CStringConverter::ParseUnsignedInt(val.substr(pos + 1));
    00091
    00092         opt = m_Options.find("Color Depth");
    00093         if (opt == m_Options.end())
    00094             D3D9_EXCEPT("Can't find \"Color Depth\" option", "CD3D9RenderSystem::Initialise");
    00095         val = opt->second.currentValue;
    00096         uint d = CStringConverter::ParseUnsignedInt(val);
    00097         if (d == 0)
    00098             D3D9_EXCEPT("Invalid Color Depth provided", "CD3D9RenderSystem::Initialise");
    00099
    00100         opt = m_Options.find("Fullscreen");
    00101         if (opt == m_Options.end())
    00102             D3D9_EXCEPT("Can't find \"Fullscreen\" option", "CD3D9RenderSystem::Initialise");
    00103         val = opt->second.currentValue;
    00104         bool f = CStringConverter::ParseBool(val);
    00105
    00106             IRenderWindow* pAutoWindow = CreateRenderWindow(strWindowTitle, w, h, d, f);
    00107
    00108         return pAutoWindow;
    00109     }
    00110
    00111     //-----------------------------------------------------------------------
    00112     void CD3D9RenderSystem::Reinitialise(void)
    00113     {
    00114                 this->Shutdown();
    00115                 this->Initialise( true );
    00116         }
    00117
    00118         //-----------------------------------------------------------------------
    00119     void CD3D9RenderSystem::Shutdown(void)
    00120     {
    00121         IRenderSystem::Shutdown();
    00122                 m_pD3D9->ReleaseDevice();
    00123     }
    00124
    00125         //-----------------------------------------------------------------------
    00126     IRenderWindow* CD3D9RenderSystem::CreateRenderWindow(const String &strName, uint nWidth, uint nHeight, uint nColourDepth, bool bFullScreen)
    00127     {
    00128         ILogger::Log("--> Create Win32 render window");
    00129
    00130         // Create the window
    00131         IRenderWindow* win = new CD3D9Window(m_pD3D9);
    00132         win->Create(strName, nWidth, nHeight, nColourDepth, bFullScreen);
    00133
    00134         AttachRenderTarget( *win );
    00135
    00136         InitCapabilities();
    00137
    00138         // Direct3D default states
    00139                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_DITHERENABLE,     true);
    00140                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_LIGHTING,         false);
    00141                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_ZENABLE,          true);
    00142                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_FOGENABLE,        false);
    00143                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE,  false);
    00144                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
    00145                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_CULLMODE,         D3DCULL_CCW);
    00146                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_STENCILMASK,      0xFF);
    00147                 m_pD3D9->pD3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xFF);
    00148                 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU,  D3DTADDRESS_WRAP);
    00149                 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP);
    00150                 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    00151                 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    00152                 m_pD3D9->pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
    00153
    00154                 SetClearColor(CColor::Black);
    00155
    00156         return win;
    00157     }
    00158
    00159         //-----------------------------------------------------------------------
    00160     void CD3D9RenderSystem::InitCapabilities()
    00161     {
    00162                 // Get caps
    00163         D3DCAPS9 Caps;
    00164         m_pD3D9->pD3DDevice->GetDeviceCaps(&Caps);
    00165
    00166         // Check for hardware mipmapping support
    00167         if ((Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0)
    00168                         m_pCapabilities->SetCapability(CAP_HW_MIPMAPPING);
    00169
    00170         // Check for texture dxt compression
    00171         if (CheckFormat(D3DFMT_DXT1, D3DRTYPE_TEXTURE) &&
    00172                                             CheckFormat(D3DFMT_DXT3, D3DRTYPE_TEXTURE) &&
    00173                                             CheckFormat(D3DFMT_DXT5, D3DRTYPE_TEXTURE))
    00174             m_pCapabilities->SetCapability(CAP_TEXTURE_COMPRESSION_DXT);
    00175
    00176         // Check for non-power-of-2 texture support
    00177         if (!(Caps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
    00178                                             !(Caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
    00179             m_pCapabilities->SetCapability(CAP_NON_POWER_OF_2_TEXTURES);
    00180
    00181                 // Set number of texture units
    00182                 m_pCapabilities->SetNumTextureUnits(Caps.MaxSimultaneousTextures);
    00183
    00184         // Check for Vertex Shaders support and set version number
    00185         SearchVertexShaderCaps(Caps);
    00186         // Check for Pixel Shaders support and set version number
    00187         SearchPixelShaderCaps(Caps);
    00188
    00189         m_pCapabilities->Log();
    00190
    00191         // Setup Cg D3D Runtime
    00192         cgD3D9SetDevice(m_pD3D9->pD3DDevice);
    00193                 if (m_pCapabilities->HasCapability(CAP_VERTEX_PROGRAM))
    00194                 {
    00195                         m_VSProfile    = cgD3D9GetLatestVertexProfile();
    00196                         m_VSOptions[0] = cgD3D9GetOptimalOptions(m_VSProfile);
    00197                         m_VSOptions[1] = NULL;
    00198                 }
    00199                 if (m_pCapabilities->HasCapability(CAP_FRAGMENT_PROGRAM))
    00200                 {
    00201                         m_PSProfile    = cgD3D9GetLatestPixelProfile();
    00202                         m_PSOptions[0] = cgD3D9GetOptimalOptions(m_PSProfile);
    00203                         m_PSOptions[1] = NULL;
    00204                 }
    00205     }
    00206
    00207     //---------------------------------------------------------------------
    00208     void CD3D9RenderSystem::SearchVertexShaderCaps(D3DCAPS9& Caps)
    00209     {
    00210         ushort nMajor, nMinor;
    00211         nMajor = static_cast<ushort>((Caps.VertexShaderVersion & 0x0000FF00) >> 8);
    00212         nMinor = static_cast<ushort>(Caps.VertexShaderVersion & 0x000000FF);
    00213
    00214         // Populate max version & params
    00215         switch (nMajor)
    00216         {
    00217         case 1:
    00218             m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
    00219             m_pCapabilities->SetMaxVertexProgramVersion("vs_1_1");
    00220             // No boolean params allowed
    00221             //m_pCapabilities->SetVertexProgramConstantBoolCount(0);
    00222             // No integer params allowed
    00223             //m_pCapabilities->SetVertexProgramConstantIntCount(0);
    00224             // float params, always 4D
    00225             //m_pCapabilities->SetVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
    00226             break;
    00227         case 2:
    00228             m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
    00229             if (nMinor > 0)
    00230             {
    00231                 m_pCapabilities->SetMaxVertexProgramVersion("vs_2_x");
    00232             }
    00233             else
    00234             {
    00235                 m_pCapabilities->SetMaxVertexProgramVersion("vs_2_0");
    00236             }
    00237             // 16 boolean params allowed
    00238             //m_pCapabilities->SetVertexProgramConstantBoolCount(16);
    00239             // 16 integer params allowed, 4D
    00240             //m_pCapabilities->SetVertexProgramConstantIntCount(16);
    00241             // float params, always 4D
    00242             //m_pCapabilities->SetVertexProgramConstantFloatCount(Caps.MaxVertexShaderConst);
    00243             break;
    00244         case 3:
    00245             m_pCapabilities->SetCapability(CAP_VERTEX_PROGRAM);
    00246             m_pCapabilities->SetMaxVertexProgramVersion("vs_3_0");
    00247             // 16 boolean params allowed
    00248             //m_pCapabilities->SetVertexProgramConstantBoolCount(16);
    00249             // 16 integer params allowed, 4D
    00250             //m_pCapabilities->SetVertexProgramConstantIntCount(16);
    00251             // float params, always 4D
    00252             //m_pCapabilities->SetVertexProgramConstantFloatCount(mCaps.MaxVertexShaderConst);
    00253             break;
    00254         default:
    00255             m_pCapabilities->SetMaxVertexProgramVersion("");
    00256             break;
    00257         }
    00258     }
    00259
    00260     //---------------------------------------------------------------------
    00261     void CD3D9RenderSystem::SearchPixelShaderCaps(D3DCAPS9& Caps)
    00262     {
    00263         ushort nMajor, nMinor;
    00264         nMajor = static_cast<ushort>((Caps.PixelShaderVersion & 0x0000FF00) >> 8);
    00265         nMinor = static_cast<ushort>(Caps.PixelShaderVersion & 0x000000FF);
    00266
    00267         switch (nMajor)
    00268         {
    00269         case 1:
    00270             m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
    00271             switch(nMinor)
    00272             {
    00273             case 1:
    00274                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_1");
    00275                 break;
    00276             case 2:
    00277                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_2");
    00278                 break;
    00279             case 3:
    00280                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_3");
    00281                 break;
    00282             case 4:
    00283                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_1_4");
    00284                 break;
    00285             }
    00286             // no boolean params allowed
    00287             //m_pCapabilities->SetFragmentProgramConstantBoolCount(0);
    00288             // no integer params allowed
    00289             //m_pCapabilities->SetFragmentProgramConstantIntCount(0);
    00290             // float params, always 4D
    00291             //m_pCapabilities->SetFragmentProgramConstantFloatCount(8);
    00292             break;
    00293         case 2:
    00294             m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
    00295                         if ((Caps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
    00296                                 (Caps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
    00297                         {
    00298                     if ((Caps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
    00299                                         (Caps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
    00300                                         (Caps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION))
    00301                     {
    00302                                         // ps_2_a is more powerful than ps_2_b? odd
    00303                             m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_a");
    00304                                 }
    00305                                 else
    00306                                 {
    00307                                         m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_b");
    00308                                 }
    00309
    00310                 // 16 boolean params allowed
    00311                 //m_pCapabilities->SetFragmentProgramConstantBoolCount(16);
    00312                 // 16 integer params allowed, 4D
    00313                 //m_pCapabilities->SetFragmentProgramConstantIntCount(16);
    00314                 // float params, always 4D
    00315                 //m_pCapabilities->SetFragmentProgramConstantFloatCount(224);
    00316             }
    00317             else
    00318             {
    00319                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_2_0");
    00320                 // no boolean params allowed
    00321                 //m_pCapabilities->SetFragmentProgramConstantBoolCount(0);
    00322                 // no integer params allowed
    00323                 //m_pCapabilities->SetFragmentProgramConstantIntCount(0);
    00324                 // float params, always 4D
    00325                 //m_pCapabilities->SetFragmentProgramConstantFloatCount(32);
    00326             }
    00327             break;
    00328         case 3:
    00329             m_pCapabilities->SetCapability(CAP_FRAGMENT_PROGRAM);
    00330             if (nMinor > 0)
    00331             {
    00332                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_3_x");
    00333             }
    00334             else
    00335             {
    00336                 m_pCapabilities->SetMaxFragmentProgramVersion("ps_3_0");
    00337             }
    00338             // 16 boolean params allowed
    00339             //m_pCapabilities->SetFragmentProgramConstantBoolCount(16);
    00340             // 16 integer params allowed, 4D
    00341             //m_pCapabilities->SetFragmentProgramConstantIntCount(16);
    00342             // float params, always 4D
    00343             //m_pCapabilities->SetFragmentProgramConstantFloatCount(224);
    00344             break;
    00345         default:
    00346             m_pCapabilities->SetMaxFragmentProgramVersion("");
    00347             break;
    00348         }
    00349     }
    00350
    00351         //-----------------------------------------------------------------------
    00352     bool CD3D9RenderSystem::CheckFormat(D3DFORMAT Format, D3DRESOURCETYPE ResourceType, ulong nUsage)
    00353         {
    00354                 Assert(m_pD3D9->pD3D != NULL);
    00355
    00356                 return SUCCEEDED(m_pD3D9->pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
    00357                                                                                                         nUsage, ResourceType, Format));
    00358         }
    00359
    00360     //-----------------------------------------------------------------------
    00361     void CD3D9RenderSystem::BeginScene() const
    00362     {
    00363         m_pD3D9->pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, m_ClearColor.ToRGBA(), 1.0f, 0x00);
    00364         m_pD3D9->pD3DDevice->BeginScene();
    00365
    00366     }
    00367
    00368     //-----------------------------------------------------------------------
    00369     void CD3D9RenderSystem::EndScene() const
    00370     {
    00371         m_pD3D9->pD3DDevice->EndScene();
    00372     }
    00373
    00374     //-----------------------------------------------------------------------
    00375     void CD3D9RenderSystem::PrintInfo() const
    00376     {
    00377         printf("Direct3D9\n");
    00378     }
    00379
    00380     //-----------------------------------------------------------------------
    00381     IBufferBase* CD3D9RenderSystem::_CreateVB(ulong nSize, ulong nStride, ulong nFlags) const
    00382     {
    00383         // Create buffer
    00384         LPDIRECT3DVERTEXBUFFER9 VertexBuffer;
    00385         if (FAILED(m_pD3D9->pD3DDevice->CreateVertexBuffer(nSize * nStride, CD3D9Enum::BufferFlags(nFlags), 0, D3DPOOL_DEFAULT, &VertexBuffer, NULL)))
    00386             D3D9_EXCEPT("Error in fonction CreateVertexBuffer", "CD3D9RenderSystem::_CreateVB");
    00387
    00388         return new CD3D9VertexBuffer(nSize, VertexBuffer);
    00389     }
    00390
    00391     //-----------------------------------------------------------------------
    00392     IBufferBase* CD3D9RenderSystem::_CreateIB(ulong nSize, ulong nStride, ulong nFlags) const
    00393     {
    00394         // Create buffer
    00395         LPDIRECT3DINDEXBUFFER9 IndexBuffer;
    00396         if (FAILED(m_pD3D9->pD3DDevice->CreateIndexBuffer(nSize * nStride, CD3D9Enum::BufferFlags(nFlags), nStride == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &IndexBuffer, NULL)))
    00397             D3D9_EXCEPT("Error in fonction CreateIndexBuffer", "CD3D9RenderSystem::_CreateIB");
    00398
    00399         return new CD3D9IndexBuffer(nSize, IndexBuffer);
    00400     }
    00401
    00402     //-----------------------------------------------------------------------
    00403     IDeclaration* CD3D9RenderSystem::CreateDeclaration(const TDeclarationElement* pElements, size_t nCount) const
    00404     {
    00405         std::vector<D3DVERTEXELEMENT9> DxElements;
    00406         std::vector<int> Offset(nCount, 0);
    00407
    00408                 // Convert declaration elements in Dx9 elements
    00409         for (const TDeclarationElement* Elt = pElements; Elt < pElements + nCount; ++Elt)
    00410         {
    00411             // Build temp element
    00412             D3DVERTEXELEMENT9 CurrentElement;
    00413
    00414             // Stream, offset and method
    00415                     CurrentElement.Stream = Elt->Stream;
    00416             CurrentElement.Offset = Offset[Elt->Stream];
    00417             CurrentElement.Method = D3DDECLMETHOD_DEFAULT;
    00418
    00419             // Usage
    00420             switch (Elt->Usage)
    00421             {
    00422                 case ELT_USAGE_POSITION :  CurrentElement.Usage = D3DDECLUSAGE_POSITION; CurrentElement.UsageIndex = 0; break;
    00423                 case ELT_USAGE_NORMAL :    CurrentElement.Usage = D3DDECLUSAGE_NORMAL;   CurrentElement.UsageIndex = 0; break;
    00424                 case ELT_USAGE_DIFFUSE :   CurrentElement.Usage = D3DDECLUSAGE_COLOR;    CurrentElement.UsageIndex = 0; break;
    00425                 case ELT_USAGE_TEXCOORD0 : CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD; CurrentElement.UsageIndex = 0; break;
    00426                 case ELT_USAGE_TEXCOORD1 : CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD; CurrentElement.UsageIndex = 1; break;
    00427                             case ELT_USAGE_TEXCOORD2 : CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD; CurrentElement.UsageIndex = 2; break;
    00428                             case ELT_USAGE_TEXCOORD3 : CurrentElement.Usage = D3DDECLUSAGE_TEXCOORD; CurrentElement.UsageIndex = 3; break;
    00429             }
    00430
    00431             // Offset
    00432             switch (Elt->DataType)
    00433             {
    00434                 case ELT_TYPE_FLOAT1 : CurrentElement.Type = D3DDECLTYPE_FLOAT1;   Offset[Elt->Stream] += 4;  break;
    00435                 case ELT_TYPE_FLOAT2 : CurrentElement.Type = D3DDECLTYPE_FLOAT2;   Offset[Elt->Stream] += 8;  break;
    00436                 case ELT_TYPE_FLOAT3 : CurrentElement.Type = D3DDECLTYPE_FLOAT3;   Offset[Elt->Stream] += 12; break;
    00437                 case ELT_TYPE_FLOAT4 : CurrentElement.Type = D3DDECLTYPE_FLOAT4;   Offset[Elt->Stream] += 16; break;
    00438                 case ELT_TYPE_COLOR :  CurrentElement.Type = D3DDECLTYPE_D3DCOLOR; Offset[Elt->Stream] += 4;  break;
    00439             }
    00440
    00441             // Add the current element
    00442                 DxElements.push_back(CurrentElement);
    00443         }
    00444
    00445                 // Add the element which is the end of the array
    00446         D3DVERTEXELEMENT9 EndElement = D3DDECL_END();
    00447             DxElements.push_back(EndElement);
    00448
    00449         // Create declaration
    00450         LPDIRECT3DVERTEXDECLARATION9 Declaration = NULL;
    00451         if (FAILED(m_pD3D9->pD3DDevice->CreateVertexDeclaration(&DxElements[0], &Declaration)))
    00452             D3D9_EXCEPT("Error in fonction CreateVertexDeclaration", "CD3D9RenderSystem::CreateDeclaration");
    00453
    00454         return new CD3D9Declaration(Declaration);
    00455     }
    00456
    00457     //-----------------------------------------------------------------------
    00458     void CD3D9RenderSystem::_SetVB(uint nStream, const IBufferBase* pBuffer, ulong nStride, ulong nMinVertex, ulong nMaxVertex)
    00459     {
    00460                 // Get the Dx buffer
    00461         const CD3D9VertexBuffer* VertexBuffer = static_cast<const CD3D9VertexBuffer*>(pBuffer);
    00462
    00463         // Send to the API
    00464         m_pD3D9->pD3DDevice->SetStreamSource(nStream, VertexBuffer ? VertexBuffer->GetBuffer() : NULL, 0, nStride);
    00465
    00466         // Save MinVertex and VertexCount
    00467         m_nMinVertex   = nMinVertex;
    00468         m_nVertexCount = nMaxVertex - nMinVertex + 1;
    00469     }
    00470
    00471     //-----------------------------------------------------------------------
    00472     void CD3D9RenderSystem::_SetIB(const IBufferBase* pBuffer, ulong nStride)
    00473     {
    00474         // Get the Dx buffer
    00475         const CD3D9IndexBuffer* IndexBuffer = static_cast<const CD3D9IndexBuffer*>(pBuffer);
    00476
    00477         // Send to the API
    00478         m_pD3D9->pD3DDevice->SetIndices(IndexBuffer ? IndexBuffer->GetBuffer() : NULL);
    00479     }
    00480
    00481     //-----------------------------------------------------------------------
    00482     void CD3D9RenderSystem::SetDeclaration(const IDeclaration* pDeclaration)
    00483     {
    00484         // Get the Dx buffer
    00485         const CD3D9Declaration* DxDeclaration = static_cast<const CD3D9Declaration*>(pDeclaration);
    00486
    00487         // Send to the API
    00488         m_pD3D9->pD3DDevice->SetVertexDeclaration(DxDeclaration ? DxDeclaration->GetDeclaration() : NULL);
    00489     }
    00490
    00491     //-----------------------------------------------------------------------
    00492     void CD3D9RenderSystem::DrawPrimitives(TPrimitiveType Type, ulong nFirstVertex, ulong nCount) const
    00493     {
    00494         m_pD3D9->pD3DDevice->DrawPrimitive(CD3D9Enum::Get(Type), nFirstVertex, nCount);
    00495     }
    00496
    00497     //-----------------------------------------------------------------------
    00498     void CD3D9RenderSystem::DrawIndexedPrimitives(TPrimitiveType Type, ulong nFirstIndex, ulong nCount) const
    00499     {
    00500         m_pD3D9->pD3DDevice->DrawIndexedPrimitive(CD3D9Enum::Get(Type), 0, m_nMinVertex, m_nVertexCount, nFirstIndex, nCount);
    00501     }
    00502
    00503     //-----------------------------------------------------------------------
    00504     void CD3D9RenderSystem::PushMatrix(TMatrixType Type)
    00505     {
    00506         m_Matrices[Type].push_back(m_Matrices[Type].back());
    00507     }
    00508
    00509     //-----------------------------------------------------------------------
    00510     void CD3D9RenderSystem::PopMatrix(TMatrixType Type)
    00511     {
    00512         m_Matrices[Type].pop_back();
    00513
    00514         m_pD3D9->pD3DDevice->SetTransform(CD3D9Enum::Get(Type), (D3DMATRIX*)&m_Matrices[Type].back());
    00515     }
    00516
    00517     //-----------------------------------------------------------------------
    00518     void CD3D9RenderSystem::LoadMatrix(TMatrixType Type, const CMatrix4& Matrix)
    00519     {
    00520         m_Matrices[Type].back() = Matrix;
    00521
    00522         m_pD3D9->pD3DDevice->SetTransform(CD3D9Enum::Get(Type), (D3DMATRIX*)&Matrix);
    00523     }
    00524
    00525     //-----------------------------------------------------------------------
    00526     void CD3D9RenderSystem::LoadMatrixMult(TMatrixType Type, const CMatrix4& Matrix)
    00527     {
    00528         m_Matrices[Type].back() = Matrix * m_Matrices[Type].back();
    00529
    00530         m_pD3D9->pD3DDevice->SetTransform(CD3D9Enum::Get(Type), (D3DMATRIX*)&m_Matrices[Type].back());
    00531     }
    00532
    00533     //-----------------------------------------------------------------------
    00534     void CD3D9RenderSystem::GetMatrix(TMatrixType Type, CMatrix4& Matrix) const
    00535     {
    00536         Matrix = m_Matrices[Type].back();
    00537     }
    00538
    00539     //-----------------------------------------------------------------------
    00540     ulong CD3D9RenderSystem::ConvertColor(const CColor& Color) const
    00541     {
    00542         return Color.ToARGB();
    00543     }
    00544
    00545     //-----------------------------------------------------------------------
    00546     ITextureBase* CD3D9RenderSystem::CreateTexture(const TVector2I& Size, TPixelFormat Format, ulong nFlags) const
    00547     {
    00548                 // Detect mipmapping options
    00549         bool bHasMipmaps  = (nFlags & TEX_NOMIPMAP) != 0;
    00550         bool bAutoMipmaps = GetCapabilities()->HasCapability(CAP_HW_MIPMAPPING) &&
    00551                         m_pD3D9->pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
    00552                                                         D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE,
    00553                                                         CD3D9Enum::Get(Format)) == D3D_OK;
    00554
    00555         // Adjust Usage
    00556         ulong nUsage = bAutoMipmaps ? D3DUSAGE_AUTOGENMIPMAP : 0;
    00557
    00558         // Create Dx9 texture
    00559         LPDIRECT3DTEXTURE9 Texture = NULL;
    00560         if (FAILED(D3DXCreateTexture(m_pD3D9->pD3DDevice, Size.x, Size.y, 0, nUsage, CD3D9Enum::Get(Format), D3DPOOL_MANAGED, &Texture)))
    00561             D3D9_EXCEPT("Error in fonction D3DXCreateTexture", "CD3D9RenderSystem::CreateTexture");
    00562
    00563         return new CD3D9Texture(Size, Format, bHasMipmaps, bAutoMipmaps, Texture);
    00564     }
    00565
    00566         //-----------------------------------------------------------------------
    00567     void CD3D9RenderSystem::SetTexture(uint nUnit, const ITextureBase* pTexture) const
    00568     {
    00569         const CD3D9Texture* DxTexture = static_cast<const CD3D9Texture*>(pTexture);
    00570         m_pD3D9->pD3DDevice->SetTexture(nUnit, DxTexture ? DxTexture->GetD3D9Texture() : NULL);
    00571     }
    00572
    00573         //-----------------------------------------------------------------------
    00574     void CD3D9RenderSystem::SetupAlphaBlending(TBlend Src, TBlend Dest) const
    00575     {
    00576         m_pD3D9->pD3DDevice->SetRenderState(D3DRS_SRCBLEND,  CD3D9Enum::Get(Src));
    00577         m_pD3D9->pD3DDevice->SetRenderState(D3DRS_DESTBLEND, CD3D9Enum::Get(Dest));
    00578     }
    00579
    00580         //-----------------------------------------------------------------------
    00581     void CD3D9RenderSystem::SetupTextureUnit(uint nUnit, TTextureOp Op, TTextureArg Arg1, TTextureArg Arg2, const CColor& Constant) const
    00582     {
    00583         // Operator and arguments
    00584         if (Op < TXO_ALPHA_FIRSTARG)
    00585         {
    00586             m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_COLOROP,   CD3D9Enum::Get(Op));
    00587             m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_COLORARG1, CD3D9Enum::Get(Arg1));
    00588             m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_COLORARG2, CD3D9Enum::Get(Arg2));
    00589         }
    00590         else
    00591         {
    00592             m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_ALPHAOP,   CD3D9Enum::Get(Op));
    00593             m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_ALPHAARG1, CD3D9Enum::Get(Arg1));
    00594             m_pD3D9->pD3DDevice->SetTextureStageState(nUnit, D3DTSS_ALPHAARG2, CD3D9Enum::Get(Arg2));
    00595         }
    00596
    00597         // Constant
    00598         if ((Arg1 == TXA_CONSTANT) || (Arg2 == TXA_CONSTANT))
    00599         {
    00600             m_pD3D9->pD3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR, ConvertColor(Constant));
    00601         }
    00602     }
    00603
    00604         //-----------------------------------------------------------------------
    00605     void CD3D9RenderSystem::Enable(TRenderParameter Param, bool bValue) const
    00606     {
    00607         m_pD3D9->pD3DDevice->SetRenderState(CD3D9Enum::Get(Param), bValue);
    00608     }
    00609
    00610         //---------------------------------------------------------------------
    00611         IShaderBase* CD3D9RenderSystem::CreateShader(CGprogram Program, TShaderType Type) const
    00612         {
    00613                 return new CD3D9Shader(Program, Type);
    00614         }
    00615
    00616         //---------------------------------------------------------------------
    00617         void CD3D9RenderSystem::SetVertexShader(const IShaderBase* pShader)
    00618         {
    00619                 const CD3D9Shader* pDxShader = static_cast<const CD3D9Shader*>(pShader);
    00620
    00621                 if (pDxShader)
    00622                 {
    00623                         if (pDxShader->GetType() != SHADER_VERTEX)
    00624                                 D3D9_EXCEPT("Incorrect shader type (Pixel Shader)", "CD3D9RenderSystem::SetVertexShader");
    00625
    00626                         cgD3D9BindProgram(pDxShader->GetProgram());
    00627                 }
    00628                 else
    00629                 {
    00630                         m_pD3D9->pD3DDevice->SetVertexShader(NULL);
    00631                 }
    00632         }
    00633
    00634         //---------------------------------------------------------------------
    00635         void CD3D9RenderSystem::SetPixelShader(const IShaderBase* pShader)
    00636         {
    00637                 const CD3D9Shader* pDxShader = static_cast<const CD3D9Shader*>(pShader);
    00638
    00639                 if (pDxShader)
    00640                 {
    00641                         if (pDxShader->GetType() != SHADER_PIXEL)
    00642                                 D3D9_EXCEPT("Incorrect shader type (Vertex Shader)", "CD3D9RenderSystem::SetPixelShader");
    00643
    00644                         cgD3D9BindProgram(pDxShader->GetProgram());
    00645                 }
    00646                 else
    00647                 {
    00648                         m_pD3D9->pD3DDevice->SetPixelShader(NULL);
    00649                 }
    00650         }
    00651
    00652         //---------------------------------------------------------------------
    00653         void CD3D9RenderSystem::RestoreLostDevice(void)
    00654         {
    00655                 // Reset the device, using the primary window presentation params
    00656                 HRESULT hr = m_pD3D9->pD3DDevice->Reset(
    00657                         ((CD3D9Window*)m_pRenderWindow)->GetPresentationParameters());
    00658
    00659                 if (hr == D3DERR_DEVICELOST)
    00660                 {
    00661                         // Don't continue
    00662                         return;
    00663                 }
    00664                 else if (FAILED(hr))
    00665                 {
    00666                         D3D9_EXCEPT("Cannot reset device !", "CD3D9RenderSystem::RestoreLostDevice");
    00667                 }
    00668
    00669                 m_bDeviceLost = false;
    00670         }
    00671
    00672         //---------------------------------------------------------------------
    00673         bool CD3D9RenderSystem::IsDeviceLost(void)
    00674         {
    00675                 return m_bDeviceLost;
    00676         }
    00677
    00678         //---------------------------------------------------------------------
    00679         void CD3D9RenderSystem::_NotifyDeviceLost(void)
    00680         {
    00681                 m_bDeviceLost = true;
    00682         }
    00683
    00684         //-----------------------------------------------------------------------
    00685         void CD3D9RenderSystem::SetClearColor(const CColor& Color)
    00686         {
    00687                 m_ClearColor = Color;
    00688         }
    00689 }