d49e0aa0d19f4b3c30ac99c454fc740d1b561b88
[reactos.git] / dll / directx / wine / d3dx9_36 / shader.c
1 /*
2 * Copyright 2008 Luis Busquets
3 * Copyright 2009 Matteo Bruni
4 * Copyright 2010, 2013 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 ctab_constant {
718 D3DXCONSTANT_DESC desc;
719 struct ctab_constant *constants;
720 };
721
722 struct ID3DXConstantTableImpl {
723 ID3DXConstantTable ID3DXConstantTable_iface;
724 LONG ref;
725 char *ctab;
726 DWORD size;
727 D3DXCONSTANTTABLE_DESC desc;
728 struct ctab_constant *constants;
729 };
730
731 static void free_constant(struct ctab_constant *constant)
732 {
733 if (constant->constants)
734 {
735 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
736
737 for (i = 0; i < count; ++i)
738 {
739 free_constant(&constant->constants[i]);
740 }
741 HeapFree(GetProcessHeap(), 0, constant->constants);
742 }
743 }
744
745 static void free_constant_table(struct ID3DXConstantTableImpl *table)
746 {
747 if (table->constants)
748 {
749 UINT i;
750
751 for (i = 0; i < table->desc.Constants; ++i)
752 {
753 free_constant(&table->constants[i]);
754 }
755 HeapFree(GetProcessHeap(), 0, table->constants);
756 }
757 HeapFree(GetProcessHeap(), 0, table->ctab);
758 }
759
760 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
761 {
762 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
763 }
764
765 static inline BOOL is_vertex_shader(DWORD version)
766 {
767 return (version & 0xffff0000) == 0xfffe0000;
768 }
769
770 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant)
771 {
772 return (D3DXHANDLE)constant;
773 }
774
775 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
776 struct ctab_constant *constant, const char *name);
777
778 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, const char *name)
779 {
780 const char *part;
781 UINT element;
782
783 TRACE("constant %p, name %s\n", constant, debugstr_a(name));
784
785 if (!name || !*name) return NULL;
786
787 element = atoi(name);
788 part = strchr(name, ']') + 1;
789
790 if (constant->desc.Elements > element)
791 {
792 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant;
793
794 switch (*part++)
795 {
796 case '.':
797 return get_constant_by_name(NULL, c, part);
798
799 case '[':
800 return get_constant_element_by_name(c, part);
801
802 case '\0':
803 TRACE("Returning parameter %p\n", c);
804 return c;
805
806 default:
807 FIXME("Unhandled case \"%c\"\n", *--part);
808 break;
809 }
810 }
811
812 TRACE("Constant not found\n");
813 return NULL;
814 }
815
816 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
817 struct ctab_constant *constant, const char *name)
818 {
819 UINT i, count, length;
820 struct ctab_constant *handles;
821 const char *part;
822
823 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name));
824
825 if (!name || !*name) return NULL;
826
827 if (!constant)
828 {
829 count = table->desc.Constants;
830 handles = table->constants;
831 }
832 else
833 {
834 count = constant->desc.StructMembers;
835 handles = constant->constants;
836 }
837
838 length = strcspn(name, "[.");
839 part = name + length;
840
841 for (i = 0; i < count; i++)
842 {
843 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length))
844 {
845 switch (*part++)
846 {
847 case '.':
848 return get_constant_by_name(NULL, &handles[i], part);
849
850 case '[':
851 return get_constant_element_by_name(&handles[i], part);
852
853 default:
854 TRACE("Returning parameter %p\n", &handles[i]);
855 return &handles[i];
856 }
857 }
858 }
859
860 TRACE("Constant not found\n");
861 return NULL;
862 }
863
864 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, D3DXHANDLE handle)
865 {
866 struct ctab_constant *c;
867 UINT i, count;
868
869 /* all variable have at least elements = 1, but not always elements */
870 if (!parent->constants) return NULL;
871
872 count = parent->desc.Elements > 1 ? parent->desc.Elements : parent->desc.StructMembers;
873 for (i = 0; i < count; ++i)
874 {
875 if (handle_from_constant(&parent->constants[i]) == handle)
876 return &parent->constants[i];
877
878 c = is_valid_sub_constant(&parent->constants[i], handle);
879 if (c) return c;
880 }
881
882 return NULL;
883 }
884
885 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
886 {
887 struct ctab_constant *c;
888 UINT i;
889
890 if (!handle) return NULL;
891
892 for (i = 0; i < table->desc.Constants; ++i)
893 {
894 if (handle_from_constant(&table->constants[i]) == handle)
895 return &table->constants[i];
896
897 c = is_valid_sub_constant(&table->constants[i], handle);
898 if (c) return c;
899 }
900
901 return get_constant_by_name(table, NULL, handle);
902 }
903
904 /*** IUnknown methods ***/
905 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
906 {
907 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
908
909 if (IsEqualGUID(riid, &IID_IUnknown) ||
910 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
911 IsEqualGUID(riid, &IID_ID3DXConstantTable))
912 {
913 ID3DXConstantTable_AddRef(iface);
914 *out = iface;
915 return S_OK;
916 }
917
918 WARN("Interface %s not found.\n", debugstr_guid(riid));
919
920 return E_NOINTERFACE;
921 }
922
923 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
924 {
925 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
926
927 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
928
929 return InterlockedIncrement(&This->ref);
930 }
931
932 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
933 {
934 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
935 ULONG ref = InterlockedDecrement(&This->ref);
936
937 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
938
939 if (!ref)
940 {
941 free_constant_table(This);
942 HeapFree(GetProcessHeap(), 0, This);
943 }
944
945 return ref;
946 }
947
948 /*** ID3DXBuffer methods ***/
949 static void * WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
950 {
951 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface);
952
953 TRACE("iface %p.\n", iface);
954
955 return table->ctab;
956 }
957
958 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
959 {
960 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
961
962 TRACE("(%p)->()\n", This);
963
964 return This->size;
965 }
966
967 /*** ID3DXConstantTable methods ***/
968 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
969 {
970 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
971
972 TRACE("(%p)->(%p)\n", This, desc);
973
974 if (!desc)
975 return D3DERR_INVALIDCALL;
976
977 *desc = This->desc;
978
979 return D3D_OK;
980 }
981
982 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
983 D3DXCONSTANT_DESC *desc, UINT *count)
984 {
985 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
986 struct ctab_constant *c = get_valid_constant(This, constant);
987
988 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
989
990 if (!c)
991 {
992 WARN("Invalid argument specified\n");
993 return D3DERR_INVALIDCALL;
994 }
995
996 if (desc) *desc = c->desc;
997 if (count) *count = 1;
998
999 return D3D_OK;
1000 }
1001
1002 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
1003 {
1004 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1005 struct ctab_constant *c = get_valid_constant(This, constant);
1006
1007 TRACE("(%p)->(%p)\n", This, constant);
1008
1009 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER)
1010 {
1011 WARN("Invalid argument specified\n");
1012 return (UINT)-1;
1013 }
1014
1015 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex);
1016 return c->desc.RegisterIndex;
1017 }
1018
1019 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
1020 {
1021 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1022 struct ctab_constant *c;
1023
1024 TRACE("(%p)->(%p, %d)\n", This, constant, index);
1025
1026 if (constant)
1027 {
1028 c = get_valid_constant(This, constant);
1029 if (c && index < c->desc.StructMembers)
1030 {
1031 c = &c->constants[index];
1032 TRACE("Returning constant %p\n", c);
1033 return handle_from_constant(c);
1034 }
1035 }
1036 else
1037 {
1038 if (index < This->desc.Constants)
1039 {
1040 c = &This->constants[index];
1041 TRACE("Returning constant %p\n", c);
1042 return handle_from_constant(c);
1043 }
1044 }
1045
1046 WARN("Index out of range\n");
1047 return NULL;
1048 }
1049
1050 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface,
1051 D3DXHANDLE constant, const char *name)
1052 {
1053 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1054 struct ctab_constant *c = get_valid_constant(This, constant);
1055
1056 TRACE("iface %p, constant %p, name %s.\n", iface, constant, debugstr_a(name));
1057
1058 c = get_constant_by_name(This, c, name);
1059 TRACE("Returning constant %p\n", c);
1060
1061 return handle_from_constant(c);
1062 }
1063
1064 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
1065 {
1066 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1067 struct ctab_constant *c = get_valid_constant(This, constant);
1068
1069 TRACE("(%p)->(%p, %d)\n", This, constant, index);
1070
1071 if (c && index < c->desc.Elements)
1072 {
1073 if (c->desc.Elements > 1) c = &c->constants[index];
1074 TRACE("Returning constant %p\n", c);
1075 return handle_from_constant(c);
1076 }
1077
1078 WARN("Invalid argument specified\n");
1079 return NULL;
1080 }
1081
1082 static inline DWORD get_index(const void **indata, UINT index, BOOL is_pointer)
1083 {
1084 if (!indata)
1085 return 0;
1086
1087 if (is_pointer)
1088 return ((DWORD **)indata)[index / 16][index % 16];
1089
1090 return (*((DWORD **)indata))[index];
1091 }
1092
1093 static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant,
1094 const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index,
1095 BOOL is_pointer)
1096 {
1097 D3DXCONSTANT_DESC *desc = &constant->desc;
1098 UINT l, i, regcount = 1, regsize = 1, cin = 1, rin = 1, ret, last = 0;
1099 DWORD tmp;
1100
1101 /* size too small to set anything */
1102 if (*size < desc->Rows * desc->Columns)
1103 {
1104 *size = 0;
1105 return 0;
1106 }
1107
1108 /* D3DXPC_STRUCT is somewhat special */
1109 if (desc->Class == D3DXPC_STRUCT)
1110 {
1111 /*
1112 * Struct array sets the last complete input to the first struct element, all other
1113 * elements are not set.
1114 * E.g.: struct {int i;} s1[2];
1115 * SetValue(device, "s1", [1, 2], 8) => s1 = {2, x};
1116 *
1117 * struct {int i; int n} s2[2];
1118 * SetValue(device, "s2", [1, 2, 3, 4, 5], 20) => s1 = {{3, 4}, {x, x}};
1119 */
1120 if (desc->Elements > 1)
1121 {
1122 UINT offset = *size / (desc->Rows * desc->Columns) - 1;
1123
1124 offset = min(desc->Elements - 1, offset);
1125 last = offset * desc->Rows * desc->Columns;
1126
1127 if ((is_pointer || inclass == D3DXPC_MATRIX_ROWS) && desc->RegisterSet != D3DXRS_BOOL)
1128 {
1129 set(table, device, &constant->constants[0], NULL, intype, size, incol, inclass, 0, is_pointer);
1130 }
1131 else
1132 {
1133 last += set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
1134 index + last, is_pointer);
1135 }
1136 }
1137 else
1138 {
1139 /*
1140 * D3DXRS_BOOL is always set. As there are only 16 bools and there are
1141 * exactly 16 input values, use matrix transpose.
1142 */
1143 if (inclass == D3DXPC_MATRIX_ROWS && desc->RegisterSet == D3DXRS_BOOL)
1144 {
1145 D3DXMATRIX mat, *m, min;
1146 D3DXMatrixTranspose(&mat, &min);
1147
1148 if (is_pointer)
1149 min = *(D3DXMATRIX *)(indata[index / 16]);
1150 else
1151 min = **(D3DXMATRIX **)indata;
1152
1153 D3DXMatrixTranspose(&mat, &min);
1154 m = &mat;
1155 for (i = 0; i < desc->StructMembers; ++i)
1156 {
1157 last += set(table, device, &constant->constants[i], (const void **)&m, intype, size, incol,
1158 D3DXPC_SCALAR, index + last, is_pointer);
1159 }
1160 }
1161 /*
1162 * For pointers or for matrix rows, only the first member is set.
1163 * All other members are set to 0. This is not true for D3DXRS_BOOL.
1164 * E.g.: struct {int i; int n} s;
1165 * SetValue(device, "s", [1, 2], 8) => s = {1, 0};
1166 */
1167 else if ((is_pointer || inclass == D3DXPC_MATRIX_ROWS) && desc->RegisterSet != D3DXRS_BOOL)
1168 {
1169 last = set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
1170 index + last, is_pointer);
1171
1172 for (i = 1; i < desc->StructMembers; ++i)
1173 {
1174 set(table, device, &constant->constants[i], NULL, intype, size, incol, inclass, 0, is_pointer);
1175 }
1176 }
1177 else
1178 {
1179 for (i = 0; i < desc->StructMembers; ++i)
1180 {
1181 last += set(table, device, &constant->constants[i], indata, intype, size, incol, D3DXPC_SCALAR,
1182 index + last, is_pointer);
1183 }
1184 }
1185 }
1186
1187 return last;
1188 }
1189
1190 /* elements */
1191 if (desc->Elements > 1)
1192 {
1193 for (i = 0; i < desc->Elements && *size > 0; ++i)
1194 {
1195 last += set(table, device, &constant->constants[i], indata, intype, size, incol, inclass,
1196 index + last, is_pointer);
1197
1198 /* adjust the vector size for matrix rows */
1199 if (inclass == D3DXPC_MATRIX_ROWS && desc->Class == D3DXPC_VECTOR && (i % 4) == 3)
1200 {
1201 last += 12;
1202 *size = *size < 12 ? 0 : *size - 12;
1203 }
1204 }
1205
1206 return last;
1207 }
1208
1209 switch (desc->Class)
1210 {
1211 case D3DXPC_SCALAR:
1212 case D3DXPC_VECTOR:
1213 case D3DXPC_MATRIX_ROWS:
1214 regcount = min(desc->RegisterCount, desc->Rows);
1215 if (inclass == D3DXPC_MATRIX_ROWS) cin = incol;
1216 else rin = incol;
1217 regsize = desc->Columns;
1218 break;
1219
1220 case D3DXPC_MATRIX_COLUMNS:
1221 regcount = min(desc->RegisterCount, desc->Columns);
1222 if (inclass == D3DXPC_MATRIX_ROWS) rin = incol;
1223 else cin = incol;
1224 regsize = desc->Rows;
1225 break;
1226
1227 default:
1228 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1229 return 0;
1230 }
1231
1232 /* specific stuff for different in types */
1233 switch (inclass)
1234 {
1235 case D3DXPC_SCALAR:
1236 ret = desc->Columns * desc->Rows;
1237 *size -= desc->Columns * desc->Rows;
1238 break;
1239
1240 case D3DXPC_VECTOR:
1241 switch (desc->Class)
1242 {
1243 case D3DXPC_MATRIX_ROWS:
1244 if (*size < regcount * 4)
1245 {
1246 *size = 0;
1247 return 0;
1248 }
1249 ret = 4 * regcount;
1250 *size -= 4 * regcount;
1251 break;
1252
1253 case D3DXPC_MATRIX_COLUMNS:
1254 ret = 4 * regsize;
1255 *size -= 4 * regcount;
1256 break;
1257
1258 case D3DXPC_SCALAR:
1259 ret = 1;
1260 *size -= ret;
1261 break;
1262
1263 case D3DXPC_VECTOR:
1264 ret = 4;
1265 *size -= ret;
1266 break;
1267
1268 default:
1269 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1270 return 0;
1271 }
1272 break;
1273
1274 case D3DXPC_MATRIX_ROWS:
1275 switch (desc->Class)
1276 {
1277 case D3DXPC_MATRIX_ROWS:
1278 case D3DXPC_MATRIX_COLUMNS:
1279 if (*size < 16)
1280 {
1281 *size = 0;
1282 return 0;
1283 }
1284 ret = 16;
1285 break;
1286
1287 case D3DXPC_SCALAR:
1288 ret = 4;
1289 break;
1290
1291 case D3DXPC_VECTOR:
1292 ret = 1;
1293 break;
1294
1295 default:
1296 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1297 return 0;
1298 }
1299 *size -= ret;
1300 break;
1301
1302 case D3DXPC_MATRIX_COLUMNS:
1303 switch (desc->Class)
1304 {
1305 case D3DXPC_MATRIX_ROWS:
1306 case D3DXPC_MATRIX_COLUMNS:
1307 if (*size < 16)
1308 {
1309 *size = 0;
1310 return 0;
1311 }
1312 ret = 16;
1313 break;
1314
1315 case D3DXPC_SCALAR:
1316 ret = 1;
1317 break;
1318
1319 case D3DXPC_VECTOR:
1320 ret = 4;
1321 break;
1322
1323 default:
1324 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1325 return 0;
1326 }
1327 *size -= ret;
1328 break;
1329
1330 default:
1331 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(inclass));
1332 return 0;
1333 }
1334
1335 /* set the registers */
1336 switch (desc->RegisterSet)
1337 {
1338 case D3DXRS_BOOL:
1339 regcount = min(desc->RegisterCount, desc->Columns * desc->Rows);
1340 l = 0;
1341 for (i = 0; i < regcount; ++i)
1342 {
1343 BOOL out;
1344 DWORD t = get_index(indata, index + i / regsize * rin + l * cin, is_pointer);
1345
1346 set_number(&tmp, desc->Type, &t, intype);
1347 set_number(&out, D3DXPT_BOOL, &tmp, desc->Type);
1348 if (is_vertex_shader(table->desc.Version))
1349 IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex + i, &out, 1);
1350 else
1351 IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex + i, &out, 1);
1352
1353 if (++l >= regsize) l = 0;
1354 }
1355 return ret;
1356
1357 case D3DXRS_INT4:
1358 for (i = 0; i < regcount; ++i)
1359 {
1360 INT vec[4] = {0, 0, 1, 0};
1361
1362 for (l = 0; l < regsize; ++l)
1363 {
1364 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer);
1365
1366 set_number(&tmp, desc->Type, &t, intype);
1367 set_number(&vec[l], D3DXPT_INT, &tmp, desc->Type);
1368 }
1369 if (is_vertex_shader(table->desc.Version))
1370 IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex + i, vec, 1);
1371 else
1372 IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex + i, vec, 1);
1373 }
1374 return ret;
1375
1376 case D3DXRS_FLOAT4:
1377 for (i = 0; i < regcount; ++i)
1378 {
1379 FLOAT vec[4] = {0};
1380
1381 for (l = 0; l < regsize; ++l)
1382 {
1383 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer);
1384
1385 set_number(&tmp, desc->Type, &t, intype);
1386 set_number(&vec[l], D3DXPT_FLOAT, &tmp, desc->Type);
1387 }
1388 if (is_vertex_shader(table->desc.Version))
1389 IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex + i, vec, 1);
1390 else
1391 IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex + i, vec, 1);
1392 }
1393 return ret;
1394
1395 default:
1396 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1397 return 0;
1398 }
1399 }
1400
1401 static HRESULT set_scalar(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1402 const void *indata, D3DXPARAMETER_TYPE intype)
1403 {
1404 struct ctab_constant *c = get_valid_constant(table, constant);
1405 UINT count = 1;
1406
1407 if (!c)
1408 {
1409 WARN("Invalid argument specified\n");
1410 return D3DERR_INVALIDCALL;
1411 }
1412
1413 switch (c->desc.Class)
1414 {
1415 case D3DXPC_SCALAR:
1416 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE);
1417 return D3D_OK;
1418
1419 case D3DXPC_VECTOR:
1420 case D3DXPC_MATRIX_ROWS:
1421 case D3DXPC_MATRIX_COLUMNS:
1422 case D3DXPC_STRUCT:
1423 return D3D_OK;
1424
1425 default:
1426 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1427 return D3DERR_INVALIDCALL;
1428 }
1429 }
1430
1431 static HRESULT set_scalar_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1432 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1433 {
1434 struct ctab_constant *c = get_valid_constant(table, constant);
1435
1436 if (!c)
1437 {
1438 WARN("Invalid argument specified\n");
1439 return D3DERR_INVALIDCALL;
1440 }
1441
1442 switch (c->desc.Class)
1443 {
1444 case D3DXPC_SCALAR:
1445 case D3DXPC_VECTOR:
1446 case D3DXPC_MATRIX_ROWS:
1447 case D3DXPC_MATRIX_COLUMNS:
1448 case D3DXPC_STRUCT:
1449 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE);
1450 return D3D_OK;
1451
1452 default:
1453 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1454 return D3DERR_INVALIDCALL;
1455 }
1456 }
1457
1458 static HRESULT set_vector(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1459 const void *indata, D3DXPARAMETER_TYPE intype)
1460 {
1461 struct ctab_constant *c = get_valid_constant(table, constant);
1462 UINT count = 4;
1463
1464 if (!c)
1465 {
1466 WARN("Invalid argument specified\n");
1467 return D3DERR_INVALIDCALL;
1468 }
1469
1470 switch (c->desc.Class)
1471 {
1472 case D3DXPC_SCALAR:
1473 case D3DXPC_VECTOR:
1474 case D3DXPC_STRUCT:
1475 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE);
1476 return D3D_OK;
1477
1478 case D3DXPC_MATRIX_ROWS:
1479 case D3DXPC_MATRIX_COLUMNS:
1480 return D3D_OK;
1481
1482 default:
1483 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1484 return D3DERR_INVALIDCALL;
1485 }
1486 }
1487
1488 static HRESULT set_vector_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1489 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1490 {
1491 struct ctab_constant *c = get_valid_constant(table, constant);
1492
1493 if (!c)
1494 {
1495 WARN("Invalid argument specified\n");
1496 return D3DERR_INVALIDCALL;
1497 }
1498
1499 switch (c->desc.Class)
1500 {
1501 case D3DXPC_SCALAR:
1502 case D3DXPC_VECTOR:
1503 case D3DXPC_MATRIX_ROWS:
1504 case D3DXPC_MATRIX_COLUMNS:
1505 case D3DXPC_STRUCT:
1506 count *= 4;
1507 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE);
1508 return D3D_OK;
1509
1510 default:
1511 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1512 return D3DERR_INVALIDCALL;
1513 }
1514 }
1515
1516 static HRESULT set_matrix_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1517 const void *indata, UINT count, BOOL transpose)
1518 {
1519 struct ctab_constant *c = get_valid_constant(table, constant);
1520
1521 if (!c)
1522 {
1523 WARN("Invalid argument specified\n");
1524 return D3DERR_INVALIDCALL;
1525 }
1526
1527 switch (c->desc.Class)
1528 {
1529 case D3DXPC_SCALAR:
1530 case D3DXPC_VECTOR:
1531 case D3DXPC_MATRIX_ROWS:
1532 case D3DXPC_MATRIX_COLUMNS:
1533 case D3DXPC_STRUCT:
1534 count *= 16;
1535 set(table, device, c, &indata, D3DXPT_FLOAT, &count, 4,
1536 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, FALSE);
1537 return D3D_OK;
1538
1539 default:
1540 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1541 return D3DERR_INVALIDCALL;
1542 }
1543 }
1544
1545 static HRESULT set_matrix_pointer_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device,
1546 D3DXHANDLE constant, const void **indata, UINT count, BOOL transpose)
1547 {
1548 struct ctab_constant *c = get_valid_constant(table, constant);
1549
1550 if (!c)
1551 {
1552 WARN("Invalid argument specified\n");
1553 return D3DERR_INVALIDCALL;
1554 }
1555
1556 switch (c->desc.Class)
1557 {
1558 case D3DXPC_SCALAR:
1559 case D3DXPC_VECTOR:
1560 case D3DXPC_MATRIX_ROWS:
1561 case D3DXPC_MATRIX_COLUMNS:
1562 case D3DXPC_STRUCT:
1563 count *= 16;
1564 set(table, device, c, indata, D3DXPT_FLOAT, &count, 4,
1565 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, TRUE);
1566 return D3D_OK;
1567
1568 default:
1569 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1570 return D3DERR_INVALIDCALL;
1571 }
1572 }
1573
1574 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1575 struct IDirect3DDevice9 *device)
1576 {
1577 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1578 UINT i;
1579
1580 TRACE("iface %p, device %p\n", iface, device);
1581
1582 if (!device)
1583 {
1584 WARN("Invalid argument specified\n");
1585 return D3DERR_INVALIDCALL;
1586 }
1587
1588 for (i = 0; i < This->desc.Constants; i++)
1589 {
1590 D3DXCONSTANT_DESC *desc = &This->constants[i].desc;
1591 HRESULT hr;
1592
1593 if (!desc->DefaultValue)
1594 continue;
1595
1596 switch (desc->RegisterSet)
1597 {
1598 case D3DXRS_BOOL:
1599 if (is_vertex_shader(This->desc.Version))
1600 hr = IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue,
1601 desc->RegisterCount);
1602 else
1603 hr = IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue,
1604 desc->RegisterCount);
1605 break;
1606
1607 case D3DXRS_INT4:
1608 if (is_vertex_shader(This->desc.Version))
1609 hr = IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue,
1610 desc->RegisterCount);
1611 else
1612 hr = IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue,
1613 desc->RegisterCount);
1614 break;
1615
1616 case D3DXRS_FLOAT4:
1617 if (is_vertex_shader(This->desc.Version))
1618 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue,
1619 desc->RegisterCount);
1620 else
1621 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue,
1622 desc->RegisterCount);
1623 break;
1624
1625 default:
1626 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1627 hr = E_NOTIMPL;
1628 break;
1629 }
1630
1631 if (hr != D3D_OK)
1632 return hr;
1633 }
1634
1635 return D3D_OK;
1636 }
1637
1638 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1639 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, unsigned int bytes)
1640 {
1641 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface);
1642 struct ctab_constant *c = get_valid_constant(table, constant);
1643 D3DXCONSTANT_DESC *desc;
1644
1645 TRACE("iface %p, device %p, constant %p, data %p, bytes %u\n", iface, device, constant, data, bytes);
1646
1647 if (!device || !c || !data)
1648 {
1649 WARN("Invalid argument specified\n");
1650 return D3DERR_INVALIDCALL;
1651 }
1652
1653 desc = &c->desc;
1654
1655 switch (desc->Class)
1656 {
1657 case D3DXPC_SCALAR:
1658 case D3DXPC_VECTOR:
1659 case D3DXPC_MATRIX_ROWS:
1660 case D3DXPC_MATRIX_COLUMNS:
1661 case D3DXPC_STRUCT:
1662 bytes /= 4;
1663 set(table, device, c, &data, desc->Type, &bytes, desc->Columns, D3DXPC_SCALAR, 0, FALSE);
1664 return D3D_OK;
1665
1666 default:
1667 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc->Class));
1668 return D3DERR_INVALIDCALL;
1669 }
1670 }
1671
1672 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1673 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1674 {
1675 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1676
1677 TRACE("iface %p, device %p, constant %p, b %d\n", iface, device, constant, b);
1678
1679 return set_scalar(This, device, constant, &b, D3DXPT_BOOL);
1680 }
1681
1682 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1683 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1684 {
1685 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1686
1687 TRACE("iface %p, device %p, constant %p, b %p, count %d\n", iface, device, constant, b, count);
1688
1689 return set_scalar_array(This, device, constant, b, count, D3DXPT_BOOL);
1690 }
1691
1692 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1693 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1694 {
1695 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1696
1697 TRACE("iface %p, device %p, constant %p, n %d\n", iface, device, constant, n);
1698
1699 return set_scalar(This, device, constant, &n, D3DXPT_INT);
1700 }
1701
1702 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1703 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1704 {
1705 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1706
1707 TRACE("iface %p, device %p, constant %p, n %p, count %d\n", iface, device, constant, n, count);
1708
1709 return set_scalar_array(This, device, constant, n, count, D3DXPT_INT);
1710 }
1711
1712 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1713 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1714 {
1715 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1716
1717 TRACE("iface %p, device %p, constant %p, f %f\n", iface, device, constant, f);
1718
1719 return set_scalar(This, device, constant, &f, D3DXPT_FLOAT);
1720 }
1721
1722 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1723 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1724 {
1725 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1726
1727 TRACE("iface %p, device %p, constant %p, f %p, count %d\n", iface, device, constant, f, count);
1728
1729 return set_scalar_array(This, device, constant, f, count, D3DXPT_FLOAT);
1730 }
1731
1732 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1733 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1734 {
1735 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1736
1737 TRACE("iface %p, device %p, constant %p, vector %p\n", iface, device, constant, vector);
1738
1739 return set_vector(This, device, constant, vector, D3DXPT_FLOAT);
1740 }
1741
1742 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1743 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1744 {
1745 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1746
1747 TRACE("iface %p, device %p, constant %p, vector %p, count %u\n", iface, device, constant, vector, count);
1748
1749 return set_vector_array(This, device, constant, vector, count, D3DXPT_FLOAT);
1750 }
1751
1752 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1753 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1754 {
1755 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1756
1757 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1758
1759 return set_matrix_array(This, device, constant, matrix, 1, FALSE);
1760 }
1761
1762 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1763 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1764 {
1765 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1766
1767 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1768
1769 return set_matrix_array(This, device, constant, matrix, count, FALSE);
1770 }
1771
1772 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1773 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1774 {
1775 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1776
1777 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count);
1778
1779 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, FALSE);
1780 }
1781
1782 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1783 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1784 {
1785 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1786
1787 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1788
1789 return set_matrix_array(This, device, constant, matrix, 1, TRUE);
1790 }
1791
1792 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1793 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1794 {
1795 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1796
1797 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1798
1799 return set_matrix_array(This, device, constant, matrix, count, TRUE);
1800 }
1801
1802 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface,
1803 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1804 {
1805 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1806
1807 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count);
1808
1809 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, TRUE);
1810 }
1811
1812 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1813 {
1814 /*** IUnknown methods ***/
1815 ID3DXConstantTableImpl_QueryInterface,
1816 ID3DXConstantTableImpl_AddRef,
1817 ID3DXConstantTableImpl_Release,
1818 /*** ID3DXBuffer methods ***/
1819 ID3DXConstantTableImpl_GetBufferPointer,
1820 ID3DXConstantTableImpl_GetBufferSize,
1821 /*** ID3DXConstantTable methods ***/
1822 ID3DXConstantTableImpl_GetDesc,
1823 ID3DXConstantTableImpl_GetConstantDesc,
1824 ID3DXConstantTableImpl_GetSamplerIndex,
1825 ID3DXConstantTableImpl_GetConstant,
1826 ID3DXConstantTableImpl_GetConstantByName,
1827 ID3DXConstantTableImpl_GetConstantElement,
1828 ID3DXConstantTableImpl_SetDefaults,
1829 ID3DXConstantTableImpl_SetValue,
1830 ID3DXConstantTableImpl_SetBool,
1831 ID3DXConstantTableImpl_SetBoolArray,
1832 ID3DXConstantTableImpl_SetInt,
1833 ID3DXConstantTableImpl_SetIntArray,
1834 ID3DXConstantTableImpl_SetFloat,
1835 ID3DXConstantTableImpl_SetFloatArray,
1836 ID3DXConstantTableImpl_SetVector,
1837 ID3DXConstantTableImpl_SetVectorArray,
1838 ID3DXConstantTableImpl_SetMatrix,
1839 ID3DXConstantTableImpl_SetMatrixArray,
1840 ID3DXConstantTableImpl_SetMatrixPointerArray,
1841 ID3DXConstantTableImpl_SetMatrixTranspose,
1842 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1843 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1844 };
1845
1846 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
1847 BOOL is_element, WORD index, WORD max_index, DWORD *offset, DWORD nameoffset, UINT regset)
1848 {
1849 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
1850 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
1851 HRESULT hr = D3D_OK;
1852 UINT i, count = 0;
1853 WORD size = 0;
1854
1855 constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
1856 constant->desc.Class = type->Class;
1857 constant->desc.Type = type->Type;
1858 constant->desc.Rows = type->Rows;
1859 constant->desc.Columns = type->Columns;
1860 constant->desc.Elements = is_element ? 1 : type->Elements;
1861 constant->desc.StructMembers = type->StructMembers;
1862 constant->desc.Name = ctab + nameoffset;
1863 constant->desc.RegisterSet = regset;
1864 constant->desc.RegisterIndex = index;
1865
1866 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name,
1867 constant->desc.Elements, index, constant->desc.DefaultValue,
1868 debug_d3dxparameter_registerset(regset));
1869 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1870 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type),
1871 type->Rows, type->Columns, type->Elements, type->StructMembers);
1872
1873 if (type->Elements > 1 && !is_element)
1874 {
1875 count = type->Elements;
1876 }
1877 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
1878 {
1879 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
1880 count = type->StructMembers;
1881 }
1882
1883 if (count)
1884 {
1885 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
1886 if (!constant->constants)
1887 {
1888 ERR("Out of memory\n");
1889 hr = E_OUTOFMEMORY;
1890 goto error;
1891 }
1892
1893 for (i = 0; i < count; ++i)
1894 {
1895 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
1896 &constant->constants[i], memberinfo == NULL, index + size, max_index, offset,
1897 memberinfo ? memberinfo[i].Name : nameoffset, regset);
1898 if (hr != D3D_OK)
1899 goto error;
1900
1901 size += constant->constants[i].desc.RegisterCount;
1902 }
1903 }
1904 else
1905 {
1906 WORD offsetdiff = type->Columns * type->Rows;
1907 BOOL fail = FALSE;
1908
1909 size = type->Columns * type->Rows;
1910
1911 switch (regset)
1912 {
1913 case D3DXRS_BOOL:
1914 fail = type->Class != D3DXPC_SCALAR && type->Class != D3DXPC_VECTOR
1915 && type->Class != D3DXPC_MATRIX_ROWS && type->Class != D3DXPC_MATRIX_COLUMNS;
1916 break;
1917
1918 case D3DXRS_FLOAT4:
1919 case D3DXRS_INT4:
1920 switch (type->Class)
1921 {
1922 case D3DXPC_VECTOR:
1923 size = 1;
1924 /* fall through */
1925 case D3DXPC_SCALAR:
1926 offsetdiff = type->Rows * 4;
1927 break;
1928
1929 case D3DXPC_MATRIX_ROWS:
1930 offsetdiff = type->Rows * 4;
1931 size = type->Rows;
1932 break;
1933
1934 case D3DXPC_MATRIX_COLUMNS:
1935 offsetdiff = type->Columns * 4;
1936 size = type->Columns;
1937 break;
1938
1939 default:
1940 fail = TRUE;
1941 break;
1942 }
1943 break;
1944
1945 case D3DXRS_SAMPLER:
1946 size = 1;
1947 fail = type->Class != D3DXPC_OBJECT;
1948 break;
1949
1950 default:
1951 fail = TRUE;
1952 break;
1953 }
1954
1955 if (fail)
1956 {
1957 FIXME("Unhandled register set %s, type class %s\n", debug_d3dxparameter_registerset(regset),
1958 debug_d3dxparameter_class(type->Class));
1959 }
1960
1961 /* offset in bytes => offsetdiff * sizeof(DWORD) */
1962 if (offset) *offset += offsetdiff * 4;
1963 }
1964
1965 constant->desc.RegisterCount = max(0, min(max_index - index, size));
1966 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns;
1967
1968 return D3D_OK;
1969
1970 error:
1971 if (constant->constants)
1972 {
1973 for (i = 0; i < count; ++i)
1974 {
1975 free_constant(&constant->constants[i]);
1976 }
1977 HeapFree(GetProcessHeap(), 0, constant->constants);
1978 constant->constants = NULL;
1979 }
1980
1981 return hr;
1982 }
1983
1984 HRESULT WINAPI D3DXGetShaderConstantTableEx(const DWORD *byte_code, DWORD flags, ID3DXConstantTable **constant_table)
1985 {
1986 struct ID3DXConstantTableImpl *object = NULL;
1987 const void *data;
1988 HRESULT hr;
1989 UINT size;
1990 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1991 const D3DXSHADER_CONSTANTINFO *constant_info;
1992 DWORD i;
1993
1994 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code, flags, constant_table);
1995
1996 if (constant_table) *constant_table = NULL;
1997
1998 if (!byte_code || !constant_table)
1999 {
2000 WARN("Invalid argument specified.\n");
2001 return D3DERR_INVALIDCALL;
2002 }
2003
2004 if (!is_valid_bytecode(*byte_code))
2005 {
2006 WARN("Invalid byte_code specified.\n");
2007 return D3D_OK;
2008 }
2009
2010 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags);
2011
2012 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
2013 if (hr != D3D_OK)
2014 {
2015 WARN("CTAB not found.\n");
2016 return D3DXERR_INVALIDDATA;
2017 }
2018
2019 if (size < sizeof(*ctab_header))
2020 {
2021 WARN("Invalid CTAB size.\n");
2022 return D3DXERR_INVALIDDATA;
2023 }
2024
2025 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
2026 if (ctab_header->Size != sizeof(*ctab_header))
2027 {
2028 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
2029 return D3DXERR_INVALIDDATA;
2030 }
2031
2032 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2033 if (!object)
2034 return E_OUTOFMEMORY;
2035
2036 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
2037 object->ref = 1;
2038
2039 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
2040 if (!object->ctab)
2041 {
2042 ERR("Out of memory\n");
2043 HeapFree(GetProcessHeap(), 0, object);
2044 return E_OUTOFMEMORY;
2045 }
2046 object->size = size;
2047 memcpy(object->ctab, data, object->size);
2048
2049 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
2050 object->desc.Version = ctab_header->Version;
2051 object->desc.Constants = ctab_header->Constants;
2052 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
2053 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
2054 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
2055
2056 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2057 sizeof(*object->constants) * object->desc.Constants);
2058 if (!object->constants)
2059 {
2060 ERR("Out of memory\n");
2061 hr = E_OUTOFMEMORY;
2062 goto error;
2063 }
2064
2065 constant_info = (const D3DXSHADER_CONSTANTINFO *)(object->ctab + ctab_header->ConstantInfo);
2066 for (i = 0; i < ctab_header->Constants; i++)
2067 {
2068 DWORD offset = constant_info[i].DefaultValue;
2069
2070 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
2071 &object->constants[i], FALSE, constant_info[i].RegisterIndex,
2072 constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
2073 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
2074 if (hr != D3D_OK)
2075 goto error;
2076
2077 /*
2078 * Set the register count, it may differ for D3DXRS_INT4, because somehow
2079 * it makes the assumption that the register size is 1 instead of 4, so the
2080 * count is 4 times bigger. This holds true only for toplevel shader
2081 * constants. The count of elements and members is always based on a
2082 * register size of 4.
2083 */
2084 if (object->constants[i].desc.RegisterSet == D3DXRS_INT4)
2085 {
2086 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
2087 }
2088 }
2089
2090 *constant_table = &object->ID3DXConstantTable_iface;
2091
2092 return D3D_OK;
2093
2094 error:
2095 free_constant_table(object);
2096 HeapFree(GetProcessHeap(), 0, object);
2097
2098 return hr;
2099 }
2100
2101 HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantTable **constant_table)
2102 {
2103 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
2104
2105 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
2106 }
2107
2108 HRESULT WINAPI D3DXCreateFragmentLinker(IDirect3DDevice9 *device, UINT size, ID3DXFragmentLinker **linker)
2109 {
2110 FIXME("device %p, size %u, linker %p: stub.\n", device, size, linker);
2111
2112 if (linker)
2113 *linker = NULL;
2114
2115
2116 return E_NOTIMPL;
2117 }
2118
2119 HRESULT WINAPI D3DXCreateFragmentLinkerEx(IDirect3DDevice9 *device, UINT size, DWORD flags, ID3DXFragmentLinker **linker)
2120 {
2121 FIXME("device %p, size %u, flags %#x, linker %p: stub.\n", device, size, flags, linker);
2122
2123 if (linker)
2124 *linker = NULL;
2125
2126 return E_NOTIMPL;
2127 }
2128
2129 HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count)
2130 {
2131 UINT i, sampler_count = 0;
2132 UINT size;
2133 const char *data;
2134 const D3DXSHADER_CONSTANTTABLE *ctab_header;
2135 const D3DXSHADER_CONSTANTINFO *constant_info;
2136
2137 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
2138
2139 if (count) *count = 0;
2140
2141 if (D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (const void **)&data, &size) != D3D_OK)
2142 return D3D_OK;
2143
2144 if (size < sizeof(*ctab_header)) return D3D_OK;
2145
2146 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
2147 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
2148
2149 constant_info = (const D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
2150 for (i = 0; i < ctab_header->Constants; i++)
2151 {
2152 const D3DXSHADER_TYPEINFO *type;
2153
2154 TRACE("name = %s\n", data + constant_info[i].Name);
2155
2156 type = (const D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
2157
2158 if (type->Type == D3DXPT_SAMPLER
2159 || type->Type == D3DXPT_SAMPLER1D
2160 || type->Type == D3DXPT_SAMPLER2D
2161 || type->Type == D3DXPT_SAMPLER3D
2162 || type->Type == D3DXPT_SAMPLERCUBE)
2163 {
2164 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
2165
2166 ++sampler_count;
2167 }
2168 }
2169
2170 TRACE("Found %u samplers\n", sampler_count);
2171
2172 if (count) *count = sampler_count;
2173
2174 return D3D_OK;
2175 }
2176
2177 static const struct
2178 {
2179 const char *name;
2180 int length;
2181 }
2182 opcode[] =
2183 {
2184 { "nop", 0 }, /* D3DSIO_NOP */
2185 { "mov", 2 }, /* D3DSIO_MOV */
2186 { "add", 3 }, /* D3DSIO_ADD */
2187 { "sub", 3 }, /* D3DSIO_SUB */
2188 { "mad", 4 }, /* D3DSIO_MAD */
2189 { "mul", 3 }, /* D3DSIO_MUL */
2190 { "rcp", 2 }, /* D3DSIO_RCP */
2191 { "rsq", 2 }, /* D3DSIO_RSQ */
2192 { "dp3", 3 }, /* D3DSIO_DP3 */
2193 { "dp4", 3 }, /* D3DSIO_DP4 */
2194 { "min", 3 }, /* D3DSIO_MIN */
2195 { "max", 3 }, /* D3DSIO_MAX */
2196 { "slt", 3 }, /* D3DSIO_SLT */
2197 { "sge", 3 }, /* D3DSIO_SGE */
2198 { "exp", 2 }, /* D3DSIO_EXP */
2199 { "log", 2 }, /* D3DSIO_LOG */
2200 { "lit", 2 }, /* D3DSIO_LIT */
2201 { "dst", 3 }, /* D3DSIO_DST */
2202 { "lrp", 4 }, /* D3DSIO_LRP */
2203 { "frc", 2 }, /* D3DSIO_FRC */
2204 { "m4x4", 3 }, /* D3DSIO_M4x4 */
2205 { "m4x3", 3 }, /* D3DSIO_M4x3 */
2206 { "m3x4", 3 }, /* D3DSIO_M3x4 */
2207 { "m3x3", 3 }, /* D3DSIO_M3x3 */
2208 { "m3x2", 3 }, /* D3DSIO_M3x2 */
2209 { "call", 1 }, /* D3DSIO_CALL */
2210 { "callnz", 2 }, /* D3DSIO_CALLNZ */
2211 { "loop", 2 }, /* D3DSIO_LOOP */
2212 { "ret", 0 }, /* D3DSIO_RET */
2213 { "endloop", 1 }, /* D3DSIO_ENDLOOP */
2214 { "label", 1 }, /* D3DSIO_LABEL */
2215 { "dcl", 1 }, /* D3DSIO_DCL (handled separately) */
2216 { "pow", 3 }, /* D3DSIO_POW */
2217 { "crs", 3 }, /* D3DSIO_CRS */
2218 { "sgn", 4 }, /* D3DSIO_SGN */
2219 { "abs", 2 }, /* D3DSIO_ABS */
2220 { "nrm", 2 }, /* D3DSIO_NRM */
2221 { "sincos", 4 }, /* D3DSIO_SINCOS */
2222 { "rep", 1 }, /* D3DSIO_REP */
2223 { "endrep", 0 }, /* D3DSIO_ENDREP */
2224 { "if", 1 }, /* D3DSIO_IF */
2225 { "if", 2 }, /* D3DSIO_IFC */
2226 { "else", 0 }, /* D3DSIO_ELSE */
2227 { "endif", 0 }, /* D3DSIO_ENDIF */
2228 { "break", 0 }, /* D3DSIO_BREAK */
2229 { "break", 2 }, /* D3DSIO_BREAKC */
2230 { "mova", 2 }, /* D3DSIO_MOVA */
2231 { "defb", 2 }, /* D3DSIO_DEFB */
2232 { "defi", 2 }, /* D3DSIO_DEFI */
2233 { "texcoord", 1 }, /* D3DSIO_TEXCOORD */
2234 { "texkill", 1 }, /* D3DSIO_TEXKILL */
2235 { "texld", 3 }, /* D3DSIO_TEX */
2236 { "texbem", 2 }, /* D3DSIO_TEXBEM */
2237 { "texbeml", 2 }, /* D3DSIO_TEXBEML */
2238 { "texreg2ar", 2 }, /* D3DSIO_TEXREG2AR */
2239 { "texreg2gb", 2 }, /* D3DSIO_TEXREG2GB */
2240 { "texm3x2pad", 2 }, /* D3DSIO_TEXM3x2PAD */
2241 { "texm3x2tex", 2 }, /* D3DSIO_TEXM3x2TEX */
2242 { "texm3x3pad", 2 }, /* D3DSIO_TEXM3x3PAD */
2243 { "texm3x3tex", 2 }, /* D3DSIO_TEXM3x3TEX */
2244 { "texm3x3diff", 2 }, /* D3DSIO_TEXM3x3DIFF */
2245 { "texm3x3spec", 3 }, /* D3DSIO_TEXM3x3SPEC */
2246 { "texm3x3vspec", 2 }, /* D3DSIO_TEXM3x3VSPEC */
2247 { "expp", 2 }, /* D3DSIO_EXPP */
2248 { "logp", 2 }, /* D3DSIO_LOGP */
2249 { "cnd", 4 }, /* D3DSIO_CND */
2250 { "def", 5 }, /* D3DSIO_DEF (handled separately) */
2251 { "texreg2rgb", 2 }, /* D3DSIO_TEXREG2RGB */
2252 { "texdp3tex", 2 }, /* D3DSIO_TEXDP3TEX */
2253 { "texm3x2depth", 2 }, /* D3DSIO_TEXM3x2DEPTH */
2254 { "texdp3", 2 }, /* D3DSIO_TEXDP3 */
2255 { "texm3x3", 2 }, /* D3DSIO_TEXM3x3 */
2256 { "texdepth", 1 }, /* D3DSIO_TEXDEPTH */
2257 { "cmp", 4 }, /* D3DSIO_CMP */
2258 { "bem", 3 }, /* D3DSIO_BEM */
2259 { "dp2add", 4 }, /* D3DSIO_DP2ADD */
2260 { "dsx", 2 }, /* D3DSIO_DSX */
2261 { "dsy", 2 }, /* D3DSIO_DSY */
2262 { "texldd", 5 }, /* D3DSIO_TEXLDD */
2263 { "setp", 3 }, /* D3DSIO_SETP */
2264 { "texldl", 3 }, /* D3DSIO_TEXLDL */
2265 { "breakp", 1 } /* D3DSIO_BREAKP */
2266 };
2267
2268 static const char *decl_usage[] = { "position", "blendweight", "blendindices", "normal", "psize", "texcoord",
2269 "tangent", "binormal", "tessfactor", "positiont", "color" };
2270
2271 static const char *tex_type[] = { "", "1d", "2d", "cube", "volume" };
2272
2273 static int add_modifier(char *buffer, DWORD param)
2274 {
2275 char *buf = buffer;
2276 DWORD dst_mod = param & D3DSP_DSTMOD_MASK;
2277
2278 if (dst_mod & D3DSPDM_SATURATE)
2279 buf += sprintf(buf, "_sat");
2280 if (dst_mod & D3DSPDM_PARTIALPRECISION)
2281 buf += sprintf(buf, "_pp");
2282 if (dst_mod & D3DSPDM_MSAMPCENTROID)
2283 buf += sprintf(buf, "_centroid");
2284
2285 return buf - buffer;
2286 }
2287
2288 static int add_register(char *buffer, DWORD param, BOOL dst, BOOL ps)
2289 {
2290 char *buf = buffer;
2291 DWORD reg_type = ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)
2292 | ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
2293 DWORD reg_num = param & D3DSP_REGNUM_MASK;
2294
2295 if (reg_type == D3DSPR_INPUT)
2296 buf += sprintf(buf, "v%d", reg_num);
2297 else if (reg_type == D3DSPR_CONST)
2298 buf += sprintf(buf, "c%d", reg_num);
2299 else if (reg_type == D3DSPR_TEMP)
2300 buf += sprintf(buf, "r%d", reg_num);
2301 else if (reg_type == D3DSPR_ADDR)
2302 buf += sprintf(buf, "%s%d", ps ? "t" : "a", reg_num);
2303 else if (reg_type == D3DSPR_SAMPLER)
2304 buf += sprintf(buf, "s%d", reg_num);
2305 else if (reg_type == D3DSPR_RASTOUT)
2306 buf += sprintf(buf, "oPos");
2307 else if (reg_type == D3DSPR_COLOROUT)
2308 buf += sprintf(buf, "oC%d", reg_num);
2309 else if (reg_type == D3DSPR_TEXCRDOUT)
2310 buf += sprintf(buf, "oT%d", reg_num);
2311 else if (reg_type == D3DSPR_ATTROUT)
2312 buf += sprintf(buf, "oD%d", reg_num);
2313 else
2314 buf += sprintf(buf, "? (%d)", reg_type);
2315
2316 if (dst)
2317 {
2318 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL)
2319 {
2320 buf += sprintf(buf, ".%s%s%s%s", param & D3DSP_WRITEMASK_0 ? "x" : "",
2321 param & D3DSP_WRITEMASK_1 ? "y" : "",
2322 param & D3DSP_WRITEMASK_2 ? "z" : "",
2323 param & D3DSP_WRITEMASK_3 ? "w" : "");
2324 }
2325 }
2326 else
2327 {
2328 if ((param & D3DVS_SWIZZLE_MASK) != D3DVS_NOSWIZZLE)
2329 {
2330 if ( ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_X | D3DVS_Y_X | D3DVS_Z_X | D3DVS_W_X)) ||
2331 ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Y | D3DVS_Y_Y | D3DVS_Z_Y | D3DVS_W_Y)) ||
2332 ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Z | D3DVS_Y_Z | D3DVS_Z_Z | D3DVS_W_Z)) ||
2333 ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_W | D3DVS_Y_W | D3DVS_Z_W | D3DVS_W_W)) )
2334 buf += sprintf(buf, ".%c", 'w' + (((param >> D3DVS_SWIZZLE_SHIFT) + 1) & 0x3));
2335 else
2336 buf += sprintf(buf, ".%c%c%c%c", 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+0)) + 1) & 0x3),
2337 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+2)) + 1) & 0x3),
2338 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+4)) + 1) & 0x3),
2339 'w' + (((param >> (D3DVS_SWIZZLE_SHIFT+6)) + 1) & 0x3));
2340 }
2341 }
2342
2343 return buf - buffer;
2344 }
2345
2346 HRESULT WINAPI D3DXDisassembleShader(const DWORD *shader, BOOL colorcode, const char *comments, ID3DXBuffer **disassembly)
2347 {
2348 DWORD *ptr = (DWORD *)shader;
2349 char *buffer, *buf;
2350 UINT capacity = 4096;
2351 BOOL ps;
2352 HRESULT hr;
2353
2354 TRACE("%p %d %s %p\n", shader, colorcode, debugstr_a(comments), disassembly);
2355
2356 if (!shader || !disassembly)
2357 return D3DERR_INVALIDCALL;
2358
2359 buf = buffer = HeapAlloc(GetProcessHeap(), 0, capacity);
2360 if (!buffer)
2361 return E_OUTOFMEMORY;
2362
2363 ps = (*ptr >> 16) & 1;
2364 buf += sprintf(buf, " %s_%d_%d\n", ps ? "ps" : "vs", D3DSHADER_VERSION_MAJOR(*ptr), D3DSHADER_VERSION_MINOR(*ptr));
2365 ptr++;
2366
2367 while (*ptr != D3DSIO_END)
2368 {
2369 if ((buf - buffer + 128) > capacity)
2370 {
2371 UINT count = buf - buffer;
2372 char *new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, capacity * 2);
2373 if (!new_buffer)
2374 {
2375 HeapFree(GetProcessHeap(), 0, buffer);
2376 return E_OUTOFMEMORY;
2377 }
2378 capacity *= 2;
2379 buffer = new_buffer;
2380 buf = buffer + count;
2381 }
2382
2383 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
2384 {
2385 ptr += 1 + ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
2386 }
2387 else if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_DEF)
2388 {
2389 buf += sprintf(buf, " def c%d, %g, %g, %g, %g\n", *(ptr+1) & D3DSP_REGNUM_MASK,
2390 (double)*(float*)(ptr+2), (double)*(float*)(ptr+3),
2391 (double)*(float*)(ptr+4), (double)*(float*)(ptr+5));
2392 ptr += 6;
2393 }
2394 else if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_DCL)
2395 {
2396 DWORD param1 = *++ptr;
2397 DWORD param2 = *++ptr;
2398 DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
2399 DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
2400
2401 buf += sprintf(buf, " dcl");
2402 if (ps)
2403 {
2404 if (param1 & D3DSP_TEXTURETYPE_MASK)
2405 buf += sprintf(buf, "_%s", (usage <= D3DSTT_VOLUME) ?
2406 tex_type[(param1 & D3DSP_TEXTURETYPE_MASK) >> D3DSP_TEXTURETYPE_SHIFT] : "???");
2407 }
2408 else
2409 {
2410 buf += sprintf(buf, "_%s", (usage <= D3DDECLUSAGE_COLOR) ? decl_usage[usage] : "???");
2411 if (usage_index)
2412 buf += sprintf(buf, "%d", usage_index);
2413 }
2414
2415 buf += add_modifier(buf, param2);
2416 buf += sprintf(buf, " ");
2417 buf += add_register(buf, param2, TRUE, TRUE);
2418 buf += sprintf(buf, "\n");
2419 ptr++;
2420 }
2421 else if ((*ptr & D3DSI_OPCODE_MASK) <= D3DSIO_BREAKP)
2422 {
2423 DWORD index = *ptr & D3DSI_OPCODE_MASK;
2424 int j;
2425
2426 if (index >= 64)
2427 index -= 15;
2428 buf += sprintf(buf, " %s", opcode[index].name);
2429 ptr++;
2430
2431 if (opcode[index].length)
2432 {
2433 buf += add_modifier(buf, *ptr);
2434
2435 for (j = 0; j < opcode[index].length; j++)
2436 {
2437 buf += sprintf(buf, "%s ", j ? "," : "");
2438
2439 if ((j != 0) && ((*ptr & D3DSP_SRCMOD_MASK) != D3DSPSM_NONE))
2440 {
2441 if ((*ptr & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG)
2442 buf += sprintf(buf, "-");
2443 else
2444 buf += sprintf(buf, "*");
2445 }
2446
2447 buf += add_register(buf, *ptr, j == 0, ps);
2448
2449 if (*ptr++ & D3DVS_ADDRESSMODE_MASK)
2450 {
2451 buf += sprintf(buf, "[");
2452 buf += add_register(buf, *ptr, FALSE, FALSE);
2453 buf += sprintf(buf, "]");
2454 ptr++;
2455 }
2456 }
2457 }
2458 buf += sprintf(buf, "\n");
2459 }
2460 else
2461 {
2462 buf += sprintf(buf, " ???\n");
2463 ptr++;
2464 }
2465 }
2466
2467 hr = D3DXCreateBuffer(buf - buffer + 1 , disassembly);
2468 if (SUCCEEDED(hr))
2469 strcpy(ID3DXBuffer_GetBufferPointer(*disassembly), buffer);
2470 HeapFree(GetProcessHeap(), 0, buffer);
2471
2472 return hr;
2473 }
2474
2475 static const DWORD* skip_instruction(const DWORD *byte_code, UINT shader_model)
2476 {
2477 TRACE("Shader model %u\n", shader_model);
2478
2479 /* Handle all special instructions whose arguments may contain D3DSIO_DCL */
2480 if ((*byte_code & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
2481 {
2482 byte_code += 1 + ((*byte_code & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
2483 }
2484 else if (shader_model >= 2)
2485 {
2486 byte_code += 1 + ((*byte_code & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT);
2487 }
2488 else if ((*byte_code & D3DSI_OPCODE_MASK) == D3DSIO_DEF)
2489 {
2490 byte_code += 1 + 5;
2491 }
2492 else
2493 {
2494 /* Handle remaining safe instructions */
2495 while (*++byte_code & (1u << 31));
2496 }
2497
2498 return byte_code;
2499 }
2500
2501 static UINT get_shader_semantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, DWORD type)
2502 {
2503 const DWORD *ptr = byte_code;
2504 UINT shader_model = (*ptr >> 8) & 0xff;
2505 UINT i = 0;
2506
2507 TRACE("Shader version: %#x\n", *ptr);
2508 ptr++;
2509
2510 while (*ptr != D3DSIO_END)
2511 {
2512 if (*ptr & (1u << 31))
2513 {
2514 FIXME("Opcode expected but got %#x\n", *ptr);
2515 return 0;
2516 }
2517 else if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_DCL)
2518 {
2519 DWORD param1 = *++ptr;
2520 DWORD param2 = *++ptr;
2521 DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
2522 DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
2523 DWORD reg_type = ((param2 & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)
2524 | ((param2 & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
2525
2526 TRACE("D3DSIO_DCL param1: %#x, param2: %#x, usage: %u, usage_index: %u, reg_type: %u\n",
2527 param1, param2, usage, usage_index, reg_type);
2528
2529 if (reg_type == type)
2530 {
2531 if (semantics)
2532 {
2533 semantics[i].Usage = usage;
2534 semantics[i].UsageIndex = usage_index;
2535 }
2536 i++;
2537 }
2538
2539 ptr++;
2540 }
2541 else
2542 {
2543 ptr = skip_instruction(ptr, shader_model);
2544 }
2545 }
2546
2547 return i;
2548 }
2549
2550 HRESULT WINAPI D3DXGetShaderInputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count)
2551 {
2552 UINT nb_semantics;
2553
2554 TRACE("byte_code %p, semantics %p, count %p\n", byte_code, semantics, count);
2555
2556 if (!byte_code)
2557 return D3DERR_INVALIDCALL;
2558
2559 nb_semantics = get_shader_semantics(byte_code, semantics, D3DSPR_INPUT);
2560
2561 if (count)
2562 *count = nb_semantics;
2563
2564 return D3D_OK;
2565 }
2566
2567
2568 HRESULT WINAPI D3DXGetShaderOutputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count)
2569 {
2570 UINT nb_semantics;
2571
2572 TRACE("byte_code %p, semantics %p, count %p\n", byte_code, semantics, count);
2573
2574 if (!byte_code)
2575 return D3DERR_INVALIDCALL;
2576
2577 nb_semantics = get_shader_semantics(byte_code, semantics, D3DSPR_OUTPUT);
2578
2579 if (count)
2580 *count = nb_semantics;
2581
2582 return D3D_OK;
2583 }
2584
2585 struct d3dx9_texture_shader
2586 {
2587 ID3DXTextureShader ID3DXTextureShader_iface;
2588 LONG ref;
2589 };
2590
2591 static inline struct d3dx9_texture_shader *impl_from_ID3DXTextureShader(ID3DXTextureShader *iface)
2592 {
2593 return CONTAINING_RECORD(iface, struct d3dx9_texture_shader, ID3DXTextureShader_iface);
2594 }
2595
2596 static HRESULT WINAPI d3dx9_texture_shader_QueryInterface(ID3DXTextureShader *iface, REFIID riid, void **out)
2597 {
2598 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
2599
2600 if (IsEqualGUID(riid, &IID_IUnknown) ||
2601 IsEqualGUID(riid, &IID_ID3DXTextureShader))
2602 {
2603 iface->lpVtbl->AddRef(iface);
2604 *out = iface;
2605 return D3D_OK;
2606 }
2607
2608 WARN("Interface %s not found.\n", debugstr_guid(riid));
2609 *out = NULL;
2610 return E_NOINTERFACE;
2611 }
2612
2613 static ULONG WINAPI d3dx9_texture_shader_AddRef(ID3DXTextureShader *iface)
2614 {
2615 struct d3dx9_texture_shader *texture_shader = impl_from_ID3DXTextureShader(iface);
2616 ULONG refcount = InterlockedIncrement(&texture_shader->ref);
2617
2618 TRACE("%p increasing refcount to %u.\n", texture_shader, refcount);
2619
2620 return refcount;
2621 }
2622
2623 static ULONG WINAPI d3dx9_texture_shader_Release(ID3DXTextureShader *iface)
2624 {
2625 struct d3dx9_texture_shader *texture_shader = impl_from_ID3DXTextureShader(iface);
2626 ULONG refcount = InterlockedDecrement(&texture_shader->ref);
2627
2628 TRACE("%p decreasing refcount to %u.\n", texture_shader, refcount);
2629
2630 if (!refcount)
2631 {
2632 HeapFree(GetProcessHeap(), 0, texture_shader);
2633 }
2634
2635 return refcount;
2636 }
2637
2638 static HRESULT WINAPI d3dx9_texture_shader_GetFunction(ID3DXTextureShader *iface, struct ID3DXBuffer **function)
2639 {
2640 FIXME("iface %p, function %p stub.\n", iface, function);
2641
2642 return E_NOTIMPL;
2643 }
2644
2645 static HRESULT WINAPI d3dx9_texture_shader_GetConstantBuffer(ID3DXTextureShader *iface, struct ID3DXBuffer **constant_buffer)
2646 {
2647 FIXME("iface %p, constant_buffer %p stub.\n", iface, constant_buffer);
2648
2649 return E_NOTIMPL;
2650 }
2651
2652 static HRESULT WINAPI d3dx9_texture_shader_GetDesc(ID3DXTextureShader *iface, D3DXCONSTANTTABLE_DESC *desc)
2653 {
2654 FIXME("iface %p, desc %p stub.\n", iface, desc);
2655
2656 return E_NOTIMPL;
2657 }
2658
2659 static HRESULT WINAPI d3dx9_texture_shader_GetConstantDesc(ID3DXTextureShader *iface, D3DXHANDLE constant, D3DXCONSTANT_DESC *constant_desc, UINT *count)
2660 {
2661 FIXME("iface %p, constant %p, constant_desc %p, count %p stub.\n", iface, constant, constant_desc, count);
2662
2663 return E_NOTIMPL;
2664 }
2665
2666 static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstant(ID3DXTextureShader *iface, D3DXHANDLE constant, UINT index)
2667 {
2668 FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index);
2669
2670 return NULL;
2671 }
2672
2673 static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstantByName(ID3DXTextureShader *iface, D3DXHANDLE constant, const char *name)
2674 {
2675 FIXME("iface %p, constant %p, name %s stub.\n", iface, constant, debugstr_a(name));
2676
2677 return NULL;
2678 }
2679
2680 static D3DXHANDLE WINAPI d3dx9_texture_shader_GetConstantElement(ID3DXTextureShader *iface, D3DXHANDLE constant, UINT index)
2681 {
2682 FIXME("iface %p, constant %p, index %u stub.\n", iface, constant, index);
2683
2684 return NULL;
2685 }
2686
2687 static HRESULT WINAPI d3dx9_texture_shader_SetDefaults(ID3DXTextureShader *iface)
2688 {
2689 FIXME("iface %p stub.\n", iface);
2690
2691 return E_NOTIMPL;
2692 }
2693
2694 static HRESULT WINAPI d3dx9_texture_shader_SetValue(ID3DXTextureShader *iface, D3DXHANDLE constant, const void *data, UINT bytes)
2695 {
2696 FIXME("iface %p, constant %p, data %p, bytes %u stub.\n", iface, constant, data, bytes);
2697
2698 return E_NOTIMPL;
2699 }
2700
2701 static HRESULT WINAPI d3dx9_texture_shader_SetBool(ID3DXTextureShader *iface, D3DXHANDLE constant, BOOL b)
2702 {
2703 FIXME("iface %p, constant %p, b %u stub.\n", iface, constant, b);
2704
2705 return E_NOTIMPL;
2706 }
2707
2708 static HRESULT WINAPI d3dx9_texture_shader_SetBoolArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const BOOL *b, UINT count)
2709 {
2710 FIXME("iface %p, constant %p, b %p, count %u stub.\n", iface, constant, b, count);
2711
2712 return E_NOTIMPL;
2713 }
2714
2715 static HRESULT WINAPI d3dx9_texture_shader_SetInt(ID3DXTextureShader *iface, D3DXHANDLE constant, INT n)
2716 {
2717 FIXME("iface %p, constant %p, n %d stub.\n", iface, constant, n);
2718
2719 return E_NOTIMPL;
2720 }
2721
2722 static HRESULT WINAPI d3dx9_texture_shader_SetIntArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const INT *n, UINT count)
2723 {
2724 FIXME("iface %p, constant %p, n %p, count %u stub.\n", iface, constant, n, count);
2725
2726 return E_NOTIMPL;
2727 }
2728
2729 static HRESULT WINAPI d3dx9_texture_shader_SetFloat(ID3DXTextureShader *iface, D3DXHANDLE constant, FLOAT f)
2730 {
2731 FIXME("iface %p, constant %p, f %f stub.\n", iface, constant, f);
2732
2733 return E_NOTIMPL;
2734 }
2735
2736 static HRESULT WINAPI d3dx9_texture_shader_SetFloatArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const FLOAT *f, UINT count)
2737 {
2738 FIXME("iface %p, constant %p, f %p, count %u stub.\n", iface, constant, f, count);
2739
2740 return E_NOTIMPL;
2741 }
2742
2743 static HRESULT WINAPI d3dx9_texture_shader_SetVector(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
2744 {
2745 FIXME("iface %p, constant %p, vector %p stub.\n", iface, constant, vector);
2746
2747 return E_NOTIMPL;
2748 }
2749
2750 static HRESULT WINAPI d3dx9_texture_shader_SetVectorArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
2751 {
2752 FIXME("iface %p, constant %p, vector %p, count %u stub.\n", iface, constant, vector, count);
2753
2754 return E_NOTIMPL;
2755 }
2756
2757 static HRESULT WINAPI d3dx9_texture_shader_SetMatrix(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix)
2758 {
2759 FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix);
2760
2761 return E_NOTIMPL;
2762 }
2763
2764 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
2765 {
2766 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2767
2768 return E_NOTIMPL;
2769 }
2770
2771 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixPointerArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
2772 {
2773 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2774
2775 return E_NOTIMPL;
2776 }
2777
2778 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTranspose(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix)
2779 {
2780 FIXME("iface %p, constant %p, matrix %p stub.\n", iface, constant, matrix);
2781
2782 return E_NOTIMPL;
2783 }
2784
2785 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTransposeArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
2786 {
2787 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2788
2789 return E_NOTIMPL;
2790 }
2791
2792 static HRESULT WINAPI d3dx9_texture_shader_SetMatrixTransposePointerArray(ID3DXTextureShader *iface, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
2793 {
2794 FIXME("iface %p, constant %p, matrix %p, count %u stub.\n", iface, constant, matrix, count);
2795
2796 return E_NOTIMPL;
2797 }
2798
2799 static const struct ID3DXTextureShaderVtbl d3dx9_texture_shader_vtbl =
2800 {
2801 /*** IUnknown methods ***/
2802 d3dx9_texture_shader_QueryInterface,
2803 d3dx9_texture_shader_AddRef,
2804 d3dx9_texture_shader_Release,
2805 /*** ID3DXTextureShader methods ***/
2806 d3dx9_texture_shader_GetFunction,
2807 d3dx9_texture_shader_GetConstantBuffer,
2808 d3dx9_texture_shader_GetDesc,
2809 d3dx9_texture_shader_GetConstantDesc,
2810 d3dx9_texture_shader_GetConstant,
2811 d3dx9_texture_shader_GetConstantByName,
2812 d3dx9_texture_shader_GetConstantElement,
2813 d3dx9_texture_shader_SetDefaults,
2814 d3dx9_texture_shader_SetValue,
2815 d3dx9_texture_shader_SetBool,
2816 d3dx9_texture_shader_SetBoolArray,
2817 d3dx9_texture_shader_SetInt,
2818 d3dx9_texture_shader_SetIntArray,
2819 d3dx9_texture_shader_SetFloat,
2820 d3dx9_texture_shader_SetFloatArray,
2821 d3dx9_texture_shader_SetVector,
2822 d3dx9_texture_shader_SetVectorArray,
2823 d3dx9_texture_shader_SetMatrix,
2824 d3dx9_texture_shader_SetMatrixArray,
2825 d3dx9_texture_shader_SetMatrixPointerArray,
2826 d3dx9_texture_shader_SetMatrixTranspose,
2827 d3dx9_texture_shader_SetMatrixTransposeArray,
2828 d3dx9_texture_shader_SetMatrixTransposePointerArray
2829 };
2830
2831 HRESULT WINAPI D3DXCreateTextureShader(const DWORD *function, ID3DXTextureShader **texture_shader)
2832 {
2833 struct d3dx9_texture_shader *object;
2834
2835 TRACE("function %p, texture_shader %p.\n", function, texture_shader);
2836
2837 if (!function || !texture_shader)
2838 return D3DERR_INVALIDCALL;
2839
2840 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
2841 if (!object)
2842 return E_OUTOFMEMORY;
2843
2844 object->ID3DXTextureShader_iface.lpVtbl = &d3dx9_texture_shader_vtbl;
2845 object->ref = 1;
2846
2847 *texture_shader = &object->ID3DXTextureShader_iface;
2848
2849 return D3D_OK;
2850 }
2851
2852 HRESULT WINAPI D3DXFillCubeTextureTX(IDirect3DCubeTexture9 *texture, ID3DXTextureShader *texture_shader)
2853 {
2854 FIXME("texture %p, texture_shader %p stub.\n", texture, texture_shader);
2855
2856 if (!texture || !texture_shader)
2857 return E_POINTER;
2858
2859 return D3D_OK;
2860 }