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