ReactOS 0.4.15-dev-8417-gb6b82fe
shader.c
Go to the documentation of this file.
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
32
33/* This function is not declared in the SDK headers yet. */
34HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename,
37
39{
40 return (token & 0xfffe0000) == 0xfffe0000;
41}
42
43const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device)
44{
45 D3DCAPS9 caps;
46
47 TRACE("device %p\n", device);
48
49 if (!device) return NULL;
50
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) &&
74 {
75 return "ps_2_a";
76 }
77 if ((caps.PS20Caps.NumTemps>=32) &&
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
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 */
104 {
106 }
107 }
108 ++ptr;
109
110 /* Return the shader size in bytes */
111 return (ptr - byte_code) * sizeof(*ptr);
112}
113
115{
116 TRACE("byte_code %p\n", byte_code);
117
118 return byte_code ? *byte_code : 0;
119}
120
121const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device)
122{
123 D3DCAPS9 caps;
124
125 TRACE("device %p\n", device);
126
127 if (!device) return NULL;
128
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) &&
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
150HRESULT WINAPI D3DXFindShaderComment(const DWORD *byte_code, DWORD fourcc, const void **data, UINT *size)
151{
152 const DWORD *ptr = byte_code;
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 */
178 {
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
202{
203 HRESULT hr;
204
205 TRACE("data %p, data_len %u, defines %p, include %p, flags %#x, shader %p, error_messages %p\n",
207
208 /* Forward to d3dcompiler: the parameter types aren't really different,
209 the actual data types are equivalent */
213
215 return hr;
216}
217
218static const void *main_file_data;
219
221{
222 0, 0, &from_file_mutex,
223 {
226 },
227 0, 0, {(DWORD_PTR)(__FILE__ ": from_file_mutex")}
228};
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. */
236static 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)
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
277 goto error;
278
279 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
280
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)
295
297 return S_OK;
298
299error:
304}
305
306static 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)
312 return S_OK;
313}
314
315const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl =
316{
319};
320
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",
330
331 if (!filename) return D3DXERR_INVALIDDATA;
332
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
339
340 HeapFree(GetProcessHeap(), 0, filename_w);
341 return ret;
342}
343
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",
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
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
370 if (FAILED(hr))
371 {
373 HeapFree(GetProcessHeap(), 0, filename_a);
374 return D3DXERR_INVALIDDATA;
375 }
376
378
381 HeapFree(GetProcessHeap(), 0, filename_a);
382 return hr;
383}
384
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",
394
395 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
396 return D3DXERR_INVALIDDATA;
398 return D3DXERR_INVALIDDATA;
401}
402
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",
412
413 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
414 return D3DXERR_INVALIDDATA;
416 return D3DXERR_INVALIDDATA;
419}
420
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",
430 flags, shader, error_msgs, constant_table);
431
432 if (D3DX_SDK_VERSION <= 36)
434
436 function, profile, flags, 0, (ID3DBlob **)shader, (ID3DBlob **)error_msgs);
437
438 if (SUCCEEDED(hr) && constant_table)
439 {
441 if (FAILED(hr))
442 {
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
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",
497 debugstr_a(profile), flags, shader, error_messages, constant_table);
498
499 if (!filename) return D3DXERR_INVALIDDATA;
500
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
507 entrypoint, profile, flags,
508 shader, error_messages, constant_table);
509
510 HeapFree(GetProcessHeap(), 0, filename_w);
511 return ret;
512}
513
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",
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
543 if (FAILED(hr))
544 {
546 HeapFree(GetProcessHeap(), 0, filename_a);
547 return D3DXERR_INVALIDDATA;
548 }
549
550 if (D3DX_SDK_VERSION <= 36)
552
553 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
554 (ID3DInclude *)include, entrypoint, profile, flags, 0,
556
557 if (SUCCEEDED(hr) && constant_table)
559 constant_table);
560
563 HeapFree(GetProcessHeap(), 0, filename_a);
564 return hr;
565}
566
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",
578 flags, shader, error_messages, constant_table);
579
580 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
581 return D3DXERR_INVALIDDATA;
583 return D3DXERR_INVALIDDATA;
584 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
585 flags, shader, error_messages, constant_table);
586}
587
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",
599 flags, shader, error_messages, constant_table);
600
601 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
602 return D3DXERR_INVALIDDATA;
604 return D3DXERR_INVALIDDATA;
605 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
606 flags, shader, error_messages, constant_table);
607}
608
611{
612 TRACE("data %s, data_len %u, defines %p, include %p, shader %p, error_messages %p.\n",
614
615 return D3DPreprocess(data, data_len, NULL,
618}
619
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",
629
630 if (!filename) return D3DXERR_INVALIDDATA;
631
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
638
639 HeapFree(GetProcessHeap(), 0, filename_w);
640 return ret;
641}
642
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",
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
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
669 if (FAILED(hr))
670 {
672 HeapFree(GetProcessHeap(), 0, filename_a);
673 return D3DXERR_INVALIDDATA;
674 }
675
677 (const D3D_SHADER_MACRO *)defines,
680
683 HeapFree(GetProcessHeap(), 0, filename_a);
684 return hr;
685}
686
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",
696
697 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
698 return D3DXERR_INVALIDDATA;
700 return D3DXERR_INVALIDDATA;
703}
704
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",
714
715 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
716 return D3DXERR_INVALIDDATA;
718 return D3DXERR_INVALIDDATA;
721
722}
723
725 ID3DXConstantTable ID3DXConstantTable_iface;
727 char *ctab;
731};
732
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
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
762static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
763{
765}
766
768{
769 return (version & 0xffff0000) == 0xfffe0000;
770}
771
773{
774 return (D3DXHANDLE)constant;
775}
776
778 struct ctab_constant *constant, const char *name);
779
781{
782 const char *part;
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
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
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
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
904}
905
906/*** IUnknown methods ***/
907static 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
912 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
913 IsEqualGUID(riid, &IID_ID3DXConstantTable))
914 {
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
925static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
926{
928
929 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
930
931 return InterlockedIncrement(&This->ref);
932}
933
934static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
935{
938
939 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
940
941 if (!ref)
942 {
945 }
946
947 return ref;
948}
949
950/*** ID3DXBuffer methods ***/
951static void * WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
952{
954
955 TRACE("iface %p.\n", iface);
956
957 return table->ctab;
958}
959
960static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
961{
963
964 TRACE("(%p)->()\n", This);
965
966 return This->size;
967}
968
969/*** ID3DXConstantTable methods ***/
971{
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
984const struct ctab_constant *d3dx_shader_get_ctab_constant(ID3DXConstantTable *iface, D3DXHANDLE constant)
985{
987
989}
990
993{
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
1012{
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
1029{
1031 struct ctab_constant *c;
1032
1033 TRACE("(%p)->(%p, %d)\n", This, constant, index);
1034
1035 if (constant)
1036 {
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
1060 D3DXHANDLE constant, const char *name)
1061{
1064
1065 TRACE("iface %p, constant %p, name %s.\n", iface, constant, debugstr_a(name));
1066
1068 TRACE("Returning constant %p\n", c);
1069
1070 return handle_from_constant(c);
1071}
1072
1074{
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
1091static 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
1102static 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{
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;
1156
1157 if (is_pointer)
1158 min = *(D3DXMATRIX *)(indata[index / 16]);
1159 else
1160 min = **(D3DXMATRIX **)indata;
1161
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
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
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:
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
1312 switch (desc->Class)
1313 {
1314 case D3DXPC_MATRIX_ROWS:
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))
1359 else
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))
1380 else
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))
1399 else
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
1411 const void *indata, D3DXPARAMETER_TYPE intype)
1412{
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:
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
1441 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1442{
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:
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
1468 const void *indata, D3DXPARAMETER_TYPE intype)
1469{
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:
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
1498 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1499{
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:
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
1526 const void *indata, UINT count, BOOL transpose)
1527{
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:
1542 case D3DXPC_STRUCT:
1543 count *= 16;
1544 set(table, device, c, &indata, D3DXPT_FLOAT, &count, 4,
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
1555 D3DXHANDLE constant, const void **indata, UINT count, BOOL transpose)
1556{
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:
1571 case D3DXPC_STRUCT:
1572 count *= 16;
1573 set(table, device, c, indata, D3DXPT_FLOAT, &count, 4,
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
1583static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1584 struct IDirect3DDevice9 *device)
1585{
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
1647static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1648 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, unsigned int bytes)
1649{
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:
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
1681static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1682 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1683{
1685
1686 TRACE("iface %p, device %p, constant %p, b %d\n", iface, device, constant, b);
1687
1689}
1690
1691static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1692 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1693{
1695
1696 TRACE("iface %p, device %p, constant %p, b %p, count %d\n", iface, device, constant, b, count);
1697
1699}
1700
1701static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1702 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1703{
1705
1706 TRACE("iface %p, device %p, constant %p, n %d\n", iface, device, constant, n);
1707
1709}
1710
1711static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1712 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1713{
1715
1716 TRACE("iface %p, device %p, constant %p, n %p, count %d\n", iface, device, constant, n, count);
1717
1719}
1720
1721static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1722 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1723{
1725
1726 TRACE("iface %p, device %p, constant %p, f %f\n", iface, device, constant, f);
1727
1729}
1730
1731static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1732 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1733{
1735
1736 TRACE("iface %p, device %p, constant %p, f %p, count %d\n", iface, device, constant, f, count);
1737
1739}
1740
1741static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1742 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1743{
1745
1746 TRACE("iface %p, device %p, constant %p, vector %p\n", iface, device, constant, vector);
1747
1749}
1750
1751static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1752 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1753{
1755
1756 TRACE("iface %p, device %p, constant %p, vector %p, count %u\n", iface, device, constant, vector, count);
1757
1759}
1760
1761static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1762 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1763{
1765
1766 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1767
1769}
1770
1771static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1772 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1773{
1775
1776 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1777
1779}
1780
1781static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1782 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1783{
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
1791static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1792 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1793{
1795
1796 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1797
1799}
1800
1801static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1802 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1803{
1805
1806 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1807
1809}
1810
1812 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1813{
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
1821static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1822{
1823 /*** IUnknown methods ***/
1827 /*** ID3DXBuffer methods ***/
1830 /*** ID3DXConstantTable methods ***/
1853};
1854
1855static 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,
1878 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
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
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),
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
1979error:
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
1993HRESULT 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
2104error:
2105 free_constant_table(object);
2106 HeapFree(GetProcessHeap(), 0, object);
2107
2108 return hr;
2109}
2110
2111HRESULT 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
2119{
2120 ID3DXFragmentLinker ID3DXFragmentLinker_iface;
2122
2123 struct IDirect3DDevice9 *device;
2125};
2126
2127static inline struct d3dx9_fragment_linker *impl_from_ID3DXFragmentLinker(ID3DXFragmentLinker *iface)
2128{
2130}
2131
2132static 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
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
2149static ULONG WINAPI d3dx9_fragment_linker_AddRef(ID3DXFragmentLinker *iface)
2150{
2152 ULONG refcount = InterlockedIncrement(&linker->ref);
2153
2154 TRACE("%p increasing refcount to %u.\n", linker, refcount);
2155
2156 return refcount;
2157}
2158
2159static ULONG WINAPI d3dx9_fragment_linker_Release(ID3DXFragmentLinker *iface)
2160{
2162 ULONG refcount = InterlockedDecrement(&linker->ref);
2163
2164 TRACE("%p decreasing refcount to %u.\n", linker, refcount);
2165
2166 if (!refcount)
2167 {
2169 heap_free(linker);
2170 }
2171
2172 return refcount;
2173}
2174
2175static HRESULT WINAPI d3dx9_fragment_linker_GetDevice(ID3DXFragmentLinker *iface, struct IDirect3DDevice9 **device)
2176{
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
2188 *device = linker->device;
2189 TRACE("Returning device %p.\n", *device);
2190
2191 return S_OK;
2192}
2193
2195{
2196 FIXME("iface %p: stub.\n", iface);
2197
2198 return E_NOTIMPL;
2199}
2200
2202{
2203 FIXME("iface %p, index %u: stub.\n", iface, index);
2204
2205 return NULL;
2206}
2207
2209 const char *name)
2210{
2211 FIXME("iface %p, name %s: stub.\n", iface, debugstr_a(name));
2212
2213 return NULL;
2214}
2215
2218{
2219 FIXME("iface %p, name %p, desc %p: stub.\n", iface, name, desc);
2220
2221 return E_NOTIMPL;
2222}
2223
2224static 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
2232{
2233 FIXME("iface %p, buffer %p: stub.\n", iface, buffer);
2234
2235 return E_NOTIMPL;
2236}
2237
2240{
2241 FIXME("iface %p, name %p, buffer %p: stub.\n", iface, name, buffer);
2242
2243 return E_NOTIMPL;
2244}
2245
2246static 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
2256static 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
2266static 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
2276static HRESULT WINAPI d3dx9_fragment_linker_ClearCache(ID3DXFragmentLinker *iface)
2277{
2278 FIXME("iface %p: stub.\n", iface);
2279
2280 return E_NOTIMPL;
2281}
2282
2283static const struct ID3DXFragmentLinkerVtbl d3dx9_fragment_linker_vtbl =
2284{
2300};
2301
2303 ID3DXFragmentLinker **linker)
2304{
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
2317 object->device = device;
2318 object->flags = flags;
2319
2320 *linker = &object->ID3DXFragmentLinker_iface;
2321
2322 return S_OK;
2323}
2324
2325HRESULT 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
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 {
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
2381static const char *decl_usage[] = { "position", "blendweight", "blendindices", "normal", "psize", "texcoord",
2382 "tangent", "binormal", "tessfactor", "positiont", "color" };
2383
2384static const char *tex_type[] = { "", "1d", "2d", "cube", "volume" };
2385
2386static 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
2401static int add_register(char *buffer, DWORD param, BOOL dst, BOOL ps)
2402{
2403 char *buf = buffer;
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 {
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 {
2442 {
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
2460{
2462 const char *name;
2464 int (*function)(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps);
2467};
2468
2469static int instr_comment(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
2470{
2472 return 0;
2473}
2474
2475static 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
2484static int instr_dcl(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
2485{
2486 DWORD param1 = *++*ptr;
2487 DWORD param2 = *++*ptr;
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) ?
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
2514static 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
2553const 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
2645HRESULT 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 {
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++)
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))
2706
2707 return hr;
2708}
2709
2711{
2712 ID3DXTextureShader ID3DXTextureShader_iface;
2714};
2715
2716static inline struct d3dx9_texture_shader *impl_from_ID3DXTextureShader(ID3DXTextureShader *iface)
2717{
2719}
2720
2721static 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
2738static 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
2748static 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
2763static 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
2770static 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
2778{
2779 FIXME("iface %p, desc %p stub.\n", iface, desc);
2780
2781 return E_NOTIMPL;
2782}
2783
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
2792{
2793 FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index);
2794
2795 return NULL;
2796}
2797
2799{
2800 FIXME("iface %p, constant %p, name %s stub.\n", iface, constant, debugstr_a(name));
2801
2802 return NULL;
2803}
2804
2806{
2807 FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index);
2808
2809 return NULL;
2810}
2811
2812static HRESULT WINAPI d3dx9_texture_shader_SetDefaults(ID3DXTextureShader *iface)
2813{
2814 FIXME("iface %p stub.\n", iface);
2815
2816 return E_NOTIMPL;
2817}
2818
2819static 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
2827{
2828 FIXME("iface %p, constant %p, b %u stub.\n", iface, constant, b);
2829
2830 return E_NOTIMPL;
2831}
2832
2834{
2835 FIXME("iface %p, constant %p, b %p, count %u stub.\n", iface, constant, b, count);
2836
2837 return E_NOTIMPL;
2838}
2839
2841{
2842 FIXME("iface %p, constant %p, n %d stub.\n", iface, constant, n);
2843
2844 return E_NOTIMPL;
2845}
2846
2848{
2849 FIXME("iface %p, constant %p, n %p, count %u stub.\n", iface, constant, n, count);
2850
2851 return E_NOTIMPL;
2852}
2853
2855{
2856 FIXME("iface %p, constant %p, f %f stub.\n", iface, constant, f);
2857
2858 return E_NOTIMPL;
2859}
2860
2862{
2863 FIXME("iface %p, constant %p, f %p, count %u stub.\n", iface, constant, f, count);
2864
2865 return E_NOTIMPL;
2866}
2867
2869{
2870 FIXME("iface %p, constant %p, vector %p stub.\n", iface, constant, vector);
2871
2872 return E_NOTIMPL;
2873}
2874
2876{
2877 FIXME("iface %p, constant %p, vector %p, count %u stub.\n", iface, constant, vector, count);
2878
2879 return E_NOTIMPL;
2880}
2881
2883{
2884 FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix);
2885
2886 return E_NOTIMPL;
2887}
2888
2890{
2891 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2892
2893 return E_NOTIMPL;
2894}
2895
2897{
2898 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2899
2900 return E_NOTIMPL;
2901}
2902
2904{
2905 FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix);
2906
2907 return E_NOTIMPL;
2908}
2909
2911{
2912 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2913
2914 return E_NOTIMPL;
2915}
2916
2918{
2919 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2920
2921 return E_NOTIMPL;
2922}
2923
2924static const struct ID3DXTextureShaderVtbl d3dx9_texture_shader_vtbl =
2925{
2926 /*** IUnknown methods ***/
2930 /*** ID3DXTextureShader methods ***/
2954};
2955
2956HRESULT WINAPI D3DXCreateTextureShader(const DWORD *function, ID3DXTextureShader **texture_shader)
2957{
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
2977static 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
3010static HRESULT get_shader_semantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count, BOOL output)
3011{
3012 static const D3DDECLUSAGE regtype_usage[] =
3013 {
3016 0,
3018 0,
3021 0,
3022 0,
3024 };
3025 static const D3DDECLUSAGE rast_usage[] =
3026 {
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
3058
3059 if (is_ps && !output && major == 2)
3060 {
3061 /* dcl with no explicit usage, look at the register. */
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 =
3084 semantics[i].UsageIndex =
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)
3118 {
3119 if (reg_type == D3DSPR_RASTOUT)
3120 rastout |= 1u << index;
3121 else if (reg_type == D3DSPR_DEPTHOUT)
3122 depth = TRUE;
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
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
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}
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
r l[0]
Definition: byte_order.h:168
Definition: _set.h:50
HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, ID3DBlob **shader, ID3DBlob **error_messages)
Definition: compiler.c:902
HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages)
Definition: compiler.c:889
#define D3DXERR_INVALIDDATA
Definition: compiler.c:30
#define D3DVS_W_Z
Definition: d3d8types.h:448
#define D3DSP_WRITEMASK_ALL
Definition: d3d8types.h:378
@ D3DSPSM_NEG
Definition: d3d8types.h:461
@ D3DSPSM_NONE
Definition: d3d8types.h:460
#define D3DSP_WRITEMASK_2
Definition: d3d8types.h:376
#define D3DVS_X_Z
Definition: d3d8types.h:433
#define D3DPS_VERSION(major, minor)
Definition: d3d8types.h:474
#define D3DVS_Z_Z
Definition: d3d8types.h:443
#define D3DVS_W_W
Definition: d3d8types.h:449
#define D3DVS_SWIZZLE_MASK
Definition: d3d8types.h:426
@ D3DSPDM_SATURATE
Definition: d3d8types.h:385
#define D3DSP_WRITEMASK_3
Definition: d3d8types.h:377
#define D3DVS_Y_Y
Definition: d3d8types.h:437
#define D3DVS_W_X
Definition: d3d8types.h:446
#define D3DSP_SWIZZLE_MASK
Definition: d3d8types.h:429
#define D3DSP_DSTMOD_MASK
Definition: d3d8types.h:381
#define D3DSI_OPCODE_MASK
Definition: d3d8types.h:306
#define D3DSP_WRITEMASK_0
Definition: d3d8types.h:374
#define D3DSHADER_VERSION_MAJOR(version)
Definition: d3d8types.h:476
#define D3DVS_Z_X
Definition: d3d8types.h:441
#define D3DSI_COMMENTSIZE_SHIFT
Definition: d3d8types.h:479
#define D3DVS_Y_X
Definition: d3d8types.h:436
#define D3DSP_SRCMOD_MASK
Definition: d3d8types.h:457
#define D3DVS_NOSWIZZLE
Definition: d3d8types.h:451
#define D3DSP_WRITEMASK_1
Definition: d3d8types.h:375
#define D3DVS_SWIZZLE_SHIFT
Definition: d3d8types.h:425
#define D3DVS_ADDRESSMODE_MASK
Definition: d3d8types.h:417
#define D3DSHADER_VERSION_MINOR(version)
Definition: d3d8types.h:477
#define D3DSI_COMMENTSIZE_MASK
Definition: d3d8types.h:480
#define D3DSP_REGTYPE_MASK
Definition: d3d8types.h:395
#define D3DVS_VERSION(major, minor)
Definition: d3d8types.h:475
@ D3DSIO_M4x4
Definition: d3d8types.h:330
@ D3DSIO_MIN
Definition: d3d8types.h:320
@ D3DSIO_MAD
Definition: d3d8types.h:314
@ D3DSIO_TEXCOORD
Definition: d3d8types.h:336
@ D3DSIO_CND
Definition: d3d8types.h:352
@ D3DSIO_TEXDP3TEX
Definition: d3d8types.h:355
@ D3DSIO_EXPP
Definition: d3d8types.h:350
@ D3DSIO_TEXM3x3SPEC
Definition: d3d8types.h:348
@ D3DSIO_M3x4
Definition: d3d8types.h:332
@ D3DSIO_CMP
Definition: d3d8types.h:360
@ D3DSIO_TEXKILL
Definition: d3d8types.h:337
@ D3DSIO_TEXM3x2PAD
Definition: d3d8types.h:343
@ D3DSIO_SGE
Definition: d3d8types.h:323
@ D3DSIO_MOV
Definition: d3d8types.h:311
@ D3DSIO_TEXBEM
Definition: d3d8types.h:339
@ D3DSIO_MAX
Definition: d3d8types.h:321
@ D3DSIO_SUB
Definition: d3d8types.h:313
@ D3DSIO_TEXDP3
Definition: d3d8types.h:357
@ D3DSIO_COMMENT
Definition: d3d8types.h:364
@ D3DSIO_FRC
Definition: d3d8types.h:329
@ D3DSIO_M4x3
Definition: d3d8types.h:331
@ D3DSIO_NOP
Definition: d3d8types.h:310
@ D3DSIO_LRP
Definition: d3d8types.h:328
@ D3DSIO_TEX
Definition: d3d8types.h:338
@ D3DSIO_ADD
Definition: d3d8types.h:312
@ D3DSIO_TEXM3x2TEX
Definition: d3d8types.h:344
@ D3DSIO_M3x3
Definition: d3d8types.h:333
@ D3DSIO_TEXBEML
Definition: d3d8types.h:340
@ D3DSIO_END
Definition: d3d8types.h:365
@ D3DSIO_EXP
Definition: d3d8types.h:324
@ D3DSIO_TEXM3x3VSPEC
Definition: d3d8types.h:349
@ D3DSIO_TEXREG2GB
Definition: d3d8types.h:342
@ D3DSIO_M3x2
Definition: d3d8types.h:334
@ D3DSIO_TEXREG2AR
Definition: d3d8types.h:341
@ D3DSIO_BEM
Definition: d3d8types.h:361
@ D3DSIO_DP4
Definition: d3d8types.h:319
@ D3DSIO_TEXM3x3
Definition: d3d8types.h:358
@ D3DSIO_TEXM3x3PAD
Definition: d3d8types.h:345
@ D3DSIO_LOGP
Definition: d3d8types.h:351
@ D3DSIO_TEXM3x3TEX
Definition: d3d8types.h:346
@ D3DSIO_LOG
Definition: d3d8types.h:325
@ D3DSIO_DST
Definition: d3d8types.h:327
@ D3DSIO_DP3
Definition: d3d8types.h:318
@ D3DSIO_TEXM3x2DEPTH
Definition: d3d8types.h:356
@ D3DSIO_RCP
Definition: d3d8types.h:316
@ D3DSIO_DEF
Definition: d3d8types.h:353
@ D3DSIO_SLT
Definition: d3d8types.h:322
@ D3DSIO_RSQ
Definition: d3d8types.h:317
@ D3DSIO_LIT
Definition: d3d8types.h:326
@ D3DSIO_TEXM3x3DIFF
Definition: d3d8types.h:347
@ D3DSIO_TEXREG2RGB
Definition: d3d8types.h:354
@ D3DSIO_PHASE
Definition: d3d8types.h:363
@ D3DSIO_TEXDEPTH
Definition: d3d8types.h:359
@ D3DSIO_MUL
Definition: d3d8types.h:315
#define D3DVS_X_X
Definition: d3d8types.h:431
#define D3DVS_Y_W
Definition: d3d8types.h:439
#define D3DVS_W_Y
Definition: d3d8types.h:447
#define D3DVS_Z_W
Definition: d3d8types.h:444
#define D3DVS_Y_Z
Definition: d3d8types.h:438
#define D3DVS_X_Y
Definition: d3d8types.h:432
#define D3DSP_REGTYPE_SHIFT
Definition: d3d8types.h:394
#define D3DVS_X_W
Definition: d3d8types.h:434
@ D3DSPR_TEXTURE
Definition: d3d8types.h:402
@ D3DSPR_RASTOUT
Definition: d3d8types.h:403
@ D3DSPR_ADDR
Definition: d3d8types.h:401
@ D3DSPR_TEMP
Definition: d3d8types.h:398
@ D3DSPR_INPUT
Definition: d3d8types.h:399
@ D3DSPR_ATTROUT
Definition: d3d8types.h:404
@ D3DSPR_CONST
Definition: d3d8types.h:400
@ D3DSPR_TEXCRDOUT
Definition: d3d8types.h:405
#define D3DVS_Z_Y
Definition: d3d8types.h:442
#define IDirect3DDevice9_GetDeviceCaps(p, a)
Definition: d3d9.h:1514
#define IDirect3DDevice9_SetPixelShaderConstantI(p, a, b, c)
Definition: d3d9.h:1618
#define IDirect3DDevice9_SetVertexShaderConstantF(p, a, b, c)
Definition: d3d9.h:1601
#define IDirect3DDevice9_SetPixelShaderConstantF(p, a, b, c)
Definition: d3d9.h:1616
#define IDirect3DDevice9_Release(p)
Definition: d3d9.h:1508
#define IDirect3DDevice9_SetVertexShaderConstantI(p, a, b, c)
Definition: d3d9.h:1603
#define IDirect3DDevice9_SetPixelShaderConstantB(p, a, b, c)
Definition: d3d9.h:1620
#define IDirect3DDevice9_SetVertexShaderConstantB(p, a, b, c)
Definition: d3d9.h:1605
#define IDirect3DDevice9_AddRef(p)
Definition: d3d9.h:1507
#define D3DPS20CAPS_NODEPENDENTREADLIMIT
Definition: d3d9caps.h:228
#define D3DPS20CAPS_GRADIENTINSTRUCTIONS
Definition: d3d9caps.h:226
#define D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
Definition: d3d9caps.h:229
#define D3DPS20CAPS_PREDICATION
Definition: d3d9caps.h:227
#define D3DPS20CAPS_ARBITRARYSWIZZLE
Definition: d3d9caps.h:225
@ D3DDECLUSAGE_FOG
Definition: d3d9types.h:231
@ D3DDECLUSAGE_TEXCOORD
Definition: d3d9types.h:225
@ D3DDECLUSAGE_DEPTH
Definition: d3d9types.h:232
@ D3DDECLUSAGE_POSITION
Definition: d3d9types.h:220
@ D3DDECLUSAGE_PSIZE
Definition: d3d9types.h:224
@ D3DDECLUSAGE_COLOR
Definition: d3d9types.h:230
#define D3DSP_REGTYPE_MASK2
Definition: d3d9types.h:508
#define D3DSP_TEXTURETYPE_SHIFT
Definition: d3d9types.h:466
#define D3DSI_INSTLENGTH_SHIFT
Definition: d3d9types.h:354
@ D3DSPDM_PARTIALPRECISION
Definition: d3d9types.h:494
@ D3DSPDM_MSAMPCENTROID
Definition: d3d9types.h:495
#define D3DSP_DCL_USAGE_MASK
Definition: d3d9types.h:461
#define D3DSP_REGTYPE_SHIFT2
Definition: d3d9types.h:506
enum _D3DDECLUSAGE D3DDECLUSAGE
#define D3DSP_DCL_USAGE_SHIFT
Definition: d3d9types.h:460
@ D3DSIO_BREAK
Definition: d3d9types.h:402
@ D3DSIO_DP2ADD
Definition: d3d9types.h:434
@ D3DSIO_CALL
Definition: d3d9types.h:383
@ D3DSIO_POW
Definition: d3d9types.h:390
@ D3DSIO_REP
Definition: d3d9types.h:396
@ D3DSIO_ENDREP
Definition: d3d9types.h:397
@ D3DSIO_CRS
Definition: d3d9types.h:391
@ D3DSIO_RET
Definition: d3d9types.h:386
@ D3DSIO_CALLNZ
Definition: d3d9types.h:384
@ D3DSIO_NRM
Definition: d3d9types.h:394
@ D3DSIO_SGN
Definition: d3d9types.h:392
@ D3DSIO_TEXLDL
Definition: d3d9types.h:439
@ D3DSIO_ENDLOOP
Definition: d3d9types.h:387
@ D3DSIO_TEXLDD
Definition: d3d9types.h:437
@ D3DSIO_DSX
Definition: d3d9types.h:435
@ D3DSIO_DEFB
Definition: d3d9types.h:405
@ D3DSIO_DCL
Definition: d3d9types.h:389