* Sync up to trunk head (r65353).
[reactos.git] / dll / directx / wine / d3dx9_36 / shader.c
1 /*
2 * Copyright 2008 Luis Busquets
3 * Copyright 2009 Matteo Bruni
4 * Copyright 2011 Travis Athougies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "d3dx9_36_private.h"
22 #include "d3dcompiler.h"
23
24
25 /* This function is not declared in the SDK headers yet. */
26 HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename,
27 const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags,
28 ID3DBlob **shader, ID3DBlob **error_messages);
29
30 static inline BOOL is_valid_bytecode(DWORD token)
31 {
32 return (token & 0xfffe0000) == 0xfffe0000;
33 }
34
35 const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device)
36 {
37 D3DCAPS9 caps;
38
39 TRACE("device %p\n", device);
40
41 if (!device) return NULL;
42
43 IDirect3DDevice9_GetDeviceCaps(device,&caps);
44
45 switch (caps.PixelShaderVersion)
46 {
47 case D3DPS_VERSION(1, 1):
48 return "ps_1_1";
49
50 case D3DPS_VERSION(1, 2):
51 return "ps_1_2";
52
53 case D3DPS_VERSION(1, 3):
54 return "ps_1_3";
55
56 case D3DPS_VERSION(1, 4):
57 return "ps_1_4";
58
59 case D3DPS_VERSION(2, 0):
60 if ((caps.PS20Caps.NumTemps>=22) &&
61 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) &&
62 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
63 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) &&
64 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
65 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
66 {
67 return "ps_2_a";
68 }
69 if ((caps.PS20Caps.NumTemps>=32) &&
70 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
71 {
72 return "ps_2_b";
73 }
74 return "ps_2_0";
75
76 case D3DPS_VERSION(3, 0):
77 return "ps_3_0";
78 }
79
80 return NULL;
81 }
82
83 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
84 {
85 const DWORD *ptr = byte_code;
86
87 TRACE("byte_code %p\n", byte_code);
88
89 if (!ptr) return 0;
90
91 /* Look for the END token, skipping the VERSION token */
92 while (*++ptr != D3DSIO_END)
93 {
94 /* Skip comments */
95 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
96 {
97 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
98 }
99 }
100 ++ptr;
101
102 /* Return the shader size in bytes */
103 return (ptr - byte_code) * sizeof(*ptr);
104 }
105
106 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
107 {
108 TRACE("byte_code %p\n", byte_code);
109
110 return byte_code ? *byte_code : 0;
111 }
112
113 const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device)
114 {
115 D3DCAPS9 caps;
116
117 TRACE("device %p\n", device);
118
119 if (!device) return NULL;
120
121 IDirect3DDevice9_GetDeviceCaps(device,&caps);
122
123 switch (caps.VertexShaderVersion)
124 {
125 case D3DVS_VERSION(1, 1):
126 return "vs_1_1";
127 case D3DVS_VERSION(2, 0):
128 if ((caps.VS20Caps.NumTemps>=13) &&
129 (caps.VS20Caps.DynamicFlowControlDepth==24) &&
130 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
131 {
132 return "vs_2_a";
133 }
134 return "vs_2_0";
135 case D3DVS_VERSION(3, 0):
136 return "vs_3_0";
137 }
138
139 return NULL;
140 }
141
142 HRESULT WINAPI D3DXFindShaderComment(const DWORD *byte_code, DWORD fourcc, const void **data, UINT *size)
143 {
144 const DWORD *ptr = byte_code;
145 DWORD version;
146
147 TRACE("byte_code %p, fourcc %x, data %p, size %p\n", byte_code, fourcc, data, size);
148
149 if (data) *data = NULL;
150 if (size) *size = 0;
151
152 if (!byte_code) return D3DERR_INVALIDCALL;
153
154 version = *ptr >> 16;
155 if (version != 0x4658 /* FX */
156 && version != 0x5458 /* TX */
157 && version != 0x7ffe
158 && version != 0x7fff
159 && version != 0xfffe /* VS */
160 && version != 0xffff) /* PS */
161 {
162 WARN("Invalid data supplied\n");
163 return D3DXERR_INVALIDDATA;
164 }
165
166 while (*++ptr != D3DSIO_END)
167 {
168 /* Check if it is a comment */
169 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
170 {
171 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
172
173 /* Check if this is the comment we are looking for */
174 if (*(ptr + 1) == fourcc)
175 {
176 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
177 const void *ctab_data = ptr + 2;
178 if (size)
179 *size = ctab_size;
180 if (data)
181 *data = ctab_data;
182 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
183 return D3D_OK;
184 }
185 ptr += comment_size;
186 }
187 }
188
189 return S_FALSE;
190 }
191
192 HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMACRO *defines,
193 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
194 {
195 HRESULT hr;
196
197 TRACE("data %p, data_len %u, defines %p, include %p, flags %#x, shader %p, error_messages %p\n",
198 data, data_len, defines, include, flags, shader, error_messages);
199
200 /* Forward to d3dcompiler: the parameter types aren't really different,
201 the actual data types are equivalent */
202 hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
203 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
204 (ID3DBlob **)error_messages);
205
206 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
207 return hr;
208 }
209
210 static const void *main_file_data;
211
212 static CRITICAL_SECTION from_file_mutex;
213 static CRITICAL_SECTION_DEBUG from_file_mutex_debug =
214 {
215 0, 0, &from_file_mutex,
216 {
217 &from_file_mutex_debug.ProcessLocksList,
218 &from_file_mutex_debug.ProcessLocksList
219 },
220 0, 0, {(DWORD_PTR)(__FILE__ ": from_file_mutex")}
221 };
222 static CRITICAL_SECTION from_file_mutex = {&from_file_mutex_debug, -1, 0, 0, 0, 0};
223
224 /* D3DXInclude private implementation, used to implement
225 * D3DXAssembleShaderFromFile() from D3DXAssembleShader(). */
226 /* To be able to correctly resolve include search paths we have to store the
227 * pathname of each include file. We store the pathname pointer right before
228 * the file data. */
229 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type,
230 const char *filename, const void *parent_data, const void **data, UINT *bytes)
231 {
232 const char *p, *parent_name = "";
233 char *pathname = NULL, *ptr;
234 char **buffer = NULL;
235 HANDLE file;
236 UINT size;
237
238 if (parent_data)
239 {
240 parent_name = *((const char **)parent_data - 1);
241 }
242 else
243 {
244 if (main_file_data)
245 parent_name = *((const char **)main_file_data - 1);
246 }
247
248 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
249
250 if ((p = strrchr(parent_name, '\\')))
251 ++p;
252 else
253 p = parent_name;
254 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
255 if(!pathname)
256 return HRESULT_FROM_WIN32(GetLastError());
257
258 memcpy(pathname, parent_name, p - parent_name);
259 strcpy(pathname + (p - parent_name), filename);
260 ptr = pathname + (p - parent_name);
261 while (*ptr)
262 {
263 if (*ptr == '/')
264 *ptr = '\\';
265 ++ptr;
266 }
267
268 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
269 if(file == INVALID_HANDLE_VALUE)
270 goto error;
271
272 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
273
274 size = GetFileSize(file, NULL);
275 if(size == INVALID_FILE_SIZE)
276 goto error;
277
278 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
279 if(!buffer)
280 goto error;
281 *buffer = pathname;
282 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
283 goto error;
284
285 *data = buffer + 1;
286 if (!main_file_data)
287 main_file_data = *data;
288
289 CloseHandle(file);
290 return S_OK;
291
292 error:
293 CloseHandle(file);
294 HeapFree(GetProcessHeap(), 0, pathname);
295 HeapFree(GetProcessHeap(), 0, buffer);
296 return HRESULT_FROM_WIN32(GetLastError());
297 }
298
299 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, const void *data)
300 {
301 HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
302 HeapFree(GetProcessHeap(), 0, (char **)data - 1);
303 if (main_file_data == data)
304 main_file_data = NULL;
305 return S_OK;
306 }
307
308 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
309 d3dincludefromfile_open,
310 d3dincludefromfile_close
311 };
312
313 struct D3DXIncludeImpl {
314 ID3DXInclude ID3DXInclude_iface;
315 };
316
317 HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines,
318 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
319 {
320 WCHAR *filename_w;
321 DWORD len;
322 HRESULT ret;
323
324 TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
325 debugstr_a(filename), defines, include, flags, shader, error_messages);
326
327 if (!filename) return D3DXERR_INVALIDDATA;
328
329 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
330 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
331 if (!filename_w) return E_OUTOFMEMORY;
332 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
333
334 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
335
336 HeapFree(GetProcessHeap(), 0, filename_w);
337 return ret;
338 }
339
340 HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
341 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
342 {
343 const void *buffer;
344 DWORD len;
345 HRESULT hr;
346 struct D3DXIncludeImpl includefromfile;
347 char *filename_a;
348
349 TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
350 debugstr_w(filename), defines, include, flags, shader, error_messages);
351
352 if(!include)
353 {
354 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
355 include = &includefromfile.ID3DXInclude_iface;
356 }
357
358 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
359 filename_a = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
360 if (!filename_a)
361 return E_OUTOFMEMORY;
362 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
363
364 EnterCriticalSection(&from_file_mutex);
365 hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
366 if (FAILED(hr))
367 {
368 LeaveCriticalSection(&from_file_mutex);
369 HeapFree(GetProcessHeap(), 0, filename_a);
370 return D3DXERR_INVALIDDATA;
371 }
372
373 hr = D3DXAssembleShader(buffer, len, defines, include, flags, shader, error_messages);
374
375 ID3DXInclude_Close(include, buffer);
376 LeaveCriticalSection(&from_file_mutex);
377 HeapFree(GetProcessHeap(), 0, filename_a);
378 return hr;
379 }
380
381 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
382 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
383 {
384 void *buffer;
385 HRSRC res;
386 DWORD len;
387
388 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
389 module, debugstr_a(resource), defines, include, flags, shader, error_messages);
390
391 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
392 return D3DXERR_INVALIDDATA;
393 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
394 return D3DXERR_INVALIDDATA;
395 return D3DXAssembleShader(buffer, len, defines, include, flags,
396 shader, error_messages);
397 }
398
399 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
400 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
401 {
402 void *buffer;
403 HRSRC res;
404 DWORD len;
405
406 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
407 module, debugstr_w(resource), defines, include, flags, shader, error_messages);
408
409 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
410 return D3DXERR_INVALIDDATA;
411 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
412 return D3DXERR_INVALIDDATA;
413 return D3DXAssembleShader(buffer, len, defines, include, flags,
414 shader, error_messages);
415 }
416
417 HRESULT WINAPI D3DXCompileShader(const char *data, UINT length, const D3DXMACRO *defines,
418 ID3DXInclude *include, const char *function, const char *profile, DWORD flags,
419 ID3DXBuffer **shader, ID3DXBuffer **error_msgs, ID3DXConstantTable **constant_table)
420 {
421 HRESULT hr;
422
423 TRACE("data %s, length %u, defines %p, include %p, function %s, profile %s, "
424 "flags %#x, shader %p, error_msgs %p, constant_table %p.\n",
425 debugstr_a(data), length, defines, include, debugstr_a(function), debugstr_a(profile),
426 flags, shader, error_msgs, constant_table);
427
428 hr = D3DCompile(data, length, NULL, (D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
429 function, profile, flags, 0, (ID3DBlob **)shader, (ID3DBlob **)error_msgs);
430
431 if (SUCCEEDED(hr) && constant_table)
432 {
433 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader), constant_table);
434 if (FAILED(hr))
435 {
436 ID3DXBuffer_Release(*shader);
437 *shader = NULL;
438 }
439 }
440
441 return hr;
442 }
443
444 HRESULT WINAPI D3DXCompileShaderFromFileA(const char *filename, const D3DXMACRO *defines,
445 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
446 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
447 {
448 WCHAR *filename_w;
449 DWORD len;
450 HRESULT ret;
451
452 TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, "
453 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
454 debugstr_a(filename), defines, include, debugstr_a(entrypoint),
455 debugstr_a(profile), flags, shader, error_messages, constant_table);
456
457 if (!filename) return D3DXERR_INVALIDDATA;
458
459 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
460 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
461 if (!filename_w) return E_OUTOFMEMORY;
462 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
463
464 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
465 entrypoint, profile, flags,
466 shader, error_messages, constant_table);
467
468 HeapFree(GetProcessHeap(), 0, filename_w);
469 return ret;
470 }
471
472 HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
473 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
474 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
475 {
476 const void *buffer;
477 DWORD len, filename_len;
478 HRESULT hr;
479 struct D3DXIncludeImpl includefromfile;
480 char *filename_a;
481
482 TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, "
483 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
484 debugstr_w(filename), defines, include, debugstr_a(entrypoint), debugstr_a(profile),
485 flags, shader, error_messages, constant_table);
486
487 if (!include)
488 {
489 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
490 include = &includefromfile.ID3DXInclude_iface;
491 }
492
493 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
494 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
495 if (!filename_a)
496 return E_OUTOFMEMORY;
497 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
498
499 EnterCriticalSection(&from_file_mutex);
500 hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
501 if (FAILED(hr))
502 {
503 LeaveCriticalSection(&from_file_mutex);
504 HeapFree(GetProcessHeap(), 0, filename_a);
505 return D3DXERR_INVALIDDATA;
506 }
507
508 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
509 (ID3DInclude *)include, entrypoint, profile, flags, 0,
510 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
511
512 if (SUCCEEDED(hr) && constant_table)
513 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
514 constant_table);
515
516 ID3DXInclude_Close(include, buffer);
517 LeaveCriticalSection(&from_file_mutex);
518 HeapFree(GetProcessHeap(), 0, filename_a);
519 return hr;
520 }
521
522 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
523 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
524 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
525 {
526 void *buffer;
527 HRSRC res;
528 DWORD len;
529
530 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, "
531 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
532 module, debugstr_a(resource), defines, include, debugstr_a(entrypoint), debugstr_a(profile),
533 flags, shader, error_messages, constant_table);
534
535 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
536 return D3DXERR_INVALIDDATA;
537 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
538 return D3DXERR_INVALIDDATA;
539 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
540 flags, shader, error_messages, constant_table);
541 }
542
543 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
544 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
545 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
546 {
547 void *buffer;
548 HRSRC res;
549 DWORD len;
550
551 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, "
552 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
553 module, debugstr_w(resource), defines, include, debugstr_a(entrypoint), debugstr_a(profile),
554 flags, shader, error_messages, constant_table);
555
556 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
557 return D3DXERR_INVALIDDATA;
558 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
559 return D3DXERR_INVALIDDATA;
560 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
561 flags, shader, error_messages, constant_table);
562 }
563
564 HRESULT WINAPI D3DXPreprocessShader(const char *data, UINT data_len, const D3DXMACRO *defines,
565 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
566 {
567 TRACE("data %s, data_len %u, defines %p, include %p, shader %p, error_messages %p.\n",
568 debugstr_a(data), data_len, defines, include, shader, error_messages);
569
570 return D3DPreprocess(data, data_len, NULL,
571 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
572 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
573 }
574
575 HRESULT WINAPI D3DXPreprocessShaderFromFileA(const char *filename, const D3DXMACRO *defines,
576 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
577 {
578 WCHAR *filename_w = NULL;
579 DWORD len;
580 HRESULT ret;
581
582 TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n",
583 debugstr_a(filename), defines, include, shader, error_messages);
584
585 if (!filename) return D3DXERR_INVALIDDATA;
586
587 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
588 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
589 if (!filename_w) return E_OUTOFMEMORY;
590 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
591
592 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
593
594 HeapFree(GetProcessHeap(), 0, filename_w);
595 return ret;
596 }
597
598 HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
599 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
600 {
601 const void *buffer;
602 DWORD len;
603 HRESULT hr;
604 struct D3DXIncludeImpl includefromfile;
605 char *filename_a;
606
607 TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n",
608 debugstr_w(filename), defines, include, shader, error_messages);
609
610 if (!include)
611 {
612 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
613 include = &includefromfile.ID3DXInclude_iface;
614 }
615
616 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
617 filename_a = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
618 if (!filename_a)
619 return E_OUTOFMEMORY;
620 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
621
622 EnterCriticalSection(&from_file_mutex);
623 hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
624 if (FAILED(hr))
625 {
626 LeaveCriticalSection(&from_file_mutex);
627 HeapFree(GetProcessHeap(), 0, filename_a);
628 return D3DXERR_INVALIDDATA;
629 }
630
631 hr = D3DPreprocess(buffer, len, NULL,
632 (const D3D_SHADER_MACRO *)defines,
633 (ID3DInclude *) include,
634 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
635
636 ID3DXInclude_Close(include, buffer);
637 LeaveCriticalSection(&from_file_mutex);
638 HeapFree(GetProcessHeap(), 0, filename_a);
639 return hr;
640 }
641
642 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
643 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
644 {
645 void *buffer;
646 HRSRC res;
647 DWORD len;
648
649 TRACE("module %p, resource %s, defines %p, include %p, shader %p, error_messages %p.\n",
650 module, debugstr_a(resource), defines, include, shader, error_messages);
651
652 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
653 return D3DXERR_INVALIDDATA;
654 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
655 return D3DXERR_INVALIDDATA;
656 return D3DXPreprocessShader(buffer, len, defines, include,
657 shader, error_messages);
658 }
659
660 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
661 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
662 {
663 void *buffer;
664 HRSRC res;
665 DWORD len;
666
667 TRACE("module %p, resource %s, defines %p, include %p, shader %p, error_messages %p.\n",
668 module, debugstr_w(resource), defines, include, shader, error_messages);
669
670 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
671 return D3DXERR_INVALIDDATA;
672 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
673 return D3DXERR_INVALIDDATA;
674 return D3DXPreprocessShader(buffer, len, defines, include,
675 shader, error_messages);
676
677 }
678
679 struct ctab_constant {
680 D3DXCONSTANT_DESC desc;
681 struct ctab_constant *constants;
682 };
683
684 struct ID3DXConstantTableImpl {
685 ID3DXConstantTable ID3DXConstantTable_iface;
686 LONG ref;
687 char *ctab;
688 DWORD size;
689 D3DXCONSTANTTABLE_DESC desc;
690 struct ctab_constant *constants;
691 };
692
693 static void free_constant(struct ctab_constant *constant)
694 {
695 if (constant->constants)
696 {
697 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
698
699 for (i = 0; i < count; ++i)
700 {
701 free_constant(&constant->constants[i]);
702 }
703 HeapFree(GetProcessHeap(), 0, constant->constants);
704 }
705 }
706
707 static void free_constant_table(struct ID3DXConstantTableImpl *table)
708 {
709 if (table->constants)
710 {
711 UINT i;
712
713 for (i = 0; i < table->desc.Constants; ++i)
714 {
715 free_constant(&table->constants[i]);
716 }
717 HeapFree(GetProcessHeap(), 0, table->constants);
718 }
719 HeapFree(GetProcessHeap(), 0, table->ctab);
720 }
721
722 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
723 {
724 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
725 }
726
727 static inline BOOL is_vertex_shader(DWORD version)
728 {
729 return (version & 0xffff0000) == 0xfffe0000;
730 }
731
732 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant)
733 {
734 return (D3DXHANDLE)constant;
735 }
736
737 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
738 struct ctab_constant *constant, const char *name);
739
740 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, const char *name)
741 {
742 const char *part;
743 UINT element;
744
745 TRACE("constant %p, name %s\n", constant, debugstr_a(name));
746
747 if (!name || !*name) return NULL;
748
749 element = atoi(name);
750 part = strchr(name, ']') + 1;
751
752 if (constant->desc.Elements > element)
753 {
754 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant;
755
756 switch (*part++)
757 {
758 case '.':
759 return get_constant_by_name(NULL, c, part);
760
761 case '[':
762 return get_constant_element_by_name(c, part);
763
764 case '\0':
765 TRACE("Returning parameter %p\n", c);
766 return c;
767
768 default:
769 FIXME("Unhandled case \"%c\"\n", *--part);
770 break;
771 }
772 }
773
774 TRACE("Constant not found\n");
775 return NULL;
776 }
777
778 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
779 struct ctab_constant *constant, const char *name)
780 {
781 UINT i, count, length;
782 struct ctab_constant *handles;
783 const char *part;
784
785 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name));
786
787 if (!name || !*name) return NULL;
788
789 if (!constant)
790 {
791 count = table->desc.Constants;
792 handles = table->constants;
793 }
794 else
795 {
796 count = constant->desc.StructMembers;
797 handles = constant->constants;
798 }
799
800 length = strcspn(name, "[.");
801 part = name + length;
802
803 for (i = 0; i < count; i++)
804 {
805 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length))
806 {
807 switch (*part++)
808 {
809 case '.':
810 return get_constant_by_name(NULL, &handles[i], part);
811
812 case '[':
813 return get_constant_element_by_name(&handles[i], part);
814
815 default:
816 TRACE("Returning parameter %p\n", &handles[i]);
817 return &handles[i];
818 }
819 }
820 }
821
822 TRACE("Constant not found\n");
823 return NULL;
824 }
825
826 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, D3DXHANDLE handle)
827 {
828 struct ctab_constant *c;
829 UINT i, count;
830
831 /* all variable have at least elements = 1, but not always elements */
832 if (!parent->constants) return NULL;
833
834 count = parent->desc.Elements > 1 ? parent->desc.Elements : parent->desc.StructMembers;
835 for (i = 0; i < count; ++i)
836 {
837 if (handle_from_constant(&parent->constants[i]) == handle)
838 return &parent->constants[i];
839
840 c = is_valid_sub_constant(&parent->constants[i], handle);
841 if (c) return c;
842 }
843
844 return NULL;
845 }
846
847 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
848 {
849 struct ctab_constant *c;
850 UINT i;
851
852 if (!handle) return NULL;
853
854 for (i = 0; i < table->desc.Constants; ++i)
855 {
856 if (handle_from_constant(&table->constants[i]) == handle)
857 return &table->constants[i];
858
859 c = is_valid_sub_constant(&table->constants[i], handle);
860 if (c) return c;
861 }
862
863 return get_constant_by_name(table, NULL, handle);
864 }
865
866 /*** IUnknown methods ***/
867 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
868 {
869 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
870
871 if (IsEqualGUID(riid, &IID_IUnknown) ||
872 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
873 IsEqualGUID(riid, &IID_ID3DXConstantTable))
874 {
875 ID3DXConstantTable_AddRef(iface);
876 *out = iface;
877 return S_OK;
878 }
879
880 WARN("Interface %s not found.\n", debugstr_guid(riid));
881
882 return E_NOINTERFACE;
883 }
884
885 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
886 {
887 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
888
889 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
890
891 return InterlockedIncrement(&This->ref);
892 }
893
894 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
895 {
896 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
897 ULONG ref = InterlockedDecrement(&This->ref);
898
899 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
900
901 if (!ref)
902 {
903 free_constant_table(This);
904 HeapFree(GetProcessHeap(), 0, This);
905 }
906
907 return ref;
908 }
909
910 /*** ID3DXBuffer methods ***/
911 static void * WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
912 {
913 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface);
914
915 TRACE("iface %p.\n", iface);
916
917 return table->ctab;
918 }
919
920 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
921 {
922 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
923
924 TRACE("(%p)->()\n", This);
925
926 return This->size;
927 }
928
929 /*** ID3DXConstantTable methods ***/
930 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
931 {
932 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
933
934 TRACE("(%p)->(%p)\n", This, desc);
935
936 if (!desc)
937 return D3DERR_INVALIDCALL;
938
939 *desc = This->desc;
940
941 return D3D_OK;
942 }
943
944 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
945 D3DXCONSTANT_DESC *desc, UINT *count)
946 {
947 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
948 struct ctab_constant *c = get_valid_constant(This, constant);
949
950 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
951
952 if (!c)
953 {
954 WARN("Invalid argument specified\n");
955 return D3DERR_INVALIDCALL;
956 }
957
958 if (desc) *desc = c->desc;
959 if (count) *count = 1;
960
961 return D3D_OK;
962 }
963
964 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
965 {
966 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
967 struct ctab_constant *c = get_valid_constant(This, constant);
968
969 TRACE("(%p)->(%p)\n", This, constant);
970
971 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER)
972 {
973 WARN("Invalid argument specified\n");
974 return (UINT)-1;
975 }
976
977 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex);
978 return c->desc.RegisterIndex;
979 }
980
981 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
982 {
983 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
984 struct ctab_constant *c;
985
986 TRACE("(%p)->(%p, %d)\n", This, constant, index);
987
988 if (constant)
989 {
990 c = get_valid_constant(This, constant);
991 if (c && index < c->desc.StructMembers)
992 {
993 c = &c->constants[index];
994 TRACE("Returning constant %p\n", c);
995 return handle_from_constant(c);
996 }
997 }
998 else
999 {
1000 if (index < This->desc.Constants)
1001 {
1002 c = &This->constants[index];
1003 TRACE("Returning constant %p\n", c);
1004 return handle_from_constant(c);
1005 }
1006 }
1007
1008 WARN("Index out of range\n");
1009 return NULL;
1010 }
1011
1012 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface,
1013 D3DXHANDLE constant, const char *name)
1014 {
1015 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1016 struct ctab_constant *c = get_valid_constant(This, constant);
1017
1018 TRACE("iface %p, constant %p, name %s.\n", iface, constant, debugstr_a(name));
1019
1020 c = get_constant_by_name(This, c, name);
1021 TRACE("Returning constant %p\n", c);
1022
1023 return handle_from_constant(c);
1024 }
1025
1026 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
1027 {
1028 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1029 struct ctab_constant *c = get_valid_constant(This, constant);
1030
1031 TRACE("(%p)->(%p, %d)\n", This, constant, index);
1032
1033 if (c && index < c->desc.Elements)
1034 {
1035 if (c->desc.Elements > 1) c = &c->constants[index];
1036 TRACE("Returning constant %p\n", c);
1037 return handle_from_constant(c);
1038 }
1039
1040 WARN("Invalid argument specified\n");
1041 return NULL;
1042 }
1043
1044 static inline DWORD get_index(const void **indata, UINT index, BOOL is_pointer)
1045 {
1046 if (!indata)
1047 return 0;
1048
1049 if (is_pointer)
1050 return ((DWORD **)indata)[index / 16][index % 16];
1051
1052 return (*((DWORD **)indata))[index];
1053 }
1054
1055 static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant,
1056 const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index,
1057 BOOL is_pointer)
1058 {
1059 D3DXCONSTANT_DESC *desc = &constant->desc;
1060 UINT l, i, regcount = 1, regsize = 1, cin = 1, rin = 1, ret, last = 0;
1061 DWORD tmp;
1062
1063 /* size too small to set anything */
1064 if (*size < desc->Rows * desc->Columns)
1065 {
1066 *size = 0;
1067 return 0;
1068 }
1069
1070 /* D3DXPC_STRUCT is somewhat special */
1071 if (desc->Class == D3DXPC_STRUCT)
1072 {
1073 /*
1074 * Struct array sets the last complete input to the first struct element, all other
1075 * elements are not set.
1076 * E.g.: struct {int i;} s1[2];
1077 * SetValue(device, "s1", [1, 2], 8) => s1 = {2, x};
1078 *
1079 * struct {int i; int n} s2[2];
1080 * SetValue(device, "s2", [1, 2, 3, 4, 5], 20) => s1 = {{3, 4}, {x, x}};
1081 */
1082 if (desc->Elements > 1)
1083 {
1084 UINT offset = *size / (desc->Rows * desc->Columns) - 1;
1085
1086 offset = min(desc->Elements - 1, offset);
1087 last = offset * desc->Rows * desc->Columns;
1088
1089 if ((is_pointer || (!is_pointer && inclass == D3DXPC_MATRIX_ROWS)) && desc->RegisterSet != D3DXRS_BOOL)
1090 {
1091 set(table, device, &constant->constants[0], NULL, intype, size, incol, inclass, 0, is_pointer);
1092 }
1093 else
1094 {
1095 last += set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
1096 index + last, is_pointer);
1097 }
1098 }
1099 else
1100 {
1101 /*
1102 * D3DXRS_BOOL is always set. As there are only 16 bools and there are
1103 * exactly 16 input values, use matrix transpose.
1104 */
1105 if (inclass == D3DXPC_MATRIX_ROWS && desc->RegisterSet == D3DXRS_BOOL)
1106 {
1107 D3DXMATRIX mat, *m, min;
1108 D3DXMatrixTranspose(&mat, &min);
1109
1110 if (is_pointer)
1111 min = *(D3DXMATRIX *)(indata[index / 16]);
1112 else
1113 min = **(D3DXMATRIX **)indata;
1114
1115 D3DXMatrixTranspose(&mat, &min);
1116 m = &mat;
1117 for (i = 0; i < desc->StructMembers; ++i)
1118 {
1119 last += set(table, device, &constant->constants[i], (const void **)&m, intype, size, incol,
1120 D3DXPC_SCALAR, index + last, is_pointer);
1121 }
1122 }
1123 /*
1124 * For pointers or for matrix rows, only the first member is set.
1125 * All other members are set to 0. This is not true for D3DXRS_BOOL.
1126 * E.g.: struct {int i; int n} s;
1127 * SetValue(device, "s", [1, 2], 8) => s = {1, 0};
1128 */
1129 else if ((is_pointer || (!is_pointer && inclass == D3DXPC_MATRIX_ROWS)) && desc->RegisterSet != D3DXRS_BOOL)
1130 {
1131 last = set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
1132 index + last, is_pointer);
1133
1134 for (i = 1; i < desc->StructMembers; ++i)
1135 {
1136 set(table, device, &constant->constants[i], NULL, intype, size, incol, inclass, 0, is_pointer);
1137 }
1138 }
1139 else
1140 {
1141 for (i = 0; i < desc->StructMembers; ++i)
1142 {
1143 last += set(table, device, &constant->constants[i], indata, intype, size, incol, D3DXPC_SCALAR,
1144 index + last, is_pointer);
1145 }
1146 }
1147 }
1148
1149 return last;
1150 }
1151
1152 /* elements */
1153 if (desc->Elements > 1)
1154 {
1155 for (i = 0; i < desc->Elements && *size > 0; ++i)
1156 {
1157 last += set(table, device, &constant->constants[i], indata, intype, size, incol, inclass,
1158 index + last, is_pointer);
1159
1160 /* adjust the vector size for matrix rows */
1161 if (inclass == D3DXPC_MATRIX_ROWS && desc->Class == D3DXPC_VECTOR && (i % 4) == 3)
1162 {
1163 last += 12;
1164 *size = *size < 12 ? 0 : *size - 12;
1165 }
1166 }
1167
1168 return last;
1169 }
1170
1171 switch (desc->Class)
1172 {
1173 case D3DXPC_SCALAR:
1174 case D3DXPC_VECTOR:
1175 case D3DXPC_MATRIX_ROWS:
1176 regcount = min(desc->RegisterCount, desc->Rows);
1177 if (inclass == D3DXPC_MATRIX_ROWS) cin = incol;
1178 else rin = incol;
1179 regsize = desc->Columns;
1180 break;
1181
1182 case D3DXPC_MATRIX_COLUMNS:
1183 regcount = min(desc->RegisterCount, desc->Columns);
1184 if (inclass == D3DXPC_MATRIX_ROWS) rin = incol;
1185 else cin = incol;
1186 regsize = desc->Rows;
1187 break;
1188
1189 default:
1190 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1191 return 0;
1192 }
1193
1194 /* specific stuff for different in types */
1195 switch (inclass)
1196 {
1197 case D3DXPC_SCALAR:
1198 ret = desc->Columns * desc->Rows;
1199 *size -= desc->Columns * desc->Rows;
1200 break;
1201
1202 case D3DXPC_VECTOR:
1203 switch (desc->Class)
1204 {
1205 case D3DXPC_MATRIX_ROWS:
1206 if (*size < regcount * 4)
1207 {
1208 *size = 0;
1209 return 0;
1210 }
1211 ret = 4 * regcount;
1212 *size -= 4 * regcount;
1213 break;
1214
1215 case D3DXPC_MATRIX_COLUMNS:
1216 ret = 4 * regsize;
1217 *size -= 4 * regcount;
1218 break;
1219
1220 case D3DXPC_SCALAR:
1221 ret = 1;
1222 *size -= ret;
1223 break;
1224
1225 case D3DXPC_VECTOR:
1226 ret = 4;
1227 *size -= ret;
1228 break;
1229
1230 default:
1231 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1232 return 0;
1233 }
1234 break;
1235
1236 case D3DXPC_MATRIX_ROWS:
1237 switch (desc->Class)
1238 {
1239 case D3DXPC_MATRIX_ROWS:
1240 case D3DXPC_MATRIX_COLUMNS:
1241 if (*size < 16)
1242 {
1243 *size = 0;
1244 return 0;
1245 }
1246 ret = 16;
1247 break;
1248
1249 case D3DXPC_SCALAR:
1250 ret = 4;
1251 break;
1252
1253 case D3DXPC_VECTOR:
1254 ret = 1;
1255 break;
1256
1257 default:
1258 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1259 return 0;
1260 }
1261 *size -= ret;
1262 break;
1263
1264 case D3DXPC_MATRIX_COLUMNS:
1265 switch (desc->Class)
1266 {
1267 case D3DXPC_MATRIX_ROWS:
1268 case D3DXPC_MATRIX_COLUMNS:
1269 if (*size < 16)
1270 {
1271 *size = 0;
1272 return 0;
1273 }
1274 ret = 16;
1275 break;
1276
1277 case D3DXPC_SCALAR:
1278 ret = 1;
1279 break;
1280
1281 case D3DXPC_VECTOR:
1282 ret = 4;
1283 break;
1284
1285 default:
1286 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1287 return 0;
1288 }
1289 *size -= ret;
1290 break;
1291
1292 default:
1293 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(inclass));
1294 return 0;
1295 }
1296
1297 /* set the registers */
1298 switch (desc->RegisterSet)
1299 {
1300 case D3DXRS_BOOL:
1301 regcount = min(desc->RegisterCount, desc->Columns * desc->Rows);
1302 l = 0;
1303 for (i = 0; i < regcount; ++i)
1304 {
1305 BOOL out;
1306 DWORD t = get_index(indata, index + i / regsize * rin + l * cin, is_pointer);
1307
1308 set_number(&tmp, desc->Type, &t, intype);
1309 set_number(&out, D3DXPT_BOOL, &tmp, desc->Type);
1310 if (is_vertex_shader(table->desc.Version))
1311 IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex + i, &out, 1);
1312 else
1313 IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex + i, &out, 1);
1314
1315 if (++l >= regsize) l = 0;
1316 }
1317 return ret;
1318
1319 case D3DXRS_INT4:
1320 for (i = 0; i < regcount; ++i)
1321 {
1322 INT vec[4] = {0, 0, 1, 0};
1323
1324 for (l = 0; l < regsize; ++l)
1325 {
1326 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer);
1327
1328 set_number(&tmp, desc->Type, &t, intype);
1329 set_number(&vec[l], D3DXPT_INT, &tmp, desc->Type);
1330 }
1331 if (is_vertex_shader(table->desc.Version))
1332 IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex + i, vec, 1);
1333 else
1334 IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex + i, vec, 1);
1335 }
1336 return ret;
1337
1338 case D3DXRS_FLOAT4:
1339 for (i = 0; i < regcount; ++i)
1340 {
1341 FLOAT vec[4] = {0};
1342
1343 for (l = 0; l < regsize; ++l)
1344 {
1345 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer);
1346
1347 set_number(&tmp, desc->Type, &t, intype);
1348 set_number(&vec[l], D3DXPT_FLOAT, &tmp, desc->Type);
1349 }
1350 if (is_vertex_shader(table->desc.Version))
1351 IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex + i, vec, 1);
1352 else
1353 IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex + i, vec, 1);
1354 }
1355 return ret;
1356
1357 default:
1358 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1359 return 0;
1360 }
1361 }
1362
1363 static HRESULT set_scalar(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1364 const void *indata, D3DXPARAMETER_TYPE intype)
1365 {
1366 struct ctab_constant *c = get_valid_constant(table, constant);
1367 UINT count = 1;
1368
1369 if (!c)
1370 {
1371 WARN("Invalid argument specified\n");
1372 return D3DERR_INVALIDCALL;
1373 }
1374
1375 switch (c->desc.Class)
1376 {
1377 case D3DXPC_SCALAR:
1378 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE);
1379 return D3D_OK;
1380
1381 case D3DXPC_VECTOR:
1382 case D3DXPC_MATRIX_ROWS:
1383 case D3DXPC_MATRIX_COLUMNS:
1384 case D3DXPC_STRUCT:
1385 return D3D_OK;
1386
1387 default:
1388 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1389 return D3DERR_INVALIDCALL;
1390 }
1391 }
1392
1393 static HRESULT set_scalar_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1394 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1395 {
1396 struct ctab_constant *c = get_valid_constant(table, constant);
1397
1398 if (!c)
1399 {
1400 WARN("Invalid argument specified\n");
1401 return D3DERR_INVALIDCALL;
1402 }
1403
1404 switch (c->desc.Class)
1405 {
1406 case D3DXPC_SCALAR:
1407 case D3DXPC_VECTOR:
1408 case D3DXPC_MATRIX_ROWS:
1409 case D3DXPC_MATRIX_COLUMNS:
1410 case D3DXPC_STRUCT:
1411 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE);
1412 return D3D_OK;
1413
1414 default:
1415 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1416 return D3DERR_INVALIDCALL;
1417 }
1418 }
1419
1420 static HRESULT set_vector(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1421 const void *indata, D3DXPARAMETER_TYPE intype)
1422 {
1423 struct ctab_constant *c = get_valid_constant(table, constant);
1424 UINT count = 4;
1425
1426 if (!c)
1427 {
1428 WARN("Invalid argument specified\n");
1429 return D3DERR_INVALIDCALL;
1430 }
1431
1432 switch (c->desc.Class)
1433 {
1434 case D3DXPC_SCALAR:
1435 case D3DXPC_VECTOR:
1436 case D3DXPC_STRUCT:
1437 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE);
1438 return D3D_OK;
1439
1440 case D3DXPC_MATRIX_ROWS:
1441 case D3DXPC_MATRIX_COLUMNS:
1442 return D3D_OK;
1443
1444 default:
1445 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1446 return D3DERR_INVALIDCALL;
1447 }
1448 }
1449
1450 static HRESULT set_vector_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1451 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1452 {
1453 struct ctab_constant *c = get_valid_constant(table, constant);
1454
1455 if (!c)
1456 {
1457 WARN("Invalid argument specified\n");
1458 return D3DERR_INVALIDCALL;
1459 }
1460
1461 switch (c->desc.Class)
1462 {
1463 case D3DXPC_SCALAR:
1464 case D3DXPC_VECTOR:
1465 case D3DXPC_MATRIX_ROWS:
1466 case D3DXPC_MATRIX_COLUMNS:
1467 case D3DXPC_STRUCT:
1468 count *= 4;
1469 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE);
1470 return D3D_OK;
1471
1472 default:
1473 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1474 return D3DERR_INVALIDCALL;
1475 }
1476 }
1477
1478 static HRESULT set_matrix_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1479 const void *indata, UINT count, BOOL transpose)
1480 {
1481 struct ctab_constant *c = get_valid_constant(table, constant);
1482
1483 if (!c)
1484 {
1485 WARN("Invalid argument specified\n");
1486 return D3DERR_INVALIDCALL;
1487 }
1488
1489 switch (c->desc.Class)
1490 {
1491 case D3DXPC_SCALAR:
1492 case D3DXPC_VECTOR:
1493 case D3DXPC_MATRIX_ROWS:
1494 case D3DXPC_MATRIX_COLUMNS:
1495 case D3DXPC_STRUCT:
1496 count *= 16;
1497 set(table, device, c, &indata, D3DXPT_FLOAT, &count, 4,
1498 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, FALSE);
1499 return D3D_OK;
1500
1501 default:
1502 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1503 return D3DERR_INVALIDCALL;
1504 }
1505 }
1506
1507 static HRESULT set_matrix_pointer_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device,
1508 D3DXHANDLE constant, const void **indata, UINT count, BOOL transpose)
1509 {
1510 struct ctab_constant *c = get_valid_constant(table, constant);
1511
1512 if (!c)
1513 {
1514 WARN("Invalid argument specified\n");
1515 return D3DERR_INVALIDCALL;
1516 }
1517
1518 switch (c->desc.Class)
1519 {
1520 case D3DXPC_SCALAR:
1521 case D3DXPC_VECTOR:
1522 case D3DXPC_MATRIX_ROWS:
1523 case D3DXPC_MATRIX_COLUMNS:
1524 case D3DXPC_STRUCT:
1525 count *= 16;
1526 set(table, device, c, indata, D3DXPT_FLOAT, &count, 4,
1527 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, TRUE);
1528 return D3D_OK;
1529
1530 default:
1531 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1532 return D3DERR_INVALIDCALL;
1533 }
1534 }
1535
1536 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1537 struct IDirect3DDevice9 *device)
1538 {
1539 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1540 UINT i;
1541
1542 TRACE("iface %p, device %p\n", iface, device);
1543
1544 if (!device)
1545 {
1546 WARN("Invalid argument specified\n");
1547 return D3DERR_INVALIDCALL;
1548 }
1549
1550 for (i = 0; i < This->desc.Constants; i++)
1551 {
1552 D3DXCONSTANT_DESC *desc = &This->constants[i].desc;
1553 HRESULT hr;
1554
1555 if (!desc->DefaultValue)
1556 continue;
1557
1558 switch (desc->RegisterSet)
1559 {
1560 case D3DXRS_BOOL:
1561 if (is_vertex_shader(This->desc.Version))
1562 hr = IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue,
1563 desc->RegisterCount);
1564 else
1565 hr = IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue,
1566 desc->RegisterCount);
1567 break;
1568
1569 case D3DXRS_INT4:
1570 if (is_vertex_shader(This->desc.Version))
1571 hr = IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue,
1572 desc->RegisterCount);
1573 else
1574 hr = IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue,
1575 desc->RegisterCount);
1576 break;
1577
1578 case D3DXRS_FLOAT4:
1579 if (is_vertex_shader(This->desc.Version))
1580 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue,
1581 desc->RegisterCount);
1582 else
1583 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue,
1584 desc->RegisterCount);
1585 break;
1586
1587 default:
1588 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1589 hr = E_NOTIMPL;
1590 break;
1591 }
1592
1593 if (hr != D3D_OK)
1594 return hr;
1595 }
1596
1597 return D3D_OK;
1598 }
1599
1600 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1601 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, unsigned int bytes)
1602 {
1603 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface);
1604 struct ctab_constant *c = get_valid_constant(table, constant);
1605 D3DXCONSTANT_DESC *desc;
1606
1607 TRACE("iface %p, device %p, constant %p, data %p, bytes %u\n", iface, device, constant, data, bytes);
1608
1609 if (!device || !c || !data)
1610 {
1611 WARN("Invalid argument specified\n");
1612 return D3DERR_INVALIDCALL;
1613 }
1614
1615 desc = &c->desc;
1616
1617 switch (desc->Class)
1618 {
1619 case D3DXPC_SCALAR:
1620 case D3DXPC_VECTOR:
1621 case D3DXPC_MATRIX_ROWS:
1622 case D3DXPC_MATRIX_COLUMNS:
1623 case D3DXPC_STRUCT:
1624 bytes /= 4;
1625 set(table, device, c, &data, desc->Type, &bytes, desc->Columns, D3DXPC_SCALAR, 0, FALSE);
1626 return D3D_OK;
1627
1628 default:
1629 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc->Class));
1630 return D3DERR_INVALIDCALL;
1631 }
1632 }
1633
1634 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1635 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1636 {
1637 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1638
1639 TRACE("iface %p, device %p, constant %p, b %d\n", iface, device, constant, b);
1640
1641 return set_scalar(This, device, constant, &b, D3DXPT_BOOL);
1642 }
1643
1644 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1645 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1646 {
1647 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1648
1649 TRACE("iface %p, device %p, constant %p, b %p, count %d\n", iface, device, constant, b, count);
1650
1651 return set_scalar_array(This, device, constant, b, count, D3DXPT_BOOL);
1652 }
1653
1654 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1655 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1656 {
1657 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1658
1659 TRACE("iface %p, device %p, constant %p, n %d\n", iface, device, constant, n);
1660
1661 return set_scalar(This, device, constant, &n, D3DXPT_INT);
1662 }
1663
1664 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1665 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1666 {
1667 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1668
1669 TRACE("iface %p, device %p, constant %p, n %p, count %d\n", iface, device, constant, n, count);
1670
1671 return set_scalar_array(This, device, constant, n, count, D3DXPT_INT);
1672 }
1673
1674 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1675 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1676 {
1677 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1678
1679 TRACE("iface %p, device %p, constant %p, f %f\n", iface, device, constant, f);
1680
1681 return set_scalar(This, device, constant, &f, D3DXPT_FLOAT);
1682 }
1683
1684 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1685 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1686 {
1687 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1688
1689 TRACE("iface %p, device %p, constant %p, f %p, count %d\n", iface, device, constant, f, count);
1690
1691 return set_scalar_array(This, device, constant, f, count, D3DXPT_FLOAT);
1692 }
1693
1694 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1695 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1696 {
1697 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1698
1699 TRACE("iface %p, device %p, constant %p, vector %p\n", iface, device, constant, vector);
1700
1701 return set_vector(This, device, constant, vector, D3DXPT_FLOAT);
1702 }
1703
1704 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1705 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1706 {
1707 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1708
1709 TRACE("iface %p, device %p, constant %p, vector %p, count %u\n", iface, device, constant, vector, count);
1710
1711 return set_vector_array(This, device, constant, vector, count, D3DXPT_FLOAT);
1712 }
1713
1714 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1715 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1716 {
1717 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1718
1719 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1720
1721 return set_matrix_array(This, device, constant, matrix, 1, FALSE);
1722 }
1723
1724 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1725 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1726 {
1727 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1728
1729 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1730
1731 return set_matrix_array(This, device, constant, matrix, count, FALSE);
1732 }
1733
1734 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1735 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1736 {
1737 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1738
1739 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count);
1740
1741 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, FALSE);
1742 }
1743
1744 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1745 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1746 {
1747 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1748
1749 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1750
1751 return set_matrix_array(This, device, constant, matrix, 1, TRUE);
1752 }
1753
1754 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1755 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1756 {
1757 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1758
1759 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1760
1761 return set_matrix_array(This, device, constant, matrix, count, TRUE);
1762 }
1763
1764 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface,
1765 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1766 {
1767 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1768
1769 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count);
1770
1771 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, TRUE);
1772 }
1773
1774 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1775 {
1776 /*** IUnknown methods ***/
1777 ID3DXConstantTableImpl_QueryInterface,
1778 ID3DXConstantTableImpl_AddRef,
1779 ID3DXConstantTableImpl_Release,
1780 /*** ID3DXBuffer methods ***/
1781 ID3DXConstantTableImpl_GetBufferPointer,
1782 ID3DXConstantTableImpl_GetBufferSize,
1783 /*** ID3DXConstantTable methods ***/
1784 ID3DXConstantTableImpl_GetDesc,
1785 ID3DXConstantTableImpl_GetConstantDesc,
1786 ID3DXConstantTableImpl_GetSamplerIndex,
1787 ID3DXConstantTableImpl_GetConstant,
1788 ID3DXConstantTableImpl_GetConstantByName,
1789 ID3DXConstantTableImpl_GetConstantElement,
1790 ID3DXConstantTableImpl_SetDefaults,
1791 ID3DXConstantTableImpl_SetValue,
1792 ID3DXConstantTableImpl_SetBool,
1793 ID3DXConstantTableImpl_SetBoolArray,
1794 ID3DXConstantTableImpl_SetInt,
1795 ID3DXConstantTableImpl_SetIntArray,
1796 ID3DXConstantTableImpl_SetFloat,
1797 ID3DXConstantTableImpl_SetFloatArray,
1798 ID3DXConstantTableImpl_SetVector,
1799 ID3DXConstantTableImpl_SetVectorArray,
1800 ID3DXConstantTableImpl_SetMatrix,
1801 ID3DXConstantTableImpl_SetMatrixArray,
1802 ID3DXConstantTableImpl_SetMatrixPointerArray,
1803 ID3DXConstantTableImpl_SetMatrixTranspose,
1804 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1805 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1806 };
1807
1808 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
1809 BOOL is_element, WORD index, WORD max_index, DWORD *offset, DWORD nameoffset, UINT regset)
1810 {
1811 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
1812 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
1813 HRESULT hr = D3D_OK;
1814 UINT i, count = 0;
1815 WORD size = 0;
1816
1817 constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
1818 constant->desc.Class = type->Class;
1819 constant->desc.Type = type->Type;
1820 constant->desc.Rows = type->Rows;
1821 constant->desc.Columns = type->Columns;
1822 constant->desc.Elements = is_element ? 1 : type->Elements;
1823 constant->desc.StructMembers = type->StructMembers;
1824 constant->desc.Name = ctab + nameoffset;
1825 constant->desc.RegisterSet = regset;
1826 constant->desc.RegisterIndex = index;
1827
1828 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name,
1829 constant->desc.Elements, index, constant->desc.DefaultValue,
1830 debug_d3dxparameter_registerset(regset));
1831 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1832 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type),
1833 type->Rows, type->Columns, type->Elements, type->StructMembers);
1834
1835 if (type->Elements > 1 && !is_element)
1836 {
1837 count = type->Elements;
1838 }
1839 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
1840 {
1841 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
1842 count = type->StructMembers;
1843 }
1844
1845 if (count)
1846 {
1847 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
1848 if (!constant->constants)
1849 {
1850 ERR("Out of memory\n");
1851 hr = E_OUTOFMEMORY;
1852 goto error;
1853 }
1854
1855 for (i = 0; i < count; ++i)
1856 {
1857 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
1858 &constant->constants[i], memberinfo == NULL, index + size, max_index, offset,
1859 memberinfo ? memberinfo[i].Name : nameoffset, regset);
1860 if (hr != D3D_OK)
1861 goto error;
1862
1863 size += constant->constants[i].desc.RegisterCount;
1864 }
1865 }
1866 else
1867 {
1868 WORD offsetdiff = type->Columns * type->Rows;
1869 BOOL fail = FALSE;
1870
1871 size = type->Columns * type->Rows;
1872
1873 switch (regset)
1874 {
1875 case D3DXRS_BOOL:
1876 fail = type->Class != D3DXPC_SCALAR && type->Class != D3DXPC_VECTOR
1877 && type->Class != D3DXPC_MATRIX_ROWS && type->Class != D3DXPC_MATRIX_COLUMNS;
1878 break;
1879
1880 case D3DXRS_FLOAT4:
1881 case D3DXRS_INT4:
1882 switch (type->Class)
1883 {
1884 case D3DXPC_VECTOR:
1885 size = 1;
1886 /* fall through */
1887 case D3DXPC_SCALAR:
1888 offsetdiff = type->Rows * 4;
1889 break;
1890
1891 case D3DXPC_MATRIX_ROWS:
1892 offsetdiff = type->Rows * 4;
1893 size = type->Rows;
1894 break;
1895
1896 case D3DXPC_MATRIX_COLUMNS:
1897 offsetdiff = type->Columns * 4;
1898 size = type->Columns;
1899 break;
1900
1901 default:
1902 fail = TRUE;
1903 break;
1904 }
1905 break;
1906
1907 case D3DXRS_SAMPLER:
1908 size = 1;
1909 fail = type->Class != D3DXPC_OBJECT;
1910 break;
1911
1912 default:
1913 fail = TRUE;
1914 break;
1915 }
1916
1917 if (fail)
1918 {
1919 FIXME("Unhandled register set %s, type class %s\n", debug_d3dxparameter_registerset(regset),
1920 debug_d3dxparameter_class(type->Class));
1921 }
1922
1923 /* offset in bytes => offsetdiff * sizeof(DWORD) */
1924 if (offset) *offset += offsetdiff * 4;
1925 }
1926
1927 constant->desc.RegisterCount = max(0, min(max_index - index, size));
1928 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns;
1929
1930 return D3D_OK;
1931
1932 error:
1933 if (constant->constants)
1934 {
1935 for (i = 0; i < count; ++i)
1936 {
1937 free_constant(&constant->constants[i]);
1938 }
1939 HeapFree(GetProcessHeap(), 0, constant->constants);
1940 constant->constants = NULL;
1941 }
1942
1943 return hr;
1944 }
1945
1946 HRESULT WINAPI D3DXGetShaderConstantTableEx(const DWORD *byte_code, DWORD flags, ID3DXConstantTable **constant_table)
1947 {
1948 struct ID3DXConstantTableImpl *object = NULL;
1949 const void *data;
1950 HRESULT hr;
1951 UINT size;
1952 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1953 const D3DXSHADER_CONSTANTINFO *constant_info;
1954 DWORD i;
1955
1956 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code, flags, constant_table);
1957
1958 if (constant_table) *constant_table = NULL;
1959
1960 if (!byte_code || !constant_table)
1961 {
1962 WARN("Invalid argument specified.\n");
1963 return D3DERR_INVALIDCALL;
1964 }
1965
1966 if (!is_valid_bytecode(*byte_code))
1967 {
1968 WARN("Invalid byte_code specified.\n");
1969 return D3D_OK;
1970 }
1971
1972 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags);
1973
1974 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1975 if (hr != D3D_OK)
1976 {
1977 WARN("CTAB not found.\n");
1978 return D3DXERR_INVALIDDATA;
1979 }
1980
1981 if (size < sizeof(*ctab_header))
1982 {
1983 WARN("Invalid CTAB size.\n");
1984 return D3DXERR_INVALIDDATA;
1985 }
1986
1987 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1988 if (ctab_header->Size != sizeof(*ctab_header))
1989 {
1990 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1991 return D3DXERR_INVALIDDATA;
1992 }
1993
1994 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1995 if (!object)
1996 return E_OUTOFMEMORY;
1997
1998 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1999 object->ref = 1;
2000
2001 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
2002 if (!object->ctab)
2003 {
2004 ERR("Out of memory\n");
2005 HeapFree(GetProcessHeap(), 0, object);
2006 return E_OUTOFMEMORY;
2007 }
2008 object->size = size;
2009 memcpy(object->ctab, data, object->size);
2010
2011 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
2012 object->desc.Version = ctab_header->Version;
2013 object->desc.Constants = ctab_header->Constants;
2014 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
2015 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
2016 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
2017
2018 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2019 sizeof(*object->constants) * object->desc.Constants);
2020 if (!object->constants)
2021 {
2022 ERR("Out of memory\n");
2023 hr = E_OUTOFMEMORY;
2024 goto error;
2025 }
2026
2027 constant_info = (const D3DXSHADER_CONSTANTINFO *)(object->ctab + ctab_header->ConstantInfo);
2028 for (i = 0; i < ctab_header->Constants; i++)
2029 {
2030 DWORD offset = constant_info[i].DefaultValue;
2031
2032 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
2033 &object->constants[i], FALSE, constant_info[i].RegisterIndex,
2034 constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
2035 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
2036 if (hr != D3D_OK)
2037 goto error;
2038
2039 /*
2040 * Set the register count, it may differ for D3DXRS_INT4, because somehow
2041 * it makes the assumption that the register size is 1 instead of 4, so the
2042 * count is 4 times bigger. This holds true only for toplevel shader
2043 * constants. The count of elements and members is always based on a
2044 * register size of 4.
2045 */
2046 if (object->constants[i].desc.RegisterSet == D3DXRS_INT4)
2047 {
2048 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
2049 }
2050 }
2051
2052 *constant_table = &object->ID3DXConstantTable_iface;
2053
2054 return D3D_OK;
2055
2056 error:
2057 free_constant_table(object);
2058 HeapFree(GetProcessHeap(), 0, object);
2059
2060 return hr;
2061 }
2062
2063 HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantTable **constant_table)
2064 {
2065 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
2066
2067 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
2068 }
2069
2070 HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count)
2071 {
2072 UINT i, sampler_count = 0;
2073 UINT size;
2074 const char *data;
2075 const D3DXSHADER_CONSTANTTABLE *ctab_header;
2076 const D3DXSHADER_CONSTANTINFO *constant_info;
2077
2078 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
2079
2080 if (count) *count = 0;
2081
2082 if (D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (const void **)&data, &size) != D3D_OK)
2083 return D3D_OK;
2084
2085 if (size < sizeof(*ctab_header)) return D3D_OK;
2086
2087 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
2088 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
2089
2090 constant_info = (const D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
2091 for (i = 0; i < ctab_header->Constants; i++)
2092 {
2093 const D3DXSHADER_TYPEINFO *type;
2094
2095 TRACE("name = %s\n", data + constant_info[i].Name);
2096
2097 type = (const D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
2098
2099 if (type->Type == D3DXPT_SAMPLER
2100 || type->Type == D3DXPT_SAMPLER1D
2101 || type->Type == D3DXPT_SAMPLER2D
2102 || type->Type == D3DXPT_SAMPLER3D
2103 || type->Type == D3DXPT_SAMPLERCUBE)
2104 {
2105 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
2106
2107 ++sampler_count;
2108 }
2109 }
2110
2111 TRACE("Found %u samplers\n", sampler_count);
2112
2113 if (count) *count = sampler_count;
2114
2115 return D3D_OK;
2116 }