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