makedep: Add support for specifying an object directory different from the current...
[wine.git] / dlls / d3dx9_36 / shader.c
blob68e747432427e080dd865541fad7dc34caa62912
1 /*
2 * Copyright 2008 Luis Busquets
3 * Copyright 2009 Matteo Bruni
4 * Copyright 2011 Travis Athougies
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
28 #include "windef.h"
29 #include "wingdi.h"
30 #include "objbase.h"
31 #include "d3dcommon.h"
32 #include "d3dcompiler.h"
33 #include "d3dx9_36_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
37 /* This function is not declared in the SDK headers yet. */
38 HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename,
39 const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags,
40 ID3DBlob **shader, ID3DBlob **error_messages);
42 static inline BOOL is_valid_bytecode(DWORD token)
44 return (token & 0xfffe0000) == 0xfffe0000;
47 const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device)
49 D3DCAPS9 caps;
51 TRACE("device %p\n", device);
53 if (!device) return NULL;
55 IDirect3DDevice9_GetDeviceCaps(device,&caps);
57 switch (caps.PixelShaderVersion)
59 case D3DPS_VERSION(1, 1):
60 return "ps_1_1";
62 case D3DPS_VERSION(1, 2):
63 return "ps_1_2";
65 case D3DPS_VERSION(1, 3):
66 return "ps_1_3";
68 case D3DPS_VERSION(1, 4):
69 return "ps_1_4";
71 case D3DPS_VERSION(2, 0):
72 if ((caps.PS20Caps.NumTemps>=22) &&
73 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) &&
74 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
75 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) &&
76 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
77 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
79 return "ps_2_a";
81 if ((caps.PS20Caps.NumTemps>=32) &&
82 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
84 return "ps_2_b";
86 return "ps_2_0";
88 case D3DPS_VERSION(3, 0):
89 return "ps_3_0";
92 return NULL;
95 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
97 const DWORD *ptr = byte_code;
99 TRACE("byte_code %p\n", byte_code);
101 if (!ptr) return 0;
103 /* Look for the END token, skipping the VERSION token */
104 while (*++ptr != D3DSIO_END)
106 /* Skip comments */
107 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
109 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
112 ++ptr;
114 /* Return the shader size in bytes */
115 return (ptr - byte_code) * sizeof(*ptr);
118 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
120 TRACE("byte_code %p\n", byte_code);
122 return byte_code ? *byte_code : 0;
125 const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device)
127 D3DCAPS9 caps;
129 TRACE("device %p\n", device);
131 if (!device) return NULL;
133 IDirect3DDevice9_GetDeviceCaps(device,&caps);
135 switch (caps.VertexShaderVersion)
137 case D3DVS_VERSION(1, 1):
138 return "vs_1_1";
139 case D3DVS_VERSION(2, 0):
140 if ((caps.VS20Caps.NumTemps>=13) &&
141 (caps.VS20Caps.DynamicFlowControlDepth==24) &&
142 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
144 return "vs_2_a";
146 return "vs_2_0";
147 case D3DVS_VERSION(3, 0):
148 return "vs_3_0";
151 return NULL;
154 HRESULT WINAPI D3DXFindShaderComment(const DWORD *byte_code, DWORD fourcc, const void **data, UINT *size)
156 const DWORD *ptr = byte_code;
157 DWORD version;
159 TRACE("byte_code %p, fourcc %x, data %p, size %p\n", byte_code, fourcc, data, size);
161 if (data) *data = NULL;
162 if (size) *size = 0;
164 if (!byte_code) return D3DERR_INVALIDCALL;
166 version = *ptr >> 16;
167 if (version != 0x4658 /* FX */
168 && version != 0x5458 /* TX */
169 && version != 0x7ffe
170 && version != 0x7fff
171 && version != 0xfffe /* VS */
172 && version != 0xffff) /* PS */
174 WARN("Invalid data supplied\n");
175 return D3DXERR_INVALIDDATA;
178 while (*++ptr != D3DSIO_END)
180 /* Check if it is a comment */
181 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
183 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
185 /* Check if this is the comment we are looking for */
186 if (*(ptr + 1) == fourcc)
188 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
189 const void *ctab_data = ptr + 2;
190 if (size)
191 *size = ctab_size;
192 if (data)
193 *data = ctab_data;
194 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
195 return D3D_OK;
197 ptr += comment_size;
201 return S_FALSE;
204 HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMACRO *defines,
205 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
207 HRESULT hr;
209 TRACE("data %p, data_len %u, defines %p, include %p, flags %#x, shader %p, error_messages %p\n",
210 data, data_len, defines, include, flags, shader, error_messages);
212 /* Forward to d3dcompiler: the parameter types aren't really different,
213 the actual data types are equivalent */
214 hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
215 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
216 (ID3DBlob **)error_messages);
218 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
219 return hr;
222 /* D3DXInclude private implementation, used to implement
223 * D3DXAssembleShaderFromFile() from D3DXAssembleShader(). */
224 /* To be able to correctly resolve include search paths we have to store the
225 * pathname of each include file. We store the pathname pointer right before
226 * the file data. */
227 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type,
228 const char *filename, const void *parent_data, const void **data, UINT *bytes)
230 const char *p, *parent_name = "";
231 char *pathname = NULL;
232 char **buffer = NULL;
233 HANDLE file;
234 UINT size;
236 if(parent_data != NULL)
237 parent_name = *((const char **)parent_data - 1);
239 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
241 if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
242 else p = parent_name;
243 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
244 if(!pathname)
245 return HRESULT_FROM_WIN32(GetLastError());
247 memcpy(pathname, parent_name, p - parent_name);
248 strcpy(pathname + (p - parent_name), filename);
250 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
251 if(file == INVALID_HANDLE_VALUE)
252 goto error;
254 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
256 size = GetFileSize(file, NULL);
257 if(size == INVALID_FILE_SIZE)
258 goto error;
260 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
261 if(!buffer)
262 goto error;
263 *buffer = pathname;
264 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
265 goto error;
267 *data = buffer + 1;
269 CloseHandle(file);
270 return S_OK;
272 error:
273 CloseHandle(file);
274 HeapFree(GetProcessHeap(), 0, pathname);
275 HeapFree(GetProcessHeap(), 0, buffer);
276 return HRESULT_FROM_WIN32(GetLastError());
279 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, const void *data)
281 HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
282 HeapFree(GetProcessHeap(), 0, (char **)data - 1);
283 return S_OK;
286 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
287 d3dincludefromfile_open,
288 d3dincludefromfile_close
291 struct D3DXIncludeImpl {
292 ID3DXInclude ID3DXInclude_iface;
295 HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines,
296 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
298 WCHAR *filename_w;
299 DWORD len;
300 HRESULT ret;
302 TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
303 debugstr_a(filename), defines, include, flags, shader, error_messages);
305 if (!filename) return D3DXERR_INVALIDDATA;
307 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
308 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
309 if (!filename_w) return E_OUTOFMEMORY;
310 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
312 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
314 HeapFree(GetProcessHeap(), 0, filename_w);
315 return ret;
318 HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
319 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
321 const void *buffer;
322 DWORD len;
323 HRESULT hr;
324 struct D3DXIncludeImpl includefromfile;
325 char *filename_a;
327 TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
328 debugstr_w(filename), defines, include, flags, shader, error_messages);
330 if(!include)
332 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
333 include = &includefromfile.ID3DXInclude_iface;
336 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
337 filename_a = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
338 if (!filename_a)
339 return E_OUTOFMEMORY;
340 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
342 hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
343 if (FAILED(hr))
345 HeapFree(GetProcessHeap(), 0, filename_a);
346 return D3DXERR_INVALIDDATA;
349 hr = D3DXAssembleShader(buffer, len, defines, include, flags, shader, error_messages);
351 ID3DXInclude_Close(include, buffer);
352 HeapFree(GetProcessHeap(), 0, filename_a);
353 return hr;
356 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
357 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
359 void *buffer;
360 HRSRC res;
361 DWORD len;
363 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
364 module, debugstr_a(resource), defines, include, flags, shader, error_messages);
366 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
367 return D3DXERR_INVALIDDATA;
368 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
369 return D3DXERR_INVALIDDATA;
370 return D3DXAssembleShader(buffer, len, defines, include, flags,
371 shader, error_messages);
374 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
375 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
377 void *buffer;
378 HRSRC res;
379 DWORD len;
381 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
382 module, debugstr_w(resource), defines, include, flags, shader, error_messages);
384 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
385 return D3DXERR_INVALIDDATA;
386 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
387 return D3DXERR_INVALIDDATA;
388 return D3DXAssembleShader(buffer, len, defines, include, flags,
389 shader, error_messages);
392 HRESULT WINAPI D3DXCompileShader(const char *data, UINT length, const D3DXMACRO *defines,
393 ID3DXInclude *include, const char *function, const char *profile, DWORD flags,
394 ID3DXBuffer **shader, ID3DXBuffer **error_msgs, ID3DXConstantTable **constant_table)
396 HRESULT hr;
398 TRACE("data %s, length %u, defines %p, include %p, function %s, profile %s, "
399 "flags %#x, shader %p, error_msgs %p, constant_table %p.\n",
400 debugstr_a(data), length, defines, include, debugstr_a(function), debugstr_a(profile),
401 flags, shader, error_msgs, constant_table);
403 hr = D3DCompile(data, length, NULL, (D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
404 function, profile, flags, 0, (ID3DBlob **)shader, (ID3DBlob **)error_msgs);
406 if (SUCCEEDED(hr) && constant_table)
408 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader), constant_table);
409 if (FAILED(hr))
411 ID3DXBuffer_Release(*shader);
412 *shader = NULL;
416 return hr;
419 HRESULT WINAPI D3DXCompileShaderFromFileA(const char *filename, const D3DXMACRO *defines,
420 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
421 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
423 WCHAR *filename_w;
424 DWORD len;
425 HRESULT ret;
427 TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, "
428 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
429 debugstr_a(filename), defines, include, debugstr_a(entrypoint),
430 debugstr_a(profile), flags, shader, error_messages, constant_table);
432 if (!filename) return D3DXERR_INVALIDDATA;
434 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
435 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
436 if (!filename_w) return E_OUTOFMEMORY;
437 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
439 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
440 entrypoint, profile, flags,
441 shader, error_messages, constant_table);
443 HeapFree(GetProcessHeap(), 0, filename_w);
444 return ret;
447 HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
448 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
449 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
451 const void *buffer;
452 DWORD len, filename_len;
453 HRESULT hr;
454 struct D3DXIncludeImpl includefromfile;
455 char *filename_a;
457 TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, "
458 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
459 debugstr_w(filename), defines, include, debugstr_a(entrypoint), debugstr_a(profile),
460 flags, shader, error_messages, constant_table);
462 if (!include)
464 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
465 include = &includefromfile.ID3DXInclude_iface;
468 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
469 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
470 if (!filename_a)
471 return E_OUTOFMEMORY;
472 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
474 hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
475 if (FAILED(hr))
477 HeapFree(GetProcessHeap(), 0, filename_a);
478 return D3DXERR_INVALIDDATA;
481 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
482 (ID3DInclude *)include, entrypoint, profile, flags, 0,
483 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
485 if (SUCCEEDED(hr) && constant_table)
486 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
487 constant_table);
489 ID3DXInclude_Close(include, buffer);
490 HeapFree(GetProcessHeap(), 0, filename_a);
491 return hr;
494 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
495 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
496 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
498 void *buffer;
499 HRSRC res;
500 DWORD len;
502 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, "
503 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
504 module, debugstr_a(resource), defines, include, debugstr_a(entrypoint), debugstr_a(profile),
505 flags, shader, error_messages, constant_table);
507 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
508 return D3DXERR_INVALIDDATA;
509 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
510 return D3DXERR_INVALIDDATA;
511 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
512 flags, shader, error_messages, constant_table);
515 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
516 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
517 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
519 void *buffer;
520 HRSRC res;
521 DWORD len;
523 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, "
524 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
525 module, debugstr_w(resource), defines, include, debugstr_a(entrypoint), debugstr_a(profile),
526 flags, shader, error_messages, constant_table);
528 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
529 return D3DXERR_INVALIDDATA;
530 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
531 return D3DXERR_INVALIDDATA;
532 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
533 flags, shader, error_messages, constant_table);
536 HRESULT WINAPI D3DXPreprocessShader(const char *data, UINT data_len, const D3DXMACRO *defines,
537 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
539 TRACE("data %s, data_len %u, defines %p, include %p, shader %p, error_messages %p.\n",
540 debugstr_a(data), data_len, defines, include, shader, error_messages);
542 return D3DPreprocess(data, data_len, NULL,
543 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
544 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
547 HRESULT WINAPI D3DXPreprocessShaderFromFileA(const char *filename, const D3DXMACRO *defines,
548 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
550 WCHAR *filename_w = NULL;
551 DWORD len;
552 HRESULT ret;
554 TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n",
555 debugstr_a(filename), defines, include, shader, error_messages);
557 if (!filename) return D3DXERR_INVALIDDATA;
559 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
560 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
561 if (!filename_w) return E_OUTOFMEMORY;
562 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
564 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
566 HeapFree(GetProcessHeap(), 0, filename_w);
567 return ret;
570 HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
571 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
573 const void *buffer;
574 DWORD len;
575 HRESULT hr;
576 struct D3DXIncludeImpl includefromfile;
577 char *filename_a;
579 TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n",
580 debugstr_w(filename), defines, include, shader, error_messages);
582 if (!include)
584 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
585 include = &includefromfile.ID3DXInclude_iface;
588 len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
589 filename_a = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
590 if (!filename_a)
591 return E_OUTOFMEMORY;
592 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL);
594 hr = ID3DXInclude_Open(include, D3D_INCLUDE_LOCAL, filename_a, NULL, &buffer, &len);
595 if (FAILED(hr))
597 HeapFree(GetProcessHeap(), 0, filename_a);
598 return D3DXERR_INVALIDDATA;
601 hr = D3DPreprocess(buffer, len, NULL,
602 (const D3D_SHADER_MACRO *)defines,
603 (ID3DInclude *) include,
604 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
606 ID3DXInclude_Close(include, buffer);
607 HeapFree(GetProcessHeap(), 0, filename_a);
608 return hr;
611 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
612 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
614 void *buffer;
615 HRSRC res;
616 DWORD len;
618 TRACE("module %p, resource %s, defines %p, include %p, shader %p, error_messages %p.\n",
619 module, debugstr_a(resource), defines, include, shader, error_messages);
621 if (!(res = FindResourceA(module, resource, (const char *)RT_RCDATA)))
622 return D3DXERR_INVALIDDATA;
623 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
624 return D3DXERR_INVALIDDATA;
625 return D3DXPreprocessShader(buffer, len, defines, include,
626 shader, error_messages);
629 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
630 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
632 void *buffer;
633 HRSRC res;
634 DWORD len;
636 TRACE("module %p, resource %s, defines %p, include %p, shader %p, error_messages %p.\n",
637 module, debugstr_w(resource), defines, include, shader, error_messages);
639 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
640 return D3DXERR_INVALIDDATA;
641 if (FAILED(load_resource_into_memory(module, res, &buffer, &len)))
642 return D3DXERR_INVALIDDATA;
643 return D3DXPreprocessShader(buffer, len, defines, include,
644 shader, error_messages);
648 struct ctab_constant {
649 D3DXCONSTANT_DESC desc;
650 struct ctab_constant *constants;
653 struct ID3DXConstantTableImpl {
654 ID3DXConstantTable ID3DXConstantTable_iface;
655 LONG ref;
656 char *ctab;
657 DWORD size;
658 D3DXCONSTANTTABLE_DESC desc;
659 struct ctab_constant *constants;
662 static void free_constant(struct ctab_constant *constant)
664 if (constant->constants)
666 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
668 for (i = 0; i < count; ++i)
670 free_constant(&constant->constants[i]);
672 HeapFree(GetProcessHeap(), 0, constant->constants);
676 static void free_constant_table(struct ID3DXConstantTableImpl *table)
678 if (table->constants)
680 UINT i;
682 for (i = 0; i < table->desc.Constants; ++i)
684 free_constant(&table->constants[i]);
686 HeapFree(GetProcessHeap(), 0, table->constants);
688 HeapFree(GetProcessHeap(), 0, table->ctab);
691 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
693 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
696 static inline BOOL is_vertex_shader(DWORD version)
698 return (version & 0xffff0000) == 0xfffe0000;
701 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant)
703 return (D3DXHANDLE)constant;
706 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
707 struct ctab_constant *constant, const char *name);
709 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, const char *name)
711 const char *part;
712 UINT element;
714 TRACE("constant %p, name %s\n", constant, debugstr_a(name));
716 if (!name || !*name) return NULL;
718 element = atoi(name);
719 part = strchr(name, ']') + 1;
721 if (constant->desc.Elements > element)
723 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant;
725 switch (*part++)
727 case '.':
728 return get_constant_by_name(NULL, c, part);
730 case '[':
731 return get_constant_element_by_name(c, part);
733 case '\0':
734 TRACE("Returning parameter %p\n", c);
735 return c;
737 default:
738 FIXME("Unhandled case \"%c\"\n", *--part);
739 break;
743 TRACE("Constant not found\n");
744 return NULL;
747 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
748 struct ctab_constant *constant, const char *name)
750 UINT i, count, length;
751 struct ctab_constant *handles;
752 const char *part;
754 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name));
756 if (!name || !*name) return NULL;
758 if (!constant)
760 count = table->desc.Constants;
761 handles = table->constants;
763 else
765 count = constant->desc.StructMembers;
766 handles = constant->constants;
769 length = strcspn(name, "[.");
770 part = name + length;
772 for (i = 0; i < count; i++)
774 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length))
776 switch (*part++)
778 case '.':
779 return get_constant_by_name(NULL, &handles[i], part);
781 case '[':
782 return get_constant_element_by_name(&handles[i], part);
784 default:
785 TRACE("Returning parameter %p\n", &handles[i]);
786 return &handles[i];
791 TRACE("Constant not found\n");
792 return NULL;
795 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, D3DXHANDLE handle)
797 struct ctab_constant *c;
798 UINT i, count;
800 /* all variable have at least elements = 1, but not always elements */
801 if (!parent->constants) return NULL;
803 count = parent->desc.Elements > 1 ? parent->desc.Elements : parent->desc.StructMembers;
804 for (i = 0; i < count; ++i)
806 if (handle_from_constant(&parent->constants[i]) == handle)
807 return &parent->constants[i];
809 c = is_valid_sub_constant(&parent->constants[i], handle);
810 if (c) return c;
813 return NULL;
816 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
818 struct ctab_constant *c;
819 UINT i;
821 if (!handle) return NULL;
823 for (i = 0; i < table->desc.Constants; ++i)
825 if (handle_from_constant(&table->constants[i]) == handle)
826 return &table->constants[i];
828 c = is_valid_sub_constant(&table->constants[i], handle);
829 if (c) return c;
832 return get_constant_by_name(table, NULL, handle);
835 /*** IUnknown methods ***/
836 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
838 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
840 if (IsEqualGUID(riid, &IID_IUnknown) ||
841 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
842 IsEqualGUID(riid, &IID_ID3DXConstantTable))
844 ID3DXConstantTable_AddRef(iface);
845 *out = iface;
846 return S_OK;
849 WARN("Interface %s not found.\n", debugstr_guid(riid));
851 return E_NOINTERFACE;
854 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
856 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
858 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
860 return InterlockedIncrement(&This->ref);
863 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
865 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
866 ULONG ref = InterlockedDecrement(&This->ref);
868 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
870 if (!ref)
872 free_constant_table(This);
873 HeapFree(GetProcessHeap(), 0, This);
876 return ref;
879 /*** ID3DXBuffer methods ***/
880 static void * WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
882 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface);
884 TRACE("iface %p.\n", iface);
886 return table->ctab;
889 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
891 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
893 TRACE("(%p)->()\n", This);
895 return This->size;
898 /*** ID3DXConstantTable methods ***/
899 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
901 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
903 TRACE("(%p)->(%p)\n", This, desc);
905 if (!desc)
906 return D3DERR_INVALIDCALL;
908 *desc = This->desc;
910 return D3D_OK;
913 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
914 D3DXCONSTANT_DESC *desc, UINT *count)
916 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
917 struct ctab_constant *c = get_valid_constant(This, constant);
919 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
921 if (!c)
923 WARN("Invalid argument specified\n");
924 return D3DERR_INVALIDCALL;
927 if (desc) *desc = c->desc;
928 if (count) *count = 1;
930 return D3D_OK;
933 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
935 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
936 struct ctab_constant *c = get_valid_constant(This, constant);
938 TRACE("(%p)->(%p)\n", This, constant);
940 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER)
942 WARN("Invalid argument specified\n");
943 return (UINT)-1;
946 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex);
947 return c->desc.RegisterIndex;
950 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
952 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
953 struct ctab_constant *c;
955 TRACE("(%p)->(%p, %d)\n", This, constant, index);
957 if (constant)
959 c = get_valid_constant(This, constant);
960 if (c && index < c->desc.StructMembers)
962 c = &c->constants[index];
963 TRACE("Returning constant %p\n", c);
964 return handle_from_constant(c);
967 else
969 if (index < This->desc.Constants)
971 c = &This->constants[index];
972 TRACE("Returning constant %p\n", c);
973 return handle_from_constant(c);
977 WARN("Index out of range\n");
978 return NULL;
981 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface,
982 D3DXHANDLE constant, const char *name)
984 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
985 struct ctab_constant *c = get_valid_constant(This, constant);
987 TRACE("iface %p, constant %p, name %s.\n", iface, constant, debugstr_a(name));
989 c = get_constant_by_name(This, c, name);
990 TRACE("Returning constant %p\n", c);
992 return handle_from_constant(c);
995 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
997 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
998 struct ctab_constant *c = get_valid_constant(This, constant);
1000 TRACE("(%p)->(%p, %d)\n", This, constant, index);
1002 if (c && index < c->desc.Elements)
1004 if (c->desc.Elements > 1) c = &c->constants[index];
1005 TRACE("Returning constant %p\n", c);
1006 return handle_from_constant(c);
1009 WARN("Invalid argument specified\n");
1010 return NULL;
1013 static inline DWORD get_index(const void **indata, UINT index, BOOL is_pointer)
1015 if (!indata)
1016 return 0;
1018 if (is_pointer)
1019 return ((DWORD **)indata)[index / 16][index % 16];
1021 return (*((DWORD **)indata))[index];
1024 static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant,
1025 const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index,
1026 BOOL is_pointer)
1028 D3DXCONSTANT_DESC *desc = &constant->desc;
1029 UINT l, i, regcount = 1, regsize = 1, cin = 1, rin = 1, ret, last = 0;
1030 DWORD tmp;
1032 /* size too small to set anything */
1033 if (*size < desc->Rows * desc->Columns)
1035 *size = 0;
1036 return 0;
1039 /* D3DXPC_STRUCT is somewhat special */
1040 if (desc->Class == D3DXPC_STRUCT)
1043 * Struct array sets the last complete input to the first struct element, all other
1044 * elements are not set.
1045 * E.g.: struct {int i;} s1[2];
1046 * SetValue(device, "s1", [1, 2], 8) => s1 = {2, x};
1048 * struct {int i; int n} s2[2];
1049 * SetValue(device, "s2", [1, 2, 3, 4, 5], 20) => s1 = {{3, 4}, {x, x}};
1051 if (desc->Elements > 1)
1053 UINT offset = *size / (desc->Rows * desc->Columns) - 1;
1055 offset = min(desc->Elements - 1, offset);
1056 last = offset * desc->Rows * desc->Columns;
1058 if ((is_pointer || (!is_pointer && inclass == D3DXPC_MATRIX_ROWS)) && desc->RegisterSet != D3DXRS_BOOL)
1060 set(table, device, &constant->constants[0], NULL, intype, size, incol, inclass, 0, is_pointer);
1062 else
1064 last += set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
1065 index + last, is_pointer);
1068 else
1071 * D3DXRS_BOOL is always set. As there are only 16 bools and there are
1072 * exactly 16 input values, use matrix transpose.
1074 if (inclass == D3DXPC_MATRIX_ROWS && desc->RegisterSet == D3DXRS_BOOL)
1076 D3DXMATRIX mat, *m, min;
1077 D3DXMatrixTranspose(&mat, &min);
1079 if (is_pointer)
1080 min = *(D3DXMATRIX *)(indata[index / 16]);
1081 else
1082 min = **(D3DXMATRIX **)indata;
1084 D3DXMatrixTranspose(&mat, &min);
1085 m = &mat;
1086 for (i = 0; i < desc->StructMembers; ++i)
1088 last += set(table, device, &constant->constants[i], (const void **)&m, intype, size, incol,
1089 D3DXPC_SCALAR, index + last, is_pointer);
1093 * For pointers or for matrix rows, only the first member is set.
1094 * All other members are set to 0. This is not true for D3DXRS_BOOL.
1095 * E.g.: struct {int i; int n} s;
1096 * SetValue(device, "s", [1, 2], 8) => s = {1, 0};
1098 else if ((is_pointer || (!is_pointer && inclass == D3DXPC_MATRIX_ROWS)) && desc->RegisterSet != D3DXRS_BOOL)
1100 last = set(table, device, &constant->constants[0], indata, intype, size, incol, inclass,
1101 index + last, is_pointer);
1103 for (i = 1; i < desc->StructMembers; ++i)
1105 set(table, device, &constant->constants[i], NULL, intype, size, incol, inclass, 0, is_pointer);
1108 else
1110 for (i = 0; i < desc->StructMembers; ++i)
1112 last += set(table, device, &constant->constants[i], indata, intype, size, incol, D3DXPC_SCALAR,
1113 index + last, is_pointer);
1118 return last;
1121 /* elements */
1122 if (desc->Elements > 1)
1124 for (i = 0; i < desc->Elements && *size > 0; ++i)
1126 last += set(table, device, &constant->constants[i], indata, intype, size, incol, inclass,
1127 index + last, is_pointer);
1129 /* adjust the vector size for matrix rows */
1130 if (inclass == D3DXPC_MATRIX_ROWS && desc->Class == D3DXPC_VECTOR && (i % 4) == 3)
1132 last += 12;
1133 *size = *size < 12 ? 0 : *size - 12;
1137 return last;
1140 switch (desc->Class)
1142 case D3DXPC_SCALAR:
1143 case D3DXPC_VECTOR:
1144 case D3DXPC_MATRIX_ROWS:
1145 regcount = min(desc->RegisterCount, desc->Rows);
1146 if (inclass == D3DXPC_MATRIX_ROWS) cin = incol;
1147 else rin = incol;
1148 regsize = desc->Columns;
1149 break;
1151 case D3DXPC_MATRIX_COLUMNS:
1152 regcount = min(desc->RegisterCount, desc->Columns);
1153 if (inclass == D3DXPC_MATRIX_ROWS) rin = incol;
1154 else cin = incol;
1155 regsize = desc->Rows;
1156 break;
1158 default:
1159 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1160 return 0;
1163 /* specific stuff for different in types */
1164 switch (inclass)
1166 case D3DXPC_SCALAR:
1167 ret = desc->Columns * desc->Rows;
1168 *size -= desc->Columns * desc->Rows;
1169 break;
1171 case D3DXPC_VECTOR:
1172 switch (desc->Class)
1174 case D3DXPC_MATRIX_ROWS:
1175 if (*size < regcount * 4)
1177 *size = 0;
1178 return 0;
1180 ret = 4 * regcount;
1181 *size -= 4 * regcount;
1182 break;
1184 case D3DXPC_MATRIX_COLUMNS:
1185 ret = 4 * regsize;
1186 *size -= 4 * regcount;
1187 break;
1189 case D3DXPC_SCALAR:
1190 ret = 1;
1191 *size -= ret;
1192 break;
1194 case D3DXPC_VECTOR:
1195 ret = 4;
1196 *size -= ret;
1197 break;
1199 default:
1200 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1201 return 0;
1203 break;
1205 case D3DXPC_MATRIX_ROWS:
1206 switch (desc->Class)
1208 case D3DXPC_MATRIX_ROWS:
1209 case D3DXPC_MATRIX_COLUMNS:
1210 if (*size < 16)
1212 *size = 0;
1213 return 0;
1215 ret = 16;
1216 break;
1218 case D3DXPC_SCALAR:
1219 ret = 4;
1220 break;
1222 case D3DXPC_VECTOR:
1223 ret = 1;
1224 break;
1226 default:
1227 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1228 return 0;
1230 *size -= ret;
1231 break;
1233 case D3DXPC_MATRIX_COLUMNS:
1234 switch (desc->Class)
1236 case D3DXPC_MATRIX_ROWS:
1237 case D3DXPC_MATRIX_COLUMNS:
1238 if (*size < 16)
1240 *size = 0;
1241 return 0;
1243 ret = 16;
1244 break;
1246 case D3DXPC_SCALAR:
1247 ret = 1;
1248 break;
1250 case D3DXPC_VECTOR:
1251 ret = 4;
1252 break;
1254 default:
1255 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1256 return 0;
1258 *size -= ret;
1259 break;
1261 default:
1262 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(inclass));
1263 return 0;
1266 /* set the registers */
1267 switch (desc->RegisterSet)
1269 case D3DXRS_BOOL:
1270 regcount = min(desc->RegisterCount, desc->Columns * desc->Rows);
1271 l = 0;
1272 for (i = 0; i < regcount; ++i)
1274 BOOL out;
1275 DWORD t = get_index(indata, index + i / regsize * rin + l * cin, is_pointer);
1277 set_number(&tmp, desc->Type, &t, intype);
1278 set_number(&out, D3DXPT_BOOL, &tmp, desc->Type);
1279 if (is_vertex_shader(table->desc.Version))
1280 IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex + i, &out, 1);
1281 else
1282 IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex + i, &out, 1);
1284 if (++l >= regsize) l = 0;
1286 return ret;
1288 case D3DXRS_INT4:
1289 for (i = 0; i < regcount; ++i)
1291 INT vec[4] = {0, 0, 1, 0};
1293 for (l = 0; l < regsize; ++l)
1295 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer);
1297 set_number(&tmp, desc->Type, &t, intype);
1298 set_number(&vec[l], D3DXPT_INT, &tmp, desc->Type);
1300 if (is_vertex_shader(table->desc.Version))
1301 IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex + i, vec, 1);
1302 else
1303 IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex + i, vec, 1);
1305 return ret;
1307 case D3DXRS_FLOAT4:
1308 for (i = 0; i < regcount; ++i)
1310 FLOAT vec[4] = {0};
1312 for (l = 0; l < regsize; ++l)
1314 DWORD t = get_index(indata, index + i * rin + l * cin, is_pointer);
1316 set_number(&tmp, desc->Type, &t, intype);
1317 set_number(&vec[l], D3DXPT_FLOAT, &tmp, desc->Type);
1319 if (is_vertex_shader(table->desc.Version))
1320 IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex + i, vec, 1);
1321 else
1322 IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex + i, vec, 1);
1324 return ret;
1326 default:
1327 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1328 return 0;
1332 static HRESULT set_scalar(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1333 const void *indata, D3DXPARAMETER_TYPE intype)
1335 struct ctab_constant *c = get_valid_constant(table, constant);
1336 UINT count = 1;
1338 if (!c)
1340 WARN("Invalid argument specified\n");
1341 return D3DERR_INVALIDCALL;
1344 switch (c->desc.Class)
1346 case D3DXPC_SCALAR:
1347 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE);
1348 return D3D_OK;
1350 case D3DXPC_VECTOR:
1351 case D3DXPC_MATRIX_ROWS:
1352 case D3DXPC_MATRIX_COLUMNS:
1353 case D3DXPC_STRUCT:
1354 return D3D_OK;
1356 default:
1357 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1358 return D3DERR_INVALIDCALL;
1362 static HRESULT set_scalar_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1363 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1365 struct ctab_constant *c = get_valid_constant(table, constant);
1367 if (!c)
1369 WARN("Invalid argument specified\n");
1370 return D3DERR_INVALIDCALL;
1373 switch (c->desc.Class)
1375 case D3DXPC_SCALAR:
1376 case D3DXPC_VECTOR:
1377 case D3DXPC_MATRIX_ROWS:
1378 case D3DXPC_MATRIX_COLUMNS:
1379 case D3DXPC_STRUCT:
1380 set(table, device, c, &indata, intype, &count, c->desc.Columns, D3DXPC_SCALAR, 0, FALSE);
1381 return D3D_OK;
1383 default:
1384 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1385 return D3DERR_INVALIDCALL;
1389 static HRESULT set_vector(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1390 const void *indata, D3DXPARAMETER_TYPE intype)
1392 struct ctab_constant *c = get_valid_constant(table, constant);
1393 UINT count = 4;
1395 if (!c)
1397 WARN("Invalid argument specified\n");
1398 return D3DERR_INVALIDCALL;
1401 switch (c->desc.Class)
1403 case D3DXPC_SCALAR:
1404 case D3DXPC_VECTOR:
1405 case D3DXPC_STRUCT:
1406 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE);
1407 return D3D_OK;
1409 case D3DXPC_MATRIX_ROWS:
1410 case D3DXPC_MATRIX_COLUMNS:
1411 return D3D_OK;
1413 default:
1414 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1415 return D3DERR_INVALIDCALL;
1419 static HRESULT set_vector_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1420 const void *indata, UINT count, D3DXPARAMETER_TYPE intype)
1422 struct ctab_constant *c = get_valid_constant(table, constant);
1424 if (!c)
1426 WARN("Invalid argument specified\n");
1427 return D3DERR_INVALIDCALL;
1430 switch (c->desc.Class)
1432 case D3DXPC_SCALAR:
1433 case D3DXPC_VECTOR:
1434 case D3DXPC_MATRIX_ROWS:
1435 case D3DXPC_MATRIX_COLUMNS:
1436 case D3DXPC_STRUCT:
1437 count *= 4;
1438 set(table, device, c, &indata, intype, &count, 4, D3DXPC_VECTOR, 0, FALSE);
1439 return D3D_OK;
1441 default:
1442 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1443 return D3DERR_INVALIDCALL;
1447 static HRESULT set_matrix_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, D3DXHANDLE constant,
1448 const void *indata, UINT count, BOOL transpose)
1450 struct ctab_constant *c = get_valid_constant(table, constant);
1452 if (!c)
1454 WARN("Invalid argument specified\n");
1455 return D3DERR_INVALIDCALL;
1458 switch (c->desc.Class)
1460 case D3DXPC_SCALAR:
1461 case D3DXPC_VECTOR:
1462 case D3DXPC_MATRIX_ROWS:
1463 case D3DXPC_MATRIX_COLUMNS:
1464 case D3DXPC_STRUCT:
1465 count *= 16;
1466 set(table, device, c, &indata, D3DXPT_FLOAT, &count, 4,
1467 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, FALSE);
1468 return D3D_OK;
1470 default:
1471 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1472 return D3DERR_INVALIDCALL;
1476 static HRESULT set_matrix_pointer_array(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device,
1477 D3DXHANDLE constant, const void **indata, UINT count, BOOL transpose)
1479 struct ctab_constant *c = get_valid_constant(table, constant);
1481 if (!c)
1483 WARN("Invalid argument specified\n");
1484 return D3DERR_INVALIDCALL;
1487 switch (c->desc.Class)
1489 case D3DXPC_SCALAR:
1490 case D3DXPC_VECTOR:
1491 case D3DXPC_MATRIX_ROWS:
1492 case D3DXPC_MATRIX_COLUMNS:
1493 case D3DXPC_STRUCT:
1494 count *= 16;
1495 set(table, device, c, indata, D3DXPT_FLOAT, &count, 4,
1496 transpose ? D3DXPC_MATRIX_ROWS : D3DXPC_MATRIX_COLUMNS, 0, TRUE);
1497 return D3D_OK;
1499 default:
1500 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c->desc.Class));
1501 return D3DERR_INVALIDCALL;
1505 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1506 struct IDirect3DDevice9 *device)
1508 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1509 UINT i;
1511 TRACE("iface %p, device %p\n", iface, device);
1513 if (!device)
1515 WARN("Invalid argument specified\n");
1516 return D3DERR_INVALIDCALL;
1519 for (i = 0; i < This->desc.Constants; i++)
1521 D3DXCONSTANT_DESC *desc = &This->constants[i].desc;
1522 HRESULT hr;
1524 if (!desc->DefaultValue)
1525 continue;
1527 switch (desc->RegisterSet)
1529 case D3DXRS_BOOL:
1530 if (is_vertex_shader(This->desc.Version))
1531 hr = IDirect3DDevice9_SetVertexShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue,
1532 desc->RegisterCount);
1533 else
1534 hr = IDirect3DDevice9_SetPixelShaderConstantB(device, desc->RegisterIndex, desc->DefaultValue,
1535 desc->RegisterCount);
1536 break;
1538 case D3DXRS_INT4:
1539 if (is_vertex_shader(This->desc.Version))
1540 hr = IDirect3DDevice9_SetVertexShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue,
1541 desc->RegisterCount);
1542 else
1543 hr = IDirect3DDevice9_SetPixelShaderConstantI(device, desc->RegisterIndex, desc->DefaultValue,
1544 desc->RegisterCount);
1545 break;
1547 case D3DXRS_FLOAT4:
1548 if (is_vertex_shader(This->desc.Version))
1549 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue,
1550 desc->RegisterCount);
1551 else
1552 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, desc->RegisterIndex, desc->DefaultValue,
1553 desc->RegisterCount);
1554 break;
1556 default:
1557 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1558 hr = E_NOTIMPL;
1559 break;
1562 if (hr != D3D_OK)
1563 return hr;
1566 return D3D_OK;
1569 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1570 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, unsigned int bytes)
1572 struct ID3DXConstantTableImpl *table = impl_from_ID3DXConstantTable(iface);
1573 struct ctab_constant *c = get_valid_constant(table, constant);
1574 D3DXCONSTANT_DESC *desc;
1576 TRACE("iface %p, device %p, constant %p, data %p, bytes %u\n", iface, device, constant, data, bytes);
1578 if (!device || !c || !data)
1580 WARN("Invalid argument specified\n");
1581 return D3DERR_INVALIDCALL;
1584 desc = &c->desc;
1586 switch (desc->Class)
1588 case D3DXPC_SCALAR:
1589 case D3DXPC_VECTOR:
1590 case D3DXPC_MATRIX_ROWS:
1591 case D3DXPC_MATRIX_COLUMNS:
1592 case D3DXPC_STRUCT:
1593 bytes /= 4;
1594 set(table, device, c, &data, desc->Type, &bytes, desc->Columns, D3DXPC_SCALAR, 0, FALSE);
1595 return D3D_OK;
1597 default:
1598 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc->Class));
1599 return D3DERR_INVALIDCALL;
1603 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1604 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1606 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1608 TRACE("iface %p, device %p, constant %p, b %d\n", iface, device, constant, b);
1610 return set_scalar(This, device, constant, &b, D3DXPT_BOOL);
1613 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1614 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1616 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1618 TRACE("iface %p, device %p, constant %p, b %p, count %d\n", iface, device, constant, b, count);
1620 return set_scalar_array(This, device, constant, b, count, D3DXPT_BOOL);
1623 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1624 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1626 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1628 TRACE("iface %p, device %p, constant %p, n %d\n", iface, device, constant, n);
1630 return set_scalar(This, device, constant, &n, D3DXPT_INT);
1633 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1634 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1636 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1638 TRACE("iface %p, device %p, constant %p, n %p, count %d\n", iface, device, constant, n, count);
1640 return set_scalar_array(This, device, constant, n, count, D3DXPT_INT);
1643 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1644 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1646 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1648 TRACE("iface %p, device %p, constant %p, f %f\n", iface, device, constant, f);
1650 return set_scalar(This, device, constant, &f, D3DXPT_FLOAT);
1653 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1654 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1656 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1658 TRACE("iface %p, device %p, constant %p, f %p, count %d\n", iface, device, constant, f, count);
1660 return set_scalar_array(This, device, constant, f, count, D3DXPT_FLOAT);
1663 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1664 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1666 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1668 TRACE("iface %p, device %p, constant %p, vector %p\n", iface, device, constant, vector);
1670 return set_vector(This, device, constant, vector, D3DXPT_FLOAT);
1673 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1674 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1676 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1678 TRACE("iface %p, device %p, constant %p, vector %p, count %u\n", iface, device, constant, vector, count);
1680 return set_vector_array(This, device, constant, vector, count, D3DXPT_FLOAT);
1683 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1684 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1686 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1688 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1690 return set_matrix_array(This, device, constant, matrix, 1, FALSE);
1693 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1694 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1696 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1698 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1700 return set_matrix_array(This, device, constant, matrix, count, FALSE);
1703 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1704 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1706 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1708 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count);
1710 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, FALSE);
1713 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1714 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1716 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1718 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface, device, constant, matrix);
1720 return set_matrix_array(This, device, constant, matrix, 1, TRUE);
1723 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1724 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1726 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1728 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface, device, constant, matrix, count);
1730 return set_matrix_array(This, device, constant, matrix, count, TRUE);
1733 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface,
1734 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1736 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1738 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface, device, constant, matrix, count);
1740 return set_matrix_pointer_array(This, device, constant, (const void **)matrix, count, TRUE);
1743 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1745 /*** IUnknown methods ***/
1746 ID3DXConstantTableImpl_QueryInterface,
1747 ID3DXConstantTableImpl_AddRef,
1748 ID3DXConstantTableImpl_Release,
1749 /*** ID3DXBuffer methods ***/
1750 ID3DXConstantTableImpl_GetBufferPointer,
1751 ID3DXConstantTableImpl_GetBufferSize,
1752 /*** ID3DXConstantTable methods ***/
1753 ID3DXConstantTableImpl_GetDesc,
1754 ID3DXConstantTableImpl_GetConstantDesc,
1755 ID3DXConstantTableImpl_GetSamplerIndex,
1756 ID3DXConstantTableImpl_GetConstant,
1757 ID3DXConstantTableImpl_GetConstantByName,
1758 ID3DXConstantTableImpl_GetConstantElement,
1759 ID3DXConstantTableImpl_SetDefaults,
1760 ID3DXConstantTableImpl_SetValue,
1761 ID3DXConstantTableImpl_SetBool,
1762 ID3DXConstantTableImpl_SetBoolArray,
1763 ID3DXConstantTableImpl_SetInt,
1764 ID3DXConstantTableImpl_SetIntArray,
1765 ID3DXConstantTableImpl_SetFloat,
1766 ID3DXConstantTableImpl_SetFloatArray,
1767 ID3DXConstantTableImpl_SetVector,
1768 ID3DXConstantTableImpl_SetVectorArray,
1769 ID3DXConstantTableImpl_SetMatrix,
1770 ID3DXConstantTableImpl_SetMatrixArray,
1771 ID3DXConstantTableImpl_SetMatrixPointerArray,
1772 ID3DXConstantTableImpl_SetMatrixTranspose,
1773 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1774 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1777 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
1778 BOOL is_element, WORD index, WORD max_index, DWORD *offset, DWORD nameoffset, UINT regset)
1780 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
1781 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
1782 HRESULT hr = D3D_OK;
1783 UINT i, count = 0;
1784 WORD size = 0;
1786 constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
1787 constant->desc.Class = type->Class;
1788 constant->desc.Type = type->Type;
1789 constant->desc.Rows = type->Rows;
1790 constant->desc.Columns = type->Columns;
1791 constant->desc.Elements = is_element ? 1 : type->Elements;
1792 constant->desc.StructMembers = type->StructMembers;
1793 constant->desc.Name = ctab + nameoffset;
1794 constant->desc.RegisterSet = regset;
1795 constant->desc.RegisterIndex = index;
1797 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name,
1798 constant->desc.Elements, index, constant->desc.DefaultValue,
1799 debug_d3dxparameter_registerset(regset));
1800 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1801 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type),
1802 type->Rows, type->Columns, type->Elements, type->StructMembers);
1804 if (type->Elements > 1 && !is_element)
1806 count = type->Elements;
1808 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
1810 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
1811 count = type->StructMembers;
1814 if (count)
1816 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
1817 if (!constant->constants)
1819 ERR("Out of memory\n");
1820 hr = E_OUTOFMEMORY;
1821 goto error;
1824 for (i = 0; i < count; ++i)
1826 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
1827 &constant->constants[i], memberinfo == NULL, index + size, max_index, offset,
1828 memberinfo ? memberinfo[i].Name : nameoffset, regset);
1829 if (hr != D3D_OK)
1830 goto error;
1832 size += constant->constants[i].desc.RegisterCount;
1835 else
1837 WORD offsetdiff = type->Columns * type->Rows;
1838 BOOL fail = FALSE;
1840 size = type->Columns * type->Rows;
1842 switch (regset)
1844 case D3DXRS_BOOL:
1845 fail = type->Class != D3DXPC_SCALAR && type->Class != D3DXPC_VECTOR
1846 && type->Class != D3DXPC_MATRIX_ROWS && type->Class != D3DXPC_MATRIX_COLUMNS;
1847 break;
1849 case D3DXRS_FLOAT4:
1850 case D3DXRS_INT4:
1851 switch (type->Class)
1853 case D3DXPC_VECTOR:
1854 size = 1;
1855 /* fall through */
1856 case D3DXPC_SCALAR:
1857 offsetdiff = type->Rows * 4;
1858 break;
1860 case D3DXPC_MATRIX_ROWS:
1861 offsetdiff = type->Rows * 4;
1862 size = type->Rows;
1863 break;
1865 case D3DXPC_MATRIX_COLUMNS:
1866 offsetdiff = type->Columns * 4;
1867 size = type->Columns;
1868 break;
1870 default:
1871 fail = TRUE;
1872 break;
1874 break;
1876 case D3DXRS_SAMPLER:
1877 size = 1;
1878 fail = type->Class != D3DXPC_OBJECT;
1879 break;
1881 default:
1882 fail = TRUE;
1883 break;
1886 if (fail)
1888 FIXME("Unhandled register set %s, type class %s\n", debug_d3dxparameter_registerset(regset),
1889 debug_d3dxparameter_class(type->Class));
1892 /* offset in bytes => offsetdiff * sizeof(DWORD) */
1893 if (offset) *offset += offsetdiff * 4;
1896 constant->desc.RegisterCount = max(0, min(max_index - index, size));
1897 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns;
1899 return D3D_OK;
1901 error:
1902 if (constant->constants)
1904 for (i = 0; i < count; ++i)
1906 free_constant(&constant->constants[i]);
1908 HeapFree(GetProcessHeap(), 0, constant->constants);
1909 constant->constants = NULL;
1912 return hr;
1915 HRESULT WINAPI D3DXGetShaderConstantTableEx(const DWORD *byte_code, DWORD flags, ID3DXConstantTable **constant_table)
1917 struct ID3DXConstantTableImpl *object = NULL;
1918 const void *data;
1919 HRESULT hr;
1920 UINT size;
1921 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1922 const D3DXSHADER_CONSTANTINFO *constant_info;
1923 DWORD i;
1925 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code, flags, constant_table);
1927 if (constant_table) *constant_table = NULL;
1929 if (!byte_code || !constant_table)
1931 WARN("Invalid argument specified.\n");
1932 return D3DERR_INVALIDCALL;
1935 if (!is_valid_bytecode(*byte_code))
1937 WARN("Invalid byte_code specified.\n");
1938 return D3D_OK;
1941 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags);
1943 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1944 if (hr != D3D_OK)
1946 WARN("CTAB not found.\n");
1947 return D3DXERR_INVALIDDATA;
1950 if (size < sizeof(*ctab_header))
1952 WARN("Invalid CTAB size.\n");
1953 return D3DXERR_INVALIDDATA;
1956 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1957 if (ctab_header->Size != sizeof(*ctab_header))
1959 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1960 return D3DXERR_INVALIDDATA;
1963 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1964 if (!object)
1965 return E_OUTOFMEMORY;
1967 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1968 object->ref = 1;
1970 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1971 if (!object->ctab)
1973 ERR("Out of memory\n");
1974 HeapFree(GetProcessHeap(), 0, object);
1975 return E_OUTOFMEMORY;
1977 object->size = size;
1978 memcpy(object->ctab, data, object->size);
1980 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1981 object->desc.Version = ctab_header->Version;
1982 object->desc.Constants = ctab_header->Constants;
1983 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1984 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
1985 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
1987 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1988 sizeof(*object->constants) * object->desc.Constants);
1989 if (!object->constants)
1991 ERR("Out of memory\n");
1992 hr = E_OUTOFMEMORY;
1993 goto error;
1996 constant_info = (const D3DXSHADER_CONSTANTINFO *)(object->ctab + ctab_header->ConstantInfo);
1997 for (i = 0; i < ctab_header->Constants; i++)
1999 DWORD offset = constant_info[i].DefaultValue;
2001 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
2002 &object->constants[i], FALSE, constant_info[i].RegisterIndex,
2003 constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
2004 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
2005 if (hr != D3D_OK)
2006 goto error;
2009 * Set the register count, it may differ for D3DXRS_INT4, because somehow
2010 * it makes the assumption that the register size is 1 instead of 4, so the
2011 * count is 4 times bigger. This holds true only for toplevel shader
2012 * constants. The count of elements and members is always based on a
2013 * register size of 4.
2015 if (object->constants[i].desc.RegisterSet == D3DXRS_INT4)
2017 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
2021 *constant_table = &object->ID3DXConstantTable_iface;
2023 return D3D_OK;
2025 error:
2026 free_constant_table(object);
2027 HeapFree(GetProcessHeap(), 0, object);
2029 return hr;
2032 HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantTable **constant_table)
2034 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
2036 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
2039 HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count)
2041 UINT i, sampler_count = 0;
2042 UINT size;
2043 const char *data;
2044 const D3DXSHADER_CONSTANTTABLE *ctab_header;
2045 const D3DXSHADER_CONSTANTINFO *constant_info;
2047 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
2049 if (count) *count = 0;
2051 if (D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (const void **)&data, &size) != D3D_OK)
2052 return D3D_OK;
2054 if (size < sizeof(*ctab_header)) return D3D_OK;
2056 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
2057 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
2059 constant_info = (const D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
2060 for (i = 0; i < ctab_header->Constants; i++)
2062 const D3DXSHADER_TYPEINFO *type;
2064 TRACE("name = %s\n", data + constant_info[i].Name);
2066 type = (const D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
2068 if (type->Type == D3DXPT_SAMPLER
2069 || type->Type == D3DXPT_SAMPLER1D
2070 || type->Type == D3DXPT_SAMPLER2D
2071 || type->Type == D3DXPT_SAMPLER3D
2072 || type->Type == D3DXPT_SAMPLERCUBE)
2074 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
2076 ++sampler_count;
2080 TRACE("Found %u samplers\n", sampler_count);
2082 if (count) *count = sampler_count;
2084 return D3D_OK;