tools: Upgrade the config.guess/config.sub scripts.
[wine/wine-gecko.git] / dlls / d3dx9_36 / shader.c
bloba0d36e2298bb5cf9854aede88d860ca4b8832c0d
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(LPCVOID data, SIZE_T datasize, LPCSTR filename,
39 const D3D_SHADER_MACRO *defines, ID3DInclude *include,
40 UINT flags,
41 ID3DBlob **shader, ID3DBlob **error_messages);
43 static inline BOOL is_valid_bytecode(DWORD token)
45 return (token & 0xfffe0000) == 0xfffe0000;
48 const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device)
50 D3DCAPS9 caps;
52 TRACE("device %p\n", device);
54 if (!device) return NULL;
56 IDirect3DDevice9_GetDeviceCaps(device,&caps);
58 switch (caps.PixelShaderVersion)
60 case D3DPS_VERSION(1, 1):
61 return "ps_1_1";
63 case D3DPS_VERSION(1, 2):
64 return "ps_1_2";
66 case D3DPS_VERSION(1, 3):
67 return "ps_1_3";
69 case D3DPS_VERSION(1, 4):
70 return "ps_1_4";
72 case D3DPS_VERSION(2, 0):
73 if ((caps.PS20Caps.NumTemps>=22) &&
74 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) &&
75 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
76 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) &&
77 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
78 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
80 return "ps_2_a";
82 if ((caps.PS20Caps.NumTemps>=32) &&
83 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
85 return "ps_2_b";
87 return "ps_2_0";
89 case D3DPS_VERSION(3, 0):
90 return "ps_3_0";
93 return NULL;
96 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
98 const DWORD *ptr = byte_code;
100 TRACE("byte_code %p\n", byte_code);
102 if (!ptr) return 0;
104 /* Look for the END token, skipping the VERSION token */
105 while (*++ptr != D3DSIO_END)
107 /* Skip comments */
108 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
110 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
113 ++ptr;
115 /* Return the shader size in bytes */
116 return (ptr - byte_code) * sizeof(*ptr);
119 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
121 TRACE("byte_code %p\n", byte_code);
123 return byte_code ? *byte_code : 0;
126 const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device)
128 D3DCAPS9 caps;
130 TRACE("device %p\n", device);
132 if (!device) return NULL;
134 IDirect3DDevice9_GetDeviceCaps(device,&caps);
136 switch (caps.VertexShaderVersion)
138 case D3DVS_VERSION(1, 1):
139 return "vs_1_1";
140 case D3DVS_VERSION(2, 0):
141 if ((caps.VS20Caps.NumTemps>=13) &&
142 (caps.VS20Caps.DynamicFlowControlDepth==24) &&
143 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
145 return "vs_2_a";
147 return "vs_2_0";
148 case D3DVS_VERSION(3, 0):
149 return "vs_3_0";
152 return NULL;
155 HRESULT WINAPI D3DXFindShaderComment(const DWORD *byte_code, DWORD fourcc, const void **data, UINT *size)
157 const DWORD *ptr = byte_code;
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;
165 if (!is_valid_bytecode(*byte_code)) return D3DXERR_INVALIDDATA;
167 while (*++ptr != D3DSIO_END)
169 /* Check if it is a comment */
170 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
172 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
174 /* Check if this is the comment we are looking for */
175 if (*(ptr + 1) == fourcc)
177 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
178 LPCVOID ctab_data = ptr + 2;
179 if (size)
180 *size = ctab_size;
181 if (data)
182 *data = ctab_data;
183 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
184 return D3D_OK;
186 ptr += comment_size;
190 return S_FALSE;
193 HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMACRO *defines,
194 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
196 /* Forward to d3dcompiler: the parameter types aren't really different,
197 the actual data types are equivalent */
198 HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
199 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
200 (ID3DBlob **)error_messages);
202 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
203 return hr;
206 /* D3DXInclude private implementation, used to implement
207 D3DXAssembleShaderFromFile from D3DXAssembleShader */
208 /* To be able to correctly resolve include search paths we have to store
209 the pathname of each include file. We store the pathname pointer right
210 before the file data. */
211 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
212 D3DXINCLUDE_TYPE include_type,
213 LPCSTR filename, LPCVOID parent_data,
214 LPCVOID *data, UINT *bytes) {
215 const char *p, *parent_name = "";
216 char *pathname = NULL;
217 char **buffer = NULL;
218 HANDLE file;
219 UINT size;
221 if(parent_data != NULL)
222 parent_name = *((const char **)parent_data - 1);
224 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
226 if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
227 else p = parent_name;
228 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
229 if(!pathname)
230 return HRESULT_FROM_WIN32(GetLastError());
232 memcpy(pathname, parent_name, p - parent_name);
233 strcpy(pathname + (p - parent_name), filename);
235 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
236 if(file == INVALID_HANDLE_VALUE)
237 goto error;
239 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
241 size = GetFileSize(file, NULL);
242 if(size == INVALID_FILE_SIZE)
243 goto error;
245 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
246 if(!buffer)
247 goto error;
248 *buffer = pathname;
249 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
250 goto error;
252 *data = buffer + 1;
254 CloseHandle(file);
255 return S_OK;
257 error:
258 CloseHandle(file);
259 HeapFree(GetProcessHeap(), 0, pathname);
260 HeapFree(GetProcessHeap(), 0, buffer);
261 return HRESULT_FROM_WIN32(GetLastError());
264 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
265 HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
266 HeapFree(GetProcessHeap(), 0, (char **)data - 1);
267 return S_OK;
270 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
271 d3dincludefromfile_open,
272 d3dincludefromfile_close
275 struct D3DXIncludeImpl {
276 ID3DXInclude ID3DXInclude_iface;
279 HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines,
280 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
282 LPWSTR filename_w = NULL;
283 DWORD len;
284 HRESULT ret;
286 if (!filename) return D3DXERR_INVALIDDATA;
288 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
289 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
290 if (!filename_w) return E_OUTOFMEMORY;
291 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
293 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
295 HeapFree(GetProcessHeap(), 0, filename_w);
296 return ret;
299 HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
300 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
302 void *buffer;
303 DWORD len;
304 HRESULT hr;
305 struct D3DXIncludeImpl includefromfile;
307 if(FAILED(map_view_of_file(filename, &buffer, &len)))
308 return D3DXERR_INVALIDDATA;
310 if(!include)
312 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
313 include = &includefromfile.ID3DXInclude_iface;
316 hr = D3DXAssembleShader(buffer, len, defines, include, flags,
317 shader, error_messages);
319 UnmapViewOfFile(buffer);
320 return hr;
323 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
324 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
326 HRSRC res;
327 LPCSTR buffer;
328 DWORD len;
330 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
331 return D3DXERR_INVALIDDATA;
332 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
333 return D3DXERR_INVALIDDATA;
334 return D3DXAssembleShader(buffer, len, defines, include, flags,
335 shader, error_messages);
338 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
339 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
341 HRSRC res;
342 LPCSTR buffer;
343 DWORD len;
345 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
346 return D3DXERR_INVALIDDATA;
347 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
348 return D3DXERR_INVALIDDATA;
349 return D3DXAssembleShader(buffer, len, defines, include, flags,
350 shader, error_messages);
353 HRESULT WINAPI D3DXCompileShader(const char *pSrcData, UINT srcDataLen, const D3DXMACRO *pDefines,
354 ID3DXInclude *pInclude, const char *pFunctionName, const char *pProfile, DWORD Flags,
355 ID3DXBuffer **ppShader, ID3DXBuffer **ppErrorMsgs, ID3DXConstantTable **ppConstantTable)
357 HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
358 (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
359 pFunctionName, pProfile, Flags, 0,
360 (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
362 if(SUCCEEDED(hr) && ppConstantTable)
363 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
364 ppConstantTable);
365 return hr;
368 HRESULT WINAPI D3DXCompileShaderFromFileA(const char *filename, const D3DXMACRO *defines,
369 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
370 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
372 LPWSTR filename_w = NULL;
373 DWORD len;
374 HRESULT ret;
376 if (!filename) return D3DXERR_INVALIDDATA;
378 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
379 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
380 if (!filename_w) return E_OUTOFMEMORY;
381 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
383 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
384 entrypoint, profile, flags,
385 shader, error_messages, constant_table);
387 HeapFree(GetProcessHeap(), 0, filename_w);
388 return ret;
391 HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
392 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
393 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
395 void *buffer;
396 DWORD len, filename_len;
397 HRESULT hr;
398 struct D3DXIncludeImpl includefromfile;
399 char *filename_a;
401 if (FAILED(map_view_of_file(filename, &buffer, &len)))
402 return D3DXERR_INVALIDDATA;
404 if (!include)
406 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
407 include = &includefromfile.ID3DXInclude_iface;
410 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
411 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
412 if (!filename_a)
414 UnmapViewOfFile(buffer);
415 return E_OUTOFMEMORY;
417 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
419 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
420 (ID3DInclude *)include, entrypoint, profile, flags, 0,
421 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
423 if (SUCCEEDED(hr) && constant_table)
424 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
425 constant_table);
427 HeapFree(GetProcessHeap(), 0, filename_a);
428 UnmapViewOfFile(buffer);
429 return hr;
432 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
433 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
434 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
436 HRSRC res;
437 LPCSTR buffer;
438 DWORD len;
440 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
441 return D3DXERR_INVALIDDATA;
442 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
443 return D3DXERR_INVALIDDATA;
444 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
445 flags, shader, error_messages, constant_table);
448 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
449 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
450 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
452 HRSRC res;
453 LPCSTR buffer;
454 DWORD len;
456 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
457 return D3DXERR_INVALIDDATA;
458 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
459 return D3DXERR_INVALIDDATA;
460 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
461 flags, shader, error_messages, constant_table);
464 HRESULT WINAPI D3DXPreprocessShader(const char *data, UINT data_len, const D3DXMACRO *defines,
465 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
467 TRACE("Forward to D3DPreprocess\n");
468 return D3DPreprocess(data, data_len, NULL,
469 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
470 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
473 HRESULT WINAPI D3DXPreprocessShaderFromFileA(const char *filename, const D3DXMACRO *defines,
474 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
476 WCHAR *filename_w = NULL;
477 DWORD len;
478 HRESULT ret;
480 if (!filename) return D3DXERR_INVALIDDATA;
482 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
483 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
484 if (!filename_w) return E_OUTOFMEMORY;
485 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
487 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
489 HeapFree(GetProcessHeap(), 0, filename_w);
490 return ret;
493 HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
494 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
496 void *buffer;
497 DWORD len;
498 HRESULT hr;
499 struct D3DXIncludeImpl includefromfile;
501 if (FAILED(map_view_of_file(filename, &buffer, &len)))
502 return D3DXERR_INVALIDDATA;
504 if (!include)
506 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
507 include = &includefromfile.ID3DXInclude_iface;
510 hr = D3DPreprocess(buffer, len, NULL,
511 (const D3D_SHADER_MACRO *)defines,
512 (ID3DInclude *) include,
513 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
515 UnmapViewOfFile(buffer);
516 return hr;
519 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
520 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
522 HRSRC res;
523 const char *buffer;
524 DWORD len;
526 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
527 return D3DXERR_INVALIDDATA;
528 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
529 return D3DXERR_INVALIDDATA;
530 return D3DXPreprocessShader(buffer, len, defines, include,
531 shader, error_messages);
534 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
535 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
537 HRSRC res;
538 const char *buffer;
539 DWORD len;
541 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
542 return D3DXERR_INVALIDDATA;
543 if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
544 return D3DXERR_INVALIDDATA;
545 return D3DXPreprocessShader(buffer, len, defines, include,
546 shader, error_messages);
550 struct ctab_constant {
551 D3DXCONSTANT_DESC desc;
552 struct ctab_constant *constants;
555 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
557 struct ID3DXConstantTableImpl {
558 ID3DXConstantTable ID3DXConstantTable_iface;
559 LONG ref;
560 char *ctab;
561 DWORD size;
562 D3DXCONSTANTTABLE_DESC desc;
563 struct ctab_constant *constants;
566 static void free_constant(struct ctab_constant *constant)
568 if (constant->constants)
570 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
572 for (i = 0; i < count; ++i)
574 free_constant(&constant->constants[i]);
576 HeapFree(GetProcessHeap(), 0, constant->constants);
580 static void free_constant_table(struct ID3DXConstantTableImpl *table)
582 if (table->constants)
584 UINT i;
586 for (i = 0; i < table->desc.Constants; ++i)
588 free_constant(&table->constants[i]);
590 HeapFree(GetProcessHeap(), 0, table->constants);
592 HeapFree(GetProcessHeap(), 0, table->ctab);
595 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
597 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
600 static inline BOOL is_vertex_shader(DWORD version)
602 return (version & 0xffff0000) == 0xfffe0000;
605 static inline struct ctab_constant *constant_from_handle(D3DXHANDLE handle)
607 return (struct ctab_constant *)handle;
610 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant)
612 return (D3DXHANDLE)constant;
615 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *, struct ctab_constant *, LPCSTR);
617 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, LPCSTR name)
619 UINT element;
620 LPCSTR part;
622 TRACE("constant %p, name %s\n", constant, debugstr_a(name));
624 if (!name || !*name) return NULL;
626 element = atoi(name);
627 part = strchr(name, ']') + 1;
629 if (constant->desc.Elements > element)
631 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant;
633 switch (*part++)
635 case '.':
636 return get_constant_by_name(NULL, c, part);
638 case '[':
639 return get_constant_element_by_name(c, part);
641 case '\0':
642 TRACE("Returning parameter %p\n", c);
643 return c;
645 default:
646 FIXME("Unhandled case \"%c\"\n", *--part);
647 break;
651 TRACE("Constant not found\n");
652 return NULL;
655 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
656 struct ctab_constant *constant, LPCSTR name)
658 UINT i, count, length;
659 struct ctab_constant *handles;
660 LPCSTR part;
662 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name));
664 if (!name || !*name) return NULL;
666 if (!constant)
668 count = table->desc.Constants;
669 handles = table->constants;
671 else
673 count = constant->desc.StructMembers;
674 handles = constant->constants;
677 length = strcspn(name, "[.");
678 part = name + length;
680 for (i = 0; i < count; i++)
682 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length))
684 switch (*part++)
686 case '.':
687 return get_constant_by_name(NULL, &handles[i], part);
689 case '[':
690 return get_constant_element_by_name(&handles[i], part);
692 default:
693 TRACE("Returning parameter %p\n", &handles[i]);
694 return &handles[i];
699 TRACE("Constant not found\n");
700 return NULL;
703 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, struct ctab_constant *constant)
705 UINT i, count;
707 /* all variable have at least elements = 1, but no elements */
708 if (!parent->constants) return NULL;
710 if (parent->desc.Elements > 1) count = parent->desc.Elements;
711 else count = parent->desc.StructMembers;
713 for (i = 0; i < count; ++i)
715 if (&parent->constants[i] == constant)
716 return constant;
718 if (is_valid_sub_constant(&parent->constants[i], constant))
719 return constant;
722 return NULL;
725 static inline struct ctab_constant *is_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
727 struct ctab_constant *c = constant_from_handle(handle);
728 UINT i;
730 if (!c) return NULL;
732 for (i = 0; i < table->desc.Constants; ++i)
734 if (&table->constants[i] == c)
735 return c;
737 if (is_valid_sub_constant(&table->constants[i], c))
738 return c;
741 return NULL;
744 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
746 struct ctab_constant *constant = is_valid_constant(table, handle);
748 if (!constant) constant = get_constant_by_name(table, NULL, handle);
750 return constant;
753 static inline void set_float_shader_constant(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device,
754 UINT register_index, const FLOAT *data, UINT count)
756 if (is_vertex_shader(table->desc.Version))
757 IDirect3DDevice9_SetVertexShaderConstantF(device, register_index, data, count);
758 else
759 IDirect3DDevice9_SetPixelShaderConstantF(device, register_index, data, count);
762 /*** IUnknown methods ***/
763 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
765 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
767 if (IsEqualGUID(riid, &IID_IUnknown) ||
768 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
769 IsEqualGUID(riid, &IID_ID3DXConstantTable))
771 ID3DXConstantTable_AddRef(iface);
772 *out = iface;
773 return S_OK;
776 WARN("Interface %s not found.\n", debugstr_guid(riid));
778 return E_NOINTERFACE;
781 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
783 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
785 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
787 return InterlockedIncrement(&This->ref);
790 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
792 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
793 ULONG ref = InterlockedDecrement(&This->ref);
795 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
797 if (!ref)
799 free_constant_table(This);
800 HeapFree(GetProcessHeap(), 0, This);
803 return ref;
806 /*** ID3DXBuffer methods ***/
807 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
809 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
811 TRACE("(%p)->()\n", This);
813 return This->ctab;
816 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
818 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
820 TRACE("(%p)->()\n", This);
822 return This->size;
825 /*** ID3DXConstantTable methods ***/
826 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
828 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
830 TRACE("(%p)->(%p)\n", This, desc);
832 if (!desc)
833 return D3DERR_INVALIDCALL;
835 *desc = This->desc;
837 return D3D_OK;
840 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
841 D3DXCONSTANT_DESC *desc, UINT *count)
843 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
844 struct ctab_constant *c = get_valid_constant(This, constant);
846 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
848 if (!c)
850 WARN("Invalid argument specified\n");
851 return D3DERR_INVALIDCALL;
854 if (desc) *desc = c->desc;
855 if (count) *count = 1;
857 return D3D_OK;
860 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
862 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
863 struct ctab_constant *c = get_valid_constant(This, constant);
865 TRACE("(%p)->(%p)\n", This, constant);
867 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER)
869 WARN("Invalid argument specified\n");
870 return (UINT)-1;
873 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex);
874 return c->desc.RegisterIndex;
877 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
879 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
880 struct ctab_constant *c;
882 TRACE("(%p)->(%p, %d)\n", This, constant, index);
884 if (constant)
886 c = get_valid_constant(This, constant);
887 if (c && index < c->desc.StructMembers)
889 c = &c->constants[index];
890 TRACE("Returning constant %p\n", c);
891 return handle_from_constant(c);
894 else
896 if (index < This->desc.Constants)
898 c = &This->constants[index];
899 TRACE("Returning constant %p\n", c);
900 return handle_from_constant(c);
904 WARN("Index out of range\n");
905 return NULL;
908 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface, D3DXHANDLE constant, LPCSTR name)
910 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
911 struct ctab_constant *c = get_valid_constant(This, constant);
913 TRACE("(%p)->(%p, %s)\n", This, constant, name);
915 c = get_constant_by_name(This, c, name);
916 TRACE("Returning constant %p\n", c);
918 return handle_from_constant(c);
921 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
923 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
924 struct ctab_constant *c = get_valid_constant(This, constant);
926 TRACE("(%p)->(%p, %d)\n", This, constant, index);
928 if (c && index < c->desc.Elements)
930 if (c->desc.Elements > 1) c = &c->constants[index];
931 TRACE("Returning constant %p\n", c);
932 return handle_from_constant(c);
935 WARN("Invalid argument specified\n");
936 return NULL;
939 static HRESULT set_scalar_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
940 UINT count, D3DXPARAMETER_TYPE type)
942 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
943 D3DXCONSTANT_DESC desc;
944 HRESULT hr;
945 UINT i, desc_count = 1;
946 float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
948 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
949 if (FAILED(hr))
951 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
952 return D3DERR_INVALIDCALL;
955 if (desc.Class != D3DXPC_SCALAR)
956 return D3D_OK;
958 switch (desc.RegisterSet)
960 case D3DXRS_FLOAT4:
961 for (i = 0; i < min(count, desc.RegisterCount); i++)
963 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
964 switch(type)
966 case D3DXPT_FLOAT:
967 row[0] = ((float *)data)[i];
968 break;
969 case D3DXPT_INT:
970 row[0] = (float)((int *)data)[i];
971 break;
972 case D3DXPT_BOOL:
973 row[0] = ((BOOL *)data)[i] ? 1.0f : 0.0f;
974 break;
975 default:
976 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
977 return D3DERR_INVALIDCALL;
979 set_float_shader_constant(This, device, desc.RegisterIndex + i, row, 1);
981 break;
982 default:
983 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
984 return E_NOTIMPL;
987 return D3D_OK;
990 static HRESULT set_vector_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
991 UINT count, D3DXPARAMETER_TYPE type)
993 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
994 D3DXCONSTANT_DESC desc;
995 HRESULT hr;
996 UINT i, j, desc_count = 1;
997 float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
999 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1000 if (FAILED(hr))
1002 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1003 return D3DERR_INVALIDCALL;
1006 if (desc.Class == D3DXPC_MATRIX_ROWS || desc.Class == D3DXPC_MATRIX_COLUMNS)
1007 return D3D_OK;
1009 switch (desc.RegisterSet)
1011 case D3DXRS_FLOAT4:
1012 for (i = 0; i < min(count, desc.RegisterCount); i++)
1014 switch (type)
1016 case D3DXPT_FLOAT:
1017 memcpy(vec, ((float *)data) + i * desc.Columns, desc.Columns * sizeof(float));
1018 break;
1019 case D3DXPT_INT:
1020 for (j = 0; j < desc.Columns; j++)
1021 vec[j] = (float)((int *)data)[i * desc.Columns + j];
1022 break;
1023 case D3DXPT_BOOL:
1024 for (j = 0; j < desc.Columns; j++)
1025 vec[j] = ((BOOL *)data)[i * desc.Columns + j] ? 1.0f : 0.0f;
1026 break;
1027 default:
1028 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1029 return D3DERR_INVALIDCALL;
1032 set_float_shader_constant(This, device, desc.RegisterIndex + i, vec, 1);
1034 break;
1035 default:
1036 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1037 return E_NOTIMPL;
1040 return D3D_OK;
1043 static HRESULT set_float_matrix(FLOAT *matrix, const D3DXCONSTANT_DESC *desc,
1044 UINT row_offset, UINT column_offset, UINT rows, UINT columns,
1045 const void *data, D3DXPARAMETER_TYPE type, UINT src_columns)
1047 UINT i, j;
1049 switch (type)
1051 case D3DXPT_FLOAT:
1052 for (i = 0; i < rows; i++)
1054 for (j = 0; j < columns; j++)
1055 matrix[i * row_offset + j * column_offset] = ((FLOAT *)data)[i * src_columns + j];
1057 break;
1058 case D3DXPT_INT:
1059 for (i = 0; i < rows; i++)
1061 for (j = 0; j < columns; j++)
1062 matrix[i * row_offset + j * column_offset] = ((INT *)data)[i * src_columns + j];
1064 break;
1065 default:
1066 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1067 return D3DERR_INVALIDCALL;
1070 return D3D_OK;
1073 static HRESULT set_matrix_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
1074 UINT count, D3DXPARAMETER_CLASS class, D3DXPARAMETER_TYPE type, UINT rows, UINT columns)
1076 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1077 struct ctab_constant *c = get_valid_constant(This, constant);
1078 D3DXCONSTANT_DESC *desc;
1079 UINT registers_per_matrix, num_rows, num_columns, i;
1080 UINT row_offset = 1, column_offset = 1;
1081 const DWORD *data_ptr;
1082 FLOAT matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1083 0.0f, 0.0f, 0.0f, 0.0f,
1084 0.0f, 0.0f, 0.0f, 0.0f,
1085 0.0f, 0.0f, 0.0f, 0.0f};
1087 if (!c)
1089 WARN("Invalid argument specified\n");
1090 return D3DERR_INVALIDCALL;
1092 desc = &c->desc;
1094 if (desc->Class == D3DXPC_MATRIX_ROWS
1095 || desc->Class == D3DXPC_MATRIX_COLUMNS
1096 || desc->Class == D3DXPC_VECTOR
1097 || desc->Class == D3DXPC_SCALAR)
1099 if (desc->Class == class) row_offset = 4;
1100 else column_offset = 4;
1102 if (class == D3DXPC_MATRIX_ROWS)
1104 if (desc->Class == D3DXPC_VECTOR) return D3D_OK;
1106 num_rows = desc->Rows;
1107 num_columns = desc->Columns;
1109 else
1111 num_rows = desc->Columns;
1112 num_columns = desc->Rows;
1115 registers_per_matrix = (desc->Class == D3DXPC_MATRIX_COLUMNS) ? desc->Columns : desc->Rows;
1117 else
1119 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1120 return E_NOTIMPL;
1123 switch (desc->RegisterSet)
1125 case D3DXRS_FLOAT4:
1126 data_ptr = data;
1127 for (i = 0; i < count; i++)
1129 HRESULT hr;
1131 if (registers_per_matrix * (i + 1) > desc->RegisterCount)
1132 break;
1134 hr = set_float_matrix(matrix, desc, row_offset, column_offset, num_rows, num_columns, data_ptr, type, columns);
1135 if (FAILED(hr)) return hr;
1137 set_float_shader_constant(This, device, desc->RegisterIndex + i * registers_per_matrix, matrix, registers_per_matrix);
1139 data_ptr += rows * columns;
1141 break;
1142 default:
1143 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1144 return E_NOTIMPL;
1147 return D3D_OK;
1150 static HRESULT set_matrix_pointer_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant,
1151 const D3DXMATRIX **data, UINT count, D3DXPARAMETER_CLASS class)
1153 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1154 D3DXCONSTANT_DESC desc;
1155 HRESULT hr;
1156 UINT registers_per_matrix;
1157 UINT i, desc_count = 1;
1158 UINT num_rows, num_columns;
1159 UINT row_offset, column_offset;
1160 FLOAT matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1161 0.0f, 0.0f, 0.0f, 0.0f,
1162 0.0f, 0.0f, 0.0f, 0.0f,
1163 0.0f, 0.0f, 0.0f, 0.0f};
1165 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1166 if (FAILED(hr))
1168 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1169 return D3DERR_INVALIDCALL;
1172 if (desc.Class == D3DXPC_MATRIX_ROWS || desc.Class == D3DXPC_MATRIX_COLUMNS)
1174 if (desc.Class == class)
1176 column_offset = 1;
1177 row_offset = 4;
1179 else
1181 column_offset = 4;
1182 row_offset = 1;
1185 if (class == D3DXPC_MATRIX_ROWS)
1187 num_rows = desc.Rows;
1188 num_columns = desc.Columns;
1190 else
1192 num_rows = desc.Columns;
1193 num_columns = desc.Rows;
1196 registers_per_matrix = (desc.Class == D3DXPC_MATRIX_ROWS) ? desc.Rows : desc.Columns;
1198 else if (desc.Class == D3DXPC_SCALAR)
1200 registers_per_matrix = 1;
1201 column_offset = 1;
1202 row_offset = 1;
1203 num_rows = desc.Rows;
1204 num_columns = desc.Columns;
1206 else if (desc.Class == D3DXPC_VECTOR)
1208 registers_per_matrix = 1;
1210 if (class == D3DXPC_MATRIX_ROWS)
1212 column_offset = 1;
1213 row_offset = 4;
1214 num_rows = desc.Rows;
1215 num_columns = desc.Columns;
1217 else
1219 column_offset = 4;
1220 row_offset = 1;
1221 num_rows = desc.Columns;
1222 num_columns = desc.Rows;
1225 else
1227 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc.Class));
1228 return D3D_OK;
1231 switch (desc.RegisterSet)
1233 case D3DXRS_FLOAT4:
1234 for (i = 0; i < count; i++)
1236 if (registers_per_matrix * (i + 1) > desc.RegisterCount)
1237 break;
1239 hr = set_float_matrix(matrix, &desc, row_offset, column_offset, num_rows, num_columns, *data, D3DXPT_FLOAT, 4);
1240 if (FAILED(hr)) return hr;
1242 set_float_shader_constant(This, device, desc.RegisterIndex + i * registers_per_matrix, matrix, registers_per_matrix);
1244 data++;
1246 break;
1247 default:
1248 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1249 return E_NOTIMPL;
1252 return D3D_OK;
1255 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1256 struct IDirect3DDevice9 *device)
1258 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1259 UINT i;
1261 TRACE("(%p)->(%p)\n", This, device);
1263 if (!device)
1264 return D3DERR_INVALIDCALL;
1266 for (i = 0; i < This->desc.Constants; i++)
1268 D3DXCONSTANT_DESC *desc = &This->constants[i].desc;
1270 if (!desc->DefaultValue)
1271 continue;
1273 set_float_shader_constant(This, device, desc->RegisterIndex, desc->DefaultValue, desc->RegisterCount);
1276 return D3D_OK;
1279 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1280 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, UINT bytes)
1282 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1283 HRESULT hr;
1284 UINT elements;
1285 UINT count = 1;
1286 D3DXCONSTANT_DESC desc;
1288 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, data, bytes);
1290 if (!device || !constant || !data)
1291 return D3DERR_INVALIDCALL;
1293 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
1294 if (FAILED(hr))
1295 return hr;
1297 elements = bytes / (desc.Bytes / desc.Elements);
1299 switch (desc.Class)
1301 case D3DXPC_SCALAR:
1302 return set_scalar_array(iface, device, constant, data, elements, desc.Type);
1303 case D3DXPC_VECTOR:
1304 return set_vector_array(iface, device, constant, data, elements, desc.Type);
1305 case D3DXPC_MATRIX_ROWS:
1306 case D3DXPC_MATRIX_COLUMNS:
1307 return set_matrix_array(iface, device, constant, data, elements,
1308 D3DXPC_MATRIX_ROWS, desc.Type, desc.Rows, desc.Columns);
1309 default:
1310 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc.Class));
1311 return D3DERR_INVALIDCALL;
1315 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1316 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1318 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1320 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, b);
1322 return set_scalar_array(iface, device, constant, &b, 1, D3DXPT_BOOL);
1325 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1326 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1328 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1330 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, b, count);
1332 return set_scalar_array(iface, device, constant, b, count, D3DXPT_BOOL);
1335 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1336 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1338 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1340 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
1342 return set_scalar_array(iface, device, constant, &n, 1, D3DXPT_INT);
1345 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1346 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1348 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1350 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
1352 return set_scalar_array(iface, device, constant, n, count, D3DXPT_INT);
1355 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1356 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1358 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1360 TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
1362 return set_scalar_array(iface, device, constant, &f, 1, D3DXPT_FLOAT);
1365 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1366 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1368 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1370 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
1372 return set_scalar_array(iface, device, constant, f, count, D3DXPT_FLOAT);
1375 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1376 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1378 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1380 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
1382 return set_vector_array(iface, device, constant, vector, 1, D3DXPT_FLOAT);
1385 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1386 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1388 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1390 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
1392 return set_vector_array(iface, device, constant, vector, count, D3DXPT_FLOAT);
1395 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1396 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1398 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1400 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1402 return set_matrix_array(iface, device, constant, matrix, 1, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4);
1405 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1406 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1408 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1410 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1412 return set_matrix_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4);
1415 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1416 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1418 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1420 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1422 return set_matrix_pointer_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_ROWS);
1425 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1426 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1428 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1430 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1432 return set_matrix_array(iface, device, constant, matrix, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4);
1435 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1436 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1438 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1440 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1442 return set_matrix_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4);
1445 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface,
1446 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1448 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1450 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1452 return set_matrix_pointer_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_COLUMNS);
1455 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1457 /*** IUnknown methods ***/
1458 ID3DXConstantTableImpl_QueryInterface,
1459 ID3DXConstantTableImpl_AddRef,
1460 ID3DXConstantTableImpl_Release,
1461 /*** ID3DXBuffer methods ***/
1462 ID3DXConstantTableImpl_GetBufferPointer,
1463 ID3DXConstantTableImpl_GetBufferSize,
1464 /*** ID3DXConstantTable methods ***/
1465 ID3DXConstantTableImpl_GetDesc,
1466 ID3DXConstantTableImpl_GetConstantDesc,
1467 ID3DXConstantTableImpl_GetSamplerIndex,
1468 ID3DXConstantTableImpl_GetConstant,
1469 ID3DXConstantTableImpl_GetConstantByName,
1470 ID3DXConstantTableImpl_GetConstantElement,
1471 ID3DXConstantTableImpl_SetDefaults,
1472 ID3DXConstantTableImpl_SetValue,
1473 ID3DXConstantTableImpl_SetBool,
1474 ID3DXConstantTableImpl_SetBoolArray,
1475 ID3DXConstantTableImpl_SetInt,
1476 ID3DXConstantTableImpl_SetIntArray,
1477 ID3DXConstantTableImpl_SetFloat,
1478 ID3DXConstantTableImpl_SetFloatArray,
1479 ID3DXConstantTableImpl_SetVector,
1480 ID3DXConstantTableImpl_SetVectorArray,
1481 ID3DXConstantTableImpl_SetMatrix,
1482 ID3DXConstantTableImpl_SetMatrixArray,
1483 ID3DXConstantTableImpl_SetMatrixPointerArray,
1484 ID3DXConstantTableImpl_SetMatrixTranspose,
1485 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1486 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1489 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
1490 BOOL is_element, WORD index, WORD max, DWORD *offset, DWORD nameoffset, UINT regset)
1492 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
1493 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
1494 HRESULT hr = D3D_OK;
1495 UINT i, count = 0;
1496 WORD size = 0;
1498 constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
1499 constant->desc.Class = type->Class;
1500 constant->desc.Type = type->Type;
1501 constant->desc.Rows = type->Rows;
1502 constant->desc.Columns = type->Columns;
1503 constant->desc.Elements = is_element ? 1 : type->Elements;
1504 constant->desc.StructMembers = type->StructMembers;
1505 constant->desc.Name = ctab + nameoffset;
1506 constant->desc.RegisterSet = regset;
1507 constant->desc.RegisterIndex = index;
1509 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name,
1510 constant->desc.Elements, index, constant->desc.DefaultValue,
1511 debug_d3dxparameter_registerset(regset));
1512 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1513 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type),
1514 type->Rows, type->Columns, type->Elements, type->StructMembers);
1516 if (type->Elements > 1 && !is_element)
1518 count = type->Elements;
1520 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
1522 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
1523 count = type->StructMembers;
1526 if (count)
1528 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
1529 if (!constant->constants)
1531 ERR("Out of memory\n");
1532 hr = E_OUTOFMEMORY;
1533 goto error;
1536 for (i = 0; i < count; ++i)
1538 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
1539 &constant->constants[i], memberinfo == NULL, index + size, max, offset,
1540 memberinfo ? memberinfo[i].Name : nameoffset, regset);
1541 if (hr != D3D_OK)
1542 goto error;
1544 size += constant->constants[i].desc.RegisterCount;
1547 else
1549 WORD offsetdiff = 0;
1551 switch (type->Class)
1553 case D3DXPC_SCALAR:
1554 case D3DXPC_VECTOR:
1555 offsetdiff = 1;
1556 size = 1;
1557 break;
1559 case D3DXPC_MATRIX_ROWS:
1560 size = is_element ? type->Rows : max(type->Rows, type->Columns);
1561 offsetdiff = type->Rows;
1562 break;
1564 case D3DXPC_MATRIX_COLUMNS:
1565 size = type->Columns;
1566 offsetdiff = type->Columns;
1567 break;
1569 case D3DXPC_OBJECT:
1570 size = 1;
1571 break;
1573 default:
1574 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type->Class));
1575 break;
1578 /* offset in bytes => offsetdiff * components(4) * sizeof(DWORD) */
1579 if (offset) *offset += offsetdiff * 4 * 4;
1581 /* int and bool registerset have different sizes */
1582 if (regset == D3DXRS_INT4 || regset == D3DXRS_BOOL)
1584 switch (type->Class)
1586 case D3DXPC_SCALAR:
1587 case D3DXPC_VECTOR:
1588 size = type->Columns;
1589 break;
1591 case D3DXPC_MATRIX_ROWS:
1592 case D3DXPC_MATRIX_COLUMNS:
1593 size = 4 * type->Columns;
1594 break;
1596 default:
1597 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type->Class));
1598 break;
1603 constant->desc.RegisterCount = max(0, min(max - index, size));
1604 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns;
1606 return D3D_OK;
1608 error:
1609 if (constant->constants)
1611 for (i = 0; i < count; ++i)
1613 free_constant(&constant->constants[i]);
1615 HeapFree(GetProcessHeap(), 0, constant->constants);
1616 constant->constants = NULL;
1619 return hr;
1622 HRESULT WINAPI D3DXGetShaderConstantTableEx(const DWORD *byte_code, DWORD flags, ID3DXConstantTable **constant_table)
1624 struct ID3DXConstantTableImpl *object = NULL;
1625 HRESULT hr;
1626 LPCVOID data;
1627 UINT size;
1628 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1629 const D3DXSHADER_CONSTANTINFO *constant_info;
1630 DWORD i;
1632 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code, flags, constant_table);
1634 if (constant_table) *constant_table = NULL;
1636 if (!byte_code || !constant_table)
1638 WARN("Invalid argument specified.\n");
1639 return D3DERR_INVALIDCALL;
1642 if (!is_valid_bytecode(*byte_code))
1644 WARN("Invalid byte_code specified.\n");
1645 return D3D_OK;
1648 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags);
1650 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1651 if (hr != D3D_OK)
1653 WARN("CTAB not found.\n");
1654 return D3DXERR_INVALIDDATA;
1657 if (size < sizeof(*ctab_header))
1659 WARN("Invalid CTAB size.\n");
1660 return D3DXERR_INVALIDDATA;
1663 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1664 if (ctab_header->Size != sizeof(*ctab_header))
1666 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1667 return D3DXERR_INVALIDDATA;
1670 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1671 if (!object)
1673 ERR("Out of memory\n");
1674 return E_OUTOFMEMORY;
1677 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1678 object->ref = 1;
1680 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1681 if (!object->ctab)
1683 ERR("Out of memory\n");
1684 HeapFree(GetProcessHeap(), 0, object);
1685 return E_OUTOFMEMORY;
1687 object->size = size;
1688 memcpy(object->ctab, data, object->size);
1690 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1691 object->desc.Version = ctab_header->Version;
1692 object->desc.Constants = ctab_header->Constants;
1693 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1694 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
1695 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
1697 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1698 sizeof(*object->constants) * object->desc.Constants);
1699 if (!object->constants)
1701 ERR("Out of memory\n");
1702 hr = E_OUTOFMEMORY;
1703 goto error;
1706 constant_info = (const D3DXSHADER_CONSTANTINFO *)(object->ctab + ctab_header->ConstantInfo);
1707 for (i = 0; i < ctab_header->Constants; i++)
1709 DWORD offset = constant_info[i].DefaultValue;
1711 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
1712 &object->constants[i], FALSE, constant_info[i].RegisterIndex,
1713 constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
1714 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
1715 if (hr != D3D_OK)
1716 goto error;
1719 *constant_table = &object->ID3DXConstantTable_iface;
1721 return D3D_OK;
1723 error:
1724 free_constant_table(object);
1725 HeapFree(GetProcessHeap(), 0, object);
1727 return hr;
1730 HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantTable **constant_table)
1732 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1734 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1737 HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count)
1739 UINT i, sampler_count = 0;
1740 UINT size;
1741 const char *data;
1742 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1743 const D3DXSHADER_CONSTANTINFO *constant_info;
1745 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
1747 if (count) *count = 0;
1749 if (D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (const void **)&data, &size) != D3D_OK)
1750 return D3D_OK;
1752 if (size < sizeof(*ctab_header)) return D3D_OK;
1754 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1755 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
1757 constant_info = (const D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
1758 for (i = 0; i < ctab_header->Constants; i++)
1760 const D3DXSHADER_TYPEINFO *type;
1762 TRACE("name = %s\n", data + constant_info[i].Name);
1764 type = (const D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
1766 if (type->Type == D3DXPT_SAMPLER
1767 || type->Type == D3DXPT_SAMPLER1D
1768 || type->Type == D3DXPT_SAMPLER2D
1769 || type->Type == D3DXPT_SAMPLER3D
1770 || type->Type == D3DXPT_SAMPLERCUBE)
1772 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
1774 ++sampler_count;
1778 TRACE("Found %u samplers\n", sampler_count);
1780 if (count) *count = sampler_count;
1782 return D3D_OK;