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
22 #include "wine/port.h"
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "wine/debug.h"
27 #include "wine/unicode.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,
41 ID3DBlob **shader, ID3DBlob **error_messages);
43 const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device)
47 TRACE("device %p\n", device);
49 if (!device) return NULL;
51 IDirect3DDevice9_GetDeviceCaps(device,&caps);
53 switch (caps.PixelShaderVersion)
55 case D3DPS_VERSION(1, 1):
58 case D3DPS_VERSION(1, 2):
61 case D3DPS_VERSION(1, 3):
64 case D3DPS_VERSION(1, 4):
67 case D3DPS_VERSION(2, 0):
68 if ((caps.PS20Caps.NumTemps>=22) &&
69 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) &&
70 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
71 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) &&
72 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
73 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
77 if ((caps.PS20Caps.NumTemps>=32) &&
78 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
84 case D3DPS_VERSION(3, 0):
91 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
93 const DWORD *ptr = byte_code;
95 TRACE("byte_code %p\n", byte_code);
99 /* Look for the END token, skipping the VERSION token */
100 while (*++ptr != D3DSIO_END)
103 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
105 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
110 /* Return the shader size in bytes */
111 return (ptr - byte_code) * sizeof(*ptr);
114 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
116 TRACE("byte_code %p\n", byte_code);
118 return byte_code ? *byte_code : 0;
121 const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device)
125 TRACE("device %p\n", device);
127 if (!device) return NULL;
129 IDirect3DDevice9_GetDeviceCaps(device,&caps);
131 switch (caps.VertexShaderVersion)
133 case D3DVS_VERSION(1, 1):
135 case D3DVS_VERSION(2, 0):
136 if ((caps.VS20Caps.NumTemps>=13) &&
137 (caps.VS20Caps.DynamicFlowControlDepth==24) &&
138 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
143 case D3DVS_VERSION(3, 0):
150 HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size)
152 CONST DWORD *ptr = byte_code;
154 TRACE("(%p, %x, %p, %p)\n", byte_code, fourcc, data, size);
156 if (data) *data = NULL;
160 return D3DERR_INVALIDCALL;
162 while (*++ptr != D3DSIO_END)
164 /* Check if it is a comment */
165 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
167 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
169 /* Check if this is the comment we are looking for */
170 if (*(ptr + 1) == fourcc)
172 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
173 LPCVOID ctab_data = ptr + 2;
178 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
188 HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMACRO *defines,
189 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
191 /* Forward to d3dcompiler: the parameter types aren't really different,
192 the actual data types are equivalent */
193 HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
194 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
195 (ID3DBlob **)error_messages);
197 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
201 /* D3DXInclude private implementation, used to implement
202 D3DXAssembleShaderFromFile from D3DXAssembleShader */
203 /* To be able to correctly resolve include search paths we have to store
204 the pathname of each include file. We store the pathname pointer right
205 before the file data. */
206 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
207 D3DXINCLUDE_TYPE include_type,
208 LPCSTR filename, LPCVOID parent_data,
209 LPCVOID *data, UINT *bytes) {
210 const char *p, *parent_name = "";
211 char *pathname = NULL;
212 char **buffer = NULL;
216 if(parent_data != NULL)
217 parent_name = *((const char **)parent_data - 1);
219 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
221 if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
222 else p = parent_name;
223 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
225 return HRESULT_FROM_WIN32(GetLastError());
227 memcpy(pathname, parent_name, p - parent_name);
228 strcpy(pathname + (p - parent_name), filename);
230 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
231 if(file == INVALID_HANDLE_VALUE)
234 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
236 size = GetFileSize(file, NULL);
237 if(size == INVALID_FILE_SIZE)
240 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
244 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
254 HeapFree(GetProcessHeap(), 0, pathname);
255 HeapFree(GetProcessHeap(), 0, buffer);
256 return HRESULT_FROM_WIN32(GetLastError());
259 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
260 HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
261 HeapFree(GetProcessHeap(), 0, (char **)data - 1);
265 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
266 d3dincludefromfile_open,
267 d3dincludefromfile_close
270 struct D3DXIncludeImpl {
271 ID3DXInclude ID3DXInclude_iface;
274 HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines,
275 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
277 LPWSTR filename_w = NULL;
281 if (!filename) return D3DXERR_INVALIDDATA;
283 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
284 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
285 if (!filename_w) return E_OUTOFMEMORY;
286 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
288 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
290 HeapFree(GetProcessHeap(), 0, filename_w);
294 HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
295 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
300 struct D3DXIncludeImpl includefromfile;
302 if(FAILED(map_view_of_file(filename, &buffer, &len)))
303 return D3DXERR_INVALIDDATA;
307 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
308 include = &includefromfile.ID3DXInclude_iface;
311 hr = D3DXAssembleShader(buffer, len, defines, include, flags,
312 shader, error_messages);
314 UnmapViewOfFile(buffer);
318 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
319 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
325 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
326 return D3DXERR_INVALIDDATA;
327 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
328 return D3DXERR_INVALIDDATA;
329 return D3DXAssembleShader(buffer, len, defines, include, flags,
330 shader, error_messages);
333 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
334 ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
340 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
341 return D3DXERR_INVALIDDATA;
342 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
343 return D3DXERR_INVALIDDATA;
344 return D3DXAssembleShader(buffer, len, defines, include, flags,
345 shader, error_messages);
348 HRESULT WINAPI D3DXCompileShader(const char *pSrcData, UINT srcDataLen, const D3DXMACRO *pDefines,
349 ID3DXInclude *pInclude, const char *pFunctionName, const char *pProfile, DWORD Flags,
350 ID3DXBuffer **ppShader, ID3DXBuffer **ppErrorMsgs, ID3DXConstantTable **ppConstantTable)
352 HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
353 (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
354 pFunctionName, pProfile, Flags, 0,
355 (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
357 if(SUCCEEDED(hr) && ppConstantTable)
358 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
363 HRESULT WINAPI D3DXCompileShaderFromFileA(const char *filename, const D3DXMACRO *defines,
364 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
365 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
367 LPWSTR filename_w = NULL;
371 if (!filename) return D3DXERR_INVALIDDATA;
373 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
374 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
375 if (!filename_w) return E_OUTOFMEMORY;
376 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
378 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
379 entrypoint, profile, flags,
380 shader, error_messages, constant_table);
382 HeapFree(GetProcessHeap(), 0, filename_w);
386 HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
387 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
388 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
391 DWORD len, filename_len;
393 struct D3DXIncludeImpl includefromfile;
396 if (FAILED(map_view_of_file(filename, &buffer, &len)))
397 return D3DXERR_INVALIDDATA;
401 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
402 include = &includefromfile.ID3DXInclude_iface;
405 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
406 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
409 UnmapViewOfFile(buffer);
410 return E_OUTOFMEMORY;
412 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
414 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
415 (ID3DInclude *)include, entrypoint, profile, flags, 0,
416 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
418 if (SUCCEEDED(hr) && constant_table)
419 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
422 HeapFree(GetProcessHeap(), 0, filename_a);
423 UnmapViewOfFile(buffer);
427 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
428 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
429 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
435 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
436 return D3DXERR_INVALIDDATA;
437 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
438 return D3DXERR_INVALIDDATA;
439 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
440 flags, shader, error_messages, constant_table);
443 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
444 ID3DXInclude *include, const char *entrypoint, const char *profile, DWORD flags,
445 ID3DXBuffer **shader, ID3DXBuffer **error_messages, ID3DXConstantTable **constant_table)
451 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
452 return D3DXERR_INVALIDDATA;
453 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
454 return D3DXERR_INVALIDDATA;
455 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
456 flags, shader, error_messages, constant_table);
459 HRESULT WINAPI D3DXPreprocessShader(const char *data, UINT data_len, const D3DXMACRO *defines,
460 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
462 TRACE("Forward to D3DPreprocess\n");
463 return D3DPreprocess(data, data_len, NULL,
464 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
465 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
468 HRESULT WINAPI D3DXPreprocessShaderFromFileA(const char *filename, const D3DXMACRO *defines,
469 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
471 WCHAR *filename_w = NULL;
475 if (!filename) return D3DXERR_INVALIDDATA;
477 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
478 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
479 if (!filename_w) return E_OUTOFMEMORY;
480 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
482 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
484 HeapFree(GetProcessHeap(), 0, filename_w);
488 HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMACRO *defines,
489 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
494 struct D3DXIncludeImpl includefromfile;
496 if (FAILED(map_view_of_file(filename, &buffer, &len)))
497 return D3DXERR_INVALIDDATA;
501 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
502 include = &includefromfile.ID3DXInclude_iface;
505 hr = D3DPreprocess(buffer, len, NULL,
506 (const D3D_SHADER_MACRO *)defines,
507 (ID3DInclude *) include,
508 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
510 UnmapViewOfFile(buffer);
514 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module, const char *resource, const D3DXMACRO *defines,
515 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
521 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
522 return D3DXERR_INVALIDDATA;
523 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
524 return D3DXERR_INVALIDDATA;
525 return D3DXPreprocessShader(buffer, len, defines, include,
526 shader, error_messages);
529 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module, const WCHAR *resource, const D3DXMACRO *defines,
530 ID3DXInclude *include, ID3DXBuffer **shader, ID3DXBuffer **error_messages)
536 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
537 return D3DXERR_INVALIDDATA;
538 if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
539 return D3DXERR_INVALIDDATA;
540 return D3DXPreprocessShader(buffer, len, defines, include,
541 shader, error_messages);
545 struct ctab_constant {
546 D3DXCONSTANT_DESC desc;
547 struct ctab_constant *constants;
550 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
552 struct ID3DXConstantTableImpl {
553 ID3DXConstantTable ID3DXConstantTable_iface;
557 D3DXCONSTANTTABLE_DESC desc;
558 struct ctab_constant *constants;
561 static void free_constant(struct ctab_constant *constant)
563 if (constant->constants)
565 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
567 for (i = 0; i < count; ++i)
569 free_constant(&constant->constants[i]);
571 HeapFree(GetProcessHeap(), 0, constant->constants);
575 static void free_constant_table(struct ID3DXConstantTableImpl *table)
577 if (table->constants)
581 for (i = 0; i < table->desc.Constants; ++i)
583 free_constant(&table->constants[i]);
585 HeapFree(GetProcessHeap(), 0, table->constants);
587 HeapFree(GetProcessHeap(), 0, table->ctab);
590 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
592 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
595 static inline int is_vertex_shader(DWORD version)
597 return (version & 0xFFFF0000) == 0xFFFE0000;
600 static inline struct ctab_constant *constant_from_handle(D3DXHANDLE handle)
602 return (struct ctab_constant *)handle;
605 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant)
607 return (D3DXHANDLE)constant;
610 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *, struct ctab_constant *, LPCSTR);
612 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, LPCSTR name)
617 TRACE("constant %p, name %s\n", constant, debugstr_a(name));
619 if (!name || !*name) return NULL;
621 element = atoi(name);
622 part = strchr(name, ']') + 1;
624 if (constant->desc.Elements > element)
626 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant;
631 return get_constant_by_name(NULL, c, part);
634 return get_constant_element_by_name(c, part);
637 TRACE("Returning parameter %p\n", c);
641 FIXME("Unhandled case \"%c\"\n", *--part);
646 TRACE("Constant not found\n");
650 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
651 struct ctab_constant *constant, LPCSTR name)
653 UINT i, count, length;
654 struct ctab_constant *handles;
657 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name));
659 if (!name || !*name) return NULL;
663 count = table->desc.Constants;
664 handles = table->constants;
668 count = constant->desc.StructMembers;
669 handles = constant->constants;
672 length = strcspn(name, "[.");
673 part = name + length;
675 for (i = 0; i < count; i++)
677 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length))
682 return get_constant_by_name(NULL, &handles[i], part);
685 return get_constant_element_by_name(&handles[i], part);
688 TRACE("Returning parameter %p\n", &handles[i]);
694 TRACE("Constant not found\n");
698 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, struct ctab_constant *constant)
702 /* all variable have at least elements = 1, but no elements */
703 if (!parent->constants) return NULL;
705 if (parent->desc.Elements > 1) count = parent->desc.Elements;
706 else count = parent->desc.StructMembers;
708 for (i = 0; i < count; ++i)
710 if (&parent->constants[i] == constant)
713 if (is_valid_sub_constant(&parent->constants[i], constant))
720 static inline struct ctab_constant *is_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
722 struct ctab_constant *c = constant_from_handle(handle);
727 for (i = 0; i < table->desc.Constants; ++i)
729 if (&table->constants[i] == c)
732 if (is_valid_sub_constant(&table->constants[i], c))
739 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
741 struct ctab_constant *constant = is_valid_constant(table, handle);
743 if (!constant) constant = get_constant_by_name(table, NULL, handle);
748 static inline void set_float_shader_constant(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device,
749 UINT register_index, const FLOAT *data, UINT count)
751 if (is_vertex_shader(table->desc.Version))
752 IDirect3DDevice9_SetVertexShaderConstantF(device, register_index, data, count);
754 IDirect3DDevice9_SetPixelShaderConstantF(device, register_index, data, count);
757 /*** IUnknown methods ***/
758 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
760 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
762 if (IsEqualGUID(riid, &IID_IUnknown) ||
763 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
764 IsEqualGUID(riid, &IID_ID3DXConstantTable))
766 ID3DXConstantTable_AddRef(iface);
771 WARN("Interface %s not found.\n", debugstr_guid(riid));
773 return E_NOINTERFACE;
776 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
778 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
780 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
782 return InterlockedIncrement(&This->ref);
785 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
787 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
788 ULONG ref = InterlockedDecrement(&This->ref);
790 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
794 free_constant_table(This);
795 HeapFree(GetProcessHeap(), 0, This);
801 /*** ID3DXBuffer methods ***/
802 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
804 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
806 TRACE("(%p)->()\n", This);
811 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
813 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
815 TRACE("(%p)->()\n", This);
820 /*** ID3DXConstantTable methods ***/
821 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
823 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
825 TRACE("(%p)->(%p)\n", This, desc);
828 return D3DERR_INVALIDCALL;
835 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
836 D3DXCONSTANT_DESC *desc, UINT *count)
838 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
839 struct ctab_constant *c = get_valid_constant(This, constant);
841 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
845 WARN("Invalid argument specified\n");
846 return D3DERR_INVALIDCALL;
849 if (desc) *desc = c->desc;
850 if (count) *count = 1;
855 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
857 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
858 struct ctab_constant *c = get_valid_constant(This, constant);
860 TRACE("(%p)->(%p)\n", This, constant);
862 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER)
864 WARN("Invalid argument specified\n");
868 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex);
869 return c->desc.RegisterIndex;
872 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
874 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
875 struct ctab_constant *c;
877 TRACE("(%p)->(%p, %d)\n", This, constant, index);
881 c = get_valid_constant(This, constant);
882 if (c && index < c->desc.StructMembers)
884 c = &c->constants[index];
885 TRACE("Returning constant %p\n", c);
886 return handle_from_constant(c);
891 if (index < This->desc.Constants)
893 c = &This->constants[index];
894 TRACE("Returning constant %p\n", c);
895 return handle_from_constant(c);
899 WARN("Index out of range\n");
903 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface, D3DXHANDLE constant, LPCSTR name)
905 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
906 struct ctab_constant *c = get_valid_constant(This, constant);
908 TRACE("(%p)->(%p, %s)\n", This, constant, name);
910 c = get_constant_by_name(This, c, name);
911 TRACE("Returning constant %p\n", c);
913 return handle_from_constant(c);
916 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
918 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
919 struct ctab_constant *c = get_valid_constant(This, constant);
921 TRACE("(%p)->(%p, %d)\n", This, constant, index);
923 if (c && index < c->desc.Elements)
925 if (c->desc.Elements > 1) c = &c->constants[index];
926 TRACE("Returning constant %p\n", c);
927 return handle_from_constant(c);
930 WARN("Invalid argument specified\n");
934 static HRESULT set_scalar_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
935 UINT count, D3DXPARAMETER_TYPE type)
937 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
938 D3DXCONSTANT_DESC desc;
940 UINT i, desc_count = 1;
941 float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
943 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
946 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
947 return D3DERR_INVALIDCALL;
950 if (desc.Class != D3DXPC_SCALAR)
953 switch (desc.RegisterSet)
956 for (i = 0; i < min(count, desc.RegisterCount); i++)
958 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
962 row[0] = ((float *)data)[i];
965 row[0] = (float)((int *)data)[i];
968 row[0] = ((BOOL *)data)[i] ? 1.0f : 0.0f;
971 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
972 return D3DERR_INVALIDCALL;
974 set_float_shader_constant(This, device, desc.RegisterIndex + i, row, 1);
978 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
985 static HRESULT set_vector_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
986 UINT count, D3DXPARAMETER_TYPE type)
988 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
989 D3DXCONSTANT_DESC desc;
991 UINT i, j, desc_count = 1;
992 float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
994 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
997 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
998 return D3DERR_INVALIDCALL;
1001 if (desc.Class == D3DXPC_MATRIX_ROWS || desc.Class == D3DXPC_MATRIX_COLUMNS)
1004 switch (desc.RegisterSet)
1007 for (i = 0; i < min(count, desc.RegisterCount); i++)
1012 memcpy(vec, ((float *)data) + i * desc.Columns, desc.Columns * sizeof(float));
1015 for (j = 0; j < desc.Columns; j++)
1016 vec[j] = (float)((int *)data)[i * desc.Columns + j];
1019 for (j = 0; j < desc.Columns; j++)
1020 vec[j] = ((BOOL *)data)[i * desc.Columns + j] ? 1.0f : 0.0f;
1023 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1024 return D3DERR_INVALIDCALL;
1027 set_float_shader_constant(This, device, desc.RegisterIndex + i, vec, 1);
1031 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1038 static HRESULT set_float_matrix(FLOAT *matrix, const D3DXCONSTANT_DESC *desc,
1039 UINT row_offset, UINT column_offset, UINT rows, UINT columns,
1040 const void *data, D3DXPARAMETER_TYPE type, UINT src_columns)
1047 for (i = 0; i < rows; i++)
1049 for (j = 0; j < columns; j++)
1050 matrix[i * row_offset + j * column_offset] = ((FLOAT *)data)[i * src_columns + j];
1054 for (i = 0; i < rows; i++)
1056 for (j = 0; j < columns; j++)
1057 matrix[i * row_offset + j * column_offset] = ((INT *)data)[i * src_columns + j];
1061 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1062 return D3DERR_INVALIDCALL;
1068 static HRESULT set_matrix_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
1069 UINT count, D3DXPARAMETER_CLASS class, D3DXPARAMETER_TYPE type, UINT rows, UINT columns)
1071 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1072 struct ctab_constant *c = get_valid_constant(This, constant);
1073 D3DXCONSTANT_DESC *desc;
1074 UINT registers_per_matrix, num_rows, num_columns, i;
1075 UINT row_offset = 1, column_offset = 1;
1076 const DWORD *data_ptr;
1077 FLOAT matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1078 0.0f, 0.0f, 0.0f, 0.0f,
1079 0.0f, 0.0f, 0.0f, 0.0f,
1080 0.0f, 0.0f, 0.0f, 0.0f};
1084 WARN("Invalid argument specified\n");
1085 return D3DERR_INVALIDCALL;
1089 if (desc->Class == D3DXPC_MATRIX_ROWS
1090 || desc->Class == D3DXPC_MATRIX_COLUMNS
1091 || desc->Class == D3DXPC_VECTOR
1092 || desc->Class == D3DXPC_SCALAR)
1094 if (desc->Class == class) row_offset = 4;
1095 else column_offset = 4;
1097 if (class == D3DXPC_MATRIX_ROWS)
1099 if (desc->Class == D3DXPC_VECTOR) return D3D_OK;
1101 num_rows = desc->Rows;
1102 num_columns = desc->Columns;
1106 num_rows = desc->Columns;
1107 num_columns = desc->Rows;
1110 registers_per_matrix = (desc->Class == D3DXPC_MATRIX_COLUMNS) ? desc->Columns : desc->Rows;
1114 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1118 switch (desc->RegisterSet)
1122 for (i = 0; i < count; i++)
1126 if (registers_per_matrix * (i + 1) > desc->RegisterCount)
1129 hr = set_float_matrix(matrix, desc, row_offset, column_offset, num_rows, num_columns, data_ptr, type, columns);
1130 if (FAILED(hr)) return hr;
1132 set_float_shader_constant(This, device, desc->RegisterIndex + i * registers_per_matrix, matrix, registers_per_matrix);
1134 data_ptr += rows * columns;
1138 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1145 static HRESULT set_matrix_pointer_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant,
1146 const D3DXMATRIX **data, UINT count, D3DXPARAMETER_CLASS class)
1148 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1149 D3DXCONSTANT_DESC desc;
1151 UINT registers_per_matrix;
1152 UINT i, desc_count = 1;
1153 UINT num_rows, num_columns;
1154 UINT row_offset, column_offset;
1155 FLOAT matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1156 0.0f, 0.0f, 0.0f, 0.0f,
1157 0.0f, 0.0f, 0.0f, 0.0f,
1158 0.0f, 0.0f, 0.0f, 0.0f};
1160 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1163 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1164 return D3DERR_INVALIDCALL;
1167 if (desc.Class == D3DXPC_MATRIX_ROWS || desc.Class == D3DXPC_MATRIX_COLUMNS)
1169 if (desc.Class == class)
1180 if (class == D3DXPC_MATRIX_ROWS)
1182 num_rows = desc.Rows;
1183 num_columns = desc.Columns;
1187 num_rows = desc.Columns;
1188 num_columns = desc.Rows;
1191 registers_per_matrix = (desc.Class == D3DXPC_MATRIX_ROWS) ? desc.Rows : desc.Columns;
1193 else if (desc.Class == D3DXPC_SCALAR)
1195 registers_per_matrix = 1;
1198 num_rows = desc.Rows;
1199 num_columns = desc.Columns;
1201 else if (desc.Class == D3DXPC_VECTOR)
1203 registers_per_matrix = 1;
1205 if (class == D3DXPC_MATRIX_ROWS)
1209 num_rows = desc.Rows;
1210 num_columns = desc.Columns;
1216 num_rows = desc.Columns;
1217 num_columns = desc.Rows;
1222 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc.Class));
1226 switch (desc.RegisterSet)
1229 for (i = 0; i < count; i++)
1231 if (registers_per_matrix * (i + 1) > desc.RegisterCount)
1234 hr = set_float_matrix(matrix, &desc, row_offset, column_offset, num_rows, num_columns, *data, D3DXPT_FLOAT, 4);
1235 if (FAILED(hr)) return hr;
1237 set_float_shader_constant(This, device, desc.RegisterIndex + i * registers_per_matrix, matrix, registers_per_matrix);
1243 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1250 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1251 struct IDirect3DDevice9 *device)
1253 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1256 TRACE("(%p)->(%p)\n", This, device);
1259 return D3DERR_INVALIDCALL;
1261 for (i = 0; i < This->desc.Constants; i++)
1263 D3DXCONSTANT_DESC *desc = &This->constants[i].desc;
1265 if (!desc->DefaultValue)
1268 set_float_shader_constant(This, device, desc->RegisterIndex, desc->DefaultValue, desc->RegisterCount);
1274 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1275 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, UINT bytes)
1277 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1281 D3DXCONSTANT_DESC desc;
1283 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, data, bytes);
1285 if (!device || !constant || !data)
1286 return D3DERR_INVALIDCALL;
1288 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
1292 elements = bytes / (desc.Bytes / desc.Elements);
1297 return set_scalar_array(iface, device, constant, data, elements, desc.Type);
1299 return set_vector_array(iface, device, constant, data, elements, desc.Type);
1300 case D3DXPC_MATRIX_ROWS:
1301 case D3DXPC_MATRIX_COLUMNS:
1302 return set_matrix_array(iface, device, constant, data, elements,
1303 D3DXPC_MATRIX_ROWS, desc.Type, desc.Rows, desc.Columns);
1305 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc.Class));
1306 return D3DERR_INVALIDCALL;
1310 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1311 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1313 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1315 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, b);
1317 return set_scalar_array(iface, device, constant, &b, 1, D3DXPT_BOOL);
1320 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1321 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1323 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1325 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, b, count);
1327 return set_scalar_array(iface, device, constant, b, count, D3DXPT_BOOL);
1330 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1331 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1333 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1335 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
1337 return set_scalar_array(iface, device, constant, &n, 1, D3DXPT_INT);
1340 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1341 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1343 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1345 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
1347 return set_scalar_array(iface, device, constant, n, count, D3DXPT_INT);
1350 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1351 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1353 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1355 TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
1357 return set_scalar_array(iface, device, constant, &f, 1, D3DXPT_FLOAT);
1360 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1361 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1363 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1365 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
1367 return set_scalar_array(iface, device, constant, f, count, D3DXPT_FLOAT);
1370 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1371 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1373 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1375 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
1377 return set_vector_array(iface, device, constant, vector, 1, D3DXPT_FLOAT);
1380 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1381 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1383 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1385 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
1387 return set_vector_array(iface, device, constant, vector, count, D3DXPT_FLOAT);
1390 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1391 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1393 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1395 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1397 return set_matrix_array(iface, device, constant, matrix, 1, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4);
1400 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1401 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1403 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1405 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1407 return set_matrix_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4);
1410 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1411 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1413 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1415 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1417 return set_matrix_pointer_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_ROWS);
1420 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1421 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1423 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1425 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1427 return set_matrix_array(iface, device, constant, matrix, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4);
1430 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1431 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1433 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1435 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1437 return set_matrix_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4);
1440 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface,
1441 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1443 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1445 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1447 return set_matrix_pointer_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_COLUMNS);
1450 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1452 /*** IUnknown methods ***/
1453 ID3DXConstantTableImpl_QueryInterface,
1454 ID3DXConstantTableImpl_AddRef,
1455 ID3DXConstantTableImpl_Release,
1456 /*** ID3DXBuffer methods ***/
1457 ID3DXConstantTableImpl_GetBufferPointer,
1458 ID3DXConstantTableImpl_GetBufferSize,
1459 /*** ID3DXConstantTable methods ***/
1460 ID3DXConstantTableImpl_GetDesc,
1461 ID3DXConstantTableImpl_GetConstantDesc,
1462 ID3DXConstantTableImpl_GetSamplerIndex,
1463 ID3DXConstantTableImpl_GetConstant,
1464 ID3DXConstantTableImpl_GetConstantByName,
1465 ID3DXConstantTableImpl_GetConstantElement,
1466 ID3DXConstantTableImpl_SetDefaults,
1467 ID3DXConstantTableImpl_SetValue,
1468 ID3DXConstantTableImpl_SetBool,
1469 ID3DXConstantTableImpl_SetBoolArray,
1470 ID3DXConstantTableImpl_SetInt,
1471 ID3DXConstantTableImpl_SetIntArray,
1472 ID3DXConstantTableImpl_SetFloat,
1473 ID3DXConstantTableImpl_SetFloatArray,
1474 ID3DXConstantTableImpl_SetVector,
1475 ID3DXConstantTableImpl_SetVectorArray,
1476 ID3DXConstantTableImpl_SetMatrix,
1477 ID3DXConstantTableImpl_SetMatrixArray,
1478 ID3DXConstantTableImpl_SetMatrixPointerArray,
1479 ID3DXConstantTableImpl_SetMatrixTranspose,
1480 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1481 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1484 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
1485 BOOL is_element, WORD index, WORD max, DWORD *offset, DWORD nameoffset, UINT regset)
1487 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
1488 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
1489 HRESULT hr = D3D_OK;
1493 constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
1494 constant->desc.Class = type->Class;
1495 constant->desc.Type = type->Type;
1496 constant->desc.Rows = type->Rows;
1497 constant->desc.Columns = type->Columns;
1498 constant->desc.Elements = is_element ? 1 : type->Elements;
1499 constant->desc.StructMembers = type->StructMembers;
1500 constant->desc.Name = ctab + nameoffset;
1501 constant->desc.RegisterSet = regset;
1502 constant->desc.RegisterIndex = index;
1504 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name,
1505 constant->desc.Elements, index, constant->desc.DefaultValue,
1506 debug_d3dxparameter_registerset(regset));
1507 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1508 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type),
1509 type->Rows, type->Columns, type->Elements, type->StructMembers);
1511 if (type->Elements > 1 && !is_element)
1513 count = type->Elements;
1515 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
1517 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
1518 count = type->StructMembers;
1523 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
1524 if (!constant->constants)
1526 ERR("Out of memory\n");
1531 for (i = 0; i < count; ++i)
1533 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
1534 &constant->constants[i], memberinfo == NULL, index + size, max, offset,
1535 memberinfo ? memberinfo[i].Name : nameoffset, regset);
1539 size += constant->constants[i].desc.RegisterCount;
1544 WORD offsetdiff = 0;
1546 switch (type->Class)
1554 case D3DXPC_MATRIX_ROWS:
1555 size = is_element ? type->Rows : max(type->Rows, type->Columns);
1556 offsetdiff = type->Rows;
1559 case D3DXPC_MATRIX_COLUMNS:
1560 size = type->Columns;
1561 offsetdiff = type->Columns;
1569 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type->Class));
1573 /* offset in bytes => offsetdiff * components(4) * sizeof(DWORD) */
1574 if (offset) *offset += offsetdiff * 4 * 4;
1576 /* int and bool registerset have different sizes */
1577 if (regset == D3DXRS_INT4 || regset == D3DXRS_BOOL)
1579 switch (type->Class)
1583 size = type->Columns;
1586 case D3DXPC_MATRIX_ROWS:
1587 case D3DXPC_MATRIX_COLUMNS:
1588 size = 4 * type->Columns;
1592 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type->Class));
1598 constant->desc.RegisterCount = max(0, min(max - index, size));
1599 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns;
1604 if (constant->constants)
1606 for (i = 0; i < count; ++i)
1608 free_constant(&constant->constants[i]);
1610 HeapFree(GetProcessHeap(), 0, constant->constants);
1611 constant->constants = NULL;
1617 HRESULT WINAPI D3DXGetShaderConstantTableEx(const DWORD *byte_code, DWORD flags, ID3DXConstantTable **constant_table)
1619 struct ID3DXConstantTableImpl *object = NULL;
1623 const D3DXSHADER_CONSTANTTABLE* ctab_header;
1624 D3DXSHADER_CONSTANTINFO* constant_info;
1627 TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
1629 if (!byte_code || !constant_table)
1631 WARN("Invalid argument specified.\n");
1632 return D3DERR_INVALIDCALL;
1635 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags);
1637 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1640 WARN("CTAB not found.\n");
1641 return D3DXERR_INVALIDDATA;
1644 if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
1646 WARN("Invalid CTAB size.\n");
1647 return D3DXERR_INVALIDDATA;
1650 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1651 if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
1653 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1654 return D3DXERR_INVALIDDATA;
1657 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1660 ERR("Out of memory\n");
1661 return E_OUTOFMEMORY;
1664 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1667 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1670 ERR("Out of memory\n");
1671 HeapFree(GetProcessHeap(), 0, object);
1672 return E_OUTOFMEMORY;
1674 object->size = size;
1675 memcpy(object->ctab, data, object->size);
1677 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1678 object->desc.Version = ctab_header->Version;
1679 object->desc.Constants = ctab_header->Constants;
1680 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1681 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
1682 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
1684 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1685 sizeof(*object->constants) * object->desc.Constants);
1686 if (!object->constants)
1688 ERR("Out of memory\n");
1693 constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
1694 for (i = 0; i < ctab_header->Constants; i++)
1696 DWORD offset = constant_info[i].DefaultValue;
1698 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
1699 &object->constants[i], FALSE, constant_info[i].RegisterIndex,
1700 constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
1701 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
1706 *constant_table = &object->ID3DXConstantTable_iface;
1711 free_constant_table(object);
1712 HeapFree(GetProcessHeap(), 0, object);
1717 HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantTable **constant_table)
1719 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1721 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1724 HRESULT WINAPI D3DXGetShaderSamplers(CONST DWORD *byte_code, LPCSTR *samplers, UINT *count)
1727 UINT i, sampler_count = 0;
1730 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1731 const D3DXSHADER_CONSTANTINFO *constant_info;
1733 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
1735 if (count) *count = 0;
1737 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (LPCVOID *)&data, &size);
1738 if (hr != D3D_OK) return D3D_OK;
1740 if (size < sizeof(D3DXSHADER_CONSTANTTABLE)) return D3D_OK;
1742 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1743 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
1745 constant_info = (D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
1746 for (i = 0; i < ctab_header->Constants; i++)
1748 const D3DXSHADER_TYPEINFO *type;
1750 TRACE("name = %s\n", data + constant_info[i].Name);
1752 type = (D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
1754 if (type->Type == D3DXPT_SAMPLER
1755 || type->Type == D3DXPT_SAMPLER1D
1756 || type->Type == D3DXPT_SAMPLER2D
1757 || type->Type == D3DXPT_SAMPLER3D
1758 || type->Type == D3DXPT_SAMPLERCUBE)
1760 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
1766 TRACE("Found %u samplers\n", sampler_count);
1768 if (count) *count = sampler_count;