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