• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Direct3DVertexDeclaration9.hpp"
16 
17 #include "Direct3DDevice9.hpp"
18 #include "Debug.hpp"
19 
20 #include <d3d9types.h>
21 #include <stdio.h>
22 #include <assert.h>
23 
24 namespace D3D9
25 {
Direct3DVertexDeclaration9(Direct3DDevice9 * device,const D3DVERTEXELEMENT9 * vertexElement)26 	Direct3DVertexDeclaration9::Direct3DVertexDeclaration9(Direct3DDevice9 *device, const D3DVERTEXELEMENT9 *vertexElement) : device(device)
27 	{
28 		int size = sizeof(D3DVERTEXELEMENT9);
29 		const D3DVERTEXELEMENT9 *element = vertexElement;
30 		preTransformed = false;
31 
32 		while(element->Stream != 0xFF)
33 		{
34 			if(element->Usage == D3DDECLUSAGE_POSITIONT)
35 			{
36 				preTransformed = true;
37 			}
38 
39 			size += sizeof(D3DVERTEXELEMENT9);
40 			element++;
41 		}
42 
43 		numElements = size / sizeof(D3DVERTEXELEMENT9);
44 		this->vertexElement = new D3DVERTEXELEMENT9[numElements];
45 		memcpy(this->vertexElement, vertexElement, size);
46 
47 		FVF = computeFVF();
48 	}
49 
Direct3DVertexDeclaration9(Direct3DDevice9 * device,unsigned long FVF)50 	Direct3DVertexDeclaration9::Direct3DVertexDeclaration9(Direct3DDevice9 *device, unsigned long FVF) : device(device)
51 	{
52 		this->FVF = FVF;
53 
54 		vertexElement = new D3DVERTEXELEMENT9[MAX_VERTEX_INPUTS];
55 
56 		numElements = 0;
57 		int offset = 0;
58 		preTransformed = false;
59 
60 		switch(FVF & D3DFVF_POSITION_MASK)
61 		{
62 		case 0:
63 			// No position stream
64 			break;
65 		case D3DFVF_XYZ:
66 			vertexElement[numElements].Stream = 0;
67 			vertexElement[numElements].Offset = offset;
68 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
69 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
70 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
71 			vertexElement[numElements].UsageIndex = 0;
72 			numElements++;
73 			offset += 4 * 3;
74 			break;
75 		case D3DFVF_XYZRHW:
76 			preTransformed = true;
77 			vertexElement[numElements].Stream = 0;
78 			vertexElement[numElements].Offset = offset;
79 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT4;
80 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
81 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITIONT;
82 			vertexElement[numElements].UsageIndex = 0;
83 			numElements++;
84 			offset += 4 * 4;
85 			break;
86 		case D3DFVF_XYZB1:
87 			vertexElement[numElements].Stream = 0;
88 			vertexElement[numElements].Offset = offset;
89 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
90 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
91 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
92 			vertexElement[numElements].UsageIndex = 0;
93 			numElements++;
94 			offset += 4 * 3;
95 
96 			vertexElement[numElements].Stream = 0;
97 			vertexElement[numElements].Offset = offset;
98 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT1;
99 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
100 			vertexElement[numElements].Usage = D3DDECLUSAGE_BLENDWEIGHT;
101 			vertexElement[numElements].UsageIndex = 0;
102 			numElements++;
103 			offset += 4 * 1;
104 			break;
105 		case D3DFVF_XYZB2:
106 			vertexElement[numElements].Stream = 0;
107 			vertexElement[numElements].Offset = offset;
108 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
109 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
110 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
111 			vertexElement[numElements].UsageIndex = 0;
112 			numElements++;
113 			offset += 4 * 3;
114 
115 			vertexElement[numElements].Stream = 0;
116 			vertexElement[numElements].Offset = offset;
117 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT2;
118 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
119 			vertexElement[numElements].Usage = D3DDECLUSAGE_BLENDWEIGHT;
120 			vertexElement[numElements].UsageIndex = 0;
121 			numElements++;
122 			offset += 4 * 2;
123 			break;
124 		case D3DFVF_XYZB3:
125 			vertexElement[numElements].Stream = 0;
126 			vertexElement[numElements].Offset = offset;
127 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
128 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
129 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
130 			vertexElement[numElements].UsageIndex = 0;
131 			numElements++;
132 			offset += 4 * 3;
133 
134 			vertexElement[numElements].Stream = 0;
135 			vertexElement[numElements].Offset = offset;
136 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
137 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
138 			vertexElement[numElements].Usage = D3DDECLUSAGE_BLENDWEIGHT;
139 			vertexElement[numElements].UsageIndex = 0;
140 			numElements++;
141 			offset += 4 * 3;
142 			break;
143 		case D3DFVF_XYZB4:
144 			vertexElement[numElements].Stream = 0;
145 			vertexElement[numElements].Offset = offset;
146 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
147 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
148 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
149 			vertexElement[numElements].UsageIndex = 0;
150 			numElements++;
151 			offset += 4 * 3;
152 
153 			vertexElement[numElements].Stream = 0;
154 			vertexElement[numElements].Offset = offset;
155 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT4;
156 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
157 			vertexElement[numElements].Usage = D3DDECLUSAGE_BLENDWEIGHT;
158 			vertexElement[numElements].UsageIndex = 0;
159 			numElements++;
160 			offset += 4 * 4;
161 			break;
162 		case D3DFVF_XYZB5:
163 			vertexElement[numElements].Stream = 0;
164 			vertexElement[numElements].Offset = offset;
165 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
166 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
167 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
168 			vertexElement[numElements].UsageIndex = 0;
169 			numElements++;
170 			offset += 4 * 3;
171 
172 			vertexElement[numElements].Stream = 0;
173 			vertexElement[numElements].Offset = offset;
174 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT4;
175 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
176 			vertexElement[numElements].Usage = D3DDECLUSAGE_BLENDWEIGHT;
177 			vertexElement[numElements].UsageIndex = 0;
178 			numElements++;
179 			offset += 4 * 5;
180 			break;
181 		case D3DFVF_XYZW:
182 			vertexElement[numElements].Stream = 0;
183 			vertexElement[numElements].Offset = offset;
184 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT4;
185 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
186 			vertexElement[numElements].Usage = D3DDECLUSAGE_POSITION;
187 			vertexElement[numElements].UsageIndex = 0;
188 			numElements++;
189 			offset += 4 * 4;
190 			break;
191 		default:
192 			ASSERT(false);
193 		}
194 
195 		if(FVF & D3DFVF_NORMAL)
196 		{
197 			vertexElement[numElements].Stream = 0;
198 			vertexElement[numElements].Offset = offset;
199 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT3;
200 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
201 			vertexElement[numElements].Usage = D3DDECLUSAGE_NORMAL;
202 			vertexElement[numElements].UsageIndex = 0;
203 			numElements++;
204 			offset += 4 * 3;
205 		}
206 
207 		if(FVF & D3DFVF_PSIZE)
208 		{
209 			vertexElement[numElements].Stream = 0;
210 			vertexElement[numElements].Offset = offset;
211 			vertexElement[numElements].Type = D3DDECLTYPE_FLOAT1;
212 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
213 			vertexElement[numElements].Usage = D3DDECLUSAGE_PSIZE;
214 			vertexElement[numElements].UsageIndex = 0;
215 			numElements++;
216 			offset += 4;
217 		}
218 
219 		if(FVF & D3DFVF_DIFFUSE)
220 		{
221 			vertexElement[numElements].Stream = 0;
222 			vertexElement[numElements].Offset = offset;
223 			vertexElement[numElements].Type = D3DDECLTYPE_D3DCOLOR;
224 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
225 			vertexElement[numElements].Usage = D3DDECLUSAGE_COLOR;
226 			vertexElement[numElements].UsageIndex = 0;
227 			numElements++;
228 			offset += 4;
229 		}
230 
231 		if(FVF & D3DFVF_SPECULAR)
232 		{
233 			vertexElement[numElements].Stream = 0;
234 			vertexElement[numElements].Offset = offset;
235 			vertexElement[numElements].Type = D3DDECLTYPE_D3DCOLOR;
236 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
237 			vertexElement[numElements].Usage = D3DDECLUSAGE_COLOR;
238 			vertexElement[numElements].UsageIndex = 1;
239 			numElements++;
240 			offset += 4;
241 		}
242 
243 		int numTexCoord = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
244 		int textureFormats = (FVF >> 16) & 0xFFFF;
245 
246 		static const int textureSize[4] =
247 		{
248 			2 * 4,   // D3DFVF_TEXTUREFORMAT2
249 			3 * 4,   // D3DFVF_TEXTUREFORMAT3
250 			4 * 4,   // D3DFVF_TEXTUREFORMAT4
251 			1 * 4    // D3DFVF_TEXTUREFORMAT1
252 		};
253 
254 		static const D3DDECLTYPE textureType[4] =
255 		{
256 			D3DDECLTYPE_FLOAT2,   // D3DFVF_TEXTUREFORMAT2
257 			D3DDECLTYPE_FLOAT3,   // D3DFVF_TEXTUREFORMAT3
258 			D3DDECLTYPE_FLOAT4,   // D3DFVF_TEXTUREFORMAT4
259 			D3DDECLTYPE_FLOAT1    // D3DFVF_TEXTUREFORMAT1
260 		};
261 
262 		for(int i = 0; i < numTexCoord; i++)
263 		{
264 			vertexElement[numElements].Stream = 0;
265 			vertexElement[numElements].Offset = offset;
266 			vertexElement[numElements].Type = textureType[textureFormats & 0x3];
267 			vertexElement[numElements].Method = D3DDECLMETHOD_DEFAULT;
268 			vertexElement[numElements].Usage = D3DDECLUSAGE_TEXCOORD;
269 			vertexElement[numElements].UsageIndex = i;
270 			numElements++;
271 			offset += textureSize[textureFormats & 0x3];
272 			textureFormats >>= 2;
273 		}
274 
275 		// D3DDECL_END()
276 		vertexElement[numElements].Stream = 0xFF;
277 		vertexElement[numElements].Offset = 0;
278 		vertexElement[numElements].Type = D3DDECLTYPE_UNUSED;
279 		vertexElement[numElements].Method = 0;
280 		vertexElement[numElements].Usage = 0;
281 		vertexElement[numElements].UsageIndex = 0;
282 		numElements++;
283 	}
284 
~Direct3DVertexDeclaration9()285 	Direct3DVertexDeclaration9::~Direct3DVertexDeclaration9()
286 	{
287 		delete[] vertexElement;
288 		vertexElement = 0;
289 	}
290 
QueryInterface(const IID & iid,void ** object)291 	long Direct3DVertexDeclaration9::QueryInterface(const IID &iid, void **object)
292 	{
293 		CriticalSection cs(device);
294 
295 		TRACE("");
296 
297 		if(iid == IID_IDirect3DVertexDeclaration9 ||
298 		   iid == IID_IUnknown)
299 		{
300 			AddRef();
301 			*object = this;
302 
303 			return S_OK;
304 		}
305 
306 		*object = 0;
307 
308 		return NOINTERFACE(iid);
309 	}
310 
AddRef()311 	unsigned long Direct3DVertexDeclaration9::AddRef()
312 	{
313 		TRACE("");
314 
315 		return Unknown::AddRef();
316 	}
317 
Release()318 	unsigned long Direct3DVertexDeclaration9::Release()
319 	{
320 		TRACE("");
321 
322 		return Unknown::Release();
323 	}
324 
GetDevice(IDirect3DDevice9 ** device)325 	long Direct3DVertexDeclaration9::GetDevice(IDirect3DDevice9 **device)
326 	{
327 		CriticalSection cs(this->device);
328 
329 		TRACE("");
330 
331 		if(!device)
332 		{
333 			return INVALIDCALL();
334 		}
335 
336 		this->device->AddRef();
337 		*device = this->device;
338 
339 		return D3D_OK;
340 	}
341 
GetDeclaration(D3DVERTEXELEMENT9 * declaration,unsigned int * numElements)342 	long Direct3DVertexDeclaration9::GetDeclaration(D3DVERTEXELEMENT9 *declaration, unsigned int *numElements)
343 	{
344 		CriticalSection cs(device);
345 
346 		TRACE("");
347 
348 		if(!declaration || !numElements)
349 		{
350 			return INVALIDCALL();
351 		}
352 
353 		*numElements = this->numElements;
354 
355 		for(int i = 0; i < this->numElements; i++)
356 		{
357 			declaration[i] = vertexElement[i];
358 		}
359 
360 		return D3D_OK;
361 	}
362 
getFVF() const363 	unsigned long Direct3DVertexDeclaration9::getFVF() const
364 	{
365 		return FVF;
366 	}
367 
isPreTransformed() const368 	bool Direct3DVertexDeclaration9::isPreTransformed() const
369 	{
370 		return preTransformed;
371 	}
372 
computeFVF()373 	unsigned long Direct3DVertexDeclaration9::computeFVF()
374 	{
375 		unsigned long FVF = 0;
376 
377 		int textureBits = 0;
378 		int numBlendWeights = 0;
379 
380 		for(int i = 0; i < numElements - 1; i++)
381 		{
382 			D3DVERTEXELEMENT9 &element = vertexElement[i];
383 
384 			if(element.Stream != 0)
385 			{
386 				return 0;
387 			}
388 
389 			switch(element.Usage)
390 			{
391 			case D3DDECLUSAGE_POSITION:
392 				if(element.Type == D3DDECLTYPE_FLOAT3 && element.UsageIndex == 0)
393 				{
394 					FVF |= D3DFVF_XYZ;
395 				}
396 				else
397 				{
398 					return 0;
399 				}
400 				break;
401 			case D3DDECLUSAGE_POSITIONT:
402 				if(element.Type == D3DDECLTYPE_FLOAT4 && element.UsageIndex == 0)
403 				{
404 					FVF |= D3DFVF_XYZRHW;
405 				}
406 				else
407 				{
408 					return 0;
409 				}
410 				break;
411 			case D3DDECLUSAGE_BLENDWEIGHT:
412 				if(element.Type <= D3DDECLTYPE_FLOAT4 && element.UsageIndex == 0)
413 				{
414 					numBlendWeights += element.Type + 1;
415 				}
416 				else
417 				{
418 					return 0;
419 				}
420 				break;
421 			case D3DDECLUSAGE_BLENDINDICES:
422 				return 0;
423 				break;
424 			case D3DDECLUSAGE_NORMAL:
425 				if(element.Type == D3DDECLTYPE_FLOAT3 && element.UsageIndex == 0)
426 				{
427 					FVF |= D3DFVF_NORMAL;
428 				}
429 				else
430 				{
431 					return 0;
432 				}
433 				break;
434 			case D3DDECLUSAGE_PSIZE:
435 				if(element.Type == D3DDECLTYPE_FLOAT1 && element.UsageIndex == 0)
436 				{
437 					FVF |= D3DFVF_PSIZE;
438 				}
439 				else
440 				{
441 					return 0;
442 				}
443 				break;
444 			case D3DDECLUSAGE_COLOR:
445 				if(element.Type == D3DDECLTYPE_D3DCOLOR && element.UsageIndex < 2)
446 				{
447 					if(element.UsageIndex == 0)
448 					{
449 						FVF |= D3DFVF_DIFFUSE;
450 					}
451 					else   // element.UsageIndex == 1
452 					{
453 						FVF |= D3DFVF_SPECULAR;
454 					}
455 				}
456 				else
457 				{
458 					return 0;
459 				}
460 				break;
461 			case D3DDECLUSAGE_TEXCOORD:
462 				if((element.Type > D3DDECLTYPE_FLOAT4) || (element.UsageIndex > 7))
463 				{
464 					return 0;
465 				}
466 
467 				int bit = 1 << element.UsageIndex;
468 
469 				if(textureBits & bit)
470 				{
471 					return 0;
472 				}
473 
474 				textureBits |= bit;
475 
476 				switch(element.Type)
477 				{
478 				case D3DDECLTYPE_FLOAT1:
479 					FVF |= D3DFVF_TEXCOORDSIZE1(element.UsageIndex);
480 					break;
481 				case D3DDECLTYPE_FLOAT2:
482 					FVF |= D3DFVF_TEXCOORDSIZE2(element.UsageIndex);
483 					break;
484 				case D3DDECLTYPE_FLOAT3:
485 					FVF |= D3DFVF_TEXCOORDSIZE3(element.UsageIndex);
486 					break;
487 				case D3DDECLTYPE_FLOAT4:
488 					FVF |= D3DFVF_TEXCOORDSIZE4(element.UsageIndex);
489 					break;
490 				}
491 			}
492 		}
493 
494 		bool isTransformed = (FVF & D3DFVF_XYZRHW) != 0;
495 
496 		if(isTransformed)
497 		{
498 			if(numBlendWeights != 0)
499 			{
500 				return 0;
501 			}
502 		}
503 		else if((FVF & D3DFVF_XYZ) == 0)
504 		{
505 			return 0;
506 		}
507 
508 		int positionMask = isTransformed ? 0x2 : 0x1;
509 
510 		if(numBlendWeights)
511 		{
512 			positionMask += numBlendWeights + 1;
513 		}
514 
515 		int numTexCoord = 0;
516 
517 		while(textureBits & 1)
518 		{
519 			textureBits >>= 1;
520 
521 			numTexCoord++;
522 		}
523 
524 		if(textureBits)   // FVF does not allow
525 		{
526 			return 0;
527 		}
528 
529 		FVF |= D3DFVF_POSITION_MASK & (positionMask << 1);
530 		FVF |= numTexCoord << D3DFVF_TEXCOUNT_SHIFT;
531 
532 		return FVF;
533 	}
534 }
535