1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreD3D9VertexDeclaration.h" 29 #include "OgreD3D9Mappings.h" 30 #include "OgreException.h" 31 #include "OgreRoot.h" 32 #include "OgreD3D9RenderSystem.h" 33 34 namespace Ogre { 35 36 //----------------------------------------------------------------------- D3D9VertexDeclaration()37 D3D9VertexDeclaration::D3D9VertexDeclaration() : mLastUsedGlobalDeclaration(0), mUsedGlobalDeclaration(false) 38 { 39 40 } 41 //----------------------------------------------------------------------- ~D3D9VertexDeclaration()42 D3D9VertexDeclaration::~D3D9VertexDeclaration() 43 { 44 releaseDeclaration(); 45 } 46 //----------------------------------------------------------------------- addElement(unsigned short source,size_t offset,VertexElementType theType,VertexElementSemantic semantic,unsigned short index)47 const VertexElement& D3D9VertexDeclaration::addElement(unsigned short source, 48 size_t offset, VertexElementType theType, 49 VertexElementSemantic semantic, unsigned short index) 50 { 51 releaseDeclaration(); 52 return VertexDeclaration::addElement(source, offset, theType, semantic, index); 53 } 54 //----------------------------------------------------------------------------- insertElement(unsigned short atPosition,unsigned short source,size_t offset,VertexElementType theType,VertexElementSemantic semantic,unsigned short index)55 const VertexElement& D3D9VertexDeclaration::insertElement(unsigned short atPosition, 56 unsigned short source, size_t offset, VertexElementType theType, 57 VertexElementSemantic semantic, unsigned short index) 58 { 59 releaseDeclaration(); 60 return VertexDeclaration::insertElement(atPosition, source, offset, theType, semantic, index); 61 } 62 //----------------------------------------------------------------------- removeElement(unsigned short elem_index)63 void D3D9VertexDeclaration::removeElement(unsigned short elem_index) 64 { 65 VertexDeclaration::removeElement(elem_index); 66 releaseDeclaration(); 67 } 68 //----------------------------------------------------------------------- removeElement(VertexElementSemantic semantic,unsigned short index)69 void D3D9VertexDeclaration::removeElement(VertexElementSemantic semantic, unsigned short index) 70 { 71 VertexDeclaration::removeElement(semantic, index); 72 releaseDeclaration(); 73 } 74 //----------------------------------------------------------------------- removeAllElements(void)75 void D3D9VertexDeclaration::removeAllElements(void) 76 { 77 VertexDeclaration::removeAllElements(); 78 releaseDeclaration(); 79 } 80 //----------------------------------------------------------------------- modifyElement(unsigned short elem_index,unsigned short source,size_t offset,VertexElementType theType,VertexElementSemantic semantic,unsigned short index)81 void D3D9VertexDeclaration::modifyElement(unsigned short elem_index, 82 unsigned short source, size_t offset, VertexElementType theType, 83 VertexElementSemantic semantic, unsigned short index) 84 { 85 VertexDeclaration::modifyElement(elem_index, source, offset, theType, semantic, index); 86 releaseDeclaration(); 87 } 88 89 //----------------------------------------------------------------------- notifyOnDeviceCreate(IDirect3DDevice9 * d3d9Device)90 void D3D9VertexDeclaration::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) 91 { 92 93 } 94 95 //----------------------------------------------------------------------- notifyOnDeviceDestroy(IDirect3DDevice9 * d3d9Device)96 void D3D9VertexDeclaration::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) 97 { 98 D3D9_DEVICE_ACCESS_CRITICAL_SECTION 99 100 DeviceToDeclarationIterator it = mMapDeviceToDeclaration.find(d3d9Device); 101 102 if (it != mMapDeviceToDeclaration.end()) 103 { 104 SAFE_RELEASE(it->second); 105 mMapDeviceToDeclaration.erase(it); 106 } 107 } 108 109 //----------------------------------------------------------------------- getD3DVertexDeclaration(VertexDeclaration * globalDeclaration,bool useGlobalInstancingVertexBufferIsAvailable)110 IDirect3DVertexDeclaration9* D3D9VertexDeclaration::getD3DVertexDeclaration( 111 VertexDeclaration * globalDeclaration, bool useGlobalInstancingVertexBufferIsAvailable) 112 { 113 if (mLastUsedGlobalDeclaration != globalDeclaration || 114 useGlobalInstancingVertexBufferIsAvailable != mUsedGlobalDeclaration ) 115 { 116 releaseDeclaration(); 117 mLastUsedGlobalDeclaration = globalDeclaration; 118 mUsedGlobalDeclaration = useGlobalInstancingVertexBufferIsAvailable; 119 } 120 121 IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device(); 122 DeviceToDeclarationIterator it = mMapDeviceToDeclaration.find(pCurDevice); 123 IDirect3DVertexDeclaration9* lpVertDecl = NULL; 124 125 // Case we have to create the declaration for this device. 126 if (it == mMapDeviceToDeclaration.end() || it->second == NULL) 127 { 128 size_t d3delemsSize = mElementList.size() + 1; 129 if(mLastUsedGlobalDeclaration != NULL && mUsedGlobalDeclaration ) 130 { 131 d3delemsSize += globalDeclaration->getElementCount(); 132 } 133 D3DVERTEXELEMENT9* d3delems = OGRE_ALLOC_T(D3DVERTEXELEMENT9, d3delemsSize, MEMCATEGORY_RENDERSYS); 134 135 VertexElementList::const_iterator i, iend; 136 unsigned int idx; 137 size_t maxSource = 0; 138 iend = mElementList.end(); 139 for (idx = 0, i = mElementList.begin(); i != iend; ++i, ++idx) 140 { 141 const VertexElement & element = *i; 142 D3DVERTEXELEMENT9 & dxElement = d3delems[idx]; 143 convertElement(element, dxElement); 144 if(element.getSource() > maxSource) 145 { 146 maxSource = element.getSource(); 147 } 148 } 149 150 if(mLastUsedGlobalDeclaration != NULL && mUsedGlobalDeclaration ) 151 { 152 iend = globalDeclaration->getElements().end(); 153 for (i = globalDeclaration->getElements().begin(); i != iend; ++i, ++idx) 154 { 155 const VertexElement & element = *i; 156 D3DVERTEXELEMENT9 & dxElement = d3delems[idx]; 157 convertElement(element, dxElement); 158 dxElement.Stream = maxSource + 1; 159 } 160 } 161 162 163 // Add terminator 164 d3delems[idx].Stream = 0xff; 165 d3delems[idx].Offset = 0; 166 d3delems[idx].Type = D3DDECLTYPE_UNUSED; 167 d3delems[idx].Method = 0; 168 d3delems[idx].Usage = 0; 169 d3delems[idx].UsageIndex = 0; 170 171 172 HRESULT hr = pCurDevice->CreateVertexDeclaration(d3delems, &lpVertDecl); 173 174 if (FAILED(hr)) 175 { 176 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 177 "Cannot create D3D9 vertex declaration: " + 178 Root::getSingleton().getErrorDescription(hr), 179 "Direct3D9VertexDeclaration::getD3DVertexDeclaration"); 180 } 181 182 OGRE_FREE(d3delems, MEMCATEGORY_RENDERSYS); 183 184 mMapDeviceToDeclaration[pCurDevice] = lpVertDecl; 185 } 186 187 // Declaration already exits. 188 else 189 { 190 lpVertDecl = mMapDeviceToDeclaration[pCurDevice]; 191 } 192 193 return lpVertDecl; 194 } 195 //----------------------------------------------------------------------- releaseDeclaration()196 void D3D9VertexDeclaration::releaseDeclaration() 197 { 198 D3D9_DEVICE_ACCESS_CRITICAL_SECTION 199 200 DeviceToDeclarationIterator it = mMapDeviceToDeclaration.begin(); 201 202 while (it != mMapDeviceToDeclaration.end()) 203 { 204 SAFE_RELEASE(it->second); 205 ++it; 206 } 207 mMapDeviceToDeclaration.clear(); 208 } 209 //----------------------------------------------------------------------- convertElement(const VertexElement & element,D3DVERTEXELEMENT9 & dxElement)210 void D3D9VertexDeclaration::convertElement( const VertexElement & element, D3DVERTEXELEMENT9 & dxElement ) 211 { 212 dxElement.Method = D3DDECLMETHOD_DEFAULT; 213 dxElement.Offset = static_cast<WORD>(element.getOffset()); 214 dxElement.Stream = element.getSource(); 215 dxElement.Type = D3D9Mappings::get(element.getType()); 216 dxElement.Usage = D3D9Mappings::get(element.getSemantic()); 217 // NB force index if colours since D3D uses the same usage for 218 // diffuse & specular 219 if (element.getSemantic() == VES_SPECULAR) 220 { 221 dxElement.UsageIndex = 1; 222 } 223 else if (element.getSemantic() == VES_DIFFUSE) 224 { 225 dxElement.UsageIndex = 0; 226 } 227 else 228 { 229 dxElement.UsageIndex = static_cast<BYTE>(element.getIndex()); 230 } 231 } 232 //----------------------------------------------------------------------- 233 234 235 } 236 237