Home | History | Annotate | Download | only in D3D9
      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 {
     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 
     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 
    285 	Direct3DVertexDeclaration9::~Direct3DVertexDeclaration9()
    286 	{
    287 		delete[] vertexElement;
    288 		vertexElement = 0;
    289 	}
    290 
    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 
    311 	unsigned long Direct3DVertexDeclaration9::AddRef()
    312 	{
    313 		TRACE("");
    314 
    315 		return Unknown::AddRef();
    316 	}
    317 
    318 	unsigned long Direct3DVertexDeclaration9::Release()
    319 	{
    320 		TRACE("");
    321 
    322 		return Unknown::Release();
    323 	}
    324 
    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 
    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 
    363 	unsigned long Direct3DVertexDeclaration9::getFVF() const
    364 	{
    365 		return FVF;
    366 	}
    367 
    368 	bool Direct3DVertexDeclaration9::isPreTransformed() const
    369 	{
    370 		return preTransformed;
    371 	}
    372 
    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