1 #ifdef __REACTOS__ 2 #include "precomp.h" 3 #else 4 /* 5 * Copyright 2008 Luis Busquets 6 * Copyright 2009 Matteo Bruni 7 * Copyright 2010, 2013, 2016 Christian Costa 8 * Copyright 2011 Travis Athougies 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 25 #include <stdio.h> 26 #include "d3dx9_private.h" 27 #include "d3dcommon.h" 28 #include "d3dcompiler.h" 29 #endif /* __REACTOS__ */ 30 31 WINE_DEFAULT_DEBUG_CHANNEL(d3dx); 32 33 /* This function is not declared in the SDK headers yet. */ 34 HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename, 35 const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags, 36 ID3DBlob **shader, ID3DBlob **error_messages); 37 38 static inline BOOL is_valid_bytecode(DWORD token) 39 { 40 return (token & 0xfffe0000) == 0xfffe0000; 41 } 42 43 const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device) 44 { 45 D3DCAPS9 caps; 46 47 TRACE("device %p\n", device); 48 49 if (!device) return NULL; 50 51 IDirect3DDevice9_GetDeviceCaps(device,&caps); 52 53 switch (caps.PixelShaderVersion) 54 { 55 case D3DPS_VERSION(1, 1): 56 return "ps_1_1"; 57 58 case D3DPS_VERSION(1, 2): 59 return "ps_1_2"; 60 61 case D3DPS_VERSION(1, 3): 62 return "ps_1_3"; 63 64 case D3DPS_VERSION(1, 4): 65 return "ps_1_4"; 66 67 case D3DPS_VERSION(2, 0): 68 if ((caps.PS20Caps.NumTemps>=22) && 69 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) && 70 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) && 71 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) && 72 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) && 73 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT)) 74 { 75 return "ps_2_a"; 76 } 77 if ((caps.PS20Caps.NumTemps>=32) && 78 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT)) 79 { 80 return "ps_2_b"; 81 } 82 return "ps_2_0"; 83 84 case D3DPS_VERSION(3, 0): 85 return "ps_3_0"; 86 } 87 88 return NULL; 89 } 90 91 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code) 92 { 93 const DWORD *ptr = byte_code; 94 95 TRACE("byte_code %p\n", byte_code); 96 97 if (!ptr) return 0; 98 99 /* Look for the END token, skipping the VERSION token */ 100 while (*++ptr != D3DSIO_END) 101 { 102 /* Skip comments */ 103 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT) 104 { 105 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT); 106 } 107 } 108 ++ptr; 109 110 /* Return the shader size in bytes */ 111 return (ptr - byte_code) * sizeof(*ptr); 112 } 113 114 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code) 115 { 116 TRACE("byte_code %p\n", byte_code); 117 118 return byte_code ? *byte_code : 0; 119 } 120 121 const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device) 122 { 123 D3DCAPS9 caps; 124 125 TRACE("device %p\n", device); 126 127 if (!device) return NULL; 128 129 IDirect3DDevice9_GetDeviceCaps(device,&caps); 130 131 switch (caps.VertexShaderVersion) 132 { 133 case D3DVS_VERSION(1, 1): 134 return "vs_1_1"; 135 case D3DVS_VERSION(2, 0): 136 if ((caps.VS20Caps.NumTemps>=13) && 137 (caps.VS20Caps.DynamicFlowControlDepth==24) && 138 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION)) 139 { 140 return "vs_2_a"; 141 } 142 return "vs_2_0"; 143 case D3DVS_VERSION(3, 0): 144 return "vs_3_0"; 145 } 146 147 return NULL; 148 } 149 150 HRESULT WINAPI D3DXFindShaderComment(const DWORD *byte_code, DWORD fourcc, const void **data, UINT *size) 151 { 152 const DWORD *ptr = byte_code; 153 DWORD version; 154 155 TRACE("byte_code %p, fourcc %x, data %p, size %p\n", byte_code, fourcc, data, size); 156 157 if (data) *data = NULL; 158 if (size) *size = 0; 159 160 if (!byte_code) return D3DERR_INVALIDCALL; 161 162 version = *ptr >> 16; 163 if (version != 0x4658 /* FX */ 164 && version != 0x5458 /* TX */ 165 && version != 0x7ffe 166 && version != 0x7fff 167 && version != 0xfffe /* VS */ 168 && version != 0xffff) /* PS */ 169 { 170 WARN("Invalid data supplied\n"); 171 return D3DXERR_INVALIDDATA; 172 } 173 174 while (*++ptr != D3DSIO_END) 175 { 176 /* Check if it is a comment */ 177 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT) 178 { 179 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT; 180 181 /* Check if this is the comment we are looking for */ 182 if (*(ptr + 1) == fourcc) 183 { 184 UINT ctab_size = (comment_size - 1) * sizeof(DWORD); 185 const void *ctab_data = ptr + 2; 186 if (size) 187 *size = ctab_size; 188 if (data) 189 *data = ctab_data; 190 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size); 191 return D3D_OK; 192 } 193 ptr += comment_size; 194 } 195 } 196 197 return S_FALSE; 198 } 199 200 HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMACRO *defines, 201 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 202 { 203 HRESULT hr; 204 205 TRACE("data %p, data_len %u, defines %p, include %p, flags %#x, shader %p, error_messages %p\n", 206 data, data_len, defines, include, flags, shader, error_messages); 207 208 /* Forward to d3dcompiler: the parameter types aren't really different, 209 the actual data types are equivalent */ 210 hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines, 211 (ID3DInclude *)include, flags, (ID3DBlob **)shader, 212 (ID3DBlob **)error_messages); 213 214 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA; 215 return hr; 216 } 217 218 static const void *main_file_data; 219 220 static CRITICAL_SECTION_DEBUG from_file_mutex_debug = 221 { 222 0, 0, &from_file_mutex, 223 { 224 &from_file_mutex_debug.ProcessLocksList, 225 &from_file_mutex_debug.ProcessLocksList 226 }, 227 0, 0, {(DWORD_PTR)(__FILE__ ": from_file_mutex")} 228 }; 229 CRITICAL_SECTION from_file_mutex = {&from_file_mutex_debug, -1, 0, 0, 0, 0}; 230 231 /* D3DXInclude private implementation, used to implement 232 * D3DXAssembleShaderFromFile() from D3DXAssembleShader(). */ 233 /* To be able to correctly resolve include search paths we have to store the 234 * pathname of each include file. We store the pathname pointer right before 235 * the file data. */ 236 static HRESULT WINAPI d3dx_include_from_file_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, 237 const char *filename, const void *parent_data, const void **data, UINT *bytes) 238 { 239 const char *p, *parent_name = ""; 240 char *pathname = NULL, *ptr; 241 char **buffer = NULL; 242 HANDLE file; 243 UINT size; 244 245 if (parent_data) 246 { 247 parent_name = *((const char **)parent_data - 1); 248 } 249 else 250 { 251 if (main_file_data) 252 parent_name = *((const char **)main_file_data - 1); 253 } 254 255 TRACE("Looking up include file %s, parent %s.\n", debugstr_a(filename), debugstr_a(parent_name)); 256 257 if ((p = strrchr(parent_name, '\\'))) 258 ++p; 259 else 260 p = parent_name; 261 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1); 262 if(!pathname) 263 return HRESULT_FROM_WIN32(GetLastError()); 264 265 memcpy(pathname, parent_name, p - parent_name); 266 strcpy(pathname + (p - parent_name), filename); 267 ptr = pathname + (p - parent_name); 268 while (*ptr) 269 { 270 if (*ptr == '/') 271 *ptr = '\\'; 272 ++ptr; 273 } 274 275 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 276 if(file == INVALID_HANDLE_VALUE) 277 goto error; 278 279 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname)); 280 281 size = GetFileSize(file, NULL); 282 if(size == INVALID_FILE_SIZE) 283 goto error; 284 285 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *)); 286 if(!buffer) 287 goto error; 288 *buffer = pathname; 289 if(!ReadFile(file, buffer + 1, size, bytes, NULL)) 290 goto error; 291 292 *data = buffer + 1; 293 if (!main_file_data) 294 main_file_data = *data; 295 296 CloseHandle(file); 297 return S_OK; 298 299 error: 300 CloseHandle(file); 301 HeapFree(GetProcessHeap(), 0, pathname); 302 HeapFree(GetProcessHeap(), 0, buffer); 303 return HRESULT_FROM_WIN32(GetLastError()); 304 } 305 306 static HRESULT WINAPI d3dx_include_from_file_close(ID3DXInclude *iface, const void *data) 307 { 308 HeapFree(GetProcessHeap(), 0, *((char **)data - 1)); 309 HeapFree(GetProcessHeap(), 0, (char **)data - 1); 310 if (main_file_data == data) 311 main_file_data = NULL; 312 return S_OK; 313 } 314 315 const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl = 316 { 317 d3dx_include_from_file_open, 318 d3dx_include_from_file_close 319 }; 320 321 HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines, 322 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 323 { 324 WCHAR *filename_w; 325 DWORD len; 326 HRESULT ret; 327 328 TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n", 329 debugstr_a(filename), defines, include, flags, shader, error_messages); 330 331 if (!filename) return D3DXERR_INVALIDDATA; 332 333 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0); 334 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 335 if (!filename_w) return E_OUTOFMEMORY; 336 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len); 337 338 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages); 339 340 HeapFree(GetProcessHeap(), 0, filename_w); 341 return ret; 342 } 343 344 HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines, 345 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 346 { 347 const void *buffer; 348 DWORD len; 349 HRESULT hr; 350 struct d3dx_include_from_file include_from_file; 351 char *filename_a; 352 353 TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n", 354 debugstr_w(filename), defines, include, flags, shader, error_messages); 355 356 if(!include) 357 { 358 include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; 359 include = &include_from_file.ID3DXInclude_iface; 360 } 361 362 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); 363 filename_a = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); 364 if (!filename_a) 365 return E_OUTOFMEMORY; 366 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL); 367 368 EnterCriticalSection(&from_file_mutex); 369 hr = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &len); 370 if (FAILED(hr)) 371 { 372 LeaveCriticalSection(&from_file_mutex); 373 HeapFree(GetProcessHeap(), 0, filename_a); 374 return D3DXERR_INVALIDDATA; 375 } 376 377 hr = D3DXAssembleShader(buffer, len, defines, include, flags, shader, error_messages); 378 379 ID3DXInclude_Close(include, buffer); 380 LeaveCriticalSection(&from_file_mutex); 381 HeapFree(GetProcessHeap(), 0, filename_a); 382 return hr; 383 } 384 385 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines, 386 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 387 { 388 void *buffer; 389 HRSRC res; 390 DWORD len; 391 392 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n", 393 module, debugstr_a(resource), defines, include, flags, shader, error_messages); 394 395 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA))) 396 return D3DXERR_INVALIDDATA; 397 if (FAILED(load_resource_into_memory(module, res, &buffer, &len))) 398 return D3DXERR_INVALIDDATA; 399 return D3DXAssembleShader(buffer, len, defines, include, flags, 400 shader, error_messages); 401 } 402 403 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines, 404 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 405 { 406 void *buffer; 407 HRSRC res; 408 DWORD len; 409 410 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n", 411 module, debugstr_w(resource), defines, include, flags, shader, error_messages); 412 413 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA))) 414 return D3DXERR_INVALIDDATA; 415 if (FAILED(load_resource_into_memory(module, res, &buffer, &len))) 416 return D3DXERR_INVALIDDATA; 417 return D3DXAssembleShader(buffer, len, defines, include, flags, 418 shader, error_messages); 419 } 420 421 HRESULT WINAPI D3DXCompileShader(const char *data, UINT length, const D3DXMACRO *defines, 422 ID3DXInclude *include, const char *function, const char *profile, DWORD flags, 423 ID3DXBuffer **shader, ID3DXBuffer **error_msgs, ID3DXConstantTable **constant_table) 424 { 425 HRESULT hr; 426 427 TRACE("data %s, length %u, defines %p, include %p, function %s, profile %s, " 428 "flags %#x, shader %p, error_msgs %p, constant_table %p.\n", 429 debugstr_a(data), length, defines, include, debugstr_a(function), debugstr_a(profile), 430 flags, shader, error_msgs, constant_table); 431 432 if (D3DX_SDK_VERSION <= 36) 433 flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; 434 435 hr = D3DCompile(data, length, NULL, (D3D_SHADER_MACRO *)defines, (ID3DInclude *)include, 436 function, profile, flags, 0, (ID3DBlob **)shader, (ID3DBlob **)error_msgs); 437 438 if (SUCCEEDED(hr) && constant_table) 439 { 440 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader), constant_table); 441 if (FAILED(hr)) 442 { 443 ID3DXBuffer_Release(*shader); 444 *shader = NULL; 445 } 446 } 447 448 /* Filter out D3DCompile warning messages that are not present with D3DCompileShader */ 449 if (SUCCEEDED(hr) && error_msgs && *error_msgs) 450 { 451 char *messages = ID3DXBuffer_GetBufferPointer(*error_msgs); 452 DWORD size = ID3DXBuffer_GetBufferSize(*error_msgs); 453 454 /* Ensure messages are null terminated for safe processing */ 455 if (size) messages[size - 1] = 0; 456 457 while (size > 1) 458 { 459 char *prev, *next; 460 461 /* Warning has the form "warning X3206: ... implicit truncation of vector type" 462 but we only search for "X3206:" in case d3dcompiler_43 has localization */ 463 prev = next = strstr(messages, "X3206:"); 464 if (!prev) break; 465 466 /* get pointer to beginning and end of current line */ 467 while (prev > messages && *(prev - 1) != '\n') prev--; 468 while (next < messages + size - 1 && *next != '\n') next++; 469 if (next < messages + size - 1 && *next == '\n') next++; 470 471 memmove(prev, next, messages + size - next); 472 size -= (next - prev); 473 } 474 475 /* Only return a buffer if the resulting string is not empty as some apps depend on that */ 476 if (size <= 1) 477 { 478 ID3DXBuffer_Release(*error_msgs); 479 *error_msgs = NULL; 480 } 481 } 482 483 return hr; 484 } 485 486 HRESULT WINAPI D3DXCompileShaderFromFileA(const char *filename, const D3DXMACRO *defines, 487 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags, 488 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table) 489 { 490 WCHAR *filename_w; 491 DWORD len; 492 HRESULT ret; 493 494 TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, " 495 "flags %#x, shader %p, error_messages %p, constant_table %p.\n", 496 debugstr_a(filename), defines, include, debugstr_a(entrypoint), 497 debugstr_a(profile), flags, shader, error_messages, constant_table); 498 499 if (!filename) return D3DXERR_INVALIDDATA; 500 501 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0); 502 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 503 if (!filename_w) return E_OUTOFMEMORY; 504 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len); 505 506 ret = D3DXCompileShaderFromFileW(filename_w, defines, include, 507 entrypoint, profile, flags, 508 shader, error_messages, constant_table); 509 510 HeapFree(GetProcessHeap(), 0, filename_w); 511 return ret; 512 } 513 514 HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines, 515 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags, 516 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table) 517 { 518 const void *buffer; 519 DWORD len, filename_len; 520 HRESULT hr; 521 struct d3dx_include_from_file include_from_file; 522 char *filename_a; 523 524 TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, " 525 "flags %#x, shader %p, error_messages %p, constant_table %p.\n", 526 debugstr_w(filename), defines, include, debugstr_a(entrypoint), debugstr_a(profile), 527 flags, shader, error_messages, constant_table); 528 529 if (!include) 530 { 531 include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; 532 include = &include_from_file.ID3DXInclude_iface; 533 } 534 535 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); 536 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char)); 537 if (!filename_a) 538 return E_OUTOFMEMORY; 539 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL); 540 541 EnterCriticalSection(&from_file_mutex); 542 hr = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &len); 543 if (FAILED(hr)) 544 { 545 LeaveCriticalSection(&from_file_mutex); 546 HeapFree(GetProcessHeap(), 0, filename_a); 547 return D3DXERR_INVALIDDATA; 548 } 549 550 if (D3DX_SDK_VERSION <= 36) 551 flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; 552 553 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines, 554 (ID3DInclude *)include, entrypoint, profile, flags, 0, 555 (ID3DBlob **)shader, (ID3DBlob **)error_messages); 556 557 if (SUCCEEDED(hr) && constant_table) 558 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader), 559 constant_table); 560 561 ID3DXInclude_Close(include, buffer); 562 LeaveCriticalSection(&from_file_mutex); 563 HeapFree(GetProcessHeap(), 0, filename_a); 564 return hr; 565 } 566 567 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines, 568 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags, 569 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table) 570 { 571 void *buffer; 572 HRSRC res; 573 DWORD len; 574 575 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, " 576 "flags %#x, shader %p, error_messages %p, constant_table %p.\n", 577 module, debugstr_a(resource), defines, include, debugstr_a(entrypoint), debugstr_a(profile), 578 flags, shader, error_messages, constant_table); 579 580 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA))) 581 return D3DXERR_INVALIDDATA; 582 if (FAILED(load_resource_into_memory(module, res, &buffer, &len))) 583 return D3DXERR_INVALIDDATA; 584 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile, 585 flags, shader, error_messages, constant_table); 586 } 587 588 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines, 589 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags, 590 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table) 591 { 592 void *buffer; 593 HRSRC res; 594 DWORD len; 595 596 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, " 597 "flags %#x, shader %p, error_messages %p, constant_table %p.\n", 598 module, debugstr_w(resource), defines, include, debugstr_a(entrypoint), debugstr_a(profile), 599 flags, shader, error_messages, constant_table); 600 601 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA))) 602 return D3DXERR_INVALIDDATA; 603 if (FAILED(load_resource_into_memory(module, res, &buffer, &len))) 604 return D3DXERR_INVALIDDATA; 605 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile, 606 flags, shader, error_messages, constant_table); 607 } 608 609 HRESULT WINAPI D3DXPreprocessShader(const char *data, UINT data_len, const D3DXMACRO *defines, 610 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 611 { 612 TRACE("data %s, data_len %u, defines %p, include %p, shader %p, error_messages %p.\n", 613 debugstr_a(data), data_len, defines, include, shader, error_messages); 614 615 return D3DPreprocess(data, data_len, NULL, 616 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include, 617 (ID3DBlob **)shader, (ID3DBlob **)error_messages); 618 } 619 620 HRESULT WINAPI D3DXPreprocessShaderFromFileA(const char *filename, const D3DXMACRO *defines, 621 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 622 { 623 WCHAR *filename_w = NULL; 624 DWORD len; 625 HRESULT ret; 626 627 TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n", 628 debugstr_a(filename), defines, include, shader, error_messages); 629 630 if (!filename) return D3DXERR_INVALIDDATA; 631 632 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0); 633 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 634 if (!filename_w) return E_OUTOFMEMORY; 635 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len); 636 637 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages); 638 639 HeapFree(GetProcessHeap(), 0, filename_w); 640 return ret; 641 } 642 643 HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines, 644 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 645 { 646 const void *buffer; 647 DWORD len; 648 HRESULT hr; 649 struct d3dx_include_from_file include_from_file; 650 char *filename_a; 651 652 TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n", 653 debugstr_w(filename), defines, include, shader, error_messages); 654 655 if (!include) 656 { 657 include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; 658 include = &include_from_file.ID3DXInclude_iface; 659 } 660 661 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); 662 filename_a = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); 663 if (!filename_a) 664 return E_OUTOFMEMORY; 665 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL); 666 667 EnterCriticalSection(&from_file_mutex); 668 hr = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &len); 669 if (FAILED(hr)) 670 { 671 LeaveCriticalSection(&from_file_mutex); 672 HeapFree(GetProcessHeap(), 0, filename_a); 673 return D3DXERR_INVALIDDATA; 674 } 675 676 hr = D3DPreprocess(buffer, len, NULL, 677 (const D3D_SHADER_MACRO *)defines, 678 (ID3DInclude *) include, 679 (ID3DBlob **)shader, (ID3DBlob **)error_messages); 680 681 ID3DXInclude_Close(include, buffer); 682 LeaveCriticalSection(&from_file_mutex); 683 HeapFree(GetProcessHeap(), 0, filename_a); 684 return hr; 685 } 686 687 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines, 688 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 689 { 690 void *buffer; 691 HRSRC res; 692 DWORD len; 693 694 TRACE("module %p, resource %s, defines %p, include %p, shader %p, error_messages %p.\n", 695 module, debugstr_a(resource), defines, include, shader, error_messages); 696 697 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA))) 698 return D3DXERR_INVALIDDATA; 699 if (FAILED(load_resource_into_memory(module, res, &buffer, &len))) 700 return D3DXERR_INVALIDDATA; 701 return D3DXPreprocessShader(buffer, len, defines, include, 702 shader, error_messages); 703 } 704 705 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines, 706 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages) 707 { 708 void *buffer; 709 HRSRC res; 710 DWORD len; 711 712 TRACE("module %p, resource %s, defines %p, include %p, shader %p, error_messages %p.\n", 713 module, debugstr_w(resource), defines, include, shader, error_messages); 714 715 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA))) 716 return D3DXERR_INVALIDDATA; 717 if (FAILED(load_resource_into_memory(module, res, &buffer, &len))) 718 return D3DXERR_INVALIDDATA; 719 return D3DXPreprocessShader(buffer, len, defines, include, 720 shader, error_messages); 721 722 } 723 724 struct ID3DXConstantTableImpl { 725 ID3DXConstantTable ID3DXConstantTable_iface; 726 LONG ref; 727 char *ctab; 728 DWORD size; 729 D3DXCONSTANTTABLE_DESC desc; 730 struct ctab_constant *constants; 731 }; 732 733 static void free_constant(struct ctab_constant *constant) 734 { 735 if (constant->constants) 736 { 737 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers; 738 739 for (i = 0; i < count; ++i) 740 { 741 free_constant(&constant->constants[i]); 742 } 743 HeapFree(GetProcessHeap(), 0, constant->constants); 744 } 745 } 746 747 static void free_constant_table(struct ID3DXConstantTableImpl *table) 748 { 749 if (table->constants) 750 { 751 UINT i; 752 753 for (i = 0; i < table->desc.Constants; ++i) 754 { 755 free_constant(&table->constants[i]); 756 } 757 HeapFree(GetProcessHeap(), 0, table->constants); 758 } 759 HeapFree(GetProcessHeap(), 0, table->ctab); 760 } 761 762 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface) 763 { 764 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface); 765 } 766 767 static inline BOOL is_vertex_shader(DWORD version) 768 { 769 return (version & 0xffff0000) == 0xfffe0000; 770 } 771 772 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant) 773 { 774 return (D3DXHANDLE)constant; 775 } 776 777 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table, 778 struct ctab_constant *constant, const char *name); 779 780 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, const char *name) 781 { 782 const char *part; 783 UINT element; 784 785 TRACE("constant %p, name %s\n", constant, debugstr_a(name)); 786 787 if (!name || !*name) return NULL; 788 789 element = atoi(name); 790 part = strchr(name, ']') + 1; 791 792 if (constant->desc.Elements > element) 793 { 794 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant; 795 796 switch (*part++) 797 { 798 case '.': 799 return get_constant_by_name(NULL, c, part); 800 801 case '[': 802 return get_constant_element_by_name(c, part); 803 804 case '\0': 805 TRACE("Returning parameter %p\n", c); 806 return c; 807 808 default: 809 FIXME("Unhandled case \"%c\"\n", *--part); 810 break; 811 } 812 } 813 814 TRACE("Constant not found\n"); 815 return NULL; 816 } 817 818 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table, 819 struct ctab_constant *constant, const char *name) 820 { 821 UINT i, count, length; 822 struct ctab_constant *handles; 823 const char *part; 824 825 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name)); 826 827 if (!name || !*name) return NULL; 828 829 if (!constant) 830 { 831 count = table->desc.Constants; 832 handles = table->constants; 833 } 834 else 835 { 836 count = constant->desc.StructMembers; 837 handles = constant->constants; 838 } 839 840 length = strcspn(name, "[."); 841 part = name + length; 842 843 for (i = 0; i < count; i++) 844 { 845 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length)) 846 { 847 switch (*part++) 848 { 849 case '.': 850 return get_constant_by_name(NULL, &handles[i], part); 851 852 case '[': 853 return get_constant_element_by_name(&handles[i], part); 854 855 default: 856 TRACE("Returning parameter %p\n", &handles[i]); 857 return &handles[i]; 858 } 859 } 860 } 861 862 TRACE("Constant not found\n"); 863 return NULL; 864 } 865 866 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, D3DXHANDLE handle) 867 { 868 struct ctab_constant *c; 869 UINT i, count; 870 871 /* all variable have at least elements = 1, but not always elements */ 872 if (!parent->constants) return NULL; 873 874 count = parent->desc.Elements > 1 ? parent->desc.Elements : parent->desc.StructMembers; 875 for (i = 0; i < count; ++i) 876 { 877 if (handle_from_constant(&parent->constants[i]) == handle) 878 return &parent->constants[i]; 879 880 c = is_valid_sub_constant(&parent->constants[i], handle); 881 if (c) return c; 882 } 883 884 return NULL; 885 } 886 887 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle) 888 { 889 struct ctab_constant *c; 890 UINT i; 891 892 if (!handle) return NULL; 893 894 for (i = 0; i < table->desc.Constants; ++i) 895 { 896 if (handle_from_constant(&table->constants[i]) == handle) 897 return &table->constants[i]; 898 899 c = is_valid_sub_constant(&table->constants[i], handle); 900 if (c) return c; 901 } 902 903 return get_constant_by_name(table, NULL, handle); 904 } 905 906 /*** IUnknown methods ***/ 907 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out) 908 { 909 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 910 911 if (IsEqualGUID(riid, &IID_IUnknown) || 912 IsEqualGUID(riid, &IID_ID3DXBuffer) || 913 IsEqualGUID(riid, &IID_ID3DXConstantTable)) 914 { 915 ID3DXConstantTable_AddRef(iface); 916 *out = iface; 917 return S_OK; 918 } 919 920 WARN("Interface %s not found.\n", debugstr_guid(riid)); 921 922 return E_NOINTERFACE; 923 } 924 925 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface) 926 { 927 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 928 929 TRACE("(%p)->(): AddRef from %d\n", This, This->ref); 930 931 return InterlockedIncrement(&This->ref); 932 } 933 934 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface) 935 { 936 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 937 ULONG ref = InterlockedDecrement(&This->ref); 938 939 TRACE("(%p)->(): Release from %d\n", This, ref + 1); 940 941 if (!ref) 942 { 943 free_constant_table(This); 944 HeapFree(GetProcessHeap(), 0, This); 945 } 946 947 return ref; 948 } 949 950 /*** ID3DXBuffer methods ***/ 951 static void * WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface) 952 { 953 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface); 954 955 TRACE("iface %p.\n", iface); 956 957 return table->ctab; 958 } 959 960 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface) 961 { 962 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 963 964 TRACE("(%p)->()\n", This); 965 966 return This->size; 967 } 968 969 /*** ID3DXConstantTable methods ***/ 970 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc) 971 { 972 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 973 974 TRACE("(%p)->(%p)\n", This, desc); 975 976 if (!desc) 977 return D3DERR_INVALIDCALL; 978 979 *desc = This->desc; 980 981 return D3D_OK; 982 } 983 984 const struct ctab_constant *d3dx_shader_get_ctab_constant(ID3DXConstantTable *iface, D3DXHANDLE constant) 985 { 986 struct ID3DXConstantTableImpl *ctab = impl_from_ID3DXConstantTable(iface); 987 988 return get_valid_constant(ctab, constant); 989 } 990 991 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant, 992 D3DXCONSTANT_DESC *desc, UINT *count) 993 { 994 struct ID3DXConstantTableImpl *ctab = impl_from_ID3DXConstantTable(iface); 995 struct ctab_constant *c = get_valid_constant(ctab, constant); 996 997 TRACE("(%p)->(%p, %p, %p)\n", ctab, constant, desc, count); 998 999 if (!c) 1000 { 1001 WARN("Invalid argument specified\n"); 1002 return D3DERR_INVALIDCALL; 1003 } 1004 1005 if (desc) *desc = c->desc; 1006 if (count) *count = 1; 1007 1008 return D3D_OK; 1009 } 1010 1011 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant) 1012 { 1013 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1014 struct ctab_constant *c = get_valid_constant(This, constant); 1015 1016 TRACE("(%p)->(%p)\n", This, constant); 1017 1018 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER) 1019 { 1020 WARN("Invalid argument specified\n"); 1021 return (UINT)-1; 1022 } 1023 1024 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex); 1025 return c->desc.RegisterIndex; 1026 } 1027 1028 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index) 1029 { 1030 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1031 struct ctab_constant *c; 1032 1033 TRACE("(%p)->(%p, %d)\n", This, constant, index); 1034 1035 if (constant) 1036 { 1037 c = get_valid_constant(This, constant); 1038 if (c && index < c->desc.StructMembers) 1039 { 1040 c = &c->constants[index]; 1041 TRACE("Returning constant %p\n", c); 1042 return handle_from_constant(c); 1043 } 1044 } 1045 else 1046 { 1047 if (index < This->desc.Constants) 1048 { 1049 c = &This->constants[index]; 1050 TRACE("Returning constant %p\n", c); 1051 return handle_from_constant(c); 1052 } 1053 } 1054 1055 WARN("Index out of range\n"); 1056 return NULL; 1057 } 1058 1059 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface, 1060 D3DXHANDLE constant, const char *name) 1061 { 1062 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1063 struct ctab_constant *c = get_valid_constant(This, constant); 1064 1065 TRACE("iface %p, constant %p, name %s.\n", iface, constant, debugstr_a(name)); 1066 1067 c = get_constant_by_name(This, c, name); 1068 TRACE("Returning constant %p\n", c); 1069 1070 return handle_from_constant(c); 1071 } 1072 1073 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index) 1074 { 1075 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1076 struct ctab_constant *c = get_valid_constant(This, constant); 1077 1078 TRACE("(%p)->(%p, %d)\n", This, constant, index); 1079 1080 if (c && index < c->desc.Elements) 1081 { 1082 if (c->desc.Elements > 1) c = &c->constants[index]; 1083 TRACE("Returning constant %p\n", c); 1084 return handle_from_constant(c); 1085 } 1086 1087 WARN("Invalid argument specified\n"); 1088 return NULL; 1089 } 1090 1091 static inline DWORD get_index(const void **indata, UINT index, BOOL is_pointer) 1092 { 1093 if (!indata) 1094 return 0; 1095 1096 if (is_pointer) 1097 return ((DWORD **)indata)[index / 16][index % 16]; 1098 1099 return (*((DWORD **)indata))[index]; 1100 } 1101 1102 static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant, 1103 const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index, 1104 BOOL is_pointer) 1105 { 1106 D3DXCONSTANT_DESC *desc = &constant->desc; 1107 UINT l, i, regcount = 1, regsize = 1, cin = 1, rin = 1, ret, last = 0; 1108 DWORD tmp; 1109 1110 /* size too small to set anything */ 1111 if (*size < desc->Rows * desc->Columns) 1112 { 1113 *size = 0; 1114 return 0; 1115 } 1116 1117 /* D3DXPC_STRUCT is somewhat special */ 1118 if (desc->Class == D3DXPC_STRUCT) 1119 { 1120 /* 1121 * Struct array sets the last complete input to the first struct element, all other 1122 * elements are not set. 1123 * E.g.: struct {int i;} s1[2]; 1124 * SetValue(device, "s1", [1, 2], 8) => s1 = {2, x}; 1125 * 1126 * struct {int i; int n} s2[2]; 1127 * SetValue(device, "s2", [1, 2, 3, 4, 5], 20) => s1 = {{3, 4}, {x, x}}; 1128 */ 1129 if (desc->Elements > 1) 1130 { 1131 UINT offset = *size / (desc->Rows * desc->Columns) - 1; 1132 1133 offset = min(desc->Elements - 1, offset); 1134 last = offset * desc->Rows * desc->Columns; 1135 1136 if ((is_pointer || inclass == D3DXPC_MATRIX_ROWS) && desc->RegisterSet != D3DXRS_BOOL) 1137 { 1138 set(table, device, &constant->constants[0], NULL, intype, size, incol, inclass, 0, is_pointer); 1139 } 1140 else 1141 { 1142 last += set(table, device, &constant->constants[0], indata, intype, size, incol, inclass, 1143 index + last, is_pointer); 1144 } 1145 } 1146 else 1147 { 1148 /* 1149 * D3DXRS_BOOL is always set. As there are only 16 bools and there are 1150 * exactly 16 input values, use matrix transpose. 1151 */ 1152 if (inclass == D3DXPC_MATRIX_ROWS && desc->RegisterSet == D3DXRS_BOOL) 1153 { 1154 D3DXMATRIX mat, *m, min; 1155 D3DXMatrixTranspose(&mat, &min); 1156 1157 if (is_pointer) 1158 min = *(D3DXMATRIX *)(indata[index / 16]); 1159 else 1160 min = **(D3DXMATRIX **)indata; 1161 1162 D3DXMatrixTranspose(&mat, &min); 1163 m = &mat; 1164 for (i = 0; i < desc->StructMembers; ++i) 1165 { 1166 last += set(table, device, &constant->constants[i], (const void **)&m, intype, size, incol, 1167 D3DXPC_SCALAR, index + last, is_pointer); 1168 } 1169 } 1170 /* 1171 * For pointers or for matrix rows, only the first member is set. 1172 * All other members are set to 0. This is not true for D3DXRS_BOOL. 1173 * E.g.: struct {int i; int n} s; 1174 * SetValue(device, "s", [1, 2], 8) => s = {1, 0}; 1175 */ 1176 else if ((is_pointer || inclass == D3DXPC_MATRIX_ROWS) && desc->RegisterSet != D3DXRS_BOOL) 1177 { 1178 last = set(table, device, &constant->constants[0], indata, intype, size, incol, inclass, 1179 index + last, is_pointer); 1180 1181 for (i = 1; i < desc->StructMembers; ++i) 1182 { 1183 set(table, device, &constant->constants[i], NULL, intype, size, incol, inclass, 0, is_pointer); 1184 } 1185 } 1186 else 1187 { 1188 for (i = 0; i < desc->StructMembers; ++i) 1189 { 1190 last += set(table, device, &constant->constants[i], indata, intype, size, incol, D3DXPC_SCALAR, 1191 index + last, is_pointer); 1192 } 1193 } 1194 } 1195 1196 return last; 1197 } 1198 1199 /* elements */ 1200 if (desc->Elements > 1) 1201 { 1202 for (i = 0; i < desc->Elements && *size > 0; ++i) 1203 { 1204 last += set(table, device, &constant->constants[i], indata, intype, size, incol, inclass, 1205 index + last, is_pointer); 1206 1207 /* adjust the vector size for matrix rows */ 1208 if (inclass == D3DXPC_MATRIX_ROWS && desc->Class == D3DXPC_VECTOR && (i % 4) == 3) 1209 { 1210 last += 12; 1211 *size = *size < 12 ? 0 : *size - 12; 1212 } 1213 } 1214 1215 return last; 1216 } 1217 1218 switch (desc->Class) 1219 { 1220 case D3DXPC_SCALAR: 1221 case D3DXPC_VECTOR: 1222 case D3DXPC_MATRIX_ROWS: 1223 regcount = min(desc->RegisterCount, desc->Rows); 1224 if (inclass == D3DXPC_MATRIX_ROWS) cin = incol; 1225 else rin = incol; 1226 regsize = desc->Columns; 1227 break; 1228 1229 case D3DXPC_MATRIX_COLUMNS: 1230 regcount = min(desc->RegisterCount, desc->Columns); 1231 if (inclass == D3DXPC_MATRIX_ROWS) rin = incol; 1232 else cin = incol; 1233 regsize = desc->Rows; 1234 break; 1235 1236 default: 1237 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class)); 1238 return 0; 1239 } 1240 1241 /* specific stuff for different in types */ 1242 switch (inclass) 1243 { 1244 case D3DXPC_SCALAR: 1245 ret = desc->Columns * desc->Rows; 1246 *size -= desc->Columns * desc->Rows; 1247 break; 1248 1249 case D3DXPC_VECTOR: 1250 switch (desc->Class) 1251 { 1252 case D3DXPC_MATRIX_ROWS: 1253 if (*size < regcount * 4) 1254 { 1255 *size = 0; 1256 return 0; 1257 } 1258 ret = 4 * regcount; 1259 *size -= 4 * regcount; 1260 break; 1261 1262 case D3DXPC_MATRIX_COLUMNS: 1263 ret = 4 * regsize; 1264 *size -= 4 * regcount; 1265 break; 1266 1267 case D3DXPC_SCALAR: 1268 ret = 1; 1269 *size -= ret; 1270 break; 1271 1272 case D3DXPC_VECTOR: 1273 ret = 4; 1274 *size -= ret; 1275 break; 1276 1277 default: 1278 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class)); 1279 return 0; 1280 } 1281 break; 1282 1283 case D3DXPC_MATRIX_ROWS: 1284 switch (desc->Class) 1285 { 1286 case D3DXPC_MATRIX_ROWS: 1287 case D3DXPC_MATRIX_COLUMNS: 1288 if (*size < 16) 1289 { 1290 *size = 0; 1291 return 0; 1292 } 1293 ret = 16; 1294 break; 1295 1296 case D3DXPC_SCALAR: 1297 ret = 4; 1298 break; 1299 1300 case D3DXPC_VECTOR: 1301 ret = 1; 1302 break; 1303 1304 default: 1305 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class)); 1306 return 0; 1307 } 1308 *size -= ret; 1309 break; 1310 1311 case D3DXPC_MATRIX_COLUMNS: 1312 switch (desc->Class) 1313 { 1314 case D3DXPC_MATRIX_ROWS: 1315 case D3DXPC_MATRIX_COLUMNS: 1316 if (*size < 16) 1317 { 1318 *size = 0; 1319 return 0; 1320 } 1321 ret = 16; 1322 break; 1323 1324 case D3DXPC_SCALAR: 1325 ret = 1; 1326 break; 1327 1328 case D3DXPC_VECTOR: 1329 ret = 4; 1330 break; 1331 1332 default: 1333 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class)); 1334 return 0; 1335 } 1336 *size -= ret; 1337 break; 1338 1339 default: 1340 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(inclass)); 1341 return 0; 1342 } 1343 1344 /* set the registers */ 1345 switch (desc->RegisterSet) 1346 { 1347 case D3DXRS_BOOL: 1348 regcount = min(desc->RegisterCount, desc->Columns * desc->Rows); 1349 l = 0; 1350 for (i = 0; i < regcount; ++i) 1351 { 1352 BOOL out; 1353 DWORD t = get_index(indata, index + i / regsize * rin + l * cin, is_pointer); 1354 1355 set_number(&tmp, desc->Type, &t, intype); 1356 set_number(&out, D3DXPT_BOOL, &tmp, desc->Type); 1357 if (is_vertex_shader(table->desc.Version)) 1358 IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex + i, &out, 1); 1359 else 1360 IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex + i, &out, 1); 1361 1362 if (++l >= regsize) l = 0; 1363 } 1364 return ret; 1365 1366 case D3DXRS_INT4: 1367 for (i = 0; i < regcount; ++i) 1368 { 1369 INT vec[4] = {0, 0, 1, 0}; 1370 1371 for (l = 0; l < regsize; ++l) 1372 { 1373 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer); 1374 1375 set_number(&tmp, desc->Type, &t, intype); 1376 set_number(&vec[l], D3DXPT_INT, &tmp, desc->Type); 1377 } 1378 if (is_vertex_shader(table->desc.Version)) 1379 IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex + i, vec, 1); 1380 else 1381 IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex + i, vec, 1); 1382 } 1383 return ret; 1384 1385 case D3DXRS_FLOAT4: 1386 for (i = 0; i < regcount; ++i) 1387 { 1388 FLOAT vec[4] = {0}; 1389 1390 for (l = 0; l < regsize; ++l) 1391 { 1392 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer); 1393 1394 set_number(&tmp, desc->Type, &t, intype); 1395 set_number(&vec[l], D3DXPT_FLOAT, &tmp, desc->Type); 1396 } 1397 if (is_vertex_shader(table->desc.Version)) 1398 IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex + i, vec, 1); 1399 else 1400 IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex + i, vec, 1); 1401 } 1402 return ret; 1403 1404 default: 1405 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet)); 1406 return 0; 1407 } 1408 } 1409 1410 static HRESULT set_scalar(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant, 1411 const void *indata, D3DXPARAMETER_TYPE intype) 1412 { 1413 struct ctab_constant *c = get_valid_constant(table, constant); 1414 UINT count = 1; 1415 1416 if (!c) 1417 { 1418 WARN("Invalid argument specified\n"); 1419 return D3DERR_INVALIDCALL; 1420 } 1421 1422 switch (c->desc.Class) 1423 { 1424 case D3DXPC_SCALAR: 1425 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE); 1426 return D3D_OK; 1427 1428 case D3DXPC_VECTOR: 1429 case D3DXPC_MATRIX_ROWS: 1430 case D3DXPC_MATRIX_COLUMNS: 1431 case D3DXPC_STRUCT: 1432 return D3D_OK; 1433 1434 default: 1435 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class)); 1436 return D3DERR_INVALIDCALL; 1437 } 1438 } 1439 1440 static HRESULT set_scalar_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant, 1441 const void *indata, UINT count, D3DXPARAMETER_TYPE intype) 1442 { 1443 struct ctab_constant *c = get_valid_constant(table, constant); 1444 1445 if (!c) 1446 { 1447 WARN("Invalid argument specified\n"); 1448 return D3DERR_INVALIDCALL; 1449 } 1450 1451 switch (c->desc.Class) 1452 { 1453 case D3DXPC_SCALAR: 1454 case D3DXPC_VECTOR: 1455 case D3DXPC_MATRIX_ROWS: 1456 case D3DXPC_MATRIX_COLUMNS: 1457 case D3DXPC_STRUCT: 1458 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE); 1459 return D3D_OK; 1460 1461 default: 1462 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class)); 1463 return D3DERR_INVALIDCALL; 1464 } 1465 } 1466 1467 static HRESULT set_vector(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant, 1468 const void *indata, D3DXPARAMETER_TYPE intype) 1469 { 1470 struct ctab_constant *c = get_valid_constant(table, constant); 1471 UINT count = 4; 1472 1473 if (!c) 1474 { 1475 WARN("Invalid argument specified\n"); 1476 return D3DERR_INVALIDCALL; 1477 } 1478 1479 switch (c->desc.Class) 1480 { 1481 case D3DXPC_SCALAR: 1482 case D3DXPC_VECTOR: 1483 case D3DXPC_STRUCT: 1484 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE); 1485 return D3D_OK; 1486 1487 case D3DXPC_MATRIX_ROWS: 1488 case D3DXPC_MATRIX_COLUMNS: 1489 return D3D_OK; 1490 1491 default: 1492 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class)); 1493 return D3DERR_INVALIDCALL; 1494 } 1495 } 1496 1497 static HRESULT set_vector_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant, 1498 const void *indata, UINT count, D3DXPARAMETER_TYPE intype) 1499 { 1500 struct ctab_constant *c = get_valid_constant(table, constant); 1501 1502 if (!c) 1503 { 1504 WARN("Invalid argument specified\n"); 1505 return D3DERR_INVALIDCALL; 1506 } 1507 1508 switch (c->desc.Class) 1509 { 1510 case D3DXPC_SCALAR: 1511 case D3DXPC_VECTOR: 1512 case D3DXPC_MATRIX_ROWS: 1513 case D3DXPC_MATRIX_COLUMNS: 1514 case D3DXPC_STRUCT: 1515 count *= 4; 1516 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE); 1517 return D3D_OK; 1518 1519 default: 1520 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class)); 1521 return D3DERR_INVALIDCALL; 1522 } 1523 } 1524 1525 static HRESULT set_matrix_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant, 1526 const void *indata, UINT count, BOOL transpose) 1527 { 1528 struct ctab_constant *c = get_valid_constant(table, constant); 1529 1530 if (!c) 1531 { 1532 WARN("Invalid argument specified\n"); 1533 return D3DERR_INVALIDCALL; 1534 } 1535 1536 switch (c->desc.Class) 1537 { 1538 case D3DXPC_SCALAR: 1539 case D3DXPC_VECTOR: 1540 case D3DXPC_MATRIX_ROWS: 1541 case D3DXPC_MATRIX_COLUMNS: 1542 case D3DXPC_STRUCT: 1543 count *= 16; 1544 set(table, device, c, &indata, D3DXPT_FLOAT, &count, 4, 1545 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, FALSE); 1546 return D3D_OK; 1547 1548 default: 1549 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class)); 1550 return D3DERR_INVALIDCALL; 1551 } 1552 } 1553 1554 static HRESULT set_matrix_pointer_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, 1555 D3DXHANDLE constant, const void **indata, UINT count, BOOL transpose) 1556 { 1557 struct ctab_constant *c = get_valid_constant(table, constant); 1558 1559 if (!c) 1560 { 1561 WARN("Invalid argument specified\n"); 1562 return D3DERR_INVALIDCALL; 1563 } 1564 1565 switch (c->desc.Class) 1566 { 1567 case D3DXPC_SCALAR: 1568 case D3DXPC_VECTOR: 1569 case D3DXPC_MATRIX_ROWS: 1570 case D3DXPC_MATRIX_COLUMNS: 1571 case D3DXPC_STRUCT: 1572 count *= 16; 1573 set(table, device, c, indata, D3DXPT_FLOAT, &count, 4, 1574 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, TRUE); 1575 return D3D_OK; 1576 1577 default: 1578 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class)); 1579 return D3DERR_INVALIDCALL; 1580 } 1581 } 1582 1583 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface, 1584 struct IDirect3DDevice9 *device) 1585 { 1586 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1587 UINT i; 1588 1589 TRACE("iface %p, device %p\n", iface, device); 1590 1591 if (!device) 1592 { 1593 WARN("Invalid argument specified\n"); 1594 return D3DERR_INVALIDCALL; 1595 } 1596 1597 for (i = 0; i < This->desc.Constants; i++) 1598 { 1599 D3DXCONSTANT_DESC *desc = &This->constants[i].desc; 1600 HRESULT hr; 1601 1602 if (!desc->DefaultValue) 1603 continue; 1604 1605 switch (desc->RegisterSet) 1606 { 1607 case D3DXRS_BOOL: 1608 if (is_vertex_shader(This->desc.Version)) 1609 hr = IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue, 1610 desc->RegisterCount); 1611 else 1612 hr = IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue, 1613 desc->RegisterCount); 1614 break; 1615 1616 case D3DXRS_INT4: 1617 if (is_vertex_shader(This->desc.Version)) 1618 hr = IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue, 1619 desc->RegisterCount); 1620 else 1621 hr = IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue, 1622 desc->RegisterCount); 1623 break; 1624 1625 case D3DXRS_FLOAT4: 1626 if (is_vertex_shader(This->desc.Version)) 1627 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue, 1628 desc->RegisterCount); 1629 else 1630 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue, 1631 desc->RegisterCount); 1632 break; 1633 1634 default: 1635 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet)); 1636 hr = E_NOTIMPL; 1637 break; 1638 } 1639 1640 if (hr != D3D_OK) 1641 return hr; 1642 } 1643 1644 return D3D_OK; 1645 } 1646 1647 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface, 1648 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, unsigned int bytes) 1649 { 1650 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface); 1651 struct ctab_constant *c = get_valid_constant(table, constant); 1652 D3DXCONSTANT_DESC *desc; 1653 1654 TRACE("iface %p, device %p, constant %p, data %p, bytes %u\n", iface, device, constant, data, bytes); 1655 1656 if (!device || !c || !data) 1657 { 1658 WARN("Invalid argument specified\n"); 1659 return D3DERR_INVALIDCALL; 1660 } 1661 1662 desc = &c->desc; 1663 1664 switch (desc->Class) 1665 { 1666 case D3DXPC_SCALAR: 1667 case D3DXPC_VECTOR: 1668 case D3DXPC_MATRIX_ROWS: 1669 case D3DXPC_MATRIX_COLUMNS: 1670 case D3DXPC_STRUCT: 1671 bytes /= 4; 1672 set(table, device, c, &data, desc->Type, &bytes, desc->Columns, D3DXPC_SCALAR, 0, FALSE); 1673 return D3D_OK; 1674 1675 default: 1676 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc->Class)); 1677 return D3DERR_INVALIDCALL; 1678 } 1679 } 1680 1681 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface, 1682 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b) 1683 { 1684 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1685 1686 TRACE("iface %p, device %p, constant %p, b %d\n", iface, device, constant, b); 1687 1688 return set_scalar(This, device, constant, &b, D3DXPT_BOOL); 1689 } 1690 1691 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface, 1692 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count) 1693 { 1694 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1695 1696 TRACE("iface %p, device %p, constant %p, b %p, count %d\n", iface, device, constant, b, count); 1697 1698 return set_scalar_array(This, device, constant, b, count, D3DXPT_BOOL); 1699 } 1700 1701 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface, 1702 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n) 1703 { 1704 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1705 1706 TRACE("iface %p, device %p, constant %p, n %d\n", iface, device, constant, n); 1707 1708 return set_scalar(This, device, constant, &n, D3DXPT_INT); 1709 } 1710 1711 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface, 1712 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count) 1713 { 1714 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1715 1716 TRACE("iface %p, device %p, constant %p, n %p, count %d\n", iface, device, constant, n, count); 1717 1718 return set_scalar_array(This, device, constant, n, count, D3DXPT_INT); 1719 } 1720 1721 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface, 1722 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f) 1723 { 1724 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1725 1726 TRACE("iface %p, device %p, constant %p, f %f\n", iface, device, constant, f); 1727 1728 return set_scalar(This, device, constant, &f, D3DXPT_FLOAT); 1729 } 1730 1731 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface, 1732 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count) 1733 { 1734 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1735 1736 TRACE("iface %p, device %p, constant %p, f %p, count %d\n", iface, device, constant, f, count); 1737 1738 return set_scalar_array(This, device, constant, f, count, D3DXPT_FLOAT); 1739 } 1740 1741 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface, 1742 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector) 1743 { 1744 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1745 1746 TRACE("iface %p, device %p, constant %p, vector %p\n", iface, device, constant, vector); 1747 1748 return set_vector(This, device, constant, vector, D3DXPT_FLOAT); 1749 } 1750 1751 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface, 1752 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count) 1753 { 1754 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1755 1756 TRACE("iface %p, device %p, constant %p, vector %p, count %u\n", iface, device, constant, vector, count); 1757 1758 return set_vector_array(This, device, constant, vector, count, D3DXPT_FLOAT); 1759 } 1760 1761 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface, 1762 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix) 1763 { 1764 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1765 1766 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix); 1767 1768 return set_matrix_array(This, device, constant, matrix, 1, FALSE); 1769 } 1770 1771 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface, 1772 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count) 1773 { 1774 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1775 1776 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count); 1777 1778 return set_matrix_array(This, device, constant, matrix, count, FALSE); 1779 } 1780 1781 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface, 1782 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count) 1783 { 1784 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1785 1786 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count); 1787 1788 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, FALSE); 1789 } 1790 1791 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface, 1792 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix) 1793 { 1794 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1795 1796 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix); 1797 1798 return set_matrix_array(This, device, constant, matrix, 1, TRUE); 1799 } 1800 1801 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface, 1802 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count) 1803 { 1804 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1805 1806 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count); 1807 1808 return set_matrix_array(This, device, constant, matrix, count, TRUE); 1809 } 1810 1811 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface, 1812 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count) 1813 { 1814 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface); 1815 1816 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count); 1817 1818 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, TRUE); 1819 } 1820 1821 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl = 1822 { 1823 /*** IUnknown methods ***/ 1824 ID3DXConstantTableImpl_QueryInterface, 1825 ID3DXConstantTableImpl_AddRef, 1826 ID3DXConstantTableImpl_Release, 1827 /*** ID3DXBuffer methods ***/ 1828 ID3DXConstantTableImpl_GetBufferPointer, 1829 ID3DXConstantTableImpl_GetBufferSize, 1830 /*** ID3DXConstantTable methods ***/ 1831 ID3DXConstantTableImpl_GetDesc, 1832 ID3DXConstantTableImpl_GetConstantDesc, 1833 ID3DXConstantTableImpl_GetSamplerIndex, 1834 ID3DXConstantTableImpl_GetConstant, 1835 ID3DXConstantTableImpl_GetConstantByName, 1836 ID3DXConstantTableImpl_GetConstantElement, 1837 ID3DXConstantTableImpl_SetDefaults, 1838 ID3DXConstantTableImpl_SetValue, 1839 ID3DXConstantTableImpl_SetBool, 1840 ID3DXConstantTableImpl_SetBoolArray, 1841 ID3DXConstantTableImpl_SetInt, 1842 ID3DXConstantTableImpl_SetIntArray, 1843 ID3DXConstantTableImpl_SetFloat, 1844 ID3DXConstantTableImpl_SetFloatArray, 1845 ID3DXConstantTableImpl_SetVector, 1846 ID3DXConstantTableImpl_SetVectorArray, 1847 ID3DXConstantTableImpl_SetMatrix, 1848 ID3DXConstantTableImpl_SetMatrixArray, 1849 ID3DXConstantTableImpl_SetMatrixPointerArray, 1850 ID3DXConstantTableImpl_SetMatrixTranspose, 1851 ID3DXConstantTableImpl_SetMatrixTransposeArray, 1852 ID3DXConstantTableImpl_SetMatrixTransposePointerArray 1853 }; 1854 1855 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant, 1856 BOOL is_element, WORD index, WORD max_index, DWORD *offset, DWORD nameoffset, UINT regset) 1857 { 1858 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset); 1859 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL; 1860 HRESULT hr = D3D_OK; 1861 UINT i, count = 0; 1862 WORD size = 0; 1863 1864 constant->desc.DefaultValue = offset ? ctab + *offset : NULL; 1865 constant->desc.Class = type->Class; 1866 constant->desc.Type = type->Type; 1867 constant->desc.Rows = type->Rows; 1868 constant->desc.Columns = type->Columns; 1869 constant->desc.Elements = is_element ? 1 : type->Elements; 1870 constant->desc.StructMembers = type->StructMembers; 1871 constant->desc.Name = ctab + nameoffset; 1872 constant->desc.RegisterSet = regset; 1873 constant->desc.RegisterIndex = index; 1874 1875 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name, 1876 constant->desc.Elements, index, constant->desc.DefaultValue, 1877 debug_d3dxparameter_registerset(regset)); 1878 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n", 1879 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type), 1880 type->Rows, type->Columns, type->Elements, type->StructMembers); 1881 1882 if (type->Elements > 1 && !is_element) 1883 { 1884 count = type->Elements; 1885 } 1886 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers) 1887 { 1888 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo); 1889 count = type->StructMembers; 1890 } 1891 1892 if (count) 1893 { 1894 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count); 1895 if (!constant->constants) 1896 { 1897 ERR("Out of memory\n"); 1898 hr = E_OUTOFMEMORY; 1899 goto error; 1900 } 1901 1902 for (i = 0; i < count; ++i) 1903 { 1904 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset, 1905 &constant->constants[i], memberinfo == NULL, index + size, max_index, offset, 1906 memberinfo ? memberinfo[i].Name : nameoffset, regset); 1907 if (hr != D3D_OK) 1908 goto error; 1909 1910 size += constant->constants[i].desc.RegisterCount; 1911 } 1912 } 1913 else 1914 { 1915 WORD offsetdiff = type->Columns * type->Rows; 1916 BOOL fail = FALSE; 1917 1918 size = type->Columns * type->Rows; 1919 1920 switch (regset) 1921 { 1922 case D3DXRS_BOOL: 1923 fail = type->Class != D3DXPC_SCALAR && type->Class != D3DXPC_VECTOR 1924 && type->Class != D3DXPC_MATRIX_ROWS && type->Class != D3DXPC_MATRIX_COLUMNS; 1925 break; 1926 1927 case D3DXRS_FLOAT4: 1928 case D3DXRS_INT4: 1929 switch (type->Class) 1930 { 1931 case D3DXPC_VECTOR: 1932 size = 1; 1933 /* fall through */ 1934 case D3DXPC_SCALAR: 1935 offsetdiff = type->Rows * 4; 1936 break; 1937 1938 case D3DXPC_MATRIX_ROWS: 1939 offsetdiff = type->Rows * 4; 1940 size = type->Rows; 1941 break; 1942 1943 case D3DXPC_MATRIX_COLUMNS: 1944 offsetdiff = type->Columns * 4; 1945 size = type->Columns; 1946 break; 1947 1948 default: 1949 fail = TRUE; 1950 break; 1951 } 1952 break; 1953 1954 case D3DXRS_SAMPLER: 1955 size = 1; 1956 fail = type->Class != D3DXPC_OBJECT; 1957 break; 1958 1959 default: 1960 fail = TRUE; 1961 break; 1962 } 1963 1964 if (fail) 1965 { 1966 FIXME("Unhandled register set %s, type class %s\n", debug_d3dxparameter_registerset(regset), 1967 debug_d3dxparameter_class(type->Class)); 1968 } 1969 1970 /* offset in bytes => offsetdiff * sizeof(DWORD) */ 1971 if (offset) *offset += offsetdiff * 4; 1972 } 1973 1974 constant->desc.RegisterCount = max(0, min(max_index - index, size)); 1975 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns; 1976 1977 return D3D_OK; 1978 1979 error: 1980 if (constant->constants) 1981 { 1982 for (i = 0; i < count; ++i) 1983 { 1984 free_constant(&constant->constants[i]); 1985 } 1986 HeapFree(GetProcessHeap(), 0, constant->constants); 1987 constant->constants = NULL; 1988 } 1989 1990 return hr; 1991 } 1992 1993 HRESULT WINAPI D3DXGetShaderConstantTableEx(const DWORD *byte_code, DWORD flags, ID3DXConstantTable **constant_table) 1994 { 1995 struct ID3DXConstantTableImpl *object = NULL; 1996 const void *data; 1997 HRESULT hr; 1998 UINT size; 1999 const D3DXSHADER_CONSTANTTABLE *ctab_header; 2000 const D3DXSHADER_CONSTANTINFO *constant_info; 2001 DWORD i; 2002 2003 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code, flags, constant_table); 2004 2005 if (constant_table) *constant_table = NULL; 2006 2007 if (!byte_code || !constant_table) 2008 { 2009 WARN("Invalid argument specified.\n"); 2010 return D3DERR_INVALIDCALL; 2011 } 2012 2013 if (!is_valid_bytecode(*byte_code)) 2014 { 2015 WARN("Invalid byte_code specified.\n"); 2016 return D3D_OK; 2017 } 2018 2019 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags); 2020 2021 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size); 2022 if (hr != D3D_OK) 2023 { 2024 WARN("CTAB not found.\n"); 2025 return D3DXERR_INVALIDDATA; 2026 } 2027 2028 if (size < sizeof(*ctab_header)) 2029 { 2030 WARN("Invalid CTAB size.\n"); 2031 return D3DXERR_INVALIDDATA; 2032 } 2033 2034 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data; 2035 if (ctab_header->Size != sizeof(*ctab_header)) 2036 { 2037 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n"); 2038 return D3DXERR_INVALIDDATA; 2039 } 2040 2041 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 2042 if (!object) 2043 return E_OUTOFMEMORY; 2044 2045 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl; 2046 object->ref = 1; 2047 2048 object->ctab = HeapAlloc(GetProcessHeap(), 0, size); 2049 if (!object->ctab) 2050 { 2051 ERR("Out of memory\n"); 2052 HeapFree(GetProcessHeap(), 0, object); 2053 return E_OUTOFMEMORY; 2054 } 2055 object->size = size; 2056 memcpy(object->ctab, data, object->size); 2057 2058 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL; 2059 object->desc.Version = ctab_header->Version; 2060 object->desc.Constants = ctab_header->Constants; 2061 TRACE("Creator %s, Version %x, Constants %u, Target %s\n", 2062 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants, 2063 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL)); 2064 2065 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2066 sizeof(*object->constants) * object->desc.Constants); 2067 if (!object->constants) 2068 { 2069 ERR("Out of memory\n"); 2070 hr = E_OUTOFMEMORY; 2071 goto error; 2072 } 2073 2074 constant_info = (const D3DXSHADER_CONSTANTINFO *)(object->ctab + ctab_header->ConstantInfo); 2075 for (i = 0; i < ctab_header->Constants; i++) 2076 { 2077 DWORD offset = constant_info[i].DefaultValue; 2078 2079 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo, 2080 &object->constants[i], FALSE, constant_info[i].RegisterIndex, 2081 constant_info[i].RegisterIndex + constant_info[i].RegisterCount, 2082 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet); 2083 if (hr != D3D_OK) 2084 goto error; 2085 2086 /* 2087 * Set the register count, it may differ for D3DXRS_INT4, because somehow 2088 * it makes the assumption that the register size is 1 instead of 4, so the 2089 * count is 4 times bigger. This holds true only for toplevel shader 2090 * constants. The count of elements and members is always based on a 2091 * register size of 4. 2092 */ 2093 if (object->constants[i].desc.RegisterSet == D3DXRS_INT4) 2094 { 2095 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount; 2096 } 2097 object->constants[i].constantinfo_reserved = constant_info[i].Reserved; 2098 } 2099 2100 *constant_table = &object->ID3DXConstantTable_iface; 2101 2102 return D3D_OK; 2103 2104 error: 2105 free_constant_table(object); 2106 HeapFree(GetProcessHeap(), 0, object); 2107 2108 return hr; 2109 } 2110 2111 HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantTable **constant_table) 2112 { 2113 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table); 2114 2115 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table); 2116 } 2117 2118 struct d3dx9_fragment_linker 2119 { 2120 ID3DXFragmentLinker ID3DXFragmentLinker_iface; 2121 LONG ref; 2122 2123 struct IDirect3DDevice9 *device; 2124 DWORD flags; 2125 }; 2126 2127 static inline struct d3dx9_fragment_linker *impl_from_ID3DXFragmentLinker(ID3DXFragmentLinker *iface) 2128 { 2129 return CONTAINING_RECORD(iface, struct d3dx9_fragment_linker, ID3DXFragmentLinker_iface); 2130 } 2131 2132 static HRESULT WINAPI d3dx9_fragment_linker_QueryInterface(ID3DXFragmentLinker *iface, REFIID riid, void **out) 2133 { 2134 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 2135 2136 if (IsEqualGUID(riid, &IID_IUnknown) 2137 || IsEqualGUID(riid, &IID_ID3DXFragmentLinker)) 2138 { 2139 iface->lpVtbl->AddRef(iface); 2140 *out = iface; 2141 return D3D_OK; 2142 } 2143 2144 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 2145 *out = NULL; 2146 return E_NOINTERFACE; 2147 } 2148 2149 static ULONG WINAPI d3dx9_fragment_linker_AddRef(ID3DXFragmentLinker *iface) 2150 { 2151 struct d3dx9_fragment_linker *linker = impl_from_ID3DXFragmentLinker(iface); 2152 ULONG refcount = InterlockedIncrement(&linker->ref); 2153 2154 TRACE("%p increasing refcount to %u.\n", linker, refcount); 2155 2156 return refcount; 2157 } 2158 2159 static ULONG WINAPI d3dx9_fragment_linker_Release(ID3DXFragmentLinker *iface) 2160 { 2161 struct d3dx9_fragment_linker *linker = impl_from_ID3DXFragmentLinker(iface); 2162 ULONG refcount = InterlockedDecrement(&linker->ref); 2163 2164 TRACE("%p decreasing refcount to %u.\n", linker, refcount); 2165 2166 if (!refcount) 2167 { 2168 IDirect3DDevice9_Release(linker->device); 2169 heap_free(linker); 2170 } 2171 2172 return refcount; 2173 } 2174 2175 static HRESULT WINAPI d3dx9_fragment_linker_GetDevice(ID3DXFragmentLinker *iface, struct IDirect3DDevice9 **device) 2176 { 2177 struct d3dx9_fragment_linker *linker = impl_from_ID3DXFragmentLinker(iface); 2178 2179 TRACE("iface %p, device %p.\n", linker, device); 2180 2181 if (!device) 2182 { 2183 WARN("Invalid argument supplied.\n"); 2184 return D3DERR_INVALIDCALL; 2185 } 2186 2187 IDirect3DDevice9_AddRef(linker->device); 2188 *device = linker->device; 2189 TRACE("Returning device %p.\n", *device); 2190 2191 return S_OK; 2192 } 2193 2194 static UINT WINAPI d3dx9_fragment_linker_GetNumberOfFragments(ID3DXFragmentLinker *iface) 2195 { 2196 FIXME("iface %p: stub.\n", iface); 2197 2198 return E_NOTIMPL; 2199 } 2200 2201 static D3DXHANDLE WINAPI d3dx9_fragment_linker_GetFragmentHandleByIndex(ID3DXFragmentLinker *iface, UINT index) 2202 { 2203 FIXME("iface %p, index %u: stub.\n", iface, index); 2204 2205 return NULL; 2206 } 2207 2208 static D3DXHANDLE WINAPI d3dx9_fragment_linker_GetFragmentHandleByName(ID3DXFragmentLinker *iface, 2209 const char *name) 2210 { 2211 FIXME("iface %p, name %s: stub.\n", iface, debugstr_a(name)); 2212 2213 return NULL; 2214 } 2215 2216 static HRESULT WINAPI d3dx9_fragment_linker_GetFragmentDesc(ID3DXFragmentLinker *iface, D3DXHANDLE name, 2217 D3DXFRAGMENT_DESC *desc) 2218 { 2219 FIXME("iface %p, name %p, desc %p: stub.\n", iface, name, desc); 2220 2221 return E_NOTIMPL; 2222 } 2223 2224 static HRESULT WINAPI d3dx9_fragment_linker_AddFragments(ID3DXFragmentLinker *iface, const DWORD *fragments) 2225 { 2226 FIXME("iface %p, fragments %p: stub.\n", iface, fragments); 2227 2228 return E_NOTIMPL; 2229 } 2230 2231 static HRESULT WINAPI d3dx9_fragment_linker_GetAllFragments(ID3DXFragmentLinker *iface, ID3DXBuffer **buffer) 2232 { 2233 FIXME("iface %p, buffer %p: stub.\n", iface, buffer); 2234 2235 return E_NOTIMPL; 2236 } 2237 2238 static HRESULT WINAPI d3dx9_fragment_linker_GetFragment(ID3DXFragmentLinker *iface, D3DXHANDLE name, 2239 ID3DXBuffer **buffer) 2240 { 2241 FIXME("iface %p, name %p, buffer %p: stub.\n", iface, name, buffer); 2242 2243 return E_NOTIMPL; 2244 } 2245 2246 static HRESULT WINAPI d3dx9_fragment_linker_LinkShader(ID3DXFragmentLinker *iface, const char *profile, 2247 DWORD flags, const D3DXHANDLE *handles, UINT fragment_count, ID3DXBuffer **buffer, 2248 ID3DXBuffer **errors) 2249 { 2250 FIXME("iface %p, profile %s, flags %#x, handles %p, fragment_count %u, buffer %p, errors %p: stub.\n", 2251 iface, debugstr_a(profile), flags, handles, fragment_count, buffer, errors); 2252 2253 return E_NOTIMPL; 2254 } 2255 2256 static HRESULT WINAPI d3dx9_fragment_linker_LinkVertexShader(ID3DXFragmentLinker *iface, const char *profile, 2257 DWORD flags, const D3DXHANDLE *handles, UINT fragment_count, IDirect3DVertexShader9 **shader, 2258 ID3DXBuffer **errors) 2259 { 2260 FIXME("iface %p, profile %s, flags %#x, handles %p, fragment_count %u, shader %p, errors %p: stub.\n", 2261 iface, debugstr_a(profile), flags, handles, fragment_count, shader, errors); 2262 2263 return E_NOTIMPL; 2264 } 2265 2266 static HRESULT WINAPI d3dx9_fragment_linker_LinkPixelShader(ID3DXFragmentLinker *iface, const char *profile, 2267 DWORD flags, const D3DXHANDLE *handles, UINT fragment_count, IDirect3DPixelShader9 **shader, 2268 ID3DXBuffer **errors) 2269 { 2270 FIXME("iface %p, profile %s, flags %#x, handles %p, fragment_count %u, shader %p, errors %p: stub.\n", 2271 iface, debugstr_a(profile), flags, handles, fragment_count, shader, errors); 2272 2273 return E_NOTIMPL; 2274 } 2275 2276 static HRESULT WINAPI d3dx9_fragment_linker_ClearCache(ID3DXFragmentLinker *iface) 2277 { 2278 FIXME("iface %p: stub.\n", iface); 2279 2280 return E_NOTIMPL; 2281 } 2282 2283 static const struct ID3DXFragmentLinkerVtbl d3dx9_fragment_linker_vtbl = 2284 { 2285 d3dx9_fragment_linker_QueryInterface, 2286 d3dx9_fragment_linker_AddRef, 2287 d3dx9_fragment_linker_Release, 2288 d3dx9_fragment_linker_GetDevice, 2289 d3dx9_fragment_linker_GetNumberOfFragments, 2290 d3dx9_fragment_linker_GetFragmentHandleByIndex, 2291 d3dx9_fragment_linker_GetFragmentHandleByName, 2292 d3dx9_fragment_linker_GetFragmentDesc, 2293 d3dx9_fragment_linker_AddFragments, 2294 d3dx9_fragment_linker_GetAllFragments, 2295 d3dx9_fragment_linker_GetFragment, 2296 d3dx9_fragment_linker_LinkShader, 2297 d3dx9_fragment_linker_LinkVertexShader, 2298 d3dx9_fragment_linker_LinkPixelShader, 2299 d3dx9_fragment_linker_ClearCache 2300 }; 2301 2302 HRESULT WINAPI D3DXCreateFragmentLinkerEx(IDirect3DDevice9 *device, UINT size, DWORD flags, 2303 ID3DXFragmentLinker **linker) 2304 { 2305 struct d3dx9_fragment_linker *object; 2306 2307 TRACE("device %p, size %u, flags %#x, linker %p.\n", device, size, flags, linker); 2308 2309 object = heap_alloc(sizeof(*object)); 2310 if (!object) 2311 return E_OUTOFMEMORY; 2312 2313 object->ID3DXFragmentLinker_iface.lpVtbl = &d3dx9_fragment_linker_vtbl; 2314 object->ref = 1; 2315 2316 IDirect3DDevice9_AddRef(device); 2317 object->device = device; 2318 object->flags = flags; 2319 2320 *linker = &object->ID3DXFragmentLinker_iface; 2321 2322 return S_OK; 2323 } 2324 2325 HRESULT WINAPI D3DXCreateFragmentLinker(IDirect3DDevice9 *device, UINT size, ID3DXFragmentLinker **linker) 2326 { 2327 TRACE("device %p, size %u, linker %p.\n", device, size, linker); 2328 2329 return D3DXCreateFragmentLinkerEx(device, size, 0, linker); 2330 } 2331 2332 HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count) 2333 { 2334 UINT i, sampler_count = 0; 2335 UINT size; 2336 const char *data; 2337 const D3DXSHADER_CONSTANTTABLE *ctab_header; 2338 const D3DXSHADER_CONSTANTINFO *constant_info; 2339 2340 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count); 2341 2342 if (count) *count = 0; 2343 2344 if (D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (const void **)&data, &size) != D3D_OK) 2345 return D3D_OK; 2346 2347 if (size < sizeof(*ctab_header)) return D3D_OK; 2348 2349 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data; 2350 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK; 2351 2352 constant_info = (const D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo); 2353 for (i = 0; i < ctab_header->Constants; i++) 2354 { 2355 const D3DXSHADER_TYPEINFO *type; 2356 2357 TRACE("name = %s\n", data + constant_info[i].Name); 2358 2359 type = (const D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo); 2360 2361 if (type->Type == D3DXPT_SAMPLER 2362 || type->Type == D3DXPT_SAMPLER1D 2363 || type->Type == D3DXPT_SAMPLER2D 2364 || type->Type == D3DXPT_SAMPLER3D 2365 || type->Type == D3DXPT_SAMPLERCUBE) 2366 { 2367 if (samplers) samplers[sampler_count] = data + constant_info[i].Name; 2368 2369 ++sampler_count; 2370 } 2371 } 2372 2373 TRACE("Found %u samplers\n", sampler_count); 2374 2375 if (count) *count = sampler_count; 2376 2377 return D3D_OK; 2378 } 2379 2380 2381 static const char *decl_usage[] = { "position", "blendweight", "blendindices", "normal", "psize", "texcoord", 2382 "tangent", "binormal", "tessfactor", "positiont", "color" }; 2383 2384 static const char *tex_type[] = { "", "1d", "2d", "cube", "volume" }; 2385 2386 static int add_modifier(char *buffer, DWORD param) 2387 { 2388 char *buf = buffer; 2389 DWORD dst_mod = param & D3DSP_DSTMOD_MASK; 2390 2391 if (dst_mod & D3DSPDM_SATURATE) 2392 buf += sprintf(buf, "_sat"); 2393 if (dst_mod & D3DSPDM_PARTIALPRECISION) 2394 buf += sprintf(buf, "_pp"); 2395 if (dst_mod & D3DSPDM_MSAMPCENTROID) 2396 buf += sprintf(buf, "_centroid"); 2397 2398 return buf - buffer; 2399 } 2400 2401 static int add_register(char *buffer, DWORD param, BOOL dst, BOOL ps) 2402 { 2403 char *buf = buffer; 2404 DWORD reg_type = ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2) 2405 | ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT); 2406 DWORD reg_num = param & D3DSP_REGNUM_MASK; 2407 2408 if (reg_type == D3DSPR_INPUT) 2409 buf += sprintf(buf, "v%d", reg_num); 2410 else if (reg_type == D3DSPR_CONST) 2411 buf += sprintf(buf, "c%d", reg_num); 2412 else if (reg_type == D3DSPR_TEMP) 2413 buf += sprintf(buf, "r%d", reg_num); 2414 else if (reg_type == D3DSPR_ADDR) 2415 buf += sprintf(buf, "%s%d", ps ? "t" : "a", reg_num); 2416 else if (reg_type == D3DSPR_SAMPLER) 2417 buf += sprintf(buf, "s%d", reg_num); 2418 else if (reg_type == D3DSPR_RASTOUT) 2419 buf += sprintf(buf, "oPos"); 2420 else if (reg_type == D3DSPR_COLOROUT) 2421 buf += sprintf(buf, "oC%d", reg_num); 2422 else if (reg_type == D3DSPR_TEXCRDOUT) 2423 buf += sprintf(buf, "oT%d", reg_num); 2424 else if (reg_type == D3DSPR_ATTROUT) 2425 buf += sprintf(buf, "oD%d", reg_num); 2426 else 2427 buf += sprintf(buf, "? (%d)", reg_type); 2428 2429 if (dst) 2430 { 2431 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) 2432 { 2433 buf += sprintf(buf, ".%s%s%s%s", param & D3DSP_WRITEMASK_0 ? "x" : "", 2434 param & D3DSP_WRITEMASK_1 ? "y" : "", 2435 param & D3DSP_WRITEMASK_2 ? "z" : "", 2436 param & D3DSP_WRITEMASK_3 ? "w" : ""); 2437 } 2438 } 2439 else 2440 { 2441 if ((param & D3DVS_SWIZZLE_MASK) != D3DVS_NOSWIZZLE) 2442 { 2443 if ( ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_X | D3DVS_Y_X | D3DVS_Z_X | D3DVS_W_X)) || 2444 ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Y | D3DVS_Y_Y | D3DVS_Z_Y | D3DVS_W_Y)) || 2445 ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Z | D3DVS_Y_Z | D3DVS_Z_Z | D3DVS_W_Z)) || 2446 ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_W | D3DVS_Y_W | D3DVS_Z_W | D3DVS_W_W)) ) 2447 buf += sprintf(buf, ".%c", 'w' + (((param >> D3DVS_SWIZZLE_SHIFT) + 1) & 0x3)); 2448 else 2449 buf += sprintf(buf, ".%c%c%c%c", 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+0)) + 1) & 0x3), 2450 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+2)) + 1) & 0x3), 2451 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+4)) + 1) & 0x3), 2452 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+6)) + 1) & 0x3)); 2453 } 2454 } 2455 2456 return buf - buffer; 2457 } 2458 2459 struct instr_info 2460 { 2461 DWORD opcode; 2462 const char *name; 2463 int length; 2464 int (*function)(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps); 2465 WORD min_version; 2466 WORD max_version; 2467 }; 2468 2469 static int instr_comment(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps) 2470 { 2471 *ptr += 1 + ((**ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT); 2472 return 0; 2473 } 2474 2475 static int instr_def(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps) 2476 { 2477 int len = sprintf(buffer, " def c%d, %g, %g, %g, %g\n", *(*ptr+1) & D3DSP_REGNUM_MASK, 2478 (double)*(float*)(*ptr+2), (double)*(float*)(*ptr+3), 2479 (double)*(float*)(*ptr+4), (double)*(float*)(*ptr+5)); 2480 *ptr += 6; 2481 return len; 2482 } 2483 2484 static int instr_dcl(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps) 2485 { 2486 DWORD param1 = *++*ptr; 2487 DWORD param2 = *++*ptr; 2488 DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; 2489 DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; 2490 char *buf = buffer; 2491 2492 buf += sprintf(buf, " dcl"); 2493 if (ps) 2494 { 2495 if (param1 & D3DSP_TEXTURETYPE_MASK) 2496 buf += sprintf(buf, "_%s", (usage <= D3DSTT_VOLUME) ? 2497 tex_type[(param1 & D3DSP_TEXTURETYPE_MASK) >> D3DSP_TEXTURETYPE_SHIFT] : "???"); 2498 } 2499 else 2500 { 2501 buf += sprintf(buf, "_%s", (usage <= D3DDECLUSAGE_COLOR) ? decl_usage[usage] : "???"); 2502 if (usage_index) 2503 buf += sprintf(buf, "%d", usage_index); 2504 } 2505 2506 buf += add_modifier(buf, param2); 2507 buf += sprintf(buf, " "); 2508 buf += add_register(buf, param2, TRUE, TRUE); 2509 buf += sprintf(buf, "\n"); 2510 (*ptr)++; 2511 return buf - buffer; 2512 } 2513 2514 static int instr_generic(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps) 2515 { 2516 char *buf = buffer; 2517 int j; 2518 2519 buf += sprintf(buf, " %s", info->name); 2520 (*ptr)++; 2521 2522 if (info->length) 2523 { 2524 buf += add_modifier(buf, **ptr); 2525 2526 for (j = 0; j < info->length; j++) 2527 { 2528 buf += sprintf(buf, "%s ", j ? "," : ""); 2529 2530 if ((j != 0) && ((**ptr & D3DSP_SRCMOD_MASK) != D3DSPSM_NONE)) 2531 { 2532 if ((**ptr & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) 2533 buf += sprintf(buf, "-"); 2534 else 2535 buf += sprintf(buf, "*"); 2536 } 2537 2538 buf += add_register(buf, **ptr, j == 0, ps); 2539 2540 if (*(*ptr)++ & D3DVS_ADDRESSMODE_MASK) 2541 { 2542 buf += sprintf(buf, "["); 2543 buf += add_register(buf, **ptr, FALSE, FALSE); 2544 buf += sprintf(buf, "]"); 2545 (*ptr)++; 2546 } 2547 } 2548 } 2549 buf += sprintf(buf, "\n"); 2550 return buf - buffer; 2551 } 2552 2553 const struct instr_info instructions[] = 2554 { 2555 { D3DSIO_NOP, "nop", 0, instr_generic, 0x0100, 0xFFFF }, 2556 { D3DSIO_MOV, "mov", 2, instr_generic, 0x0100, 0xFFFF }, 2557 { D3DSIO_ADD, "add", 3, instr_generic, 0x0100, 0xFFFF }, 2558 { D3DSIO_SUB, "sub", 3, instr_generic, 0x0100, 0xFFFF }, 2559 { D3DSIO_MAD, "mad", 4, instr_generic, 0x0100, 0xFFFF }, 2560 { D3DSIO_MUL, "mul", 3, instr_generic, 0x0100, 0xFFFF }, 2561 { D3DSIO_RCP, "rcp", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2562 { D3DSIO_RSQ, "rsq", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2563 { D3DSIO_DP3, "dp3", 3, instr_generic, 0x0100, 0xFFFF }, 2564 { D3DSIO_DP4, "dp4", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 1.2 for PS */ 2565 { D3DSIO_MIN, "min", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2566 { D3DSIO_MAX, "max", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2567 { D3DSIO_SLT, "slt", 3, instr_generic, 0x0100, 0xFFFF }, 2568 { D3DSIO_SGE, "sge", 3, instr_generic, 0x0100, 0xFFFF }, /* VS only */ 2569 { D3DSIO_EXP, "exp", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2570 { D3DSIO_LOG, "log", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2571 { D3DSIO_LIT, "lit", 2, instr_generic, 0x0100, 0xFFFF }, /* VS only */ 2572 { D3DSIO_DST, "dst", 3, instr_generic, 0x0100, 0xFFFF }, /* VS only */ 2573 { D3DSIO_LRP, "lrp", 4, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for VS */ 2574 { D3DSIO_FRC, "frc", 2, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2575 { D3DSIO_M4x4, "m4x4", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2576 { D3DSIO_M4x3, "m4x3", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2577 { D3DSIO_M3x4, "m3x4", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2578 { D3DSIO_M3x3, "m3x3", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2579 { D3DSIO_M3x2, "m3x2", 3, instr_generic, 0x0100, 0xFFFF }, /* >= 2.0 for PS */ 2580 { D3DSIO_CALL, "call", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2581 { D3DSIO_CALLNZ, "callnz", 2, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2582 { D3DSIO_LOOP, "loop", 2, instr_generic, 0x0200, 0xFFFF }, /* >= 3.0 for PS */ 2583 { D3DSIO_RET, "ret", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2584 { D3DSIO_ENDLOOP, "endloop", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 3.0 for PS */ 2585 { D3DSIO_LABEL, "label", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2586 { D3DSIO_DCL, "dcl", 1, instr_dcl, 0x0100, 0xFFFF }, 2587 { D3DSIO_POW, "pow", 3, instr_generic, 0x0200, 0xFFFF }, 2588 { D3DSIO_CRS, "crs", 3, instr_generic, 0x0200, 0xFFFF }, 2589 { D3DSIO_SGN, "sgn", 4, instr_generic, 0x0200, 0xFFFF }, /* VS only */ 2590 { D3DSIO_ABS, "abs", 2, instr_generic, 0x0200, 0xFFFF }, 2591 { D3DSIO_NRM, "nrm", 2, instr_generic, 0x0200, 0xFFFF }, 2592 { D3DSIO_SINCOS, "sincos", 4, instr_generic, 0x0200, 0x02FF }, 2593 { D3DSIO_SINCOS, "sincos", 2, instr_generic, 0x0300, 0xFFFF }, 2594 { D3DSIO_REP, "rep", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2595 { D3DSIO_ENDREP, "endrep", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2596 { D3DSIO_IF, "if", 1, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2597 { D3DSIO_IFC, "if_comp", 2, instr_generic, 0x0200, 0xFFFF }, 2598 { D3DSIO_ELSE, "else", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2599 { D3DSIO_ENDIF, "endif", 0, instr_generic, 0x0200, 0xFFFF }, /* >= 2.a for PS */ 2600 { D3DSIO_BREAK, "break", 0, instr_generic, 0x0201, 0xFFFF }, 2601 { D3DSIO_BREAKC, "break_comp", 2, instr_generic, 0x0201, 0xFFFF }, 2602 { D3DSIO_MOVA, "mova", 2, instr_generic, 0x0200, 0xFFFF }, /* VS only */ 2603 { D3DSIO_DEFB, "defb", 2, instr_generic, 0x0100, 0xFFFF }, 2604 { D3DSIO_DEFI, "defi", 2, instr_generic, 0x0100, 0xFFFF }, 2605 { D3DSIO_TEXCOORD, "texcoord", 1, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2606 { D3DSIO_TEXCOORD, "texcrd", 2, instr_generic, 0x0104, 0x0104 }, /* PS only */ 2607 { D3DSIO_TEXKILL, "texkill", 1, instr_generic, 0x0100, 0xFFFF }, /* PS only */ 2608 { D3DSIO_TEX, "tex", 1, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2609 { D3DSIO_TEX, "texld", 2, instr_generic, 0x0104, 0x0104 }, /* PS only */ 2610 { D3DSIO_TEX, "texld", 3, instr_generic, 0x0200, 0xFFFF }, /* PS only */ 2611 { D3DSIO_TEXBEM, "texbem", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2612 { D3DSIO_TEXBEML, "texbeml", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2613 { D3DSIO_TEXREG2AR, "texreg2ar", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2614 { D3DSIO_TEXREG2GB, "texreg2gb", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */ 2615 { D3DSIO_TEXM3x2PAD, "texm3x2pad", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2616 { D3DSIO_TEXM3x2TEX, "texm3x2tex", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2617 { D3DSIO_TEXM3x3PAD, "texm3x3pad", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2618 { D3DSIO_TEXM3x3TEX, "texm3x3tex", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2619 { D3DSIO_TEXM3x3DIFF, "texm3x3diff", 2, instr_generic, 0x0100, 0xFFFF }, /* PS only - Not documented */ 2620 { D3DSIO_TEXM3x3SPEC, "texm3x3spec", 3, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2621 { D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", 2, instr_generic, 0x0100, 0x0103 }, /* PS only */ 2622 { D3DSIO_EXPP, "expp", 2, instr_generic, 0x0100, 0xFFFF }, /* VS only */ 2623 { D3DSIO_LOGP, "logp", 2, instr_generic, 0x0100, 0xFFFF }, /* VS only */ 2624 { D3DSIO_CND, "cnd", 4, instr_generic, 0x0100, 0x0104 }, /* PS only */ 2625 { D3DSIO_DEF, "def", 5, instr_def, 0x0100, 0xFFFF }, 2626 { D3DSIO_TEXREG2RGB, "texreg2rgb", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */ 2627 { D3DSIO_TEXDP3TEX, "texdp3tex", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */ 2628 { D3DSIO_TEXM3x2DEPTH, "texm3x2depth", 2, instr_generic, 0x0103, 0x0103 }, /* PS only */ 2629 { D3DSIO_TEXDP3, "texdp3", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */ 2630 { D3DSIO_TEXM3x3, "texm3x3", 2, instr_generic, 0x0102, 0x0103 }, /* PS only */ 2631 { D3DSIO_TEXDEPTH, "texdepth", 1, instr_generic, 0x0104, 0x0104 }, /* PS only */ 2632 { D3DSIO_CMP, "cmp", 4, instr_generic, 0x0102, 0xFFFF }, /* PS only */ 2633 { D3DSIO_BEM, "bem", 3, instr_generic, 0x0104, 0x0104 }, /* PS only */ 2634 { D3DSIO_DP2ADD, "dp2add", 4, instr_generic, 0x0200, 0xFFFF }, /* PS only */ 2635 { D3DSIO_DSX, "dsx", 2, instr_generic, 0x0201, 0xFFFF }, /* PS only */ 2636 { D3DSIO_DSY, "dsy", 2, instr_generic, 0x0201, 0xFFFF }, /* PS only */ 2637 { D3DSIO_TEXLDD, "texldd", 5, instr_generic, 0x0201, 0xFFFF }, /* PS only - not existing for 2.b */ 2638 { D3DSIO_SETP, "setp_comp", 3, instr_generic, 0x0201, 0xFFFF }, 2639 { D3DSIO_TEXLDL, "texldl", 3, instr_generic, 0x0300, 0xFFFF }, 2640 { D3DSIO_BREAKP, "breakp", 1, instr_generic, 0x0201, 0xFFFF }, 2641 { D3DSIO_PHASE, "phase", 0, instr_generic, 0x0104, 0x0104 }, /* PS only */ 2642 { D3DSIO_COMMENT, "", 0, instr_comment, 0x0100, 0xFFFF } 2643 }; 2644 2645 HRESULT WINAPI D3DXDisassembleShader(const DWORD *shader, BOOL colorcode, const char *comments, ID3DXBuffer **disassembly) 2646 { 2647 DWORD *ptr = (DWORD *)shader; 2648 char *buffer, *buf; 2649 UINT capacity = 4096; 2650 BOOL ps; 2651 WORD version; 2652 HRESULT hr; 2653 2654 TRACE("%p %d %s %p\n", shader, colorcode, debugstr_a(comments), disassembly); 2655 2656 if (!shader || !disassembly) 2657 return D3DERR_INVALIDCALL; 2658 2659 buf = buffer = HeapAlloc(GetProcessHeap(), 0, capacity); 2660 if (!buffer) 2661 return E_OUTOFMEMORY; 2662 2663 ps = (*ptr >> 16) & 1; 2664 version = *ptr & 0xFFFF; 2665 buf += sprintf(buf, " %s_%d_%d\n", ps ? "ps" : "vs", D3DSHADER_VERSION_MAJOR(*ptr), D3DSHADER_VERSION_MINOR(*ptr)); 2666 ptr++; 2667 2668 while (*ptr != D3DSIO_END) 2669 { 2670 DWORD index; 2671 2672 if ((buf - buffer + 128) > capacity) 2673 { 2674 UINT count = buf - buffer; 2675 char *new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, capacity * 2); 2676 if (!new_buffer) 2677 { 2678 HeapFree(GetProcessHeap(), 0, buffer); 2679 return E_OUTOFMEMORY; 2680 } 2681 capacity *= 2; 2682 buffer = new_buffer; 2683 buf = buffer + count; 2684 } 2685 2686 for (index = 0; index < sizeof(instructions)/sizeof(instructions[0]); index++) 2687 if (((*ptr & D3DSI_OPCODE_MASK) == instructions[index].opcode) && 2688 (version >= instructions[index].min_version) && (version <= instructions[index].max_version)) 2689 break; 2690 2691 if (index != sizeof(instructions)/sizeof(instructions[0])) 2692 { 2693 buf += instructions[index].function(&(instructions[index]), &ptr, buf, ps); 2694 } 2695 else 2696 { 2697 buf += sprintf(buf, " ??? (Unknown opcode %x)\n", *ptr); 2698 while (*++ptr & (1u << 31)); 2699 } 2700 } 2701 2702 hr = D3DXCreateBuffer(buf - buffer + 1 , disassembly); 2703 if (SUCCEEDED(hr)) 2704 strcpy(ID3DXBuffer_GetBufferPointer(*disassembly), buffer); 2705 HeapFree(GetProcessHeap(), 0, buffer); 2706 2707 return hr; 2708 } 2709 2710 struct d3dx9_texture_shader 2711 { 2712 ID3DXTextureShader ID3DXTextureShader_iface; 2713 LONG ref; 2714 }; 2715 2716 static inline struct d3dx9_texture_shader *impl_from_ID3DXTextureShader(ID3DXTextureShader *iface) 2717 { 2718 return CONTAINING_RECORD(iface, struct d3dx9_texture_shader, ID3DXTextureShader_iface); 2719 } 2720 2721 static HRESULT WINAPI d3dx9_texture_shader_QueryInterface(ID3DXTextureShader *iface, REFIID riid, void **out) 2722 { 2723 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 2724 2725 if (IsEqualGUID(riid, &IID_IUnknown) || 2726 IsEqualGUID(riid, &IID_ID3DXTextureShader)) 2727 { 2728 iface->lpVtbl->AddRef(iface); 2729 *out = iface; 2730 return D3D_OK; 2731 } 2732 2733 WARN("Interface %s not found.\n", debugstr_guid(riid)); 2734 *out = NULL; 2735 return E_NOINTERFACE; 2736 } 2737 2738 static ULONG WINAPI d3dx9_texture_shader_AddRef(ID3DXTextureShader *iface) 2739 { 2740 struct d3dx9_texture_shader *texture_shader = impl_from_ID3DXTextureShader(iface); 2741 ULONG refcount = InterlockedIncrement(&texture_shader->ref); 2742 2743 TRACE("%p increasing refcount to %u.\n", texture_shader, refcount); 2744 2745 return refcount; 2746 } 2747 2748 static ULONG WINAPI d3dx9_texture_shader_Release(ID3DXTextureShader *iface) 2749 { 2750 struct d3dx9_texture_shader *texture_shader = impl_from_ID3DXTextureShader(iface); 2751 ULONG refcount = InterlockedDecrement(&texture_shader->ref); 2752 2753 TRACE("%p decreasing refcount to %u.\n", texture_shader, refcount); 2754 2755 if (!refcount) 2756 { 2757 HeapFree(GetProcessHeap(), 0, texture_shader); 2758 } 2759 2760 return refcount; 2761 } 2762 2763 static HRESULT WINAPI d3dx9_texture_shader_GetFunction(ID3DXTextureShader *iface, struct ID3DXBuffer **function) 2764 { 2765 FIXME("iface %p, function %p stub.\n", iface, function); 2766 2767 return E_NOTIMPL; 2768 } 2769 2770 static HRESULT WINAPI d3dx9_texture_shader_GetConstantBuffer(ID3DXTextureShader *iface, struct ID3DXBuffer **constant_buffer) 2771 { 2772 FIXME("iface %p, constant_buffer %p stub.\n", iface, constant_buffer); 2773 2774 return E_NOTIMPL; 2775 } 2776 2777 static HRESULT WINAPI d3dx9_texture_shader_GetDesc(ID3DXTextureShader *iface, D3DXCONSTANTTABLE_DESC *desc) 2778 { 2779 FIXME("iface %p, desc %p stub.\n", iface, desc); 2780 2781 return E_NOTIMPL; 2782 } 2783 2784 static HRESULT WINAPI d3dx9_texture_shader_GetConstantDesc(ID3DXTextureShader *iface, D3DXHANDLE constant, D3DXCONSTANT_DESC *constant_desc, UINT *count) 2785 { 2786 FIXME("iface %p, constant %p, constant_desc %p, count %p stub.\n", iface, constant, constant_desc, count); 2787 2788 return E_NOTIMPL; 2789 } 2790 2791 static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstant(ID3DXTextureShader *iface, D3DXHANDLE constant, UINT index) 2792 { 2793 FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index); 2794 2795 return NULL; 2796 } 2797 2798 static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstantByName(ID3DXTextureShader *iface, D3DXHANDLE constant, const char *name) 2799 { 2800 FIXME("iface %p, constant %p, name %s stub.\n", iface, constant, debugstr_a(name)); 2801 2802 return NULL; 2803 } 2804 2805 static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstantElement(ID3DXTextureShader *iface, D3DXHANDLE constant, UINT index) 2806 { 2807 FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index); 2808 2809 return NULL; 2810 } 2811 2812 static HRESULT WINAPI d3dx9_texture_shader_SetDefaults(ID3DXTextureShader *iface) 2813 { 2814 FIXME("iface %p stub.\n", iface); 2815 2816 return E_NOTIMPL; 2817 } 2818 2819 static HRESULT WINAPI d3dx9_texture_shader_SetValue(ID3DXTextureShader *iface, D3DXHANDLE constant, const void *data, UINT bytes) 2820 { 2821 FIXME("iface %p, constant %p, data %p, bytes %u stub.\n", iface, constant, data, bytes); 2822 2823 return E_NOTIMPL; 2824 } 2825 2826 static HRESULT WINAPI d3dx9_texture_shader_SetBool(ID3DXTextureShader *iface, D3DXHANDLE constant, BOOL b) 2827 { 2828 FIXME("iface %p, constant %p, b %u stub.\n", iface, constant, b); 2829 2830 return E_NOTIMPL; 2831 } 2832 2833 static HRESULT WINAPI d3dx9_texture_shader_SetBoolArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const BOOL *b, UINT count) 2834 { 2835 FIXME("iface %p, constant %p, b %p, count %u stub.\n", iface, constant, b, count); 2836 2837 return E_NOTIMPL; 2838 } 2839 2840 static HRESULT WINAPI d3dx9_texture_shader_SetInt(ID3DXTextureShader *iface, D3DXHANDLE constant, INT n) 2841 { 2842 FIXME("iface %p, constant %p, n %d stub.\n", iface, constant, n); 2843 2844 return E_NOTIMPL; 2845 } 2846 2847 static HRESULT WINAPI d3dx9_texture_shader_SetIntArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const INT *n, UINT count) 2848 { 2849 FIXME("iface %p, constant %p, n %p, count %u stub.\n", iface, constant, n, count); 2850 2851 return E_NOTIMPL; 2852 } 2853 2854 static HRESULT WINAPI d3dx9_texture_shader_SetFloat(ID3DXTextureShader *iface, D3DXHANDLE constant, FLOAT f) 2855 { 2856 FIXME("iface %p, constant %p, f %f stub.\n", iface, constant, f); 2857 2858 return E_NOTIMPL; 2859 } 2860 2861 static HRESULT WINAPI d3dx9_texture_shader_SetFloatArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const FLOAT *f, UINT count) 2862 { 2863 FIXME("iface %p, constant %p, f %p, count %u stub.\n", iface, constant, f, count); 2864 2865 return E_NOTIMPL; 2866 } 2867 2868 static HRESULT WINAPI d3dx9_texture_shader_SetVector(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXVECTOR4 *vector) 2869 { 2870 FIXME("iface %p, constant %p, vector %p stub.\n", iface, constant, vector); 2871 2872 return E_NOTIMPL; 2873 } 2874 2875 static HRESULT WINAPI d3dx9_texture_shader_SetVectorArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count) 2876 { 2877 FIXME("iface %p, constant %p, vector %p, count %u stub.\n", iface, constant, vector, count); 2878 2879 return E_NOTIMPL; 2880 } 2881 2882 static HRESULT WINAPI d3dx9_texture_shader_SetMatrix(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix) 2883 { 2884 FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix); 2885 2886 return E_NOTIMPL; 2887 } 2888 2889 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count) 2890 { 2891 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count); 2892 2893 return E_NOTIMPL; 2894 } 2895 2896 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixPointerArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count) 2897 { 2898 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count); 2899 2900 return E_NOTIMPL; 2901 } 2902 2903 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTranspose(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix) 2904 { 2905 FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix); 2906 2907 return E_NOTIMPL; 2908 } 2909 2910 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTransposeArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count) 2911 { 2912 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count); 2913 2914 return E_NOTIMPL; 2915 } 2916 2917 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTransposePointerArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count) 2918 { 2919 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count); 2920 2921 return E_NOTIMPL; 2922 } 2923 2924 static const struct ID3DXTextureShaderVtbl d3dx9_texture_shader_vtbl = 2925 { 2926 /*** IUnknown methods ***/ 2927 d3dx9_texture_shader_QueryInterface, 2928 d3dx9_texture_shader_AddRef, 2929 d3dx9_texture_shader_Release, 2930 /*** ID3DXTextureShader methods ***/ 2931 d3dx9_texture_shader_GetFunction, 2932 d3dx9_texture_shader_GetConstantBuffer, 2933 d3dx9_texture_shader_GetDesc, 2934 d3dx9_texture_shader_GetConstantDesc, 2935 d3dx9_texture_shader_GetConstant, 2936 d3dx9_texture_shader_GetConstantByName, 2937 d3dx9_texture_shader_GetConstantElement, 2938 d3dx9_texture_shader_SetDefaults, 2939 d3dx9_texture_shader_SetValue, 2940 d3dx9_texture_shader_SetBool, 2941 d3dx9_texture_shader_SetBoolArray, 2942 d3dx9_texture_shader_SetInt, 2943 d3dx9_texture_shader_SetIntArray, 2944 d3dx9_texture_shader_SetFloat, 2945 d3dx9_texture_shader_SetFloatArray, 2946 d3dx9_texture_shader_SetVector, 2947 d3dx9_texture_shader_SetVectorArray, 2948 d3dx9_texture_shader_SetMatrix, 2949 d3dx9_texture_shader_SetMatrixArray, 2950 d3dx9_texture_shader_SetMatrixPointerArray, 2951 d3dx9_texture_shader_SetMatrixTranspose, 2952 d3dx9_texture_shader_SetMatrixTransposeArray, 2953 d3dx9_texture_shader_SetMatrixTransposePointerArray 2954 }; 2955 2956 HRESULT WINAPI D3DXCreateTextureShader(const DWORD *function, ID3DXTextureShader **texture_shader) 2957 { 2958 struct d3dx9_texture_shader *object; 2959 2960 TRACE("function %p, texture_shader %p.\n", function, texture_shader); 2961 2962 if (!function || !texture_shader) 2963 return D3DERR_INVALIDCALL; 2964 2965 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object)); 2966 if (!object) 2967 return E_OUTOFMEMORY; 2968 2969 object->ID3DXTextureShader_iface.lpVtbl = &d3dx9_texture_shader_vtbl; 2970 object->ref = 1; 2971 2972 *texture_shader = &object->ID3DXTextureShader_iface; 2973 2974 return D3D_OK; 2975 } 2976 2977 static unsigned int get_instr_length(const DWORD *byte_code, unsigned int major, unsigned int minor) 2978 { 2979 DWORD opcode = *byte_code & 0xffff; 2980 unsigned int len = 0; 2981 2982 if (opcode == D3DSIO_COMMENT) 2983 return (*byte_code & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT; 2984 2985 if (major > 1) 2986 return (*byte_code & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT; 2987 2988 switch (opcode) 2989 { 2990 case D3DSIO_END: 2991 ERR("Unexpected END token.\n"); 2992 return 0; 2993 case D3DSIO_DEF: 2994 case D3DSIO_DEFI: 2995 return 5; 2996 case D3DSIO_DEFB: 2997 return 2; 2998 default: 2999 ++byte_code; 3000 while (*byte_code & 0x80000000) 3001 { 3002 ++byte_code; 3003 ++len; 3004 } 3005 } 3006 3007 return len; 3008 } 3009 3010 static HRESULT get_shader_semantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count, BOOL output) 3011 { 3012 static const D3DDECLUSAGE regtype_usage[] = 3013 { 3014 D3DDECLUSAGE_COLOR, 3015 D3DDECLUSAGE_COLOR, 3016 0, 3017 D3DDECLUSAGE_TEXCOORD, 3018 0, 3019 D3DDECLUSAGE_COLOR, 3020 D3DDECLUSAGE_TEXCOORD, 3021 0, 3022 0, 3023 D3DDECLUSAGE_DEPTH 3024 }; 3025 static const D3DDECLUSAGE rast_usage[] = 3026 { 3027 D3DDECLUSAGE_POSITION, 3028 D3DDECLUSAGE_FOG, 3029 D3DDECLUSAGE_PSIZE 3030 }; 3031 DWORD reg_type, usage, index, version_token = *byte_code; 3032 BOOL is_ps = version_token >> 16 == 0xffff; 3033 unsigned int major, minor, i = 0, j; 3034 BYTE colors = 0, rastout = 0; 3035 BOOL has_dcl, depth = 0; 3036 WORD texcoords = 0; 3037 3038 if ((version_token & 0xffff0000) != 0xfffe0000 && (version_token & 0xffff0000) != 0xffff0000) 3039 return D3DXERR_INVALIDDATA; 3040 3041 major = version_token >> 8 & 0xff; 3042 minor = version_token & 0xff; 3043 3044 TRACE("%s shader, version %u.%u.\n", is_ps ? "Pixel" : "Vertex", major, minor); 3045 ++byte_code; 3046 3047 has_dcl = (!is_ps && (!output || major == 3)) || (is_ps && !output && major >= 2); 3048 3049 while (*byte_code != D3DSIO_END) 3050 { 3051 if (has_dcl && (*byte_code & 0xffff) == D3DSIO_DCL) 3052 { 3053 DWORD usage_token = byte_code[1]; 3054 DWORD reg = byte_code[2]; 3055 3056 reg_type = ((reg & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) 3057 | ((reg & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2); 3058 3059 if (is_ps && !output && major == 2) 3060 { 3061 /* dcl with no explicit usage, look at the register. */ 3062 reg_type = ((reg & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) 3063 | ((reg & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2); 3064 index = reg & D3DSP_REGNUM_MASK; 3065 if (reg_type >= ARRAY_SIZE(regtype_usage)) 3066 { 3067 WARN("Invalid register type %u.\n", reg_type); 3068 reg_type = 0; 3069 } 3070 usage = regtype_usage[reg_type]; 3071 if (semantics) 3072 { 3073 semantics[i].Usage = usage; 3074 semantics[i].UsageIndex = index; 3075 } 3076 ++i; 3077 } 3078 else if ((!output && reg_type == D3DSPR_INPUT) || (output && reg_type == D3DSPR_OUTPUT)) 3079 { 3080 if (semantics) 3081 { 3082 semantics[i].Usage = 3083 (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; 3084 semantics[i].UsageIndex = 3085 (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; 3086 } 3087 ++i; 3088 } 3089 byte_code += 3; 3090 } 3091 else if (!has_dcl) 3092 { 3093 unsigned int len = get_instr_length(byte_code, major, minor) + 1; 3094 3095 switch (*byte_code & 0xffff) 3096 { 3097 case D3DSIO_COMMENT: 3098 case D3DSIO_DEF: 3099 case D3DSIO_DEFB: 3100 case D3DSIO_DEFI: 3101 byte_code += len; 3102 break; 3103 default: 3104 ++byte_code; 3105 while (*byte_code & 0x80000000) 3106 { 3107 reg_type = ((*byte_code & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) 3108 | ((*byte_code & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2); 3109 index = *byte_code & D3DSP_REGNUM_MASK; 3110 3111 if ((reg_type == D3DSPR_TEMP && is_ps && major == 1) 3112 || (reg_type == D3DSPR_INPUT && is_ps) 3113 || (reg_type == D3DSPR_TEXTURE && is_ps && !output) 3114 || reg_type == D3DSPR_RASTOUT 3115 || reg_type == D3DSPR_ATTROUT 3116 || reg_type == D3DSPR_OUTPUT 3117 || reg_type == D3DSPR_DEPTHOUT) 3118 { 3119 if (reg_type == D3DSPR_RASTOUT) 3120 rastout |= 1u << index; 3121 else if (reg_type == D3DSPR_DEPTHOUT) 3122 depth = TRUE; 3123 else if (reg_type == D3DSPR_TEXTURE || reg_type == D3DSPR_OUTPUT) 3124 texcoords |= 1u << index; 3125 else 3126 colors |= 1u << index; 3127 } 3128 ++byte_code; 3129 } 3130 } 3131 } 3132 else 3133 { 3134 byte_code += get_instr_length(byte_code, major, minor) + 1; 3135 } 3136 } 3137 3138 if (!has_dcl) 3139 { 3140 i = j = 0; 3141 while (texcoords) 3142 { 3143 if (texcoords & 1) 3144 { 3145 if (semantics) 3146 { 3147 semantics[i].Usage = D3DDECLUSAGE_TEXCOORD; 3148 semantics[i].UsageIndex = j; 3149 } 3150 ++i; 3151 } 3152 texcoords >>= 1; 3153 ++j; 3154 } 3155 j = 0; 3156 while (colors) 3157 { 3158 if (colors & 1) 3159 { 3160 if (semantics) 3161 { 3162 semantics[i].Usage = D3DDECLUSAGE_COLOR; 3163 semantics[i].UsageIndex = j; 3164 } 3165 ++i; 3166 } 3167 colors >>= 1; 3168 ++j; 3169 } 3170 j = 0; 3171 while (rastout) 3172 { 3173 if (rastout & 1) 3174 { 3175 if (j >= ARRAY_SIZE(rast_usage)) 3176 { 3177 WARN("Invalid RASTOUT register index.\n"); 3178 usage = 0; 3179 } 3180 else 3181 { 3182 usage = rast_usage[j]; 3183 } 3184 if (semantics) 3185 { 3186 semantics[i].Usage = usage; 3187 semantics[i].UsageIndex = 0; 3188 } 3189 ++i; 3190 } 3191 rastout >>= 1; 3192 ++j; 3193 } 3194 if (depth) 3195 { 3196 if (semantics) 3197 { 3198 semantics[i].Usage = D3DDECLUSAGE_DEPTH; 3199 semantics[i].UsageIndex = 0; 3200 } 3201 ++i; 3202 } 3203 } 3204 3205 if (count) 3206 *count = i; 3207 3208 return D3D_OK; 3209 } 3210 3211 HRESULT WINAPI D3DXGetShaderInputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count) 3212 { 3213 TRACE("byte_code %p, semantics %p, count %p.\n", byte_code, semantics, count); 3214 3215 return get_shader_semantics(byte_code, semantics, count, FALSE); 3216 } 3217 3218 HRESULT WINAPI D3DXGetShaderOutputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count) 3219 { 3220 TRACE("byte_code %p, semantics %p, count %p.\n", byte_code, semantics, count); 3221 3222 return get_shader_semantics(byte_code, semantics, count, TRUE); 3223 } 3224