[SHELL32] Remove 2 redundant initializations
[reactos.git] / dll / directx / wine / d3dx9_36 / shader.c
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 }